Skip to content

Add fail-closed signed worker release gate#50

Merged
dovvnloading merged 1 commit into
mainfrom
codex/signed-worker-release-gate
Jul 23, 2026
Merged

Add fail-closed signed worker release gate#50
dovvnloading merged 1 commit into
mainfrom
codex/signed-worker-release-gate

Conversation

@dovvnloading

Copy link
Copy Markdown
Owner

Summary

Adds the fail-closed release boundary needed to turn the reviewed one-folder recipe worker package into a verifiable signed generation without making provider execution available by accident.

Why

The package contains a large PyInstaller dependency closure. Signing only the executable would leave the copied runtime tree outside the manifest integrity boundary, while the prior 128-entry limit could not represent the real package. The release path now binds every ordinary package file and keeps executable-role selection separate from inert dependency resources.

What changed

  • Added worker_release.py, a release-only Ed25519 manifest builder that hashes every ordinary one-folder file with stable identity checks.
  • Assigns the sole image_transform role to recipe_worker.exe and records all other files as inert resource entries.
  • Rejects reparse points, hardlinks, empty or oversized files, reserved manifest.json, mutable inputs, missing workers, and oversized trees.
  • Self-verifies the canonical manifest before returning metadata.
  • Added tools/sign_recipe_worker.py with external raw 32-byte key ingestion, atomic manifest output, bounded machine-readable status, and no private-key persistence or output.
  • Extended the manifest contract for PyInstaller _internal paths and safe metadata names, and raised the explicit complete-tree bound to 1,024 entries.
  • Added optional signing parameters to packaging/build_recipe_worker.ps1; unsigned builds remain the default and are not launch-authorized.
  • Added seven regression tests covering exact-tree installation/provenance, resource entries, CLI output, invalid packages, invalid key material, and reparse-root rejection.
  • Updated the Phase 2 ADRs, evidence log, and worker packaging README.

Security and compatibility notes

  • No private key, signed production manifest, or trust-root update is committed.
  • The signer is release tooling only; installation still requires the pinned public-key trust root and SignedBundleInstaller.
  • The provider lifecycle remains disabled. The qualification harness still fails closed until a signed installed generation and live broker PID/token binding are available.
  • The pre-existing local Cortex.pyproj edit was intentionally left unstaged and is not part of this PR.

Validation

  • Python: 258 passed, 1 skipped (the existing non-Windows native-broker case); one pre-existing pytest-asyncio deprecation warning.
  • Targeted manifest and release tests: 16 passed.
  • Ruff, compileall, contract generation, and git diff --check: passed.
  • Frontend lint, typecheck, production build, and 39 frontend tests: passed.
  • Windows PyInstaller package build: passed; direct worker launch refused with exit code 78.
  • External-key smoke: signed and independently verified the complete 822-file package closure with one image_transform entry and 821 inert resource entries; the temporary key and manifest were discarded.
  • Native launcher and sandbox qualification probes: expected blocked status at the absent signed-worker and live-broker gates; no provider launch was authorized.

Remaining release gate

This PR intentionally stops before production enablement. The next controlled stage is to provision the real pinned public trust root, install the signed package through the existing immutable-generation installer, execute the authenticated broker PID/token handshake through the suspended AppContainer/Job Object launcher, run the hostile decoder/cancellation corpus, obtain external security review, and only then wire lifecycle and UI enablement.

Copy link
Copy Markdown
Owner Author

CI verification

Quality run 95 completed successfully on commit 6244d3e.

  • Headless Python tests, module compilation, and generated API contract verification passed.
  • Frontend typecheck, lint, unit tests, and production build passed.
  • Launcher-managed bundle and signed WebView2 bootstrapper checks passed.
  • One-folder Windows package build and packaged bootstrapper verification passed.

The release gate remains intentionally fail-closed: no provider execution is enabled until a real signed worker generation is installed with the pinned public trust root and the live broker PID/token handshake is qualified.

@dovvnloading
dovvnloading merged commit f707abe into main Jul 23, 2026
1 check passed
@dovvnloading
dovvnloading deleted the codex/signed-worker-release-gate branch July 23, 2026 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant