<feed xmlns='http://www.w3.org/2005/Atom'>
<title>domain-dig.git/DomainReportExporter.swift, branch v4.9.0</title>
<subtitle>local-first ios domain inspection toolkit. dns, tls, rdap, audit.
</subtitle>
<id>http://git.krz.sh/krz/domain-dig.git/atom?h=v4.9.0</id>
<link rel='self' href='http://git.krz.sh/krz/domain-dig.git/atom?h=v4.9.0'/>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/'/>
<updated>2026-07-20T21:27:59+00:00</updated>
<entry>
<title>v4.8.3: Clear SonarCloud new-code issues</title>
<updated>2026-07-20T21:27:59+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T21:22:28+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=bb18197860ffdb491f010648ec903003b6e1bb65'/>
<id>urn:sha1:bb18197860ffdb491f010648ec903003b6e1bb65</id>
<content type='text'>
Fixes the 4 reported bugs and ~97 code smells flagged in the new-code
period. No behavior changes.

Bugs (swift:S3923) — DomainInspectionService's confidenceFor* helpers each
returned `error == nil ? .low : .low`, an inert conditional. Simplified to
`return .low` and dropped the now-unused `error` parameter.

Smells:
- Merged 14 identical `.empty`/`.error` switch branches in DomainViewModel
- Consolidated duplicate implementations (clearPresentedResults/reset,
  String.nonEmpty/nilIfEmpty, ExportFormat.id/fileExtension)
- Extracted nested ternaries into TLSGrade.tone, EmailSecurityGrade.tone,
  and ChangeImpactClassification.color; removed ContentView.impactColor
  and the duplicate mapping in BatchResultsView
- Documented empty closures and singleton inits
- Marked unused protocol-conformance parameters `_`
- Renamed CloudSyncTrigger.`import` to `imported` (raw value preserved)
  and SSLSessionDelegate's _serverTrust/_tlsMetadata
- Merged nested ifs in the DER parser; flattened closure nesting in
  PortScanService and IntegrationService
- Replaced two-case switches with if/else

Left open: S107 (init parameter counts), S115 (constants mirroring DoH and
ipapi JSON keys), S1075 (false positives on https:// literals), and two
S117 hits on SwiftUI $binding shorthand. These want a Won't Fix resolution
in SonarCloud, not a code change.
</content>
</entry>
<entry>
<title>fix: markdown report underlines and duplicate DNS record values</title>
<updated>2026-07-20T19:48:54+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T19:48:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=1c3d19b233f135a059f5d111dd1a7514af25ed3f'/>
<id>urn:sha1:1c3d19b233f135a059f5d111dd1a7514af25ed3f</id>
<content type='text'>
The plain-text-to-Markdown transform only recognized '-' underlines, but
batchText writes '=' — under the document title and as a 48-character
separator between reports. Both leaked through as literal bullets, so a
generated report opened with:

  # Scheduled Watchlist Report
  - ==========================

Title underlines are now consumed alongside the title, '=' underlines
promote to H2 the same as '-', and standalone divider runs render as a
Markdown horizontal rule.

Separately, the DNS section concatenated apex and wildcard records
without dedup. On a domain with wildcard DNS resolving to the same
addresses as the apex, every value was listed twice. Now deduped while
preserving order, so a wildcard value that genuinely differs is still
shown.
</content>
</entry>
<entry>
<title>v4.8.0: Add scheduled report generation</title>
<updated>2026-07-20T18:56:41+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-17T16:18:25+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=fd8ca178a379da71f5bb19c461524888cad9447e'/>
<id>urn:sha1:fd8ca178a379da71f5bb19c461524888cad9447e</id>
<content type='text'>
- ScheduledReportService (@MainActor, headless/storage-backed like
  DomainMonitoringService): builds the latest report for every tracked domain
  from persisted history, exports it via DomainReportExporter in the
  configured format (markdown/PDF/JSON), writes it to a local Documents
  subdirectory, logs the run, and fires a "Scheduled Report Ready" local
  notification.
- ScheduledReportScheduler mirrors DomainMonitoringScheduler's BGTaskScheduler
  approach with its own task identifier (net.cleberg.DomainDig.report.schedule,
  added to Info.plist) and a daily/weekly cadence.
- ScheduledReportsView (Settings → Scheduled Reports): enable toggle, cadence
  and format pickers, "Generate Now", and a log of past reports each shareable
  via the existing ExportPresenter share sheet.
- Gated behind the existing .automatedMonitoring capability (Pro), consistent
  with monitoring being the other background-automation feature.
- Settings/logs persist via UserDefaults (DomainExportFormat is now Codable),
  not DomainDataPortabilityService backup/restore — this is local automation
  configuration, not user-authored content, same reasoning as v4.7.0's
  watchlist saved views.
</content>
</entry>
<entry>
<title>v4.8.0: Add markdown and PDF export formats</title>
<updated>2026-07-20T18:56:41+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-17T16:09:02+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=01c3d342f6980a69feb8df27a3454fd721d6298e'/>
<id>urn:sha1:01c3d342f6980a69feb8df27a3454fd721d6298e</id>
<content type='text'>
- DomainExportFormat gains .markdown and .pdf (CaseIterable, Identifiable,
  titled), alongside the existing text/csv/json.
- Markdown reuses the existing text-export content verbatim via a line-based
  transform (section "Title\n----" underlines become "## Title", the leading
  title becomes an H1, other lines become bullets), so the two formats can
  never drift apart.
- PDF renders that Markdown as a simple monospaced multi-page document via
  UIGraphicsPDFRenderer (mirrors AuditExporter's existing PDF approach;
  degrades to raw Markdown bytes on non-UIKit platforms).
- Replaced the single/batch/tracked-domains/workflow share call sites' hand-
  written per-format switches with format-agnostic functions
  (exportSingleReportData, exportBatchReportData, exportTrackedDomainsData,
  exportWorkflowData) that delegate straight to DomainReportExporter, removing
  the now-orphaned per-format helper functions those switches used to call.
</content>
</entry>
<entry>
<title>v4.7.0: Add domain reputation/blocklist data source</title>
<updated>2026-07-17T15:57:30+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-17T15:39:17+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=6e273c2676ce29cef057d117e4427e031886e743'/>
<id>urn:sha1:6e273c2676ce29cef057d117e4427e031886e743</id>
<content type='text'>
- New DomainReputationResult model (status: clean/listed/unknown, listed
  sources, checked-at) and a `reputation(domain:)` method on ExternalDataService,
  mirroring the existing pluggable-URL enrichment pattern (ownership history,
  DNS history, extended subdomains, pricing). With no endpoint configured
  (the default; DomainDig ships no bundled third-party reputation dependency)
  it resolves to unavailable rather than "clean".
- New .reputation FeatureCapability/DataCapability, gated Pro+ like domainPricing.
- Threaded reputation/reputationError through LookupSnapshot and HistoryEntry
  (backward-compatible decode) so results persist with history entries.
- Auto-fetched in performLookup alongside pricing; surfaced as a "Reputation"
  info row, folded into DomainInsightEngine's risk score/factors and top-level
  insights (a listed domain raises risk score and adds a factor/insight), and
  exported in text, CSV, and JSON report output.
- Reputation-driven risk changes ride the existing change-severity pipeline, so
  a listed status flip is visible to monitoring the same way any other risk
  delta is, without bespoke monitoring wiring.
</content>
</entry>
<entry>
<title>feat(v3.7.0): add timeline and advanced diffing system</title>
<updated>2026-04-24T17:38:38+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-04-24T17:38:38+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=d0b3b7a15b59266b4ae4262fdb0364245092c17c'/>
<id>urn:sha1:d0b3b7a15b59266b4ae4262fdb0364245092c17c</id>
<content type='text'>
- introduce TimelineView for historical snapshots
- allow comparison between any two snapshots
- implement DiffService for structured domain diffs
- improve diff visualization with clear change indicators
- add navigation across changes
- optimize history loading for performance
- extend CLI and export to support timeline data
</content>
</entry>
<entry>
<title>feat(v3.2.0): add Data+ tier and external data integrations</title>
<updated>2026-04-22T18:47:37+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-04-22T18:47:37+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=6c23daaaba2a954220ece2afa7193dbdcad55c22'/>
<id>urn:sha1:6c23daaaba2a954220ece2afa7193dbdcad55c22</id>
<content type='text'>
- introduce Data+ tier for advanced data features
- add ownership history and DNS history
- expand subdomain discovery with external sources
- add domain pricing insights
- implement local usage/credit system
- integrate external data service layer with rate limiting
- extend export and CLI for Data+ features
</content>
</entry>
<entry>
<title>feat(v3.0.0): unify platform architecture and introduce feature tiers</title>
<updated>2026-04-22T16:46:52+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-04-22T16:46:52+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=37b02e5ee360d61751951b77b7b556165a3af1fc'/>
<id>urn:sha1:37b02e5ee360d61751951b77b7b556165a3af1fc</id>
<content type='text'>
* consolidate DomainReport as canonical data model
* add feature tier system (free/pro/data+ scaffolding)
* apply clean feature gating across workflows and tracking
* refactor app structure for maintainability
* standardize navigation and settings
* add data lifecycle controls
* ensure consistency across UI, export, and CLI
* stabilize internal inspection API
</content>
</entry>
<entry>
<title>feat(v2.9.0): add risk scoring and deterministic insight engine</title>
<updated>2026-04-22T16:28:28+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-04-22T16:28:28+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=ceac99c05f180d9008b75c9329822466ff60255b'/>
<id>urn:sha1:ceac99c05f180d9008b75c9329822466ff60255b</id>
<content type='text'>
* introduce domain risk assessment with transparent factors
* add insight engine for actionable observations
* implement cross-domain insights for workflows
* improve DNS, subdomain, email, and TLS interpretation
* classify change impact severity
* include insights and risk in export
</content>
</entry>
<entry>
<title>feat(v2.7.0): add provenance, confidence, and reproducibility metadata</title>
<updated>2026-04-22T14:47:24+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-04-22T14:47:24+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=7b41195620eadd54d25fa98dcd36735cba906ba3'/>
<id>urn:sha1:7b41195620eadd54d25fa98dcd36735cba906ba3</id>
<content type='text'>
* add result provenance across major sections
* introduce confidence levels for ambiguous outputs
* distinguish observed facts from inferred summaries
* expand snapshot metadata for reproducibility
* improve error classification and partial snapshot handling
* include provenance and confidence in export
* add local notes for tracked domains and history
</content>
</entry>
</feed>
