gh shim: refuse writes when a once-valid manifest is missing or broken

Merged
AF
2d ago
+672-26

On a machine that has had a valid signed GitHub-routing manifest, a missing or broken manifest now refuses every GitHub write before the real gh runs. Before, the write fell through to the operator's own login. Reads keep working.

  • The refusal text is the approved wording, pinned byte for byte in tests.
  • Every path that hands a command to the real gh rechecks the current manifest first, including the early captured-background path.
  • The audited operator bypass from #1112 is unchanged when an active manifest exists. Worker-shell refusals still win, with or without the bypass.
  • A machine that was never provisioned still passes calls through to gh unchanged, with its own tests.

Verified on the build server: 537 gh shim library tests and 107 serial gh shim integration tests passed, plus the Windows target check. Two Landlock setup probes were left out of the worker's run because that server can't enforce Landlock; CI runs them.

No release note: the gh shim only runs on CortexKit's own governed setup.


Summary by cubic

Fails closed on GitHub writes when a machine that once held a valid signed routing manifest loses, corrupts, or cannot read it, so unsafe commands no longer fall through to the operator's own login. Previously the write fell through to the operator's own account; now it exits 86 with an approved refusal, and reads keep working.

  • Refuses writes with a new gh_shim_manifest_unavailable code when durable provisioning records exist but no valid manifest does.
  • Rechecks the current manifest before every native gh delegation, including protected captured-background writes.
  • Never-provisioned machines still pass all calls through to gh unchanged.
  • The audited operator bypass from #1112 is unchanged when an active manifest exists; worker-shell refusals keep priority with or without the bypass.
  • Where the last valid manifest governs nothing (Windows), a broken manifest refuses as unclassified instead of regressed, with the same exit 86 and no delegation.