railiance-platform/docs/task-execution-plan-compiler.md

111 lines
7.5 KiB
Markdown
Raw Normal View History

# Owner-derived typed metadata plan compiler
Prepared source component for RPF-WP-0035-T12, with completed bounded source
preparation RPF-WP-ADHOC-2026-10-11-T02. This component does not authorize,
dispatch, authenticate or mint anything. CCR38 stays identity/self-only.
`OwnerConfig` is independently installed by the Platform owner. It is never
parsed from an HTTP body, CheckRequest or a service-supplied configuration.
It fixes the Platform repository, Secrets source repository, owner-admitted local
catalogue directory and exact CCR/catalogue filenames and reviewed source hashes.
The closed source set contains this compiler, existing credential-change validator,
CCR, its one reader HCL artifact, catalogue entry and the actual Secrets catalogue
loader/package/errors/redactor files. Arbitrary additional files are refused.
Paths/hashes are public provenance, not credentials or authority. Source authenticity
and admitted runtime/continuous exclusive source custody remain external gates;
before/after filesystem hashes detect observed changes, not adversarial same-UID
swap-and-restore or arbitrary mutation of Python memory.
The compiler reuses `validate_ccr`, `applier_readiness_blockers`, `apply_blockers`,
`generated_policy_hcl` and `auth_payload`. It only accepts freshly approved,
confirmed production `workload-kv-read` CCRs whose reviewed HCL matches generated
read-only policy, with existing netkingdom OIDC or Kubernetes auth mount. Already
applied/verified/active CCRs refuse rather than silently become replay authority.
No other lane module, mount enable/config, KV read/write, token/SecretID delivery,
AppRole mutation, caller HCL/JSON body, paths or command argv can be compiled.
The catalogue comes from a separately owner-pinned local Secrets catalogue file,
loaded by `secrets_engine.catalog.validate_entry` executed directly from the
verified source snapshot, together with its pinned package/errors/redactor.
Each compilation uses temporary private module names and removes them on success
or failure. Canonical application imports remain untouched. Cached modules and
timestamp-based bytecode cannot substitute different code for the verified bytes;
new Secrets Engine imports outside the closed source set refuse. This is source
consistency within the admitted Python runtime, not a Python security sandbox.
Its catalogue id, existing mount, logical path, fields, production stage and
approval CCR reference must match the owner CCR. Engine-managed mounts and auth
are refused: existing delivery-auth metadata can be carried, but is never applied
or authenticated by this action. This is not a new credential-grants catalogue.
The exact thirteen-field `CatalogEntry` projection matches
`build_action_request.context.catalog_target`; its digest uses sorted compact UTF8
JSON with `ensure_ascii=False`, matching the actual ExecutionContract helper.
Actual Forgejo CCR42 is in_flight and no matching Secrets catalogue exists. Neither
is invented. Positive tests only make explicitly synthetic approved/pilot copies
of existing public owner fixtures in temporary directories; they grant nothing.
## Concrete interfaces
`Compiler.proposal()` locally derives metadata: action `execute-ccr`, kind
`workload-kv-read`, catalogue id, CCR bytes digest, exact catalogue-target projection
and digest, and six ordered operation method/path/payload hashes. It is preparation,
not an admission or a complete ExecutionContract. Order matches the proposed Access
package: GET/PUT/GET ACL, then GET/PUT/GET OIDC/Kubernetes role. GET payload is empty;
PUT JSON bytes are deterministic, sorted compact ASCII JSON containing generated
HCL or `auth_payload`, with no caller-selected body.
`Compiler.compile(request)` accepts exactly that metadata, operation UUID and the
opaque served canonical PDP request digest `sha256:<64 lowercase hex>`.
It compares the exact owner-derived proposal and returns a frozen serialized Plan.
It does not recompute Access canonicalization, strip the prefix, validate a PDP or
accept an unsigned digest as authority. The authenticated mediator must establish
correspondence with exact full CheckRequest/claim/consume bytes independently.
Plan content digest is explicitly bare64hex for Journal.Binding.plan_digest;
request and catalogue/payload hashes retain their required sha256 prefix.
`Compiler.before_call(plan, ordinal)` accepts exact integer0..5, recompiles the
immutable plan and source bundle, re-derives fresh owner payload bytes and compares
again before returning one frozen local Call. A forged Plan constructor, extra
field, body hash/path/method/ordinal substitution, source drift or readiness change
refuses. Call.call_digest is the bare hash of exact ordinal/kind/method/path/payload
hash for the durable journal. The future mediator must validate this call immediately
before persisting its journal intent and dispatching these same bytes; this API
has no native callback, no backend opener and no credential.
## Enforced integration gates still missing
The compiler only binds its closed local component request. It does not construct
or approve the complete `SECRETS-EXEC-20261011-v1` descriptor. The mediator must
compare the exact owner-derived CCR/catalogue/six operations and full independently
pinned source bundle, authoritative grant CCR/hash, origin/cluster, approved native
before/after state expectations, deadline and TTL/use ceilings against locally
admitted inputs. Caller-selected grant/baseline/estate/configuration cannot supply
these. Missing authoritative inputs or whole-descriptor correspondence must refuse
before protected backend effects. Expected native baseline/readback normalization,
conflict handling and source/time enforcement spanning revalidation-to-dispatch
remain unimplemented; source comparison alone is not native atomic CAS.
The proposed Access package still hard-refuses owner admission. No initiator
projection or verified/member/MFA flags are produced here; existing readiness
refusal remains. Actual identity/PIP/representation/service/PDP/claim/consume,
Journal admission/replay/unknown state handling, independent provider confirmation,
restricted native adapter and whole-request/source/deadline enforcement must be
integrated. The proposed task token ceilings are120s/12uses, with at least one
cleanup use; this component records limits, it does not enforce native expiry/uses
or provide a hard elapsed timer. Trusted owner runtime must bound parser/import/
filesystem/compiler work by remaining action budget before any actual call.
Token custody/revoke, temporary object removal, owner-private recovery after unknown
and truthful native readback remain gates. General lifecycle/apply/exec/default
migration and SecretsT06/RPF35T02/T12 cannot close from this source component.
Validation:45 compiler tests and 15 journal tests pass, covering real owner K8s/OIDC body generation,
exact catalogue unicode digest interoperability, refusal of alternate action/kind/
path/body/ordinal, re-pinned root policy, nonapproved/unconfirmed/replayed CCR,
engine-managed catalogue, forged immutable plan, source drift/duplicates and
symlink/hardlink/writable source. No native action, credential/Secret access or owner checkout writes.
October 13 correction: a regression first demonstrated that a cached validator
could replace the hashed source. Additional cases cover cached dependencies,
invalid catalogue acceptance through a substituted validator, and private-module
cleanup on both success and refusal. The October 11 v2 review remains evidence
for its original bytes only; it does not attest this corrected revision.