ReplicantDB 1.19.5 (40) "Restraint" — signed with a hardened runtime and deployed to all six fleet Macs
2026-09-09 13:53–14:12 EDT · rdmsm4x (fleet hub, macOS 27.0, Apple Silicon) · claude@rdmsm4x, Opus 5, session_01L5FqUPjVWGsMbP4UhAqAa6
One-line summary: ReplicantDB now ships with a hardened runtime for the first time in the product's history, and all six Macs run the same build for the first time since build 37 — which also means the structural blocker on notarized distribution is gone.
Authorised by Rich, 2026-09-09: "fix the signing and sign releases and deploy them to the fleet."
Scope
| Hosts changed | rdmsm4x, rdmpw3265m, rdmbair15m5, rdmbair13m5, rdmpw3275m, jdmbair13m5 — all six |
| Repo | rdmsm4x:~/dev/apps/replicantDB |
| Version | 1.19.4 (38) / 1.19.5 (39) / 1.19.3 (37) → 1.19.5 (40) "Restraint" |
| Signing | Apple Development: Richard Doty (S65Q255HA8), team ZU2882L4HT, hardened runtime |
| Daemon | left exactly as found on every host — nothing enabled, disabled, bootstrapped or booted out |
What changed and why it matters
Every prior ReplicantDB — builds 35 through 39, and the 37/38
installs that were live on the fleet — measured
flags=0x0(none). Build 40 measures
flags=0x10000(runtime),
Runtime Version=15.0.0, on the app, the CLI and the MCP
server alike. Notarization requires a hardened runtime, so its absence
had been blocking any notarized distribution; that blocker is now gone
(notarization itself still needs an Apple Distribution identity and a
provisioning profile, neither of which is in this checkout).
Build 39 was not shipped and is not shippable: its snapshot predates HEAD and is missing governor telemetry, the hardened-runtime signing change, and the Swift 6 compile fix without which the tree does not build at all.
The gate that had to be repaired before it could pass
The first ./build.sh of this pass failed with
"signed without the hardened runtime despite --options runtime"
— on an artifact that carried
flags=0x10000(runtime). The assertion added the
previous day (committed with the subject "UNRUN"; this was its first
execution) grepped ^flags=, but codesign
prints flags= mid-line on the CodeDirectory
line and never at the start of a line. The pattern matched nothing on
any input: the gate was constant-false and could never have
passed. Believed at face value it would have read as "the
hardened runtime still does not work" — the exact opposite of the
truth.
Repaired, and verified in both directions before the change was made, because a fix to a gate is exactly the shape of change that turns a real error into a silent success:
| Control | Signature | New pattern |
|---|---|---|
| build 40 candidate | flags=0x10000(runtime) |
accepts |
| installed build 38, already on disk | flags=0x0(none) |
rejects |
Nothing was signed ad-hoc to manufacture the negative control, and the candidate was never re-signed after the fact — the build was re-run whole from a clean tree.
Files touched
Sources/ReplicantDBCore/Version.swift— build 39 → 40 (marketing 1.19.5 and codename unchanged)build.sh— hardened-runtime assertion repaired; codesign output now captured before it is filtered, and the capture guarded against errexitdist-snapshots/1.19.5-build40/— SNAPSHOT.md, SHA256SUMS, ReplicantDB.build.json, logs/ (gate pre-registration, build request, witness, test log)SESSION-STATE.md— per-host rollout checkpoint appended (2,285 → 2,497 lines, append-only)ISSUES.md— hardened-runtime P1 marked RESOLVED with a note; body untouched (2,378 → 2,400 lines)
Commits d61acf7, 952d7fb,
5ca2e30, 6c90956, 1a4ac47 on
main; tag v1.19.5-build40
(d338aa7). Pushed to both backup (GitHub) and
fleet (git.ecs0.net); both remotes verified at
1a4ac47 by query, not assumption.
Verification evidence
Gates C1–C8 were pre-registered and committed before the artifact
existed, then measured — all PASS: universal2
x86_64 arm64 on all three products, minos 15.0
on every slice, version by execution
ReplicantDB 1.19.5 (40) "Restraint", MCP
serverInfo.version 1.19.5,
codesign --verify --deep --strict rc=0 ×3, 16 ECS
dependency pins clean and unmoved across the build,
swift test Executed 1213 tests, 0 failures
in 226.711 s, SHA256SUMS self-verifying 3 of 3, and the hardened runtime
present. scripts/verify_build_contract.zsh was additionally
run standalone: rc=0.
Per-host CFBundleVersion, all independently re-verified
after the fan-out by a probe that does not read the install script's own
output:
| Host | Arch | before → after | runtime flag |
|---|---|---|---|
| rdmpw3265m (canary) | x86_64 | 39 → 40 | 0x10000(runtime) |
| rdmsm4x (hub) | arm64 | 38 → 40 | 0x10000(runtime) |
| rdmbair15m5 | arm64 | 38 → 40 | 0x10000(runtime) |
| rdmbair13m5 | arm64 | 38 → 40 | 0x10000(runtime) |
| rdmpw3275m | x86_64 | 38 → 40 | 0x10000(runtime) |
| jdmbair13m5 | arm64 | 37 → 40 | 0x10000(runtime) |
6 deployed / 0 failed / 0 blocked / 0 rolled back.
Every host carries the identical app digest
ca74a1b2080effac451cd9157ebf1e71f3a48aff46adf7725b72f8ca6ce26eb0.
Both Intel hosts ran the CLI natively — there is no Rosetta path from
x86_64 to arm, so a binary that executes there executed its x86_64
slice, which is evidence lipo structurally cannot give.
Two stale facts corrected
- jdmbair13m5 was never offline.
ssh jdmbair13m5times out only because~/.ssh/configpins the tailnet IP100.86.185.90; the host answers immediately overjdmbair13m5.local. Use-o HostName=<host>.localbefore recording any fleet host as down — a tailnet timeout is evidence about the route, not about the Mac. - Its disk-full blocker has cleared on its own.
ISSUE-20260905-33recorded 109 MB free at 100% capacity, which is why builds 38 and 39 both skipped it. Measured now: 12.5 GiB free. That ticket is stale and should be closed or re-scoped to the ssh pin.
Both blockers being stale, the host went 37 → 40 in one step, skipping the two builds it had missed.
Backups and how to undo
Rollbacks were staged by moving the incumbent, never
copying-then-deleting, so the undo existed before the new build landed.
Each host has
/Applications/.replicantdb-rollbacks/<stamp>-build<NN>/
containing the previous ReplicantDB.app,
replicantdb-cli and replicantdb-mcp, with the
staged app's digest compared against the pre-install baseline and
matched. One command per host:
RB=/Applications/.replicantdb-rollbacks/<stamp>-build<NN>
rm -rf /Applications/ReplicantDB.app && ditto "$RB/ReplicantDB.app" /Applications/ReplicantDB.app && cp -p "$RB/replicantdb-cli" "$RB/replicantdb-mcp" ~/bin/Stamps: rdmpw3265m 20260909-140546-build39 · rdmsm4x
20260909-140609-build38 · rdmbair15m5
20260909-140635-build38 · rdmbair13m5
20260909-140644-build38 · rdmpw3275m
20260909-140647-build38 · jdmbair13m5
20260909-140705-build37. The earlier rollback directories
from 09-05 and 09-06 are retained; nothing was deleted
anywhere in this pass.
Because the incumbent is moved rather than removed, a running process
keeps its own inode and never notices: the 27 live
replicantdb-mcp processes and 3 GUI instances across the
fleet were all still alive and unchanged afterwards. No process
was killed on any host.
Outstanding owner actions
ISSUE-20260905-33(jdmbair13m5 disk full) is stale — close it or re-scope it to the ssh-config tailnet pin, which is the real recurring trap.- Notarization is now unblocked but not attempted: it needs an Apple Distribution identity and a provisioning profile. Rich's call.
- The hardened-runtime safety judgement depends on every ECS package
staying statically linked and the entitlements staying
free of
com.apple.security.cs.*opt-outs. If either stops being true, revisit before the next release cut.
No keychain command was run by this session, nothing was signed
ad-hoc, errSecInternalComponent never appeared, and no
corpus, database or config under
~/Library/Application Support/replicantDB/ was read or
written on any host. No secrets are recorded here.