feat(execution): bind immutable task grants before native effects
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
codex 2026-10-16 07:51:42 +02:00
parent 4021ca5e79
commit d042d468df
7 changed files with 460 additions and 7 deletions

View file

@ -0,0 +1,85 @@
# Proposed task-execution-grant immutable projection
RPF-WP-0035-T12 source preparation, 2026-10-16. This proposes and implements the
owner's pure projection/binding code; it approves no grant and registers no native
or legacy delegated applier. Existing production readiness remains refused.
Use the existing `task-execution-grant` CCR type proposed by Platform and
SECRETS-WP-0013. Use the existing execution descriptor's
`execution_grant_ccr_id` and `grant_immutable_sha256` join. No second consumer
execution descriptor, authorization token or broker is introduced.
`scripts/task_execution_grant.py` defines a closed CCR root with existing identity,
status/date/requester/review/target fields, effectful `execution` and `openbao`
objects, and an explicitly typed evidence event list. `immutable_digest` uses
SHA256 over sorted compact ASCII JSON of the complete validated projection.
It includes status, updated, title, requester, review requirements/approvers,
target coordinates, all execution inputs, generated HCL, token body and cleanup.
It excludes exactly `review.comments` and `evidence.events` by replacing those
lists with empty lists. No generic evidence-prefix stripping or caller-selected
exclusion exists. Unknown root/review/evidence fields refuse. Fields nested in
execution/openbao remain fully hashed and must exactly match independently
reconstructed effects when bound. Projection alone is not semantic admission.
Reviews have exactly at/reviewer/decision/comment; evidence events have exactly
at/kind/result/reference_sha256. These append-only annotations cannot supply a
runtime approval or become policy inputs. `require_append_only` independently
checks that each old list is an exact prefix of the new list and that the
immutable projection is unchanged. Removal, replacement and reordering refuse.
The owner must use known history when checking an update; a current file cannot
prove its own history. Updating `updated` or status changes the digest and requires
a new exact join. There is no guessed exclusion for convenience.
The compiler's optional independently installed `OwnerConfig.grant_filename`
selects one different CCR file under credential-change-requests. It adds exactly
that record and the pure validator source to the closed owner source-pin set.
The compiler reads verified bytes and executes the pinned validator source directly,
without a module-cache substitute. It reconstructs the entire effectful grant:
- The existing descriptor, excluding only its own `grant_immutable_sha256` to avoid
self-reference, plus action/catalogue and the actual owner source pins. The
record's own raw file hash is omitted from its own source-pin projection; all
other source hashes, including the validator, remain included.
- Deterministic `cleanup_specs(operation_id)`, its fixed private credential slots,
exact revoke/verification and delete/verification paths/methods, declared
no-issue/no-create branches, one reserved cleanup use and the cleanup obligation
after business expiry.
- Exact operation-specific task policy HCL on the two independently compiled
metadata endpoints plus revoke-self, and the exact parented service token body:
nonrenewable, no default policies, no identity policies, 30–120s TTL and twelve
uses. No caller HCL, body, handle, wildcard or mount administration is accepted.
It compares those structures with the owner record and compares the resulting
immutable SHA and grant ID with the existing descriptor fields before returning
a bound Plan. Unknown or changed effectful fields fail equality even if the caller
re-pins the record and recomputes its digest. The complete descriptor must still
match independently installed owner descriptor bytes. Raw source file hashes and
immutable hashes serve different purposes: even an annotation-only file edit
requires owner source-pin refresh and Plan reconstruction; it does not silently
change the grant immutable digest or restore an admission.
The disposable native adapter now refuses missing/unbound or proposed grants,
rebuilds the exact bound Plan from pinned owner sources at construction, checks
all source pins immediately before each native request, reconstructs each actual
metadata body via the compiler and compares actual token/ACL bodies with the bound
projection before issuing them. It still requires the same live postconsume
journal admission and the live owner-spawned disposable OpenBao process handle.
Native fault tests explicitly use synthetic approved copies in temporary directories;
no real owner CCR status, policy or grant is created or changed.
The normal credential-change CLI deliberately continues to reject this type for
execution. Adding it to LANE_MODULES would expose generic applier methods and is
not part of this source preparation. The pure validator is actually called by
the compiler/native fixture path; it is not a paper-only schema. An owner can
review this projection and later integrate source validation/recording into the
CCR tooling without enabling execution.
Remaining production work is now specific: approve/adopt this owner CCR projection;
verify owner source/grant admission and immutable target CCR semantics; integrate
authenticated principal, served exact claim/PDP/package and independent signed
consume; finish total native baseline/readback normalization/conflict control;
install bounded isolated owner runtime, trusted served deadlines/use accounting,
audit and protected recovery; then run the exact founder-scoped attended trial.
Neither an approved string nor this projection authenticates human approval.
Approval replay prevention and uncertain backend-effect reconciliation remain
separate. T12 and Secrets WP13 stay open.