<feed xmlns='http://www.w3.org/2005/Atom'>
<title>domain-dig.git/README.md, branch main</title>
<subtitle>local-first ios domain inspection toolkit. dns, tls, rdap, audit.
</subtitle>
<id>http://git.krz.sh/krz/domain-dig.git/atom?h=main</id>
<link rel='self' href='http://git.krz.sh/krz/domain-dig.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/'/>
<updated>2026-08-02T20:35:31+00:00</updated>
<entry>
<title>convert readme to nfo; convert docs to txt; relicense to 0bsd</title>
<updated>2026-08-02T20:35:31+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-02T20:29:31+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=fe83ff502ffcaa59c7a22471c634d565972e7644'/>
<id>urn:sha1:fe83ff502ffcaa59c7a22471c634d565972e7644</id>
<content type='text'>
</content>
</entry>
<entry>
<title>update org name</title>
<updated>2026-08-02T14:36:32+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-02T06:51:21+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=fa75b888d30e281230e98d58b30d611309431c1d'/>
<id>urn:sha1:fa75b888d30e281230e98d58b30d611309431c1d</id>
<content type='text'>
</content>
</entry>
<entry>
<title>update email</title>
<updated>2026-08-02T14:36:32+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-02T06:46:46+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=4496e44c1548b21cbcc23797c571169e43a71f6f'/>
<id>urn:sha1:4496e44c1548b21cbcc23797c571169e43a71f6f</id>
<content type='text'>
</content>
</entry>
<entry>
<title>docs: polish repo documentation after the v5.0.0 work</title>
<updated>2026-07-25T16:40:57+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-25T16:39:55+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=b824dae8ea16d20d75136687a7c59bc7b01afe27'/>
<id>urn:sha1:b824dae8ea16d20d75136687a7c59bc7b01afe27</id>
<content type='text'>
Brings the docs in line with the shipped v5.0.0 state and fixes staleness that
accumulated across the release.

- README: add a Tests section documenting the DomainDigTests unit net and that
  the scheme's test action runs both it and the accessibility audit; reword the
  roadmap pointer (v5.0.0 shipped, no longer "planned"); align the contact
  address to hello@zerolabs.sh (was cleberg.net, inconsistent with SECURITY.md).
- ARCHITECTURE: drop the stale "v4.4.1" from the title; note DomainReportExporter
  also renders Markdown and PDF; describe the DomainViewModel concern extensions
  and the ContentView split (SettingsViews / ResultSectionViews); record that
  v5.0.0 stabilized the Local API contract with links to local-api.md and
  data-migration.md; add a Testing section covering both test targets.
- SECURITY: bump the supported-versions table from 4.x to 5.x.

ACCESSIBILITY.md, local-api.md, and data-migration.md were already current and
are unchanged. Docs-only; no code changes.
</content>
</entry>
<entry>
<title>feat: versioned store-migration policy for persisted data (v5 step 2)</title>
<updated>2026-07-25T04:37:00+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-25T04:35:18+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=99e4623af1b08f36120a01b67cbe60df99668651'/>
<id>urn:sha1:99e4623af1b08f36120a01b67cbe60df99668651</id>
<content type='text'>
Third v5.0.0 roadmap item: define and implement a migration policy for the
on-device persisted store (tracked domains, history/snapshots, audits,
workflows, monitoring, settings), so data upgrades cleanly across app versions
instead of relying on a one-shot marker.

- DataMigrationService is reworked from a single boolean marker
  (`data.migrations.v3_4_0`) into a versioned runner keyed by an integer store
  schema version (`data.storeSchemaVersion`). It runs each step once in
  ascending order up to `currentStoreSchemaVersion`, stamping the version as it
  goes. Adding a future migration is now a `case N:` plus a version bump.

  Policy guarantees, all covered by tests:
  - Forward-only and idempotent; every step must be safe on an empty/older store.
  - Never downgrades: a store written by a newer build (higher version) is left
    byte-for-byte untouched.
  - Pre-versioning installs are handled: a set legacy boolean marker reads as
    "already at v1", so the v1 normalization never re-runs for them.

  v1 is the existing normalization pass (dedup + drop the legacy `watchedDomains`
  key + sanitize monitoring settings), now expressed as migration step 1.

- Docs/data-migration.md documents the persisted surface, the two independent
  version lines (store vs. backup export), when to use lenient decoding vs. a
  migration step, the runner contract, an "adding a migration" checklist, and
  backup-import compatibility. Linked from the README.

- DataMigrationServiceTests: 6 tests over legacy fixtures — fresh-store stamping,
  legacy `watchedDomains` migration + key drop, in-place dedup of the stored
  blob, idempotence, legacy-marker-as-v1, and the no-downgrade guard. Full unit
  suite: 58 passing.
</content>
</entry>
<entry>
<title>feat: stabilize and document the Local API v1 response contract (v5 step 3)</title>
<updated>2026-07-25T04:29:01+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-25T04:14:23+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=a52dee116d4066d1b59bd90b4ebc4def4e1597d6'/>
<id>urn:sha1:a52dee116d4066d1b59bd90b4ebc4def4e1597d6</id>
<content type='text'>
Second v5.0.0 roadmap item: make the Local API's public JSON contract explicit,
documented, and regression-locked, so external consumers (Shortcuts, scripts,
integrations) have a stable surface with a defined compatibility promise.

- LocalAPIContract: new single source of truth for the wire-format version
  ("v1") and the canonical JSON encoder (ISO-8601 dates, sorted keys). Both the
  success and error paths in LocalAPIService now route through it, so the format
  can't drift between them, and the ad-hoc per-call-site encoders are gone.

- The response envelope and every payload struct are promoted from `private` to
  internal so the contract is a first-class, testable part of the module. The
  transport/handler internals (request parser, HTTP response, secret store)
  stay private.

- Docs/local-api.md documents the base URL/auth, the envelope, the encoding
  conventions (notably: absent optionals are omitted, not null), every endpoint
  and its payload fields, the error codes, and the semantic-version-style
  compatibility policy (additive changes keep v1; renames/removals/type changes
  bump the version). Linked from the README.

- LocalAPIContractTests: 16 structure/"golden" tests pinning the envelope shape,
  each payload's field names, the enum encodings, and the ISO-8601 date format.
  They assert structure, not values, so ordinary behavior changes don't churn
  them but a renamed or dropped field fails CI. Full unit suite: 52 passing.
</content>
</entry>
<entry>
<title>ci: split accessibility coverage between local runtimes and CI</title>
<updated>2026-07-20T22:55:24+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T22:50:56+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=1e25fb947d3c01fc983b481fff5b064ed82349ab'/>
<id>urn:sha1:1e25fb947d3c01fc983b481fff5b064ed82349ab</id>
<content type='text'>
The two-job CI matrix was buying two near-identical iOS 26.x runs at
double the macOS minutes. GitHub's macos-26 image ships only 26.x
simulator runtimes, so it cannot test the 17.6 floor at all, and floor
coverage was the entire justification for the second job.

Split the work by what each side can uniquely do instead:

CI keeps one job on the newest runtime. Its real value is not the
runtime — it is building a clean checkout of the merge result, which
catches a file that was never committed. A local run cannot, and that
failure mode is live here: DomainDig.xcodeproj is hand-edited and uses
file-system-synchronized groups, where an entire missing folder still
builds locally. sr.ht cannot run macOS, so this is the only place that
check exists. Collapsing the matrix also removed the deployment-target
math, since "newest" is always above the floor.

Scripts/audit-a11y.sh runs the audit against real runtimes, defaulting
to floor + current. It reads the deployment target from the project
rather than hard-coding it, selects the oldest runtime at or above it
(one below is useless — the app cannot install), and says so plainly
when the nearest installed runtime is a major version above the target
rather than implying floor coverage it does not have.

.githooks/pre-push runs the floor tier, and only when Swift, asset, or
project files changed. Pre-push rather than pre-commit because the suite
takes ~85s: at pre-commit that blocks every commit, and a hook routinely
bypassed with --no-verify is worse than none. Opt in per clone with
'git config core.hooksPath .githooks'.

Docs/ACCESSIBILITY.md records the split, the measured non-nested
coverage that motivates it, and the enforcement ratchet.
</content>
</entry>
<entry>
<title>docs: correct license references to MIT</title>
<updated>2026-07-20T21:00:20+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T21:00:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=083dfa723739eedd409ea8a6ae27332e48515210'/>
<id>urn:sha1:083dfa723739eedd409ea8a6ae27332e48515210</id>
<content type='text'>
The badge added alongside the SonarCloud badges claimed GPL v3, and the
README's License section claimed 'GPL 3.0 or later'. LICENSE has always
been MIT, so both statements misrepresented the project's terms on its
public front page. The section text predates this branch.
</content>
</entry>
<entry>
<title>add all SonarCloud badges to README</title>
<updated>2026-07-20T21:00:20+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-20T20:27:04+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=876ff4ef5ed9ebcbd019a4abc773b01f1e89ff25'/>
<id>urn:sha1:876ff4ef5ed9ebcbd019a4abc773b01f1e89ff25</id>
<content type='text'>
</content>
</entry>
<entry>
<title>misc. cleanup</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:11:48+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/domain-dig.git/commit/?id=ce71e6d93f5200972b9baff0fd17f55d93dbd2b9'/>
<id>urn:sha1:ce71e6d93f5200972b9baff0fd17f55d93dbd2b9</id>
<content type='text'>
</content>
</entry>
</feed>
