docs: document the macOS code-signing identity convention#52
Conversation
Add distribution.md §2A (macOS code-signing identity): the ad-hoc/cdhash re-prompt rationale, the org.open-cli-collective.<binary> identifier invariant, the centralized goreleaser hooks.post snippet, and the check-signature acceptance gate. Extend §6 with the four MACOS_CERT_* secrets and the explicit four-line secrets: pass-through rule (never inherit). Cross-reference from release.md §4 and ci.md §4. Closes #51
|
Findings:
No blockers, majors, or minors. The new §2A matches the approved architecture: stable |
§2A now makes release-time signing the standard, so the cask's quarantine removal applies to the non-notarized (not unsigned) binary.
monit-reviewer
left a comment
There was a problem hiding this comment.
Automated PR Review
Reviewed commit: 0e27ad5
Approved with 2 non-blocking suggestions below. Address at your discretion.
Summary
| Reviewer | Findings |
|---|---|
| harness-engineering:harness-enforcement-reviewer | 1 |
| harness-engineering:harness-knowledge-reviewer | 1 |
harness-engineering:harness-enforcement-reviewer (1 findings)
💡 Suggestion - docs/distribution.md:145
Markdown list-item continuation line starting with 'notarized — Gatekeeper still quarantines downloads' has no leading indentation. CommonMark requires continuation lines to be indented to at least the bullet's content column (2 spaces here); GitHub's renderer will break this into a separate paragraph, producing a loose list and a floating sentence fragment. Add 2-space indentation to the continuation line.
harness-engineering:harness-knowledge-reviewer (1 findings)
💡 Suggestion - docs/distribution.md:93
The §2A invariants block states the cert is 'generated once and reused forever' but does not address cert expiration. Self-signed certs have a finite validity period; expiry simultaneously breaks every user's 'Always Allow' Keychain grant for every signed tool — a larger blast radius than the per-upgrade ad-hoc rehash problem §2A is solving. The invariants section should note the recommended cert lifetime (e.g. 10–25 years) and the migration path (re-release all tools, expect one re-prompt per user) so operators can plan for eventual rotation.
4 info-level observations excluded. Run with --verbose to include.
1 PR discussion thread considered.
Completed in 4m 19s | $0.75 | sonnet | daemon 0.2.121 | Glorfindel
| Field | Value |
|---|---|
| Model | sonnet |
| Reviewers | hybrid-synthesis, documentation:docs-reviewer, harness-engineering:harness-architecture-reviewer, harness-engineering:harness-enforcement-reviewer, harness-engineering:harness-knowledge-reviewer |
| Engine | claude · sonnet |
| Reviewed by | pr-review-daemon · monit-pr-reviewer |
| Duration | 4m 19s wall · 8m 09s compute (Reviewers: 3m 20s · Synthesis: 56s) |
| Cost | $0.75 |
| Tokens | 154.1k in / 31.9k out |
| Turns | 9 |
Per-workstream usage
| Workstream | Model | In | Out | Cache read | Cache create | Cost |
|---|---|---|---|---|---|---|
| hybrid-synthesis | sonnet | 30.9k | 3.6k | 0 | 30.9k (1h) | $0.17 |
| documentation:docs-reviewer | haiku | 5.8k | 7.7k | 0 | 5.8k (1h) | $0.05 |
| harness-engineering:harness-architecture-reviewer | sonnet | 46.2k | 3.2k | 33.9k | 12.3k (1h) | $0.11 |
| harness-engineering:harness-enforcement-reviewer | sonnet | 38.6k | 11.6k | 17.8k | 20.8k (1h) | $0.26 |
| harness-engineering:harness-knowledge-reviewer | sonnet | 32.7k | 5.8k | 17.8k | 14.9k (1h) | $0.15 |
Re-reviews only run when @monit-reviewer is re-requested as a reviewer — push as many commits as you need, then re-request when ready. PRs targeting branches other than main, master are skipped, even when @monit-reviewer is re-requested.
| differ). | ||
| - A **cask, not a formula** — we ship a prebuilt binary, not a source build. The | ||
| cask also handles Gatekeeper quarantine removal for the unsigned binary. The | ||
| cask also handles Gatekeeper quarantine removal for the non-notarized binary (signed per §2A, but not |
There was a problem hiding this comment.
🔵 Low (harness-engineering:harness-enforcement-reviewer): Markdown list-item continuation line starting with 'notarized — Gatekeeper still quarantines downloads' has no leading indentation. CommonMark requires continuation lines to be indented to at least the bullet's content column (2 spaces here); GitHub's renderer will break this into a separate paragraph, producing a loose list and a floating sentence fragment. Add 2-space indentation to the continuation line.
Reply to this thread when addressed.
| — no `cdhash` — so the grant survives rebuilds **as long as the cert and identifier | ||
| never change.** No Apple Developer account, no notarization: Homebrew binaries aren't | ||
| quarantined and we establish a local identity, not Gatekeeper trust — so `codesign` | ||
| MUST omit `--timestamp` and `--options runtime`. |
There was a problem hiding this comment.
🔵 Low (harness-engineering:harness-knowledge-reviewer): The §2A invariants block states the cert is 'generated once and reused forever' but does not address cert expiration. Self-signed certs have a finite validity period; expiry simultaneously breaks every user's 'Always Allow' Keychain grant for every signed tool — a larger blast radius than the per-upgrade ad-hoc rehash problem §2A is solving. The invariants section should note the recommended cert lifetime (e.g. 10–25 years) and the migration path (re-release all tools, expect one re-prompt per user) so operators can plan for eventual rotation.
Reply to this thread when addressed.
Document that the DR pins the leaf hash (not expiry) so an expired cert doesn't break existing grants, but new builds can't be signed with it. Reflow the §3 cask continuation lines to keep the CommonMark bullet indentation.
State the cask removes any quarantine metadata for the non-notarized binary, without the Gatekeeper-quarantines claim that read as contradicting §2A.
|
Codex final pass (9e) — post-daemon. STATUS: blockers=0 majors=0 minors=1; the minor (§3/§2A quarantine wording) is fixed in the follow-up commit. Findings:
The cert-expiry invariant is accurate and consistent with the agreed design: DR continuity depends on the pinned leaf hash, while signing new builds depends on the cert still being valid. |
Documents the macOS code-signing convention so every current and future keychain-backed CLI inherits it (part of the stable-code-signing initiative; shared infra lands in
open-cli-collective/.github).Changes
distribution.md§2A "macOS code-signing identity" (new): the ad-hoc/cdhashre-prompt rationale; theorg.open-cli-collective.<binary>identifier invariant; the centralized goreleaserhooks.postsnippet (one byte-identical line per darwin build, using the absolute$CODESIGN_DARWIN_SCRIPT); thedarwin-gate check-signatureacceptance gate (parse only thedesignated =>line; pincertificate leaf, nocdhash); per-caller self-gating; the one-time final re-prompt.distribution.md§6: the fourMACOS_CERT_*secrets + the explicit four-linesecrets:pass-through rule (neverinherit).release.md§4 andci.md§4: cross-references to §2A.Docs-only.
make checkpasses (tidy/lint/test).Closes #51