<feed xmlns='http://www.w3.org/2005/Atom'>
<title>domain-dig.git/DomainDig, branch v4.8.1</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.8.1</id>
<link rel='self' href='http://git.krz.sh/krz/domain-dig.git/atom?h=v4.8.1'/>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/'/>
<updated>2026-07-20T20:07:40+00:00</updated>
<entry>
<title>fix: match IAP product IDs to App Store Connect</title>
<updated>2026-07-20T20:07:40+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T19:03:36+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=024f611fbbf4d2405a10d649a59968617321732a'/>
<id>urn:sha1:024f611fbbf4d2405a10d649a59968617321732a</id>
<content type='text'>
The four product ID constants did not match the auto-renewable
subscriptions configured in App Store Connect, so Product.products(for:)
returned an empty array and tier(for:) resolved every purchase to .free.

Product IDs are permanent in App Store Connect, so the code is corrected
to match the configured values rather than the reverse:

  domaindig.pro.monthly      -&gt; domaindig.pro.month
  domaindig.pro.yearly       -&gt; domaindig.pro.annually
  domaindig.dataplus.monthly -&gt; domaindig.proplus.monthly
  domaindig.dataplus.yearly  -&gt; domaindig.proplus.annually
</content>
</entry>
<entry>
<title>v4.8.1: Bump version and mark shipped in roadmap</title>
<updated>2026-07-20T20:07:16+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T20:05:19+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=d69aa35d8843e45e1d13bae82259043787a661b0'/>
<id>urn:sha1:d69aa35d8843e45e1d13bae82259043787a661b0</id>
<content type='text'>
Bump AppVersion/marketing version to 4.8.1 and build number to 41 across the
app, widget, and share extension targets. Mark v4.8.1 (scheduled report tap
target, completed Pro gate, markdown underline rendering, DNS record dedup,
inspect tab keyboard behavior) shipped in RELEASE_ROADMAP.md, and note the
three follow-ups filed during UAT.
</content>
</entry>
<entry>
<title>fix: Generate Now tap target, remove keyboard dismiss button and launch focus</title>
<updated>2026-07-20T19:42:07+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T19:16:52+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=91041af60b5a98ef01f5588478302c1ef04e043d'/>
<id>urn:sha1:91041af60b5a98ef01f5588478302c1ef04e043d</id>
<content type='text'>
Scheduled Reports: the entire Overview section was wrapped in a single
VStack inside one List row, so SwiftUI collapsed every control into one
tap target and the menu-style Cadence Picker captured taps intended for
the Generate Now button. Unwraps the VStack so each control is its own
row, matching the pattern used in IntegrationsView and elsewhere.

Also extends the .automatedMonitoring gate to the two Pickers and the
Generate Now button. Previously only the Toggle was disabled, leaving a
button that appeared active on Free but silently no-opped against the
guard in ScheduledReportService.

Inspect tab: removes the keyboard toolbar's Dismiss Keyboard button and
the onAppear that focused the single-domain field at launch.
</content>
</entry>
<entry>
<title>fix: reject non-HTTPS webhook URLs at save time</title>
<updated>2026-07-20T18:56:41+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T17:05:18+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=6f8a441b622987ffe102cf7153e1bcdd1b730cfc'/>
<id>urn:sha1:6f8a441b622987ffe102cf7153e1bcdd1b730cfc</id>
<content type='text'>
Validating only at send time meant an http:// URL saved fine and then
failed silently on delivery. Validate in upsert so the integration editor
surfaces it, and give the failure its own error case rather than reusing
the generic invalid-URL message.

The send-time guard stays as defense in depth for URLs saved before this.
</content>
</entry>
<entry>
<title>fix: harden webhook transport and gate debug logging</title>
<updated>2026-07-20T18:56:41+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T16:56:37+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=77a42a8b4f3dd89e631f8246bdea3e95f83bac6a'/>
<id>urn:sha1:77a42a8b4f3dd89e631f8246bdea3e95f83bac6a</id>
<content type='text'>
Require HTTPS for outbound integration webhooks. Webhook URLs are
themselves secrets (Slack in particular), so an http:// endpoint leaked
both the URL and the alert payload in cleartext.

Disable DomainDebugLog in release builds. Every message used
privacy: .public, which opted out of OSLog redaction and wrote looked-up
domains to the unified log in shipped builds.
</content>
</entry>
<entry>
<title>v4.8.0: Bump version and mark shipped in roadmap</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:20:50+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=6e9dea95d015c0f2d335d9b89b8ee843b4c2b05e'/>
<id>urn:sha1:6e9dea95d015c0f2d335d9b89b8ee843b4c2b05e</id>
<content type='text'>
Bump AppVersion/marketing version to 4.8.0 and build number to 40 across the
app, widget, and share extension targets. Mark v4.8.0 (markdown/PDF export,
scheduled reports, stronger share affordances, verified local API consistency)
shipped in RELEASE_ROADMAP.md.
</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: Wire markdown/PDF export buttons into share menus</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:12:16+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=2b52ee5520cad3c47d30d513946645366f268762'/>
<id>urn:sha1:2b52ee5520cad3c47d30d513946645366f268762</id>
<content type='text'>
Adds "Export Markdown"/"Export PDF" (and batch/workflow equivalents) to the
single-result, batch, watchlist, and workflow export menus, gated behind
.advancedExports like the existing CSV/JSON options. Matches the existing
menu structure and Pro-gate wording per file rather than introducing a new
shared component, consistent with how CSV/JSON were already duplicated across
these five menus before this change.
</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: Bump version and mark shipped in roadmap</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:47:27+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=54c151e22f8a5d4d7a9c290e79fc7626415f7083'/>
<id>urn:sha1:54c151e22f8a5d4d7a9c290e79fc7626415f7083</id>
<content type='text'>
Bump AppVersion/marketing version to 4.7.0 and build number to 39 across the
app, widget, and share extension targets. Mark v4.7.0 (comparison, reputation,
tags/saved views) shipped in RELEASE_ROADMAP.md and escalate the overdue
XCTest-target gap ahead of v5.0.0.
</content>
</entry>
</feed>
