A personal security watchtower for iOS — pin the sites you care about and NetSweep silently checks their TLS certificates, DNS, security headers, and CVE exposure, alerting you locally before anything breaks.
NetSweep is a personal watchtower for the public websites you actually depend on — your bank, your email, your own domain. Pin a site and NetSweep runs a full security inspection, then keeps watch in the background and tells you the moment something changes: a cert nearing expiry, a fingerprint rotation, weakened headers, a new CVE match.
Instead of a wall of table rows, your watched hosts orbit your device on a living spatial canvas — tinted by health, breathing softly, recoloring the whole scene when something needs attention. Underneath the calm is a real engine: a concurrent on-device probe pipeline (TLS handshake capture, OCSP revocation, Certificate Transparency, NVD CVE search) — all inside Apple's sandbox, with nothing leaving your phone but the requests a browser would already make.
🎯 Built to be opened, not configured. No accounts. No dashboards. No setup. Pin a few sites and NetSweep takes it from there — you only hear from it when something actually changes.
NetSweep is an experiment in making a deeply technical tool feel calm, spatial, and alive — borrowing from observatory and command-center design more than from security dashboards.
- A place, not a list. Your trust surface is a navigable canvas you pan and zoom — your device at the center, each pinned host a node orbiting around it. Spatial memory does the work scrolling usually does.
- The interface has a mood. A single health signal drives the entire color temperature — cyan when every cert is healthy, warming through amber to red as risk rises. You feel the state before you read it.
- Only what changed. Open the app and the noise is gone — just the deltas surface. A morning brief for the infrastructure you trust.
- Restraint over density. Motion is purposeful and respects Reduce Motion; type respects Dynamic Type; nothing animates just to animate.
| Feature | Description | |
|---|---|---|
| 🔍 | Deep per-host inspection | TLS chain, OCSP revocation, DNS, HTTP→HTTPS redirect, six security headers, HSTS preload eligibility, Certificate Transparency, and matching CVEs — one polished report per host |
| ⏱️ | Background watchtower | A BGAppRefreshTask re-probes every pinned host on iOS's schedule (~12h, capped to 4 concurrent) so your battery never notices |
| 🔔 | Local expiry alerts | Notifications fire 30 / 14 / 7 / 1 days before a watched certificate stops being valid — computed on-device, no push server |
| ✦ | What's New | Only the deltas surface: cert renewed, expiring soon, new CVE matches, fingerprint rotation, weakened headers |
| 🗺️ | Spatial trust map | Your device at the center, every watched site orbiting — draggable, pinch-to-zoom, tinted by health |
| ◎ | Health dashboard + tags | Tag sites (Work, Personal, Family) and filter; stat tiles drill into the broken, the expiring, the watched |
| 📶 | Connection quality | Latency, jitter, throughput estimate, public-IP / ISP info, with history |
| ⤓ | Portable watchlist | Export your pinned hosts and tags as tidy JSON; import merges tags rather than overwriting |
| 🗣️ | Siri & Shortcuts | An "Inspect Website" App Intent and a netsweep:// URL scheme hand any URL straight into the Inspector |
| ♿ | Accessible | Respects Dynamic Type and Reduce Motion throughout |
The parts worth a closer look for fellow engineers:
- Custom spatial canvas. A SwiftUI pan/zoom surface backed by UIKit gesture recognizers to get true simultaneous pan + pinch — something SwiftUI's native gesture composition couldn't deliver cleanly. Node positions are cached and only rebuilt on data change, so panning stays at frame rate regardless of host count.
- Concurrent probe engine. Each refresh runs TLS, DNS, headers, and redirect probes concurrently on async/await with a bounded
TaskGroup(cap 4), built entirely onNetwork.framework— no private APIs, no raw sockets. - Real TLS + revocation. The certificate chain and negotiated protocol are captured from an
NWConnectionsec_protocolverify block; OCSP revocation is evaluated in-process viaSecTrust/SecPolicyCreateRevocation, and SHA-256 leaf fingerprints are pinned to flag silent rotations. - On-device data model with delta detection. SwiftData persists watched hosts, changes, lookups, and quality tests with
#Predicatequeries; every refresh diffs against the last snapshot and journals only what changed. - Background + system integration. A single
BGAppRefreshTaskkeeps the loop alive,UserNotificationsdrives the local expiry ladder, and App Intents expose the Inspector to Siri, Shortcuts, and Spotlight. - Zero dependencies. Entirely first-party frameworks — nothing to audit, nothing to break on update.
Your watchlist stays yours.
- 🏠 100% on-device — your watchlist, every inspection result, and every detected change live only on your phone
- 🚫 No accounts, no analytics, no ads, no trackers
- 📋 Ships with a privacy manifest (
PrivacyInfo.xcprivacy) declaring zero data collection - 🌐 The only outbound requests are the ones a browser would make to the hosts you pinned, plus four query-only public lookups:
ipwho.is— public IP / ISP infoCloudflare— connection speed estimateNIST NVD— CVE searchcrt.sh— Certificate Transparency log entries
- 🙅 No LAN scanning. NetSweep never touches other devices on your network — it does not request the iOS Local Network permission and declares no Bonjour service types.
📄 Full policy: netsweepapp.com/privacy.html (App Store Connect Privacy Policy URL)
| Layer | Technology |
|---|---|
| 🎨 Interface | SwiftUI + a custom spatial pan/zoom canvas |
| 👆 Gestures | UIKit recognizers (simultaneous pan + pinch) |
| 💾 Persistence | SwiftData (#Predicate queries, delta journaling) |
| 🌐 Networking | Network.framework (NWConnection TLS + HTTP probes, path monitoring) |
| 🔐 Security | Security (SecTrust OCSP) · CryptoKit (leaf fingerprints) |
| 🔔 Background | BackgroundTasks (BGAppRefreshTask) · UserNotifications |
| 🗣️ Integration | App Intents · netsweep:// URL scheme · StoreKit review prompt |
| 📦 Dependencies | Zero third-party packages |
.
├── 📱 app/ The iOS app — open app/NetSweep.xcodeproj in Xcode
│ └── NetSweep/
│ ├── App/ Entry, root flow, home canvas, onboarding, settings, history
│ ├── Models/ Probe engine (TLS, DNS, OCSP, CT, headers, NVD), watchtower,
│ │ notifications, persistence, App Intents
│ ├── Modules/ Feature screens (Website Inspector, Health, Vuln Insights, Connection)
│ ├── Shared/ Design system, spatial canvas, gestures, haptics, shared UI
│ └── Assets.xcassets/
└── 🌐 site/ Static marketing + privacy site for netsweepapp.com (HTML/CSS/JS)
| Name | NetSweep |
| Bundle ID | com.camgarrison.netsweep |
| Domain | netsweepapp.com |
| Version | 1.0 · single-sourced from MARKETING_VERSION (About screen reads it at runtime) |
| Deployment target | iOS 18.0+ |
| Destinations | iPhone · iPad |
Static HTML / CSS / JS marketing and privacy site for netsweepapp.com — extends the app's observatory aesthetic to the web with a light/dark theme toggle, scroll reveals, the NetSweep sweep mark, and App Store download badges throughout. No build step, no dependencies.
- 🏠
index.html— overview, the eight inspection signals, the watchtower loop, download CTA - 💡
use-cases.html— your own domain, team infra, digital footprint & pre-ship scenarios - 🔒
privacy.html— full privacy policy (App Store Connect URL:netsweepapp.com/privacy.html) - 🎨
styles.css·app.js— shared across all pages
☁️ Deploy: Cloudflare Pages with the build output directory set to
site.🔗 App Store: apps.apple.com/app/netsweep/id6777156826
- 📲 Open
app/NetSweep.xcodeprojand build to a physical iPhone — designed and tested on real hardware - 🔢 App version is single-sourced from
MARKETING_VERSION/CURRENT_PROJECT_VERSION; the About screen reads it at runtime, so there's nothing to hand-edit on a version bump - 🧪 67 unit tests (Swift Testing) cover the parsers, scoring, health ranking, and watchlist round-trips
- 🎯 The app icon is a single 1024×1024 universal asset — Clean Build Folder after any asset change
- 🔑 Signing, certificates & provisioning profiles are never committed (handled in Xcode)
- 🙈
.gitignoreexcludes Xcode user state, build output, DerivedData, and all signing artifacts
This project is released under a proprietary license — see LICENSE.
It is public for portfolio and reference viewing: you're welcome to read it, clone it for study, and learn from it. It is not open-source so please don't republish it, ship it, or present it as your own. If you'd like to use a part of it, reach out.