Skip to content

feat(release): verify installed gateway identity against wheel bytes - #1320

Draft
seonghobae wants to merge 4 commits into
mainfrom
feat/runtime-package-identity-1023
Draft

seonghobae wants to merge 4 commits into
mainfrom
feat/runtime-package-identity-1023

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Scope

Adds the first release identity slice for #1023. The release workflow embeds the checked-out protected source SHA and canonical API schema digest in the wheel, then verifies the installed wheel before publication. An inference-authenticated /v1/gateway/identity reports those fields and a package-tree digest only when installed package files match wheel RECORD hashes. Source checkouts, missing manifests, changed files, and extra importable files fail closed.

This does not close #1023: independently authenticated deployment identity, scoped/ephemeral Actions credentials, an immutable published release, and consumer migration remain separate gates.

Evidence

  • Focused runtime, API, health, and release workflow tests: 46 passed on 83f30d250b7111d411e5478501a8078f8239d94f.
  • actionlint .github/workflows/release.yml and git diff --check: passed.
  • Two wheels built with SOURCE_DATE_EPOCH matched byte-for-byte; an isolated install returned the exact source SHA and package digest.
  • The original checkout and fix(review): clear bootstrap credentials before serving #1314 branch were not changed.

Research

Torres-Arias et al., in-toto: Providing farm-to-table guarantees for bits and bytes, USENIX Security 2019: https://www.usenix.org/system/files/sec19-torres-arias.pdf. The paper motivates independent artifact-chain verification. This PR contributes one verifiable package link and does not claim the full signed in-toto chain. The PDF is linked because redistribution terms were not established.

Bytecode cache correction (2026-09-28)

Current head 352ac71547eef293aa4052181d57349f2717c8e5 closes a source-versus-executed-bytecode gap. A timestamp-valid .pyc can run changed code while its wheel-recorded .py remains intact; this was reproduced before the fix. The identity check now refuses any package bytecode cache. Release verification runs the freshly installed wheel with python -B, and the release runbook requires a cache-free runtime package tree. The focused release/API/health tests passed (66), actionlint passed, and an isolated wheel built from this commit returned its exact source SHA and package digest; the same install refused identity after a normal Python launch created caches. The Semgrep finding on the discarded marshal.loads approach was addressed by removing marshal entirely. Current-head hosted security and independent review remain pending. This is package-local evidence, not independent deployment attestation or signed release provenance.

Embed the exact release source and API schema in the built wheel. Expose an inference-authenticated receipt only when installed package files match wheel RECORD hashes, and fail closed on source shadowing or mutation.
@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 11 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 6039b545-e868-4c55-af78-334d22edbe34

📥 Commits

Reviewing files that changed from the base of the PR and between 8e1f1a8 and 352ac71.

📒 Files selected for processing (8)
  • .github/workflows/release.yml
  • contextual_orchestrator/api_contract.py
  • contextual_orchestrator/runtime_identity.py
  • contextual_orchestrator/server.py
  • docs/RELEASING.md
  • pyproject.toml
  • scripts/ci/build_runtime_identity.py
  • tests/test_runtime_package_identity.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae
seonghobae enabled auto-merge (squash) September 28, 2026 04:42
@seonghobae

seonghobae commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Local #1083 integration check, updated for this PR's current head 27262638107634a11ec617a71dda9673ed9cc84c (the earlier 83f30d25 evidence is historical): merged it with release probe 4039e0f127c943ee8f2819e61d521947322bcdb4 in local synthetic commit 8fef87f43f45dc20f4abc0510eb119cd6e7a7835, without conflicts.

On that synthetic tree, tests/test_runtime_package_identity.py passed (2 tests). With Python 3.12.13, uv_build==0.12.5, and SOURCE_DATE_EPOCH=1790571949, two wheels matched byte-for-byte at SHA-256 0c7d0f4c2bfde1f695da382c8b826fb82f254daa6565a5e961fd72199eae32c0. The wheel contained _release_identity.json and no native .so; an isolated install returned synthetic source SHA 8fef87f4 and package-tree digest 14fbff307bc0bac3b06e91426222ce26cd7e63708d6bef54f0d2cf0ae4daa9e8.

This confirms local compatibility with the current probe. It is not hosted acceptance, independent review, a published release, or a consumer deployment. The tool.setuptools.package-data stanza is inactive once the uv_build change lands; uv_build includes the in-package JSON without it.

Keep generated Python bytecode caches outside the wheel digest while rejecting unrecorded source and data files. Document that the receipt verifies installed wheel bytes rather than already-loaded code.
Comment thread contextual_orchestrator/runtime_identity.py Fixed
@seonghobae

Copy link
Copy Markdown
Contributor Author

#1083 release integration check for exact head 352ac71547eef293aa4052181d57349f2717c8e5:

The removal of marshal.loads addresses the reported unsafe deserialization, and this head's hosted Semgrep job is green. I built this exact head's wheel after generating its identity manifest, installed it into an isolated writable target, then ran the installed package with the project Python 3.12 interpreter. python -B -c '... verified_runtime_identity() ...' returned the expected source SHA. The same command with ordinary python produced 31 normal __pycache__/*.pyc files during import and raised RuntimeIdentityUnavailable (the endpoint would return 503). The new docs require a cache-free install and -B, and the release smoke now uses -B, so that smoke does not cover a normal writable installation/startup. Please make this deployment constraint explicit in the supported release/consumer launcher and test that exact launch path; a standard wheel installation must not be described as sufficient on its own.

I tested a local alternative that recompiles verified source and compares raw .pyc payloads without unmarshalling. It passed the toy unit test but failed on a real installed wheel's normal caches, so do not apply that patch. The current reject-cache behavior is the safer fail-closed policy until there is a valid cache verifier.

Separate #1083 container gap: current Dockerfile copies contextual_orchestrator/ directly into site-packages without the wheel's .dist-info/RECORD or generated _release_identity.json. That container cannot return this wheel identity even if no bytecode cache is present; the container release path needs an exact-wheel installation/proof before it can advertise the identity endpoint.

Copy link
Copy Markdown
Contributor Author

Exact-head admission correction — 352ac71547eef293aa4052181d57349f2717c8e5

Ready is review admission only. Fresh audit against base 8e1f1a8bf3e96e56dc8fcc90ec777883a1d56ce6 found:

  • latest terminal workflow blockers: CodeQL PR 36385155957=failure, Security and Quality 36385156065=failure

This PR is moved to Draft/Proposed until the causal owner repair is present on a successor exact head and re-audited. Queued/pending work is neither an additional blocker nor passing evidence. No Close, force push, destructive rebase, manual rerun, synthetic status/approval, merge, auto-merge, or bypass was performed.

@seonghobae
seonghobae marked this pull request as draft September 30, 2026 05:19

This branch has not been deployed

No deployments
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.

[Owner Gap] Publish immutable orchestrator/free Actions gateway contract

2 participants