krz/domain-dig

an ios app for DNS & SSL analysis

clone: git clone https://gitbay.org/krz/domain-dig.git

v4.8.2: RELEASE_ROADMAP.md · raw

  1# DomainDig Release Roadmap
  2
  3Priority lens: **new user-facing features.** The inspection engine is already
  4deep (DNS, DNSSEC, CAA, TLS, TLSA/DANE, email security incl. BIMI/MTA-STS, RDAP,
  5ports, geolocation, subdomains, availability). The next several releases invest
  6in *reach and surfacing* — getting that data onto more iOS surfaces and into more
  7workflows — rather than adding raw protocol checks.
  8
  9Current version: `v4.8.2`.
 10
 11## v4.4.1 Patch: Release Readiness — ✅ shipped
 12
 13- Consolidated Audit Mode onto the single `DomainDig/DomainDig/Audit*`
 14  implementation and retired the prototype files.
 15- Aligned `AppVersion.current`, Xcode marketing version, and build number.
 16- Included audit sessions in backup/restore counts, summaries, and merge behavior.
 17- Removed the retired `DomainDigCLI` target and refreshed README/architecture docs.
 18
 19## v4.5.0 Minor: Home Screen & Shortcuts Reach — ✅ shipped
 20
 21Goal: put DomainDig data and actions where the user already is.
 22
 23- **App Intents / Shortcuts** — `InspectDomainIntent`, `AddToWatchlistIntent`, and
 24  `RunSweepIntent`, exposed via `DomainDigShortcuts` for Shortcuts, Spotlight, the
 25  Action button, and Siri.
 26- **`domaindig://` deep links** — `inspect`, `watch`, `domain` (detail), and
 27  `sweep`, routed in `RootTabView`.
 28- **WidgetKit portfolio widget** (Home Screen small/medium/large) — per-domain
 29  health, certificate countdowns, and portfolio health counts, shared from the app
 30  via an App Group; tapping a domain deep-links into its detail.
 31
 32Deferred to a later minor: **Lock Screen accessory widget families** and a richer
 33per-widget "last change" indicator.
 34
 35## v4.6.0 Minor: Alerts, Glances & iPad — ✅ shipped
 36
 37Goal: make monitoring and results feel first-class across contexts.
 38
 39- **Sweep Live Activity** — a batch/watchlist sweep drives a Live Activity with a
 40  progress bar, current domain, and change/warning counts on the Lock Screen and
 41  in the Dynamic Island (`SweepActivityController` around the batch pipeline).
 42- **Share extension** (`DomainDigShareExtension`) — "Dig Domain" accepts a web URL
 43  from the system share sheet, extracts the host, and hands it to the app via the
 44  App Group inbox; the app inspects it on next activation.
 45- **iPad-optimized layout** — `RootTabView` renders a `NavigationSplitView`
 46  (sidebar + detail) in the regular size class and the tab bar in compact.
 47- **Actionable notifications** — per-domain `threadIdentifier` grouping, a
 48  "Re-inspect" action, and taps that route into the domain's detail.
 49
 50Deferred: monitoring-alert Live Activities (only the sweep activity shipped) and
 51Lock Screen accessory widget families (carried over from v4.5.0).
 52
 53## v4.7.0 Minor: Intelligence & Comparison — ✅ shipped
 54
 55Goal: help users interpret and organize, not just collect.
 56
 57- **Domain-vs-domain comparison** — `DiffService.compare(domainA:domainB:)`
 58  reuses the existing section-diff builders; `DomainCompareView` (Watchlist
 59  toolbar → "Compare Domains") picks two tracked domains and renders the result
 60  with the existing diff section UI.
 61- **Reputation / blocklist signals** — a new pluggable data source
 62  (`ExternalDataService.reputation(domain:)`, Pro+) mirroring the existing
 63  ownership/DNS-history/pricing enrichment pattern. Ships with no bundled
 64  third-party endpoint; folds a listed status into risk score/factors and
 65  insights, so it rides the existing report and monitoring change-severity
 66  pipeline rather than needing bespoke monitoring wiring.
 67- **Tags and saved views** for the watchlist — freeform tags per tracked
 68  domain, tag filter chips, and named saved filter/sort/tag presets
 69  (UserDefaults-backed; not yet part of backup/restore).
 70
 71## v4.8.0 Minor: Reporting & Sharing — ✅ shipped
 72
 73Goal: turn point-in-time snapshots into shareable, scheduled deliverables.
 74
 75- **Markdown and PDF export formats** — `DomainExportFormat` gains `.markdown`
 76  and `.pdf` alongside text/csv/json. Markdown reuses the existing text-export
 77  content via a line-based transform (never drifts from the text export); PDF
 78  renders that Markdown via `UIGraphicsPDFRenderer`, mirroring the approach
 79  `AuditExporter` already used for audit sessions.
 80- **Scheduled report generation** — `ScheduledReportService` /
 81  `ScheduledReportScheduler` (Settings → Scheduled Reports): a BGTaskScheduler-
 82  driven daily/weekly job that builds a markdown/PDF/JSON report bundle for all
 83  tracked domains, writes it locally, logs the run, and notifies when ready.
 84  Mirrors `DomainMonitoringService`'s headless, storage-backed design; gated
 85  behind the same Pro `.automatedMonitoring` capability.
 86- **Stronger share affordances** — "Export Markdown"/"Export PDF" added to the
 87  single-result, batch, watchlist, and workflow export menus; generated
 88  scheduled reports are individually shareable from their log.
 89- **Export consistency verified** — the local API already serves the canonical
 90  `DomainReport` directly (no field allowlist), so `reputation`, `domainPricing`,
 91  and every other field added since v4.7.0 already flow through automatically.
 92  No code change was needed there.
 93
 94Deferred/scoped out: scheduled-report settings and logs are UserDefaults-only
 95(not part of `DomainDataPortabilityService` backup/restore), same reasoning as
 96v4.7.0's watchlist saved views — this is local automation config, not
 97user-authored content.
 98
 99## v4.8.1 Patch: Reporting & Sharing Fixes — ✅ shipped
100
101Goal: fix what UAT of v4.8.0 turned up.
102
103- **Scheduled reports were unreachable manually** — the Overview section wrapped
104  every control in a single `VStack` inside one `List` row, so SwiftUI collapsed
105  them into one tap target and the Cadence `Picker` captured taps meant for
106  "Generate Now". Each control is now its own row.
107- **Pro gate completed on that screen** — `.automatedMonitoring` previously
108  disabled only the toggle, leaving both pickers and "Generate Now" interactive
109  on Free where they silently no-opped against the service-side guard.
110- **Markdown/PDF reports rendered `=` underlines as bullets** — the plain-text
111  transform only recognized `-`, so `batchText`'s title underline and its
112  48-character inter-report separators leaked through as literal list items.
113- **Duplicate DNS record values** — the report concatenated apex and wildcard
114  records without dedup, listing every value twice on domains with wildcard DNS.
115- **Inspect tab keyboard behavior** — removed the "Dismiss Keyboard" toolbar
116  button and the launch-time focus that raised the keyboard on app open.
117- **In-app purchases were unbuyable** — none of the four product ID constants in
118  `PurchaseService` matched the auto-renewable subscriptions configured in App
119  Store Connect, so `Product.products(for:)` returned nothing and `tier(for:)`
120  resolved every purchase to `.free`. Product IDs are permanent once created, so
121  the constants were corrected to match the store rather than the reverse.
122- **Local StoreKit testing** — added `DomainDig.storekit` mirroring the App Store
123  Connect group (Pro+ at level 1, Pro at level 2) and wired it into the Run
124  action, so the purchase and entitlement paths can be exercised without the
125  `DOMAIN_DIG_FORCE_PRO_PLUS` launch argument that bypasses StoreKit entirely.
126
127Follow-ups filed during UAT (#8, #9, #10) were all resolved in v4.8.2.
128
129## v4.8.2 Patch: Delivery Visibility & Build Health — ✅ shipped
130
131Goal: close the UAT follow-ups and make failures legible instead of silent.
132
133- **Disabled integrations no longer swallow events** (#8) — `enqueue(events:)`
134  filtered to enabled targets before writing any `DeliveryRecord`, so events
135  routed to a disabled integration vanished entirely. They now log a `.skipped`
136  entry with a reason. `sendTest` also respects `isEnabled`, which previously
137  delivered against targets that dropped every real event.
138- **"Process Queue Now" forces backed-off retries** (#9) — it only restarted the
139  processing task, never moving `nextAttemptAt`, so an item in backoff (up to an
140  hour) stayed undue and the button appeared inert. It now pulls queued items
141  forward, and reports an empty queue instead of doing nothing silently.
142- **Unreachable domains report as unreachable** (#10) — when the snapshot
143  fallback fired, the run compared old data against itself and claimed "No
144  meaningful changes" for a domain it never reached. `MonitoringDomainResult`
145  now carries `unreachableReason`, the summary says so, and a warning-severity
146  `monitoringFailure` reaches configured integrations.
147- **Swift 6 concurrency warnings cleared** — `SweepActivityAttributes` is
148  explicitly `nonisolated` (the app target sets
149  `SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor` while the widget target does not),
150  and `LocalAPIService`'s logger closures capture `self` coherently. Build is
151  warning-free.
152- **StoreKit configuration corrected and synced** — the scheme's path was wrong,
153  and the hand-authored file has been replaced by `SyncedProducts.storekit`,
154  synced against App Store Connect. Registered in the project without target
155  membership so it is not bundled into shipping builds.
156
157## v5.0.0 Major: Contract Stabilization & Engineering Health
158
159Goal: earn long-term compatibility promises — and pay down the debt that the
160feature releases above will accumulate.
161
162- Define migration policy for persisted snapshots, backups, audits, workflows,
163  and settings.
164- Stabilize the public local API response contract; document compatibility
165  guarantees and planned deprecations.
166- **Establish a test target.** The project currently has no XCTest target and no
167  tests; add one and cover the deterministic core first — `DomainReportBuilder`,
168  `DomainReportExporter`, `DomainDataPortabilityService` (merge/replace dedup),
169  and `DiffService` — before locking down external contracts.
170- **Decompose the god-files** behind that test net: `DomainViewModel.swift`
171  (~4.7k lines) and `ContentView.swift` (~3.8k lines) into focused units
172  (audit, monitoring, workflows, portability).
173
174## Cross-cutting note
175
176New feature surfaces (widgets, intents, extensions) each add a target and a
177persistence/entitlement seam. This project still has **no XCTest target**178v4.5.0 through v4.7.0 all shipped without the characterization-test safety net
179originally recommended before v4.7.0. That gap is now larger (comparison,
180reputation, and tags/saved-views all touch persisted models with hand-written
181backward-compatible decoders) and should be the very first thing v5.0.0 does,
182not a later item within it.