krz/domain-dig

an ios app for DNS & SSL analysis

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

main: Docs/ARCHITECTURE.txt · raw

  1# DomainDig Architecture
  2
  3## Overview
  4
  5DomainDig is a local-first inspection and audit app built around one canonical output model: `DomainReport`.
  6
  7Inspection flow:
  8
  91. `LookupRuntime` coordinates the section services that gather DNS, web, TLS, ownership, reachability, redirect, email, port, and enrichment data.
 102. `DomainInspectionService` normalizes live and cached results into `LookupSnapshot`.
 113. `DomainReportBuilder` converts each snapshot into the canonical `DomainReport`.
 124. SwiftUI screens, exports, and the local API render from `DomainReport` or data derived from it.
 13
 14`LookupSnapshot` remains the internal persistence shape for raw inspection state. `DomainReport` is the stable presentation/export contract.
 15
 16## App Layers
 17
 18- Section services: network collection and local normalization only.
 19- `LookupRuntime`: orchestrates section services for a single inspection.
 20- `DomainInspectionService`: builds inspection snapshots with provenance, cache state, and failure metadata.
 21- `DomainReportBuilder`: assembles summaries, insights, risk scoring, workflow context, and report metadata.
 22- `DomainReportExporter`: renders TXT, CSV, JSON, Markdown, and PDF output for app and local API use.
 23- `DomainViewModel`: coordinates SwiftUI state, persistence, audit sessions, monitoring, workflows, batch operations, imports, and exports. Its surface is split by concern across `DomainViewModel+Audit`, `+Monitoring`, `+Export`, `+Workflows`, `+History`, and `+Widget` extensions; the core type keeps the stored state and the inspection pipeline.
 24- SwiftUI views: render screens and invoke view-model actions. The largest view file was decomposed too — Settings screens live in `SettingsViews.swift` and the result detail sections in `ResultSectionViews.swift`.
 25
 26## Audit Mode
 27
 28The app has one active Audit Mode implementation:
 29
 30- Models live in `DomainDig/DomainDig/AuditModels.swift`.
 31- UI lives in `DomainDig/DomainDig/AuditViews.swift`.
 32- Export rendering lives in `DomainDig/DomainDig/AuditExporter.swift`.
 33- Persistence is owned by `DomainViewModel` through `DomainDataPortabilityService`.
 34
 35An audit session captures:
 36
 37- Domain and reviewer metadata
 38- Session status
 39- Point-in-time `HistoryEntry` and `DomainReport`
 40- Historical snapshot context
 41- Evidence asset references
 42- Checklist progress
 43- Findings with severity, status, evidence references, notes, and checklist areas
 44- Reviewer notes
 45
 46Audit sessions are stored under the same local portability service as the rest of app data and are included in full backup/restore flows.
 47
 48The older standalone prototype files, `DomainDig/AuditMode.swift` and `DomainDig/AuditModeView.swift`, are preserved in the repository for reference but excluded from synchronized target membership. They are not the release audit path.
 49
 50## Data Portability
 51
 52`DomainDataPortabilityService` owns backup, import, validation, lifecycle counts, and merge/replace behavior for:
 53
 54- Tracked domains
 55- History snapshots
 56- Audit sessions
 57- Workflows
 58- Monitoring settings and logs
 59- App settings
 60- Local feature metadata
 61
 62Backup imports support merge and replace modes. Merge mode deduplicates by stable IDs or normalized domain keys, keeps local data where appropriate, and merges audit-session reviewer notes when the same audit session appears in multiple backups.
 63
 64## Feature Tiers
 65
 66`FeatureAccessService`, `PremiumAccessService`, `PurchaseService`, and `UsageCreditService` provide the app's feature-gating surfaces.
 67
 68The app remains local-first. Purchase and entitlement code is local app infrastructure and does not introduce a hosted DomainDig backend.
 69
 70## Local API
 71
 72`LocalAPIService` is an automation surface over the same inspection/reporting pipeline:
 73
 74- `DomainInspectionService`
 75- `DomainReportBuilder`
 76- `DomainReportExporter`
 77- `LocalAPIModels`
 78
 79`v5.0.0` stabilized this contract: `LocalAPIContract` is the single source of truth for the `v1` wire version and JSON encoder, the response envelope and payloads are documented, and the shape is regression-locked by `LocalAPIContractTests`. See [local-api.txt](local-api.txt) for the endpoint and compatibility reference, and [data-migration.txt](data-migration.txt) for how the persisted store is versioned across app updates.
 80
 81## Testing
 82
 83Two test targets run from the `DomainDig` scheme's test action:
 84
 85- `DomainDigTests` — unit coverage of the deterministic core: `DomainReportBuilder`, `DomainReportExporter`, `DiffService`, `DomainDataPortabilityService` (merge/replace dedup), the store-migration runner, and the Local API contract. `SnapshotFixture` builds the deep `LookupSnapshot`/`DomainReport` models through the real builder so tests construct inputs without wiring every field.
 86- `DomainDigUITests` — Apple's `performAccessibilityAudit()` over every primary screen at default and largest Dynamic Type, plus metadata and screenshot assertions. See [ACCESSIBILITY.txt](ACCESSIBILITY.txt).
 87
 88A plain `xcodebuild test` (and CI) runs both. The unit net went in first in `v5.0.0` and is what made the god-file decomposition safe to attempt.
 89
 90## Xcode Project Structure
 91
 92`DomainDig.xcodeproj` uses filesystem-synchronized groups for the `DomainDig` folder. Target membership exclusions are therefore important release metadata. Files that should remain in the tree but not compile, such as retired prototypes, must be listed in the appropriate synchronized build file exception set.
 93
 94## Adding A New Data Source
 95
 961. Add the raw collection call to `LookupRuntime` or an existing section service.
 972. Integrate it in `DomainInspectionService` with provenance, cache source, and normalized failures.
 983. Extend `LookupSnapshot` only if the raw result must persist.
 994. Add summarized representation to `DomainReportBuilder`.
1005. Expose it through `DomainReportExporter` or `LocalAPIModels` when it is part of the external contract.
1016. Render it in SwiftUI from `DomainReport` fields or view-model state.
1027. Update backup/restore only when the data is user-authored state or long-lived app state.