Skip to content

Follow-up: deferred review findings from PR #800 #829

Description

@philcunliffe

Filed at triage of PR #800 (head b8a4033d54997bd59e014cb1f462a1c2b427a45e), whose Fixes #793 closes that issue on merge. Every residual finding from the two review rounds on #800 was re-verified against the current head from Linux; all are non-blocking. This issue is the carrier so none is lost. Full analysis lives in the two review comments on PR #800 and on #793 / #790.

Deferred review findings (each re-verified at the PR head)

1. Exactly 8 duplicate certificates produce a false residue warning (nit)

src/core/tls/darwin_trust.js:129-155. The sweep's only exit that clears the warning is the not-found pass, so 8 successful deletes consume the whole bound and fall out with detail set: a keychain the sweep just cleared completely still prints ! keychain trust may not be fully removed (stopped after 8 passes...), sending the user to Keychain Access for nothing. Inherent to any bound, hedged by "may", and reached only after eight CA re-mints. Both review rounds concluded the obvious fix (a confirming extra pass) just moves the edge to 9 and churns the bound test; leave it unless the bound is touched for another reason, and then add a doc-comment line.

2. The two trust probes run serially, so hyp status can block 2 x 5s (nit)

src/core/daemon/status.js:1345-1358 awaits isCaTrustedFn then isLaunchdEnvSetFn, each bounded by TRUST_PROBE_TIMEOUT_MS (5s, status.js:1284). Worst case (locked login keychain) is a 10s stall instead of 5s, then both render unknown. Parallelising with per-probe catches attached before the await keeps the tri-state exactly, but restructures the block that carries the argument for independent catches. Not worth it alone; noted for whoever next touches the collector.

3. hyp detach --purge --json drops the purge lines entirely (pre-existing, wants a design decision)

src/core/commands/clients.js:150-153 gates purged.lines on if (!parsed.json), so the residue warning from finding 1 above, and every other purge line, is invisible to a scripted caller. Pre-existing shape, not made worse by #800. The fix is a JSON-envelope decision (a purge block? fold into a warnings key?), which wants a short decision doc, not a drive-by repair.

4. A dNSName containing ", " renders as two entries in the joined text line (nit)

displayableCaHosts (src/core/tls/ca.js:414-421) strips control bytes, bounds length and count, but a printable comma-space inside one entry is indistinguishable from the separator in the joined text surfaces (src/core/commands/status.js:643, hypaware-core/plugins-workspace/claude/src/index.js:550). It can only appear to widen the stated grant, never narrow it; --json is unambiguous; unreachable through our own mint (assertAsciiHost). Left as recorded.

Design items still open from #793 (carried so the close loses nothing)

  • F1 (medium): the keychain grant is all-policy. security add-trusted-cert -r trustRoot with no -p trusts every policy while the name constraints only bound TLS server identity. Adding -p ssl touches the exact keychain-merge path the live macOS runs proved, so it needs a Mac plus a Remote Control acceptance re-run; alternatives (EKU serverAuth re-mint, or accept-and-record via a doc extending LLP 0237) are on Follow-up: deferred review findings from PR #782 #790/Follow-up: F1 and F2 from #790, plus proxy-trust status findings deferred from PR #792 #793.
  • F3 residue: lifecycle gaps. Fingerprint-drift detection between the on-disk CA and the trusted keychain entry (LLP 0238#ten-year-validity requires renewal to surface; nothing does), and narrower re-mint triggers so config churn does not rotate the CA. Both change lifecycle behaviour and want a decision doc.
  • Post-detach repair prompt (low). After hyp detach claude, hyp status renders launchd env: NODE_USE_SYSTEM_CA not set - run 'hyp attach claude' to set it indefinitely for a state the user chose. Gating on "a proxy attach is live" needs mode plumbed out of the attach probe into ClientAttachReport, plus a decision about what status claims in the CA-minted-never-attached state.

macOS acceptance items (explicitly owed; unprovable from Linux)

Whichever change next ships in this area should carry a docs/ACCEPTANCE.md pass on a real Mac covering:

  1. security delete-certificate -c multi-match semantics. The hyp status names the CA's permitted hosts, uninstall clears every duplicate root (#793) #800 sweep is safe under either reading (byte-identical argv per pass, hard bound, every non-zero exit either ends cleanly or carries a detail), but which reading is true is unverified. On a Mac with a 2-3x re-minted CA, run hyp daemon uninstall and assert Keychain Access holds no HypAware Local CA.
  2. The 5s probe timeout in situ. The unit test proves runServiceCommand kills and rejects; it cannot prove a locked login keychain's GUI prompt is actually cleared by the SIGKILL, nor that 5s is right for a cold keychain. Lock the login keychain, run hyp status, confirm the line reads unknown - the keychain probe could not run and no dialog is left on screen.
  3. The rendered attach-dialog line. ensureDarwinProxyTrust is darwin-gated and unexported, so the round-2 sanitize wiring is proven only at the shared-helper level. On a real CA the dialog preamble should read (limited to: api.anthropic.com, api.openai.com, chatgpt.com), exactly as before.
  4. F1, if attempted: the -p ssl variant needs the Remote Control acceptance check re-run, since Bun's keychain merge honouring a policy-scoped trust setting is the unverified part.

Backlinks: PR #800 (fix and both review rounds), #793 (the findings issue this PR closes), #790 (original analysis).

Metadata

Metadata

Assignees

No one assigned

    Labels

    neutral:fixDelegate this issue to neutral for an autonomous fix attempt (reproduce -> fix -> PR)neutral:stuckneutral attempted this but cannot complete it autonomously — needs a human

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions