diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38e248d..13e350d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,7 +83,7 @@ jobs: - name: Run test suite run: | - python -m coverage run -m unittest discover -s tests -t . + python -m coverage run -m pytest -q python -m coverage report - name: Chronicle migration tests diff --git a/CHANGELOG.md b/CHANGELOG.md index 72dd0fb..8bc558b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ versioned schemas plus explicit migration notes for compatibility. installer state, Host diagnostics, repair, rollback, and uninstall. - Added checksummed release assets, SBOM/provenance generation, installer CI, GitHub Pages publication, and installation documentation. +- Added the bounded Phase 3 contract-only local slice: published Execution, + Storage, Outcome, assurance, and Patch Promotion validation/replay contracts + with authority-bearing paths fail closed pending verified external facts and + RFC acceptance. See [release notes](docs/en/releases/0.3.0rc2.md). diff --git a/README.md b/README.md index d9364f8..424b77a 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,9 @@ canonical transition. Accepted events are written to a local, append-only Chronicle with chained SHA-256 Sigils and receipts. > Project status: `0.3.0rc2` release candidate. Phase 2 freezes the Codex -> Plugin-first Instrumentarium while preserving host-neutral scientific -> contracts. +> Plugin-first Instrumentarium while Phase 3 adds a bounded contract-only, +> fail-closed local slice; canonical authority and RFC acceptance remain +> external prerequisites. ## Why Benchwork @@ -408,7 +409,7 @@ examples/ Minimal research artifacts Run the test suite: ```bash -python3 -m unittest discover -s tests -v +python3 -m pytest -q ``` Changes to canonical transitions should include tests for replay, schema @@ -424,6 +425,7 @@ changes should preserve locale paths and follow - [Compatibility policy](docs/en/COMPATIBILITY.md) - [Release process](docs/en/RELEASE_PROCESS.md) - [M10 acceptance matrix](docs/en/M10_ACCEPTANCE.md) +- [Phase 3 contract gate](docs/en/PHASE3_ACCEPTANCE.md) ## License diff --git a/README.zh-CN.md b/README.zh-CN.md index e00a56d..005f23c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -8,8 +8,9 @@ Benchwork 将科研活动转化为明确、可审查的状态。智能体和工 提案,但只有确定性的 Athanor 内核能够接受规范状态迁移。获准事件写入本地 追加式 Chronicle,并通过链式 SHA-256 Sigil 与 Receipt 留下记录。 -> 项目状态:`0.3.0rc1` 候选版本。Phase 2 已冻结 Codex Plugin-first -> Instrumentarium,同时保留宿主中立的科研契约;稳定命名仍为 provisional。 +> 项目状态:`0.3.0rc2` 候选版本。Phase 2 已冻结 Codex Plugin-first +> Instrumentarium;Phase 3 增加了范围受限、默认 fail-closed 的本地合同纵切, +> 规范权威与 RFC 接受仍是外部前置条件。 ## 为什么需要 Benchwork diff --git a/docs/en/OPEN_DECISIONS.md b/docs/en/OPEN_DECISIONS.md index 8144e6c..031d322 100644 --- a/docs/en/OPEN_DECISIONS.md +++ b/docs/en/OPEN_DECISIONS.md @@ -18,3 +18,17 @@ canonical: true `PIVOT` outcome automatically creates lineage. 6. Define Provider leases, cancellation, result transport, and executor isolation before direct research verbs automatically execute Task Capsules. + +## Resolved decision record (2026-08-06) + +The user approved four synchronized Phase 3 decision packages. They are no +longer open decisions; their canonical text is incorporated in the owning RFCs: + +1. OD22: RFC-0012 Heartbeat Collision Wire Closure HCW1–HCW10. +2. OD23: RFC-0012 Initial State Reducer ISR1–ISR3. +3. OD24: RFC-0013 namespace closure AC1 and RFC-0012 Result Authority Closure + AC2–AC4. +4. OD25: RFC-0015 Observation projection clarification OP1–OP2. + +These decisions do not by themselves publish a runtime, authorize journal or +storage mutation, accept a Result, or confer scientific authority. diff --git a/docs/en/PHASE3_ACCEPTANCE.md b/docs/en/PHASE3_ACCEPTANCE.md new file mode 100644 index 0000000..7e63405 --- /dev/null +++ b/docs/en/PHASE3_ACCEPTANCE.md @@ -0,0 +1,18 @@ +# Phase 3 contract gate + +Run the repeatable Phase 3 evidence gate from the repository root: + +```bash +.venv/bin/python scripts/ci/check-phase3-contracts.py +``` + +It verifies the published Schema family, RFC-0012 execution and storage +contract validators, RFC-0015 Job Outcome validator, local durable +start/observe/cancel/restart flow, and the MCP boundary that rejects generic +execution authority. + +The gate is intentionally contract-only. A passing run is evidence for the +local reference slice; it does not claim a complete RFC-0012 Journal replayer, +RFC-0013 Storage backend, RFC-0015 Result acceptance, remote Worker support, +or scientific authority. Those remain the Phase 3 release-exit work named in +the [roadmap](ROADMAP.md#phase-3--sanctum-04). diff --git a/docs/en/PHASE3_BLOCKER_REGISTER.md b/docs/en/PHASE3_BLOCKER_REGISTER.md new file mode 100644 index 0000000..0857836 --- /dev/null +++ b/docs/en/PHASE3_BLOCKER_REGISTER.md @@ -0,0 +1,42 @@ +# Phase 3 blocker register + +This register records implementation boundaries found by local independent +review. It is not an authority grant, RFC acceptance record, or a substitute +for a complete Chronicle/Storage replay. + +## Active blockers + +| Area | Why the installed local comparator must fail closed | Required before a local reducer/comparator may be installed | +| --- | --- | --- | +| RFC-0012 retry scheduling and readiness | The published Event payload has opaque terminal-reason, backoff, queue, deadline, and freshness values. The repository has neither an immutable Specification resolver nor a non-forgeable resolver Receipt/authorization result. A self-Sigiled “resolution” record would let a caller authorize `ACTIVE -> RETRY_WAIT -> QUEUED`. | A resolver-owned, verified eligibility and readiness result; exact Specification and terminal/settlement/assurance bindings; persistent eligibility binding for the State; and a continuous prefix test through the next Attempt allocation. | +| RFC-0013 quota-pressure transitions | Quota counters are independent projected entities, but the current closed Storage State does not retain their per-counter revisions. Reusing the Journal sequence would produce invalid entity-revision algebra. | An approved State/Schema evolution that persists independent quota-counter revisions, plus exact `observed_at`/clock semantics and pressure transition tests. | +| RFC-0013 transfer preparation | `transfer.prepared` would create a Transfer request, Attempt, Reservation, and quota effects. Current records contain bare authorization/fence/policy/backend references, Reservation has no verified issuer result, and State lacks quota-counter revisions. Treating their self-Sigils as admission authority would permit caller-controlled state transitions. | Verified authorization, lease/fence, backend, policy, and reservation-issuance inputs; an approved quota-revision State evolution; and a continuous prepare-to-terminal transfer replay with exact quota accounting. | +| RFC-0013 retention-policy registration | The installed replay accepts only locally closed `ACTIVE` PROJECT and already-projected exact Reference Set branches. BLOB scope still needs a replayed Blob lifecycle and PROGRAM needs a verified program-to-project resolver. Initialization cannot yet be encoded: RFC-0013 requires a migration-protection policy but does not provide its fixed ID, complete field values, or authorization-Sigil derivation, so accepting any guessed two-policy set would be unsafe. | A canonical migration-protection policy identity/full-field/authorization definition (or an accepted resolver contract), then initialization-policy reducers plus exact activation checks; a replayed Blob scope relation; a verified PROGRAM resolver; and fixtures covering every scope and the two initialization registrations. | +| RFC-0013 canonical-reference release | Local facts can close self-Sigils and a Head advance, but cannot prove that a Chronicle suffix contains no binding Event. | An authoritative full Chronicle replay/adaptor or an externally verified absence authority. The public reducer remains fail closed. | +| Full RFC-0013 Storage replay | The prefix dispatcher still deliberately rejects transfer, replica, materialization, quarantine, retention, GC, and disposition Events without their authoritative immutable-record and backend facts. | Reducers and supplied-facts comparators for each Event family, followed by retained-output, quarantine, and recovery prefix fixtures. | +| RFC-0014 Patch MCP and Host-native application | The four Patch tool names and closed schemas are published, but the MCP server intentionally registers no Patch module. Implementing a route without the Promotion Journal, authenticated human confirmation, Storage/Chronicle authority, and the reference atomic-CAS adapter would expose a misleading mutation surface. | A complete Promotion Coordinator and Journal replayer; verified confirmation and Athanor/Storage boundaries; the `FULL_TREE_ATOMIC_CAS` reference adapter with durable evidence/recovery; then four exact MCP routes with their success/error contracts. | + +## Local review record + +The following local reviews were performed in the active project session. They +are advisory implementation review evidence only; no source was disclosed to +an external reviewer. + +| Scope | Disposition | Evidence | +| --- | --- | --- | +| Result acceptance, Outcome and assurance-Claim local closures | Findings were fixed before the corresponding commits; the installed paths retain fail-closed authority boundaries. | `ab5ed53`, `c64b377`; focused suite and full test baseline in the exit audit. | +| Lease fencing and retained multi-Attempt selection | A stale-lease/fence-regression finding was fixed before merge. | `d4fa717`; final-floor guards and replay tests. | +| Canonical-reference commit/release local facts | Closure, quota-settlement, and release-absence findings were resolved by retaining fail-closed release behavior where authority is missing. | `9f1b605`, `f74cc66`; Storage contract tests. | +| Proposed retry and quota-pressure reducers | Rejected, not merged: their initial forms would have treated caller-controlled inputs as authority or violated independent entity revisions. | No implementation commit; blockers above describe the required design inputs. | + +## Verification baseline + +Run from the repository root: + +```bash +.venv/bin/python -m pytest -q +PYTHONPATH=src .venv/bin/python scripts/ci/check-phase3-contracts.py +``` + +These commands establish only the contract-only local slice. They do not +accept any RFC, establish backend truth, or grant Athanor/Chronicle authority. diff --git a/docs/en/PHASE3_EXIT_AUDIT.md b/docs/en/PHASE3_EXIT_AUDIT.md new file mode 100644 index 0000000..20c13bb --- /dev/null +++ b/docs/en/PHASE3_EXIT_AUDIT.md @@ -0,0 +1,47 @@ +# Phase 3 exit audit + +This document records the release-exit evidence required by the Phase 3 +roadmap. It is an audit aid, not an RFC acceptance record and not a claim of +runtime or scientific authority. + +| Exit requirement | Current evidence | Status | +| --- | --- | --- | +| Five accepted RFCs | RFC-0011 through RFC-0015 remain `draft`. | Blocked by explicit RFC acceptance. | +| Executable Schemas and examples | `scripts/ci/check-schemas.py` validates 214 published Schemas; Phase 3 fixtures are checked by the contract suite, including Promotion Journal revision algebra, abandonment-record closure, and adapter-generation consistency. | Present. | +| Threat-model review | [Independent local trust-boundary review](PHASE3_THREAT_MODEL_REVIEW.md) found no P1/P2 in the bounded implementation slice. It explicitly leaves external authority and RFC acceptance open. | Partial retained review evidence. | +| Conformance suite | `scripts/ci/check-phase3-contracts.py` validates the contract-only local slice. It deliberately does not establish full conformance. | Partial. | +| Local reference vertical slice | Local `benchwork-local-*/0.1` storage and execution primitives retain bounded operational evidence. RFC-0012 replay preserves multi-Attempt history, fresh retry-allocation identities, lease-fence monotonicity, Result acceptance local closure, and supplied-facts assurance-Claim closure. RFC-0013 replay projects exact supplied provenance-policy registrations and active-Store retention-policy registrations with locally closed PROJECT or already-projected Reference Set scope. Retry scheduling/readiness, initialization retention policies, BLOB/PROGRAM retention scopes, and complete Storage replay remain unavailable; all authority-bearing paths fail closed. | Partial. | +| Local runtime lifecycle demonstrations | `tests/test_execution.py` exercises lease-expired negative terminalization, cancellation, duplicate terminal delivery rejection, stale observation cursors, and restart recovery across queued and terminal Jobs. | Present for the bounded `benchwork-local-execution/0.1` runtime only. | + +## Verified baseline + +The current repeatable baseline is: + +```bash +.venv/bin/python -m pytest -q +PYTHONPATH=src .venv/bin/python scripts/ci/check-phase3-contracts.py +``` + +It is evidence for contract integrity and the bounded local slice only. It +does not change the ownership rules in the RFCs: Athanor remains the only +canonical authority, and the Executor cannot promote a Worker result into a +scientific fact. + +## Remaining implementation order + +1. Install RFC-0012 retry scheduling and readiness with the missing supplied + Specification, terminal-event, deadline, and freshness facts; then + demonstrate a terminal Attempt through scheduling, readiness, new + allocation, and restart replay. +2. Install the required RFC-0013 Storage reducers and prove retained output, + quarantine, and recovery projections from a complete Storage prefix. +3. Extend the existing supplied-facts Result and assurance-Claim comparators + only to consume their remaining externally verified resolver results. A + `CLAIMED` outcome already cannot be established by an opaque Sigil alone in + the installed replay path. +4. Resolve the authority and State-evolution prerequisites in the + [Phase 3 blocker register](PHASE3_BLOCKER_REGISTER.md), then run the + expanded conformance suite and retain the required formal threat-model + review evidence beyond the bounded local review. +5. Request explicit acceptance for each RFC. This repository forbids sealing + an RFC without that confirmation. diff --git a/docs/en/PHASE3_RFC_ACCEPTANCE_PACKET.md b/docs/en/PHASE3_RFC_ACCEPTANCE_PACKET.md new file mode 100644 index 0000000..cfa4bb4 --- /dev/null +++ b/docs/en/PHASE3_RFC_ACCEPTANCE_PACKET.md @@ -0,0 +1,36 @@ +# Phase 3 RFC acceptance packet + +This packet prepares a human acceptance review; it does not accept, seal, or +change the status of any RFC. Each RFC remains `draft` until the project owner +explicitly accepts it. + +## Shared review boundary + +The current baseline is 214 published Schemas, the contract-only Phase 3 gate, +and the bounded `benchwork-local-*/0.1` runtime. The reproducible commands +are in the [exit audit](PHASE3_EXIT_AUDIT.md#verified-baseline). Those checks +do not prove a complete RFC-0012 Journal replayer, a complete RFC-0013 Storage +backend, canonical Result acceptance, or scientific authority. The exact gaps +are maintained in the [blocker register](PHASE3_BLOCKER_REGISTER.md). + +## Per-RFC acceptance checklist + +| RFC | Evidence ready for review | Acceptance blocker | +| --- | --- | --- | +| RFC-0011 — Sanctum Execution Model | Published Schema family, bounded local runtime lifecycle tests, fail-closed MCP/runtime boundaries, and a [retained independent local trust-boundary review](PHASE3_THREAT_MODEL_REVIEW.md). | Formal RFC acceptance and the external authority evidence remain pending. | +| RFC-0012 — Job, Lease, and Worker Protocol | Execution State/Journal schemas; Job Outcome contracts; multi-Attempt, lease-fence, terminalization, assurance-Claim, cancellation, expiry, duplicate-delivery, and restart tests. | Retry scheduling/readiness still lacks externally verified Specification, deadline, freshness, and resolver facts; complete Storage/Result authority replay is also unavailable. | +| RFC-0013 — Artifact Storage Model | Storage schemas; initialization, activation, recovery, message rejection, failed legacy-protection, Reference Set, canonical-reference, provenance-policy registration, and active-Store retention-policy registration for locally closed PROJECT/Reference Set scopes. | Transfer lifecycle, quota revisions, full retention initialization details (including the unspecified migration-policy identity), BLOB/PROGRAM scopes, full backend replay, and authoritative Chronicle absence are incomplete. | +| RFC-0014 — Patch Promotion Protocol | Published Patch schemas and contract tests for journal, bundle, checkpoint, mutation intent, target guard, attempt, outcome, recovery record, revision algebra, abandonment disposition closure, and the retained [local trust-boundary review](PHASE3_THREAT_MODEL_REVIEW.md). | The four RFC Patch MCP routes and their authority-bearing implementation are not yet published; final cross-RFC replay/Storage evidence and reference Host-native adapter evidence are also required before the Phase 3 release gate can be asserted. | +| RFC-0015 — Experiment Executor API | Typed request/Outcome schemas; strict Result v2 local closure; supplied-facts acceptance comparator; Result/Observation contract tests. | Comparator intentionally does not grant canonical acceptance; it still requires externally verified Chronicle/Storage/Outcome facts. | + +## Required human decision + +For each RFC, the reviewer must make one explicit choice: + +1. accept the exact draft and its documented boundaries; +2. request named changes; or +3. defer acceptance pending named evidence. + +No blanket Phase 3 approval changes five `draft` RFCs into accepted documents. +Any acceptance record must identify the exact RFC, version, reviewed commit, +reviewer, time, and rationale. diff --git a/docs/en/PHASE3_THREAT_MODEL_REVIEW.md b/docs/en/PHASE3_THREAT_MODEL_REVIEW.md new file mode 100644 index 0000000..883f2fe --- /dev/null +++ b/docs/en/PHASE3_THREAT_MODEL_REVIEW.md @@ -0,0 +1,58 @@ +# Phase 3 local threat-boundary review + +## Status and scope + +This is an independent local implementation review conducted against commit +`7ea893b`. It is retained Phase 3 evidence only. It is not an RFC acceptance +decision, an Athanor Receipt, or proof of any external Storage, Chronicle, +Ward, approval, or Worker authority. + +The review examined the RFC-0011 and RFC-0013 trust boundaries in: + +- `src/benchwork/execution.py` +- `src/benchwork/execution_contracts.py` +- `src/benchwork/artifact_storage_contracts.py` +- `src/benchwork/patch_promotion_contracts.py` +- MCP registration/runtime code, Phase 3 documents, and relevant tests + +## Conclusion + +No P1 or P2 finding was identified. The installed local slice does not treat +a self-Sigil, a caller-supplied fact, a Worker result, or a local comparator as +external authorization. Unresolved authority-bearing paths remain fail closed. + +## Reviewed boundaries + +| Boundary | Review conclusion | +| --- | --- | +| MCP tool surface | Only the fixed read, task, canon, and experiment modules are registered. The local `benchwork_start_job` helper is not published as an MCP tool. | +| Worker and local execution | `execution.py` is bounded operational code: it does not interpret arbitrary commands or append Chronicle records. Its trusted-local terminal hook does not make the resulting outcome acceptance-eligible. | +| Self-Sigil and supplied facts | Result v2 and supplied-facts helpers perform local deterministic closure only; they do not resolve Chronicle, Storage, Ward, approval, or acceptance authority. | +| Storage and Chronicle | Uninstalled Storage events fail closed. Canonical release requires an authoritative suffix-absence proof, while Storage replay/runtime authority functions reject in the contract-only slice. | +| Patch promotion | The contract validates wire and supplied facts only; its runtime-authority entry point rejects. | +| Status documents | The blocker register and acceptance packet consistently describe the local slice as non-authoritative and leave unresolved paths fail closed. | + +## Reproduction evidence + +The reviewer ran the following checks in `/Users/momo/benchwork-phase3-recovery`: + +```bash +git status --short && git rev-parse --short HEAD +PYTHONPATH=src .venv/bin/python scripts/ci/check-phase3-contracts.py +``` + +The worktree was clean at `7ea893b`; the gate validated 214 published Schemas, +ran 182 tests, and reported Ruff clean for its checked source set. + +## Residual assumptions + +- `ExecutionService.record_terminal` is a trusted local-adapter hook. It is + not MCP-exposed and cannot make an outcome acceptance-eligible, but its + safety still depends on the host process boundary. +- A local contract gate cannot establish authoritative Chronicle suffixes, + Storage backend state, or Ward/Registry/approval facts. Those prerequisites + remain explicitly outside this review and must be supplied by their owning + authoritative systems. + +These residual items keep the RFC acceptance gate open; they are not evidence +that the bounded local implementation crosses those boundaries. diff --git a/docs/en/README.md b/docs/en/README.md index ce00c64..ae44df1 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -64,6 +64,10 @@ English is the canonical source for all Benchwork documentation. - [Release process](RELEASE_PROCESS.md) - [M10 acceptance matrix](M10_ACCEPTANCE.md) - [Phase 2 acceptance matrix](PHASE2_ACCEPTANCE.md) +- [Phase 3 contract gate](PHASE3_ACCEPTANCE.md) +- [Phase 3 exit audit](PHASE3_EXIT_AUDIT.md) +- [Phase 3 local threat-boundary review](PHASE3_THREAT_MODEL_REVIEW.md) +- [Phase 3 RFC acceptance packet](PHASE3_RFC_ACCEPTANCE_PACKET.md) - [Benchwork Codex plugin](plugins/benchwork.md) - [Acceptance Exception Policy](plugins/acceptance-exception-policy.md) - [0.3.0rc1 migration guide](migrations/0.3.0rc1.md) diff --git a/docs/en/ROADMAP.md b/docs/en/ROADMAP.md index a0ba882..d452513 100644 --- a/docs/en/ROADMAP.md +++ b/docs/en/ROADMAP.md @@ -38,6 +38,10 @@ scientific lineage, and a governed extension ecosystem. an accepted RFC, migration guidance, and replay or contract coverage. - Phase 3's RFC gate is open. No current release claims executor-enforced isolation, remote jobs, GPU scheduling, or a production Artifact store. +- The approved OD22–OD25 closure decisions are incorporated in RFC-0012, + RFC-0013, and RFC-0015. They close specified contract and selector choices + only; reducer/replay/append, durable resolver, live execution, Result + acceptance, and scientific authority remain fail-closed. See the [Phase 2 acceptance matrix](PHASE2_ACCEPTANCE.md), [Compatibility Policy](COMPATIBILITY.md), and diff --git a/docs/en/releases/0.3.0rc2.md b/docs/en/releases/0.3.0rc2.md index 0919215..8629b75 100644 --- a/docs/en/releases/0.3.0rc2.md +++ b/docs/en/releases/0.3.0rc2.md @@ -5,9 +5,11 @@ canonical: true # Benchwork 0.3.0rc2 — The Invitation -`0.3.0rc2` adds the auditable macOS/Linux/WSL installer. The M17 scientific -control-plane contracts are unchanged apart from one additive optional field, -recorded under Fixed below. +`0.3.0rc2` adds the auditable macOS/Linux/WSL installer and a bounded Phase 3 +contract-only implementation slice. The M17 scientific control-plane +contracts are unchanged apart from one additive optional field, recorded under +Fixed below. The Phase 3 additions do not accept or seal an RFC, grant +Chronicle/Storage/Athanor authority, or make a Worker result a scientific fact. ## Added @@ -19,6 +21,22 @@ recorded under Fixed below. - opt-in Codex plugin/MCP and experimental Claude MCP configuration - installer-owned repair, rollback, PATH blocks, and uninstall - release assets, SBOM, provenance, GitHub Pages publication, and installer CI +- 214 published Schemas plus contract tests for the RFC-0011 through RFC-0015 + local validation and replay surfaces +- locally closed Execution Result/Outcome, assurance-Claim, lease-fence, + Storage Reference Set/provenance-policy/retention-policy, and Patch + Promotion record invariants; every authority-bearing path without verified + external facts remains fail closed + +## Phase 3 boundary + +This prerelease exposes a contract-only local vertical slice, not a complete +Phase 3 runtime or RFC acceptance. Retry scheduling, full Storage replay, +canonical Chronicle absence, Patch MCP application, and the external +authority/resolver inputs they require remain unavailable by design. The exact +evidence and open release work are maintained in the +[Phase 3 exit audit](../PHASE3_EXIT_AUDIT.md) and +[blocker register](../PHASE3_BLOCKER_REGISTER.md). ## Fixed diff --git a/docs/en/rfcs/RFC-0012-job-lease-worker-protocol.md b/docs/en/rfcs/RFC-0012-job-lease-worker-protocol.md index 5cf5364..a898ff6 100644 --- a/docs/en/rfcs/RFC-0012-job-lease-worker-protocol.md +++ b/docs/en/rfcs/RFC-0012-job-lease-worker-protocol.md @@ -3916,7 +3916,7 @@ are: | `recovery.started` | Recovery transaction creation in `STARTED`; Executor sets `active_recovery_id` and closes `RECOVERY_ACTIVE` gate | `recovery_id`, `prior_recovery_id`, `replay_through_sequence`, `replay_through_event_sigil`, `old_epoch`, `new_epoch`, `nonterminal_job_ids`, `nonterminal_attempt_ids`, `nonterminal_lease_ids`, `nonterminal_worker_session_ids`, `initial_action_set_sigil` | | `recovery.action_set_rebased` | Active Recovery remains in its current phase | `recovery_id`, `phase`, `prior_action_set_sigil`, `replacement_action_set_sigil`, `reason_event_id`, `new_epoch`, `carried_completion_event_ids` | | `recovery.phase_advanced` | Recovery phase named in payload | `recovery_id`, `from_phase`, `to_phase`, `completed_action_set_sigil`, `next_action_set_sigil`, `completed_entity_ids`, `quarantined_entity_ids` | -| `recovery.completed` | Recovery `FINALIZING -> COMPLETED`; Executor clears `active_recovery_id` and reopens `RECOVERY_ACTIVE` gate | `recovery_id`, `completed_action_set_sigil`, `recovered_state_sigil`, `fence_tombstone_event_ids`, `quarantined_entity_ids`, `resumable_job_ids` | +| `recovery.completed` | Recovery `FINALIZING -> COMPLETED`; Executor clears `active_recovery_id` and reopens `RECOVERY_ACTIVE` gate | `recovery_id`, `completed_action_set_sigil`, `finalizing_state_sigil`, `fence_tombstone_event_ids`, `quarantined_entity_ids`, `resumable_job_ids` | | `worker.definition_registered` | Worker definition none `-> REGISTERED` | `worker_binding_sigil`, `definition_revision`, `supersedes_worker_binding_sigil` | | `worker.enabled` | Worker definition `REGISTERED`, `DRAINING`, or `QUARANTINED -> ENABLED` | `worker_binding_sigil`, `verification_evidence_set_sigil` | | `worker.draining` | Worker definition `ENABLED -> DRAINING` | `reason_code`, `affected_worker_session_ids` | @@ -4091,7 +4091,7 @@ transaction remains terminal history but does not prevent a later fresh | `STARTED` | `FENCING` | `recovery.phase_advanced`; the `STARTED` action set is complete and the exact durable `FENCING` action set is bound. | | `FENCING` | `RECONCILING` | `recovery.phase_advanced`; the `FENCING` action set is complete, all old `OFFERED`/`ACTIVE` Leases have durable tombstones, and the exact `RECONCILING` action set is bound. | | `RECONCILING` | `FINALIZING` | `recovery.phase_advanced`; reconciliation actions verified, terminated, settled, or quarantined resources and the exact `FINALIZING` action set is bound. | -| `FINALIZING` | `COMPLETED` | `recovery.completed`; the `FINALIZING` action set, Attempt, assurance, retry, and Job consequences are durable and the replayed state Sigil validates. | +| `FINALIZING` | `COMPLETED` | `recovery.completed`; the `FINALIZING` action set, Attempt, assurance, retry, and Job consequences are durable and its exact pre-transition State Sigil validates. The completed post-State is then sealed from the Event, avoiding a self-referential Event/State Sigil cycle. | `COMPLETED` is terminal. Each action-set document is made durable before the event that binds its Sigil. A phase event is appended only after every action @@ -4444,6 +4444,1491 @@ Outcome, and negative evidence remain unchanged. store, policy source, Chronicle, canonical projections, or any part of `.benchwork/`. +## Approved 2026-08-06 Result Authority Closure AC2–AC4 v0.1 + +The user approved AC1 through AC4 as one synchronized cross-RFC decision +bundle. RFC-0013 owns AC1's namespace replacement-index root, row, protected +Head, checked replacement, and visibility rules. This RFC owns the following +AC2–AC4 OWR subject domains, authority/role mapping, and mutually dependent +authority-substrate family. Partial implementation, a caller-supplied trust +fact, or a Schema-valid record grants no Result authority. + +## AC2 — private OWR EIA subject domains + +For an OWE manifest, `OwnerBinding` and `decoded_observation` mean the exact +closed objects already owned by the OWR/OWE contracts. RFC-0012 selects: + +```text +owner_binding_sigil = Sigil([ + "execution-output-writer-revocation-owner-binding/1.0", + OwnerBinding +]) + +decoded_observation_sigil = Sigil([ + "execution-output-writer-revocation-decoded-observation/1.0", + decoded_observation +]) +``` + +The OWE's EIA `subject` equals, byte-for-byte: + +```text +{ + subject_kind: "OUTPUT_WRITER_REVOCATION", + raw_evidence_id: OWE.raw_evidence_id, + raw_evidence_kind: OWE.kind, + owner_binding_sigil: the first derivation above, + decoded_observation_sigil: the second derivation above +} +``` + +The `PRODUCER` EIA may bind only the closed `PRODUCER_REVOCATION` decoded +branch; the `VERIFIER` EIA may bind only `VERIFIER_CONFIRMATION`. The two OWR +domains are distinct from the existing Observation Evidence domains. A bare +Sigil equality, the Observation domain, a self-Sigil of either enclosing +record, or a caller-supplied subject is invalid. + +AC2 defines deterministic subject identity only. It neither authenticates the +subject nor authorizes the EIA or OWR. + +## AC3 — OWR authority and role mapping + +For both OWR raw-evidence records, EIA `authority_binding` is exactly: + +```text +{ + authority_kind: "OUTPUT_WRITER_REVOCATION_OWNER", + authority_id: rederived OWR ID, + authority_sigil: owner_binding_sigil +} +``` + +The EIA consumer does not resolve an enclosing OWR to obtain that ID. It +mechanically rederives +`"OWR-" + UPPER_HEX(SHA256(canonical_json([ +"execution-output-writer-revocation-evidence-id/1.0", OwnerBinding.job_id, +OwnerBinding.attempt_id, OwnerBinding.output_handle_id])))` from the complete +AC2-bound OwnerBinding and requires equality. Its preimage does not depend on +either EIA or the OWR self-Sigil. Using `OWR.revocation_evidence_sigil` would +create a cycle and is forbidden. `output_handle_id`, a mutable owner +projection, or a profile ID cannot substitute for the authority ID. + +The complete evidence-role matrix is: + +| OWE kind | Required decoded branch | Required EIA/OWE role | Allowed role kinds | +| --- | --- | --- | --- | +| `PRODUCER` | `PRODUCER_REVOCATION` | exact OWR `producer_identity` | `EXECUTOR_SUPERVISOR`, `ENFORCEMENT_BACKEND` | +| `VERIFIER` | `VERIFIER_CONFIRMATION` | exact OWR `verifier_identity` | `HOST_VERIFIER`, `INDEPENDENT_BACKEND_VERIFIER` | + +The OWE identity and decoded-branch identity are byte-for-byte equal to the +selected OWR identity. EIA uses its differently named closed wire and is the +mechanical mapping `{role_kind: OWR identity.kind, identity_id: OWR +identity.identity_id, implementation_version: OWR +identity.implementation_version, implementation_sigil: OWR +identity.implementation_sigil}`; no renaming other than `kind -> role_kind` is +allowed. The producer and verifier have +different identity IDs, implementation Sigils, process-instance identities, +role-controller domains, issuer-controller domains, credential domains, +collection-context Sigils, +authentication IDs, decoder implementation Sigils, and issuer +`(registry_id, key_id, key_generation)` tuples. Neither may resolve to the +Worker or Worker Session. The installed AC4 profile and registry snapshot must +authorize the exact complete row; string inequality alone is not independence. + +AC3 closes authority selection and role ownership. It does not establish that +a role, issuer, key, proof, decoder, generation, or writer inventory is +trusted; AC4 and its later executable implementation do that. + +## AC4 — OWR authority substrate family + +AC4 selects five mutually dependent closed control records plus seven resolver +operations. They form one synchronized decision: no subset is OWR authority. + +### AC4.1 independent OWR profile + +`execution-output-writer-revocation-evidence-profile/1.0` has exactly: + +```text +schema_version +evidence_profile_id +evidence_profile_version +subject_kind +producer_implementations +verifier_implementations +allowed_role_pairs +decoder_profiles +raw_media_profiles +authentication_profiles +proof_profiles +sealed_generation_profiles +raw_store_profile_binding +anti_replay_profile_binding +writer_inventory_profile_sigil +revocation_profile_sigil +independence_profile_sigil +maximum_writer_handles +maximum_raw_payload_bytes +profile_sigil +``` + +The first four values are respectively the Schema constant, +`EXECUTION_OUTPUT_WRITER_REVOCATION`, `1.0`, and +`OUTPUT_WRITER_REVOCATION`. `maximum_writer_handles` is exactly 4,096. +`maximum_raw_payload_bytes` is PositiveU63. Each array has 1..4,096 entries, +is strictly sorted by the tuple printed below, and is unique by complete +canonical JSON. + +Implementation entries are exactly +`{role_kind, implementation_version, implementation_sigil}` and use only the +AC3 side's role kinds. A role-pair entry is exactly +`{producer_role_kind, verifier_role_kind}` and never permits one identity or +implementation on both sides. + +A decoder entry is exactly: + +```text +{ + evidence_kind, + decoder_binding, + media_type, + maximum_input_bytes, + maximum_output_bytes, + maximum_cpu_time_milliseconds, + maximum_memory_bytes, + maximum_recursion_depth, + decoded_contract_sigil +} +``` + +All five limits are PositiveU63. A raw-media entry is exactly +`{evidence_kind, media_type, maximum_input_bytes}`. An authentication entry is +exactly `{evidence_kind, role_kind, authority_kind, issuer_kind, registry_id, +registry_version, registry_snapshot_sigil, allowed_key_profile_sigil, +verification_profile_sigil, allowed_proof_kind}`. `authority_kind` is constant +`OUTPUT_WRITER_REVOCATION_OWNER`; proof kind is `SIGNATURE` or `ATTESTATION`. + +`proof_profiles` is a closed union. A signature entry is exactly +`{proof_kind: "SIGNATURE", algorithm: "ED25519", media_type: +"application/vnd.benchwork.ed25519-signature", size_bytes: 64, +verification_profile_sigil}`. An attestation entry is exactly: + +```text +{ + proof_kind: "ATTESTATION", + attestation_profile_id, + verification_algorithm_id, + media_type, + root_media_type, + maximum_input_bytes, + maximum_root_bytes, + maximum_output_bytes, + maximum_cpu_time_milliseconds, + maximum_memory_bytes, + maximum_recursion_depth, + claims_decoder_binding, + nonce_domain_sigil, + challenge_profile_sigil, + root_profile_sigil, + verification_profile_sigil +} +``` + +All attestation limits are PositiveU63. The profile fixes the algorithm, +claims decoder, nonce/challenge domain, root class, and verification +implementation; it cannot +delegate any of them to attestation payload bytes. The EIA proof branch, +authentication row, registry key/material row, and selected proof-profile row +must have the same proof kind, attestation profile ID when applicable, media +type, and verification-profile Sigil. Every proof payload is read through the +same AC4.3 immutable resolver before verification. Signature bytes retain the +canonical exact 64-octet rule. + +A sealed-generation entry is exactly: + +```text +{ + generation_kind, + backend_profile_sigil, + exact_generation_read_profile_sigil, + write_rejection_profile_sigil, + immutability_profile_sigil +} +``` + +`generation_kind` is `BACKEND_GENERATION` or `OPAQUE_SEALED_GENERATION`. +In both branches, `backend_profile_sigil` equals the OWR generation binding's +same-named member and authorizes the complete backend ID, object-identity, and +exact-generation resolver class. No mutable latest read is an allowed profile. + +`raw_store_profile_binding` is exactly `{raw_store_id, raw_store_version, +resolver_implementation_sigil, head_resolver_implementation_sigil, +monotonic_anchor_profile_sigil}` and +selects the one installed AC4.3 +append-only content index and descriptor-relative resolver. It deliberately +does not bind a mutable latest root Sigil: every historical entry is immutable, +and the exact payload descriptor selects the entry. `anti_replay_profile_binding` +is exactly `{anti_replay_store_id, anti_replay_store_version, +resolver_implementation_sigil, head_resolver_implementation_sigil, +monotonic_anchor_profile_sigil}` and +selects the one installed AC4.4 index and +checked replacement implementation. Both IDs and versions are protocol +identifiers; all four implementation Sigils are resolved as installed code, +not caller instructions. + +Sort tuples are: implementations by `(role rank, version, Sigil)`; role pairs +by `(producer-role rank, verifier-role rank)`; decoders by `(evidence-kind +rank, decoder ID, decoder version, implementation Sigil, media type, five +numeric limits, decoded-contract Sigil)`; media by `(evidence-kind rank, +media_type, maximum_input_bytes)`; authentication by the member order printed +above using enum rank then unsigned-ASCII/Sigil order; proof profiles by +`(proof-kind rank, verification-profile Sigil, then complete canonical JSON)`; +and generation entries +by `(generation-kind rank, the four Sigils)`. `PRODUCER` precedes `VERIFIER`; +all other enum ranks use their order printed in AC3 and this section. + +Every decoder, raw-media, proof input/output, and attestation-root byte bound is +at most `maximum_raw_payload_bytes`. `profile_sigil` is the ordinary self-Sigil +omitting only itself. The profile +selected by the OWR ID/version/Sigil must contain the exact producer, +verifier, role pair, both decoders/media rows, both authentication rows, and +every selected proof row and the selected generation row. It may narrow the +canonical matrix but cannot +widen it or waive an equality, distinctness, resource, or proof requirement. + +### AC4.2 trusted authority registry snapshot + +`execution-evidence-authority-registry-snapshot/1.0` has exactly: + +```text +schema_version +registry_id +registry_version +role_records +issuer_records +key_records +created_at +registry_snapshot_sigil +``` + +Role records are closed +`{role_identity, process_instance_identity_sigil, controller_domain_sigil, +credential_domain_sigil, host_backend_identity_sigil, +allowed_subject_kinds, allowed_evidence_kinds, allowed_authority_kinds, +role_record_sigil}`. For this profile the three allowed arrays contain only +`OUTPUT_WRITER_REVOCATION`, the role's one evidence side, and +`OUTPUT_WRITER_REVOCATION_OWNER`. Roles are keyed by the complete +`(role_kind, identity_id, implementation_version, implementation_sigil)`. + +Issuer records are closed +`{issuer_identity, controller_domain_sigil, allowed_role_kinds, +allowed_subject_kinds, allowed_evidence_kinds, allowed_authority_kinds, +allowed_proof_kinds, +issuer_record_sigil}`. Key records are closed +`{issuer_id, key_id, key_generation, key_profile_sigil, +verification_profile_sigil, verification_material, authorizations, valid_from, +valid_until, revoked_at, key_record_sigil}`. Each `authorizations` entry is +exactly `{subject_kind, evidence_kind, role_kind, authority_kind, proof_kind}`; +for this family its subject and authority are constant +`OUTPUT_WRITER_REVOCATION` and `OUTPUT_WRITER_REVOCATION_OWNER`, and the other +three values equal one complete profile authentication row. The array is +strictly enum-ranked, unique, non-empty, and bounded at 4,096. +`verification_material` is exactly one closed +branch: `ED25519_PUBLIC_KEY {kind, raw_payload}` or +`ATTESTATION_ROOT {kind, attestation_profile_id, root_payload}`. Payloads use +the existing immutable `RawPayloadBinding`; no key bytes, roots, URLs, or paths +are accepted inline. The Ed25519 public-key payload has media type +`application/vnd.benchwork.ed25519-public-key` and exactly 32 raw octets. An +attestation root's profile ID and media type equal one selected proof-profile +row and its size is at most that row's `maximum_root_bytes`. Signature proof +bytes, attestation proof bytes, Ed25519 +public-key bytes, and attestation-root bytes all resolve through the same +profile-bound AC4.3 immutable resolver and must pass actual byte-count and Blob +Sigil recomputation before use. No caller-supplied verification material is an +alternative. + +All arrays are non-empty, at most 4,096, strictly sorted, and unique by their +complete keys: roles by the four-part role key, issuers by `issuer_id`, and +keys by `(issuer_id, key_id, key_generation)`. Each nested allowed-value array +is strictly enum-ranked and unique. `valid_until` and `revoked_at` are nullable +Timestamp; when present they are no earlier than `valid_from`. Every row Sigil +is domain-separated over its complete preceding members: role rows use +`execution-evidence-authority-role-record/1.0`, issuer rows use +`execution-evidence-authority-issuer-record/1.0`, and key rows use +`execution-evidence-authority-key-record/1.0`. +`registry_snapshot_sigil` is the ordinary root self-Sigil omitting only itself. +The snapshot is immutable and single-assignment by `(registry_id, +registry_version)` and by its Sigil; same-slot unequal bytes are an integrity +failure. + +The EIA's `registry_snapshot_binding` resolves this exact ID, version, and +Sigil. Its key binding resolves exactly one key row and its issuer identity +resolves exactly one issuer row. A role identity resolves exactly one role row +in the same snapshot. The role, issuer, key authorization entry, proof kind, +key/verification profile Sigils, and AC4.1 authentication entry must form one +complete matching row; no field-wise union of separately allowed rows is +valid. Current registry state, field mixing across snapshots, +or using one registry for role inequality and a different registry for the same +EIA's proof verification are invalid. The producer and verifier may use +different exact snapshots only when their separate AC4.1 authentication rows +name those snapshots and the AC3 cross-side independence comparison succeeds. + +### AC4.3 immutable raw-store index and resolver + +`execution-evidence-raw-store-index/1.0` is an append-only replacement root +with exactly: + +```text +schema_version +raw_store_id +raw_store_version +index_generation +previous_index_sigil +entries +index_sigil +``` + +Each entry is exactly `{blob_sigil, size_bytes, media_type, +object_identity_sigil, immutable_generation_sigil, installed_at, +entry_sigil}`. Entries are strictly sorted and unique by `(blob_sigil, +size_bytes, media_type)` and are also unique by `(object_identity_sigil, +immutable_generation_sigil)`. The root contains 0..4,096 entries; a full root +rejects new evidence authority without deletion or overwrite. The empty and +successor +`index_generation`/`previous_index_sigil` rules are identical to AC1. A legal +successor inserts exactly one entry at its unique sorted position while every +historical entry's bytes and relative order remain unchanged; an exact retry +returns the installed root. Entry Sigils use the domain +`execution-evidence-raw-store-entry/1.0` with the exact preimage: + +```text +entry_sigil = Sigil([ + "execution-evidence-raw-store-entry/1.0", + blob_sigil, + size_bytes, + media_type, + object_identity_sigil, + immutable_generation_sigil, + installed_at +]) + +index_sigil = Sigil([ + "execution-evidence-raw-store-index/1.0", + raw_store_id, + raw_store_version, + index_generation, + previous_index_sigil, + entries +]) +``` + +The domain constants are the respective `schema_version` values and are not +also repeated as an object argument. Protocol visibility additionally requires +the exact protected AC4.5 Head; atomic replacement and reopen alone do not +grant authority. + +Resolution accepts only the installed profile binding, the complete validated +canonical index root, and the exact raw-payload descriptor. The binding's +store ID/version equal the root; its resolver and Head-resolver Sigils select +installed code. The descriptor selects exactly one immutable entry. The resolver +performs an exact-generation read, rejects any byte-count or Blob-Sigil +mismatch, and returns bytes only after both are recomputed. It exposes no path, +URL, directory enumeration, prefix, object-latest, or caller-selected backend +key. The index is evidence to validate, never a command to fetch an arbitrary +object. Reading a newer append-only root is allowed only because the selected +historical entry is byte-immutable; absence or conflict fails closed and never +selects another object. + +### AC4.4 durable anti-replay index + +`execution-evidence-anti-replay-index/1.0` is a closed replacement root with +exactly `{schema_version, anti_replay_store_id, anti_replay_store_version, +index_generation, previous_index_sigil, rows, index_sigil}`. Its store ID and +version equal the installed AC4.1 profile binding. A row has exactly +`{registry_id, key_id, key_generation, subject_kind, raw_evidence_id, +anti_replay_sigil, authentication, row_sigil}`. `authentication` is the +complete closed canonical `execution-evidence-issuer-authentication/1.0` +object. Every preceding row field is mechanically rederived from that object; +its EIA ID and self-Sigil are read from the embedded object and are not +duplicated as caller-selected row fields. + +The exact derivations are: + +| Row member | Embedded EIA source | +| --- | --- | +| `registry_id` | `key_binding.registry_id`, which also equals `registry_snapshot_binding.registry_id` | +| `key_id` | `key_binding.key_id` | +| `key_generation` | `key_binding.key_generation` | +| `subject_kind` | `subject.subject_kind` | +| `raw_evidence_id` | `subject.raw_evidence_id` | +| `anti_replay_sigil` | recomputed canonical EIA anti-replay preimage and the EIA member | + +Rows are strictly increasing by `(registry_id, key_id, numeric key_generation, +subject-kind rank, raw_evidence_id)`, using unsigned-ASCII order except for the +numeric member. They are independently unique by that canonical EIA +single-assignment key, by `anti_replay_sigil`, and by the embedded +`authentication.authentication_id`. A row +Sigil is `Sigil(["execution-evidence-anti-replay-index-row/1.0", +registry_id, key_id, key_generation, subject_kind, raw_evidence_id, +anti_replay_sigil, authentication])`. The empty +root and successor generation/predecessor rules are identical to AC1. A legal +successor inserts exactly one row at its unique sorted position while every +historical row's bytes and relative order remain unchanged; an exact retry +returns the installed row without a generation change. The root +contains 0..4,096 rows; a full root rejects new authentication authority +without deletion, overwrite, wraparound, or implicit compaction. + +The root self-Sigil is +`Sigil(["execution-evidence-anti-replay-index/1.0", +anti_replay_store_id, anti_replay_store_version, index_generation, +previous_index_sigil, rows])`. + +The OWE `issuer_authentication_binding` resolves only by exact authentication +ID to this index and requires its Sigil to equal the embedded EIA self-Sigil. +There is no bare-Sigil or separate mutable authentication lookup. Atomic +replacement plus parent-directory durability, complete reopen, and the exact +protected AC4.5 Head are jointly the only visibility point. An authentication +record is not authoritative until its complete embedded row is visible. A +conflicting key, nonce Sigil, authentication ID, predecessor, historical byte, +or embedded EIA is an integrity failure; expiry or later key revocation never +rewrites historical rows. + +### AC4.5 protected evidence-index Head + +`execution-evidence-index-head/1.0` has exactly: + +```text +schema_version +index_kind +store_id +store_version +anchor_profile_sigil +index_generation +index_sigil +previous_head_sigil +anchored_at +head_sigil +``` + +`index_kind` is `RAW_STORE` or `ANTI_REPLAY`; the store ID/version equal the +selected AC4.1 binding, and `anchor_profile_sigil` equals that binding's +`monotonic_anchor_profile_sigil`. Its initial/successor generation, predecessor, +single-assignment, crash-ahead, and rollback matrices are the AC1.3 protected +Head rules applied independently per `(index_kind, store_id, store_version)`. +`head_sigil` is +`Sigil(["execution-evidence-index-head/1.0", index_kind, store_id, +store_version, anchor_profile_sigil, index_generation, index_sigil, +previous_head_sigil, anchored_at])`. + +The profile-bound Head resolver reads a trusted append-only monotonic anchor +store separate from either replaceable root. A root at `n+1` with Head `n` +gates authority until exact one-delta recovery advances the Head. An anchored +Head ahead of, unequal to, or newer than the root proves rollback or integrity +failure. No self-Sigil, predecessor member, process memory, or caller-supplied +Head substitutes for this independent anchor. The concrete anchor store, +locking, durability, and crash implementation remains a post-approval gate. +If a deployment cannot supply the selected monotonic store or cannot protect +it from the rollback class being checked, it grants no namespace, EIA, OWR, or +Result authority; this RFC does not pretend a self-Sigil detects rollback of +all local files together. + +### AC4.6 required resolver operations + +The canonical authority graph names seven operations with exact fail-closed +inputs and outputs; canonical incorporation does not implement them: + +1. `resolve_owr_profile(id, version, sigil)` returns one byte-exact AC4.1 + record, never current/latest. +2. `resolve_role_and_key(snapshot_binding, role_identity, issuer_identity, + key_binding)` returns one AC4.2 role/issuer/key triple from one exact + snapshot and its historical validity decision. +3. `read_immutable_payload(raw_store_profile_binding, raw_payload)` returns + only byte-count- and Blob-Sigil-verified immutable bytes. +4. `decode_owr_payload(profile, evidence_kind, decoder_binding, media_type, + bytes)` runs the separately installed exact implementation with the + profile's CPU, memory, size, and recursion limits; it has no network or + ambient filesystem access, rejects unknown/extra values, and returns one + closed decoded branch whose canonical JSON bytes equal the OWE member. +5. `verify_eia_proof(profile, registry_snapshot, authentication, proof_bytes)` + verifies the existing canonical EIA signed/attested preimage, algorithm, + authorization, validity, revocation, and controller-domain rules; hashing + or successful decoding is not proof verification. +6. `install_anti_replay(authentication)` derives every AC4.4 row key, performs + the checked root replacement and AC4.5 Head advance, and returns the exact + installed row or exact retry only after joint visibility. +7. `resolve_eia(issuer_authentication_binding)` looks up exactly one jointly + visible AC4.4 row by the binding ID, requires the embedded EIA self-Sigil to + equal the binding Sigil, fully revalidates the row and EIA, and returns that + complete immutable object; absence, ambiguity, or a bare Sigil fails closed. + +Successful resolution additionally requires both authenticated raw payloads, +both proof payloads, complete writer-inventory equality, AC3 independence, +the selected sealed-generation profile, verifier collection no earlier than +revocation completion, complete write rejection, exact-generation reopen, and +immutable-generation confirmation. A supplied comparator object can test these +equalities but cannot stand in for any resolver operation. + +### Rejected shortcuts + +- Publishing only the five namespace leaves and inferring a map or array root. +- Treating a private file or leaf record as visible before the complete index. +- Omitting predecessor/generation checks or the protected monotonic Head + because the replaceable root has a self-Sigil. +- Deleting aborted or consumed rows, reusing ST/SA or prepared Event IDs, or + compacting history without a later separately approved checkpoint protocol. +- Reusing Observation Evidence subject domains for OWR. +- Binding EIA authority to the OWR self-Sigil and creating a circular preimage. +- Using unequal role strings, two keys, or two decoder names as proof of + producer/verifier independence. +- Reusing the Observation Evidence profile as an OWR profile. +- Resolving a current/latest profile, registry, key, raw object, generation, + or backend listing. +- Treating a Blob Sigil, successful parse, caller-supplied decoded object, or + local decoder availability as issuer authentication. +- Making Schema validation or a pure supplied-fact comparator perform proof + verification, immutable reads, index visibility, locking, replay, or Result + admission. + +### Remaining implementation gates + +`execution-result/1.0` publication still waits +for all of the following executable, independently reviewed work: + +1. AC1 root/row/Head Schemas, strict literal-byte loader, comparator, durable + replacement implementation, allocator consultation, lock-order tests, + crash cuts, replay, and recovery. +2. AC2/AC3 EIA-to-OWE subject/authority comparators and negative fixtures. +3. All AC4 Schemas, installed exact-ID resolvers, immutable stores, bounded + decoder implementations, conformance corpora, signature/attestation + verification, historical registry/key validation, anti-replay replacement, + protected monotonic-anchor stores, exact Head-resolver implementations, + rollback/crash-cut tests, and producer/verifier independence tests. +4. Actual writer revocation, complete writer-inventory proof, sealed-generation + write rejection, immutable exact-generation read, checked full-byte hash and + length comparison, and SSB installation while holding the canonical gate. +5. The already required executable Log closure, cross-Journal namespace + consumption/recovery, Storage terminal-prefix resolution, and live Result + admission/disposition integration. + +None of these executable gates is silently approved as an implementation by a +wire decision. Their failures preserve negative evidence and grant no fallback +authority. + +RFC-0013's AC1 index visibility is a normative prerequisite of the RFC-0012 +Result path. Failure to resolve either side byte-for-byte, failure of the +independent cross-RFC review, or absence of any listed implementation gate +keeps Result admission and both namespace allocators fail-closed. These rules +do not alter OD22 Heartbeat collision semantics, the ISR1–ISR3 reducer rules, +R1–R10, E1–E2, or the formal RFC-0012 contract count. + + +## Approved 2026-08-06 Initial State Reducer ISR1–ISR3 v0.1 + +The user approved ISR1 through ISR3 as one synchronized decision unit. These +rules are normative for sequence-one replay and every later Executor epoch. +They close the initial epoch, exact Executor projection, and complete initial +State bytes, but they do not themselves create a Journal, install a Head, +authorize append, or prove a replay/runtime implementation. + +### ISR1–ISR3 synchronized requirements + +ISR1 through ISR3 are one inseparable canonical decision unit. + +### ISR1 — initial and successor epoch equations + +ISR1 makes the sequence-one case an if-and-only-if rule: + +```text +sequence == 1 +iff +prior_epoch == null +and startup_reason == INITIAL_START +and new_epoch == envelope.executor_epoch == 1 +``` + +Epoch value `1` is fixed for the first allocated Executor epoch so that +`0` remains the unambiguous no-prior-epoch sentinel where canonical records +require a non-null numeric value. + +For every non-first `executor.epoch_started` Event, ISR1 requires: + +```text +sequence > 1 +current replayed Executor epoch <= U63_MAX +prior_epoch == current replayed Executor epoch +new_epoch == checked_add_u64(current replayed Executor epoch, 1) +envelope.executor_epoch == new_epoch +startup_reason != INITIAL_START +``` + +The current published Event Schema makes `prior_epoch` nullable U63 while +`new_epoch` and the envelope epoch are U64. Therefore a current epoch equal to +`U63_MAX` can produce exactly one representable successor with +`new_epoch == U63_MAX + 1`; after replay reaches any epoch greater than +`U63_MAX`, another successor `executor.epoch_started` cannot encode its prior +epoch. Any further startup must fail closed before reserving an Event ID or +sequence and before any partial Journal write. ISR1 does not silently widen +`prior_epoch` to U64; such a change would require a separate Schema amendment. +Checked addition never wraps, saturates, or uses binary64. A caller-supplied or +cached epoch is not sufficient without the verified replay prefix. + +### ISR2 — exact sequence-one Executor projection + +After applying the valid sequence-one Event defined by ISR1, the State's +singleton `executor` projection equals exactly: + +```text +executor_instance_id = Event.executor_instance_id +executor_epoch = Event.executor_epoch +executor_build_binding = Event.payload.executor_build_binding +revision = 0 +clock_state = TRUSTED +last_trusted_utc = Event.recorded_at +clock_uncertain_event_id = null +active_recovery_id = null +authority_gates = [] +last_event_id = Event.event_id +last_event_sigil = Event.event_sigil +``` + +The Event payload build binding must already be closed and self-Sigil-valid, +and its `executor_build_sigil` must equal the Event envelope value. ISR2 does +not infer Host trust, clock trust, or build identity from an unverified fixture; +those are prerequisites of the valid Event and its trusted time input. + +### ISR3 — exact complete initial State + +The canonical initial State immediately after the sequence-one Event has exactly the +canonical `execution-state/1.0` root members and these values: + +```text +schema_version = execution-state/1.0 +limit_profile = EXECUTION_JOURNAL_V1_FIXED_LIMITS +journal_binding = { + journal_id: Event.journal_id, + through_sequence: 1, + through_event_id: Event.event_id, + through_event_sigil: Event.event_sigil +} +executor = ISR2 projection +recoveries = [] +workers = [] +worker_sessions = [] +jobs = [] +attempts = [] +leases = [] +log_streams = [] +deadlines = [] +idempotency_records = [] +state_sigil = Sigil(all other State members) +``` + +All nine arrays are present and empty. No pre-existing Worker, Session, Job, +Attempt, Lease, Log stream, deadline, Recovery, or idempotency row may be +injected into the initial projection. + +Conformance requires a new mutually consistent retained triplet containing +the sequence-one Event, its exact initial State, and the matching Journal Head. +The current shape-only State fixture is not a reducer oracle and must not be +reused as that triplet. Journal Head `updated_at` is diagnostic Head metadata; +it does not enter the State or its `state_sigil` preimage. + +### Fail-closed validation and authority boundary + +Canonical incorporation closes the reducer choice but grants no runtime +authority. Conformance requires strict JSON loading, +closed Schema validation, Event and build self-Sigils, the exact ISR1 +equations, the unique `CREATE(EXECUTOR)` revision, byte-for-byte ISR2/ISR3 +projection equality, checked arithmetic, and a consistent Event/State/Head +triplet. Canonical text alone does not prove a runtime implementation. + + + +## Approved 2026-08-06 Heartbeat Collision Wire Closure HCW1–HCW10 v0.1 + +The user approved HCW1 through HCW10 as one synchronized decision unit. The +following text is normative and closes the collision-family serialization, +package-internal versions, shared-definition ownership, equality, retry, +retention, and conformance choices left open by H8. It preserves the canonical +H1–H10 safety semantics and the final 81-Event order. Approval does not itself +publish an unimplemented Schema, install a package, mutate State, append or +replay an Event, or grant execution, Storage, Result, assurance, or scientific +authority. + +## Fixed canonical inputs and non-goals + +The following H8 rules are fixed inputs rather than choices in this approved clarification: + +1. marker identity is selected by `(owner_kind, owner_id, message_kind, + identity_kind, identity_sigil)`; +2. `identity_kind` is `CANONICAL_MESSAGE` or `RAW_FRAME`; +3. a marker contains every surviving candidate and records whether one + installed package already exists; +4. total installed-plus-candidate package bindings never exceed 4,096; +5. a committed marker is permanent and precedes HFP, HCE, HGI, HGR, Event, + response, and further ordinary-candidate work; +6. every frozen candidate receives exactly one deterministic HPR and HFP; +7. complete candidates compare their exact message bytes, while partial + candidates compare the fixed presence/length/fragment stream; +8. HCE groups byte-equal packages, sorts sides by exact unsigned octets, and + requires at least two unequal `MESSAGE_BYTES` sides under one identity; +9. the marker freezes complete canonical Journal Event bytes and State effects; + and +10. inability to finish evidence never reopens marker-driven authority. + +This approved closure does not change candidate caps, package paths, lock order, +Event types, State transitions, transition causes, revocation obligations, +retention lifetime, or the final 81-Event order. + +## HCW1 — exact candidate inventory `I` + +### Closed root and entry order + +`I` is exactly the UTF-8 bytes of `canonical_json(candidate_inventory)`, where +`candidate_inventory` is this closed two-member object: + +```text +schema_version +entries +``` + +`schema_version` is constant +`execution-heartbeat-collision-candidate-inventory/1.0`. `entries` is a +non-empty array of the closed HCW2 entry. It contains exactly one entry for +every descriptor-relative ordinary candidate frozen by the marker, contains no +installed package, is unique by `source_candidate_id`, and is strictly +increasing by unsigned-ASCII `source_candidate_id`. + +Every `source_candidate_id` is the narrow ordinary-candidate wire +`^HOC-[0-7][0-9A-HJKMNP-TV-Z]{25}$`, exactly 30 ASCII bytes and the canonical +unpadded Crockford Base32 encoding of 128 bits. A path, candidate-directory +nonce, absolute descriptor, inode, URL, arrival ordinal, or scheduler value is +not serialized. + +The marker equalities are exact: + +```text +candidate_count = length(candidate_inventory.entries) +candidate_inventory_size_bytes = length(I) +candidate_inventory_bytes_sigil = SigilBytes( + utf8("execution-heartbeat-collision-candidate-inventory/1.0\0") || I +) +``` + +The existing conditional count matrix remains unchanged: + +```text +installed_package_present = true -> candidate_count in 1..4095 +installed_package_present = false -> candidate_count in 2..4096 +candidate_count + (installed_package_present ? 1 : 0) <= 4096 +``` + +There is no inventory root self-Sigil. The marker's size, domain-separated +byte-Sigil, and marker self-Sigil bind the complete `I`; HCW2 separately gives +each entry the identity required by HPR. + +### Exact fragment descriptor + +Every entry carries three closed fragment descriptors. Each descriptor has +exactly: + +```text +present +length_bytes +fragment_bytes_sigil +``` + +`present` is Boolean and `length_bytes` is U63. When `present` is `false`, +`length_bytes` is zero and `fragment_bytes_sigil` is null. When `present` is +`true`, `length_bytes` is the exact length of the surviving source fragment, +including legal zero length, and `fragment_bytes_sigil` is non-null and uses +the literal domain selected below. An absent fragment is not the same fact as +a present zero-length fragment. + +The domains are: + +| Entry member | Exact present-fragment Sigil | +| --- | --- | +| `record_fragment` | `SigilBytes(utf8("execution-heartbeat-collision-source-record-fragment/1.0\0") || exact record.json fragment bytes)` | +| `bytes_fragment`, `source_record_kind: CANONICAL_MESSAGE` | `SigilBytes(utf8("execution-heartbeat-canonical-json/1.0\0") || exact bytes.bin fragment bytes)` | +| `bytes_fragment`, `source_record_kind: RAW_FRAME` | `SigilBytes(utf8("execution-heartbeat-received-frame/1.0\0") || exact bytes.bin fragment bytes)` | +| `manifest_fragment` | `SigilBytes(utf8("execution-heartbeat-collision-source-manifest-fragment/1.0\0") || exact manifest.json fragment bytes)` | + +Thus the bytes fragment retains the original HCM or HFR source-domain Sigil +even when the fragment is partial, while record and manifest fragments have +distinct domains and cannot be exchanged. + +## HCW2 — candidate entry and HPR source binding + +Each `entries` member is one closed six-member object: + +```text +source_candidate_id +source_record_kind +record_fragment +bytes_fragment +manifest_fragment +source_candidate_inventory_entry_sigil +``` + +`source_record_kind` is `CANONICAL_MESSAGE` or `RAW_FRAME` and equals the +marker's `identity_kind`. The three fragment members are HCW1 descriptors for +the literal files `record.json`, `bytes.bin`, and `manifest.json` in that +printed order. `source_candidate_inventory_entry_sigil` is the ordinary +self-Sigil over the other five members: + +```text +source_candidate_inventory_entry_sigil = Sigil({ + source_candidate_id, + source_record_kind, + record_fragment, + bytes_fragment, + manifest_fragment +}) +``` + +HPR resolution requires its `source_candidate_id` and +`source_candidate_inventory_entry_sigil` to equal one literal entry in the +marker-bound `I`. It also requires HPR marker ID/Sigil and `reserved_at` to +equal the same committed marker and `detected_at`. A bare entry Sigil, an +entry from another inventory, a reserialized inventory, or a hash match +without exact `I` bytes is insufficient. + +The inventory entry is immutable after the marker commits. A newly discovered +fragment, a different length/Sigil, or a candidate omitted from `I` is an +integrity failure; no recovery rewrites the entry or marker. + +## HCW3 — HCG marker package and gate commit + +The existing 23-member +`execution-heartbeat-collision-authority-gate-marker/1.0` root remains +unchanged. Its descriptor-relative package contains exactly these members and +no other member: + +```text +marker.json +inventory.bin +commit.json +``` + +`marker.json` is the exact UTF-8 `canonical_json` bytes of the marker, +`inventory.bin` is exact `I`, and `commit.json` is the exact UTF-8 +`canonical_json` bytes of this closed six-member object: + +```text +schema_version +collision_gate_commit_id +collision_gate_marker_id +collision_gate_marker_sigil +commit_state +collision_gate_commit_sigil +``` + +`schema_version` is constant +`execution-heartbeat-collision-authority-gate-commit/1.0` and `commit_state` +is constant `COMMITTED`. The canonical H8 formulas remain exact: + +```text +collision_gate_commit_id = + "HGC-" || UPPER_HEX(SHA256(canonical_json([ + "execution-heartbeat-collision-authority-gate-commit-id/1.0", + collision_gate_marker_id, + collision_gate_marker_sigil + ]))) + +collision_gate_commit_sigil = + Sigil(commit object without collision_gate_commit_sigil) +``` + +The HGC ID matches `^HGC-[0-9A-F]{64}$` and is 68 ASCII bytes. The package +resolver strictly reloads all JSON, recomputes `I`, every entry and fragment +Sigil, marker ID/self-Sigil, HGC ID/self-Sigil, and literal bytes. It rejects +an uncommitted, partial, extra-member, wrong-type, symlink-followed, +rename-uncertain, parent-unsynced, or byte-different package. Filesystem +installation and `GATE_COMMITTED_VISIBLE` remain external authority, not a +fact established by these three files alone. + +## HCW4 — HPR reservation package and commit + +The existing ten-member +`execution-heartbeat-forensic-package-reservation-index-row/1.0` root remains +unchanged. Its descriptor-relative reservation package contains exactly: + +```text +reservation.json +commit.json +``` + +`reservation.json` is the exact UTF-8 `canonical_json` bytes of the HPR row. +Its `commit.json` is the exact UTF-8 `canonical_json` bytes of this closed +six-member object: + +```text +schema_version +reservation_commit_id +forensic_reservation_id +forensic_reservation_sigil +commit_state +reservation_commit_sigil +``` + +`schema_version` is constant +`execution-heartbeat-forensic-package-reservation-commit/1.0` and +`commit_state` is constant `COMMITTED`. The formulas are: + +```text +reservation_commit_id = + "HPC-" || UPPER_HEX(SHA256(canonical_json([ + "execution-heartbeat-forensic-package-reservation-commit-id/1.0", + forensic_reservation_id, + forensic_reservation_sigil + ]))) + +reservation_commit_sigil = + Sigil(commit object without reservation_commit_sigil) +``` + +The HPC ID matches `^HPC-[0-9A-F]{64}$` and is 68 ASCII bytes. HPR and HFP IDs +retain their canonical formulas over `(collision_gate_marker_id, +source_candidate_id)`. HPR is single-assignment independently by reservation +ID, source candidate ID, and forensic package ID. The complete package must be +byte-identical under each key; a changed marker, entry Sigil, reserved time, +row, or commit conflicts. + +Reservation package writing, file and directory `fsync`, staging arbitration, +rename, parent `fsync`, reopen, and `RESERVATION_COMMITTED_VISIBLE` remain +external. Shape, ID, or self-Sigil validity never proves visibility. + +## HCW5 — exact HFP fragment inventory and comparison bytes + +### Fragment inventory + +`fragment-inventory.json` is the exact UTF-8 `canonical_json` bytes of this +closed eight-member object: + +```text +schema_version +source_candidate_id +source_candidate_inventory_entry_sigil +source_record_kind +record_fragment +bytes_fragment +manifest_fragment +fragment_inventory_sigil +``` + +`schema_version` is constant +`execution-heartbeat-forensic-package-fragment-inventory/1.0`. +`source_candidate_id`, `source_record_kind`, all three descriptors, and the +entry Sigil equal the one literal HCW2 entry byte-for-byte. +`fragment_inventory_sigil` is the ordinary self-Sigil over the other seven +members. + +`source_state` is `COMPLETE` exactly when all three descriptors have +`present: true`; otherwise it is `PARTIAL`, including an empty surviving +candidate directory whose three descriptors are absent. For every physical +HFP source-fragment container: + +- a present descriptor requires the container to hold the exact original + fragment bytes with the same length and domain Sigil; and +- an absent descriptor requires a physically present zero-length container, + while its descriptor remains `present: false`, length zero, and Sigil null. + +The zero-length absent container is packaging structure, not invented source +content. A present zero-length source fragment is distinguished by +`present: true` and the non-null domain Sigil of empty bytes. + +### Comparison source and `K` + +For `COMPLETE`, `comparison_kind` is `MESSAGE_BYTES` and `X` is the exact +`source-bytes.fragment` content. For `PARTIAL`, `comparison_kind` is +`PARTIAL_FRAGMENT_SET` and `X` is the unambiguous concatenation, in +`record_fragment`, `bytes_fragment`, `manifest_fragment` order, of: + +```text +one presence octet (0x00 absent, 0x01 present) +U64BE(exact original fragment length) +exact original fragment bytes when present +``` + +The canonical H8 construction remains: + +```text +MESSAGE_BYTES: K = 0x00 || U64BE(length(X)) || X +PARTIAL_FRAGMENT_SET: K = 0x01 || U64BE(length(X)) || X + +comparison_size_bytes = length(K) +comparison_bytes_sigil = SigilBytes( + utf8("execution-heartbeat-collision-side-order-bytes/1.0\0") || K +) +``` + +All lengths are checked before U64BE encoding and remain within U63 where the +canonical HFP binding requires U63. `comparison-bytes.bin` is exact `K`, not +`X`, a raw digest, a JSON encoding, or a reconstructed complete package. + +The HFP package contains exactly these six members: + +```text +fragment-inventory.json +comparison-bytes.bin +source-record.fragment +source-bytes.fragment +source-manifest.fragment +forensic-manifest.json +``` + +No absent source fragment permits omission of its zero-length container. + +## HCW6 — forensic manifest and package binding + +`forensic-manifest.json` is the exact UTF-8 `canonical_json` bytes of this +closed 14-member object: + +```text +schema_version +forensic_manifest_id +forensic_package_id +forensic_reservation_id +forensic_reservation_sigil +source_candidate_id +source_record_kind +source_state +comparison_kind +comparison_size_bytes +comparison_bytes_sigil +fragment_inventory_sigil +storage_profile +forensic_manifest_sigil +``` + +`schema_version` is constant +`execution-heartbeat-forensic-package-manifest/1.0` and `storage_profile` is +constant `DESCRIPTOR_RELATIVE_ATOMIC_DIRECTORY_V1`. `source_record_kind` is +`CANONICAL_MESSAGE` or `RAW_FRAME`; `source_state` and `comparison_kind` obey +HCW5's exact matrix. The canonical ID formula remains: + +```text +forensic_manifest_id = + "HFM-" || UPPER_HEX(SHA256(canonical_json([ + "execution-heartbeat-forensic-package-manifest-id/1.0", + forensic_package_id, + forensic_reservation_id, + forensic_reservation_sigil, + source_candidate_id, + source_record_kind, + source_state, + comparison_kind, + comparison_size_bytes, + comparison_bytes_sigil, + fragment_inventory_sigil + ]))) + +forensic_manifest_sigil = + Sigil(forensic manifest without forensic_manifest_sigil) +``` + +HFM matches `^HFM-[0-9A-F]{64}$` and is 68 ASCII bytes. + +The public `heartbeat_forensic_package_binding` has exactly the canonical 12 +members: + +```text +forensic_package_id +forensic_reservation_id +forensic_reservation_sigil +source_candidate_id +source_record_kind +source_state +comparison_kind +comparison_size_bytes +comparison_bytes_sigil +fragment_inventory_sigil +forensic_manifest_id +forensic_manifest_sigil +``` + +It is an exact projection of the resolved manifest plus its reservation. It +does not carry a path, storage profile, fragment bytes, candidate nonce, +marker binding, HCE ID, or visibility assertion. + +HFP resolution reopens the committed HPR package and all six HFP members, +proves the HCW2 entry equality, recomputes every fragment descriptor, +inventory Sigil, `X`, `K`, comparison Sigil, HFP/HFM IDs, manifest self-Sigil, +and literal file bytes. No isolated binding, Sigil, or complete-looking final +directory establishes `HFP_COMMITTED_VISIBLE`. + +## HCW7 — HCE collision kind, sides, and descriptor + +### Exact `collision_kind` interpretation + +The canonical HCE root retains its member name `collision_kind`. Its exact enum +is: + +```text +CANONICAL_MESSAGE +RAW_FRAME +``` + +It equals the bound HCG marker's `identity_kind` byte-for-byte. The differing +field names do not create two concepts: `collision_kind` is the HCE projection +of marker `identity_kind`. It also equals every complete source record's kind +and every HFP `source_record_kind`. The HCG marker does not gain a new +`collision_kind` member, and HCE is not renamed to `identity_kind`. + +This resolves the canonical sentence that `collision_kind` equals the gate +marker without changing the already fixed HCG 23-member root. + +### Gate binding and sides + +`collision_gate_binding` remains the exact closed five-member object: + +```text +collision_gate_marker_id +collision_gate_marker_sigil +collision_gate_journal_event +collision_gate_index_row_id +collision_gate_index_row_sigil +``` + +`collision_gate_journal_event` is the full canonical Execution EventRef. Each +`collision_sides` member remains the exact closed object: + +```text +comparison_kind +comparison_size_bytes +comparison_bytes_sigil +packages +``` + +`packages` contains these closed branches: + +```text +INSTALLED_PACKAGE { + kind, + record_id, + record_sigil, + stored_size_bytes, + stored_bytes_sigil, + install_manifest_id, + install_manifest_sigil +} + +FORENSIC_PACKAGE { + kind, + forensic_package +} +``` + +`forensic_package` is HCW6's complete binding. For +`collision_kind: CANONICAL_MESSAGE`, an installed `record_id` is an HCM ID and +its byte Sigil uses the HCM canonical-JSON domain. For `RAW_FRAME`, it is an +HFR ID and uses the received-frame domain. Its HMI must resolve the exact +record and bytes. + +For that installed branch, `X` is the exact resolved HCM or HFR `bytes.bin`, +and its side values are derived, never accepted as declarations: + +```text +comparison_kind = MESSAGE_BYTES +K = 0x00 || U64BE(length(X)) || X +comparison_size_bytes = length(K) +comparison_bytes_sigil = SigilBytes( + utf8("execution-heartbeat-collision-side-order-bytes/1.0\0") || K +) +``` + +The HMI `stored_size_bytes` and `stored_bytes_sigil` describe `X` using the +HCM/HFR source domain; the side size and Sigil describe `K` using the distinct +side-order domain. Neither pair substitutes for the other. The derived `K` +must equal the exact comparison bytes of the side that contains the installed +branch. + +There is at most one installed branch globally; its presence equals the marker +Boolean. Every HCW2 entry appears exactly once through its one HFP binding, +and the total package-binding count is at most 4,096. + +Side equality and order are determined only after reopening exact comparison +bytes: + +1. byte-equal packages are grouped in one side; +2. different sides have byte-different comparison bytes; +3. sides strictly increase by unsigned-octet comparison of exact `K`; +4. the installed branch sorts first within its side; +5. HFP branches then sort by `forensic_package_id` ASCII; and +6. at least two `MESSAGE_BYTES` sides are unequal under the same marker key. + +Partial sides remain retained context and cannot alone prove a collision. + +### HCE descriptor and package + +`D` remains exactly: + +```text +D = utf8(canonical_json([collision_gate_binding, collision_sides])) +``` + +The HCE package is the existing generic committed package with +`record_kind: COLLISION_EVIDENCE`, `record.json` equal to exact canonical HCE +JSON, `bytes.bin` equal to `D`, and `manifest.json` equal to the HMI. Its HMI +facts are: + +```text +stored_size_bytes = length(D) +stored_bytes_sigil = SigilBytes( + utf8("execution-heartbeat-collision-evidence-descriptor/1.0\0") || D +) +``` + +The HCE ID remains a fresh canonical 128-bit Crockford ID matching +`^HCE-[0-7][0-9A-HJKMNP-TV-Z]{25}$`, length 30, redrawn on collision. Its +self-Sigil omits only `collision_evidence_sigil`. HCE `detected_at`, +owner/message tuple, `identity_sigil`, and `collision_kind` equal the marker. + +Raw SHA-256, undomained `SigilBytes(D)`, an HCM/HFR domain, a generic +byte-Sigil, omitted side, reordered side, two-side truncation, package +substitution, or descriptor/`bytes.bin` inequality fails closed. + +## HCW8 — canonical `$defs` ownership and imports + +The eventual Schemas must use the following literal owners and absolute URIs. +There is no placeholder-substitution step. A consumer must not clone, widen, +or privately rename a shared wire. + +### Collision-family owners + +| Definition | Exact canonical URI | +| --- | --- | +| HCG ID | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-marker/1.0#/$defs/collisionGateMarkerId` | +| HGC ID | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-marker/1.0#/$defs/collisionGateCommitId` | +| complete HGC commit | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-marker/1.0#/$defs/collisionGateCommit` | +| HOC ID | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-marker/1.0#/$defs/sourceCandidateId` | +| candidate inventory | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-marker/1.0#/$defs/candidateInventory` | +| candidate entry | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-marker/1.0#/$defs/candidateInventoryEntry` | +| source fragment descriptor | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-marker/1.0#/$defs/sourceFragmentDescriptor` | +| dependent suffix plan | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-marker/1.0#/$defs/dependentSuffixPlan` | +| revocation obligation | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-marker/1.0#/$defs/revocationObligation` | +| HGI ID | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-index-row/1.0#/$defs/collisionGateIndexRowId` | +| complete HGI row | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-index-row/1.0#/$defs/collisionGateIndexRow` | +| HPR ID | `https://benchwork.dev/schemas/execution-heartbeat-forensic-package-reservation-index-row/1.0#/$defs/forensicReservationId` | +| HFP ID | `https://benchwork.dev/schemas/execution-heartbeat-forensic-package-reservation-index-row/1.0#/$defs/forensicPackageId` | +| HPC ID | `https://benchwork.dev/schemas/execution-heartbeat-forensic-package-reservation-index-row/1.0#/$defs/reservationCommitId` | +| complete HPR row | `https://benchwork.dev/schemas/execution-heartbeat-forensic-package-reservation-index-row/1.0#/$defs/forensicReservationRow` | +| reservation commit | `https://benchwork.dev/schemas/execution-heartbeat-forensic-package-reservation-index-row/1.0#/$defs/reservationCommit` | +| HCE ID | `https://benchwork.dev/schemas/execution-heartbeat-collision-evidence/1.0#/$defs/collisionEvidenceId` | +| HFM ID | `https://benchwork.dev/schemas/execution-heartbeat-collision-evidence/1.0#/$defs/forensicManifestId` | +| collision kind | `https://benchwork.dev/schemas/execution-heartbeat-collision-evidence/1.0#/$defs/collisionKind` | +| fragment inventory | `https://benchwork.dev/schemas/execution-heartbeat-collision-evidence/1.0#/$defs/fragmentInventory` | +| forensic manifest | `https://benchwork.dev/schemas/execution-heartbeat-collision-evidence/1.0#/$defs/forensicManifest` | +| forensic package binding | `https://benchwork.dev/schemas/execution-heartbeat-collision-evidence/1.0#/$defs/heartbeatForensicPackageBinding` | +| collision gate binding | `https://benchwork.dev/schemas/execution-heartbeat-collision-evidence/1.0#/$defs/collisionGateBinding` | +| collision side | `https://benchwork.dev/schemas/execution-heartbeat-collision-evidence/1.0#/$defs/collisionSide` | +| installed/forensic package union | `https://benchwork.dev/schemas/execution-heartbeat-collision-evidence/1.0#/$defs/collisionPackage` | +| HGR ID | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-recovery/1.0#/$defs/collisionGateRecoveryId` | +| HRE evidence | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-recovery/1.0#/$defs/revocationCompletionEvidence` | +| revocation completion result | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-recovery/1.0#/$defs/revocationCompletionResult` | +| complete HGR row | `https://benchwork.dev/schemas/execution-heartbeat-collision-authority-gate-recovery/1.0#/$defs/collisionGateRecovery` | + +The new collision-family `$defs` aliases above use the printed lower-camel +names. Top-level HCG, HGI, HPR, HCE, and HGR records validate against their +respective root Schema URI; their root `schema_version` constants remain, +respectively: + +```text +execution-heartbeat-collision-authority-gate-marker/1.0 +execution-heartbeat-collision-authority-gate-index-row/1.0 +execution-heartbeat-forensic-package-reservation-index-row/1.0 +execution-heartbeat-collision-evidence/1.0 +execution-heartbeat-collision-authority-gate-recovery/1.0 +``` + +### Imported foundation owners + +These are imports, not collision-owned aliases. Existing snake-case `$defs` +names remain snake case. + +| Imported definition | Exact canonical URI | +| --- | --- | +| complete HCM record | `https://benchwork.dev/schemas/execution-heartbeat-canonical-message/1.0` | +| HCM record ID | `https://benchwork.dev/schemas/execution-heartbeat-canonical-message/1.0#/$defs/canonicalMessageRecordId` | +| complete HFR record | `https://benchwork.dev/schemas/execution-heartbeat-raw-frame/1.0` | +| HFR record ID | `https://benchwork.dev/schemas/execution-heartbeat-raw-frame/1.0#/$defs/rawFrameRecordId` | +| complete HMI | `https://benchwork.dev/schemas/execution-heartbeat-message-store-install-manifest/1.0` | +| HMI ID | `https://benchwork.dev/schemas/execution-heartbeat-message-store-install-manifest/1.0#/$defs/installManifestId` | +| HMI record kind | `https://benchwork.dev/schemas/execution-heartbeat-message-store-install-manifest/1.0#/$defs/recordKind` | +| complete Execution Journal Event | `https://benchwork.dev/schemas/execution-journal-event/1.0` | +| Event type | `https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_type` | +| EventRef | `https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_ref` | +| Event ID | `https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id` | +| entity revision | `https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/entity_revision` | +| transition cause | `https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/transition_cause` | +| Worker-Session State | `https://benchwork.dev/schemas/execution-state/1.0#/$defs/worker_session_state` | +| Lease State | `https://benchwork.dev/schemas/execution-state/1.0#/$defs/lease_state` | +| Attempt State | `https://benchwork.dev/schemas/execution-state/1.0#/$defs/attempt_state` | +| Job State | `https://benchwork.dev/schemas/execution-state/1.0#/$defs/job_state` | +| Worker Session ID | `https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId` | +| Lease ID | `https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId` | +| Attempt ID | `https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId` | +| Job ID | `https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId` | +| Timestamp | `https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp` | +| Sigil | `https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil` | +| U63 | `https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63` | +| PositiveU63 | `https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63` | + +The EventRef, Event ID, entity-revision, transition-cause, and four State enum +URIs in this table resolve through the canonically incorporated and published +SWC/JEW strongly connected pair. This clarification assigns their owner but +does not by itself grant replay, append, runtime, or filesystem authority. + +Schema cycles may use Draft 2020-12 registry resolution but may not replace a +direct `$ref` with a copied shape. + +HPR and the already published local contract-only leaves may lexically check an +HCG/HFP ID before the owning Schema is available. Such lexical checks are not +marker or package resolution. Full resolvers must use the owner URI above. + +## HCW9 — IDs, Sigils, retry, retention, and authority boundaries + +### Fixed ID and Sigil table + +This approved closure adds no new operational identity algorithm. The complete collision +family uses: + +| Object | Fixed identity rule | +| --- | --- | +| HCG marker | canonical H8 deterministic ID over owner/message/identity tuple; ordinary marker self-Sigil | +| HGC commit | HCW3 deterministic ID over HCG ID/Sigil; ordinary commit self-Sigil | +| HPR reservation | canonical H8 deterministic ID over HCG ID and HOC ID; ordinary row self-Sigil | +| HFP package | canonical H8 deterministic ID over HCG ID and HOC ID | +| HPC commit | HCW4 deterministic ID over HPR ID/Sigil; ordinary commit self-Sigil | +| inventory entry | HCW2 ordinary self-Sigil | +| fragment inventory | HCW5 ordinary self-Sigil | +| HFM manifest | canonical H8 deterministic ID over complete manifest identity tuple; ordinary manifest self-Sigil | +| HCE evidence | fresh canonical 128-bit Crockford ID; ordinary HCE self-Sigil | +| HGI row | canonical H8 deterministic ID over owner/message/identity lookup key; ordinary row self-Sigil | +| HGR recovery | fresh canonical 128-bit Crockford ID; ordinary HGR self-Sigil | +| HRE evidence | canonical H8 deterministic ID over obligation ID/Sigil and full EventRef; canonical HRE domain-separated evidence Sigil | + +No ID formula gains a timestamp, path, size, package state, Event sequence, or +filesystem value. No ordinary self-Sigil is replaced by a byte-Sigil, and no +domain-separated byte-Sigil is replaced by a raw digest. + +### Retry and single assignment + +The following keys are independent: + +- HCG: marker ID and complete owner/message/identity lookup key; +- HPR: reservation ID, source candidate ID, and forensic package ID; +- HFP: forensic package ID and `(collision_gate_marker_id, + source_candidate_id)`; +- HGI: index row ID and complete owner/message/identity lookup key; and +- HCE, HGR: their random IDs, with redraw before installation when already + occupied. + +An exact retry reopens every required package and compares every record, +inventory, fragment container, comparison byte, manifest, commit, EventRef, +and self-Sigil byte-for-byte before returning the first installed object. A +match on size or Sigil alone is never an exact retry. Different bytes under any +independent key are permanent integrity failure. They are not overwritten, +merged, repaired from hashes, assigned a second deterministic ID, or treated +as an ordinary duplicate. + +HGR remains an append-only recovery evidence record rather than a mutable +single logical slot. An occupied random HGR ID is redrawn; a committed HGR is +immutable. + +### Parser, local validator, resolver, and replay split + +Every JSON object above uses strict UTF-8 loading and rejects a BOM, duplicate +keys at every depth, non-finite numbers, trailing content, invalid scalar +encoding, non-object roots where an object is required, and unknown members. +Binary files are never JSON-normalized. + +Pure local validation may establish only: + +- closed shape, primitive bounds, enums, conditional nulls, and array bounds; +- deterministic IDs and locally owned self-Sigils; +- canonical ordering derivable from one complete supplied object; and +- exact length/domain-Sigil equality for explicitly supplied bytes. + +Dependency-fed immutable resolution additionally reopens and byte-compares +the HCG, `I`, entry, HPR, HFP, HMI, HCE, HGI, HGR, Event, and obligation +objects required by that branch. It proves all owner, source, marker, +inventory, EventRef, package, and timestamp equalities. A supplied dictionary +or Boolean saying that a dependency was verified is not a resolver. + +Filesystem installation and visibility require the canonical no-symlink, +file-`fsync`, directory-`fsync`, reopen, atomic rename, parent-`fsync`, and +descriptor-relative final reopen state machines. Journal replay requires the +complete verified prefix, exact Event bytes, State reducer, revision algebra, +transition admissibility, and recovery suffix. These authorities remain +external and fail closed from contract-only helpers. + +### Retention + +The canonical retention rule is unchanged. Marker, inventory, entry, +ordinary package and candidate fragments, HPR, every reservation and HFP +staging candidate, HFP, HCE, HGI, HGR, Event, obligation, and completion +evidence are retained for the affected Journal and integrity-export lifetime. +Before that shared lifetime ends, no successful HFP/HCE construction, +terminal owner, index rebuild, cache cleanup, or shorter component retention +expiry deletes or substitutes collision material. Expiry of that canonical +shared lifetime is not prohibited by this approved closure. The committed HCG marker is +the one separate permanent exception: it remains immutable and is never +deleted, superseded, or changed to an open state. + +## HCW10 — conformance evidence and remaining approval gates + +### Required local fixtures + +Retained local Schema and validator fixtures must include at least: + +1. candidate inventories at both conditional count boundaries, strict HOC + order, and all eight present/absent combinations for the three fragments; +2. present empty versus absent fragment, wrong length, null/non-null Sigil + inversion, raw SHA, undomained Sigil, and all record/bytes/manifest + cross-domain substitutions; +3. missing, duplicate, reordered, and changed inventory entries, wrong entry + self-Sigil, duplicate HOC ID, wrong `source_record_kind`, and marker + candidate-count inequality; +4. exact HCG/HGC and HPR/HPC package members, schema versions, IDs, self-Sigils, + and rejection of extra, missing, wrong-type, or substituted members; +5. complete HCM and HFR HFPs, every partial fragment combination, absent + zero-container versus present-empty distinction, wrong source-domain Sigil, + malformed U64BE framing, comparison-kind tag substitution, and `K`/file + inequality; +6. exact forensic manifest, HFM preimage, storage profile, fragment inventory + equality, HPR/HFP source equality, and all manifest field substitutions; +7. HCE canonical and raw collision kinds, installed/no-installed branches, + byte-equal package grouping, two through 4,096 sides/packages, full + inventory coverage, partial-only non-proof, side/package reorder, and + descriptor/HMI domain substitutions; +8. HPR/HFP/HCG/HGI independent-key collisions and exact byte-equal retries; +9. strict-loader BOM, bad UTF-8, duplicate-key, non-finite, trailing-content, + non-object, unknown-member, identifier-case, Crockford, bound, and null + failures; and +10. every external-authority entry point failing closed when only local shape, + a bare Sigil, a path, a final directory, or a supplied verification flag is + available. + +### Required crash/replay fixtures + +Integration evidence must separately cover every file, directory, rename, and +parent-`fsync` cut for HCG, HPR, HFP, and HCE; multiple HPR/HFP staging +candidates; ASCII-smallest arbitration; partial final paths; marker-first +startup closure; missing or byte-different collision Event; partial dependent +suffix; incomplete credential/handle revocation; HGI rebuild; HGR result-set +completion; and permanent closure after every failure. + + +The SWC1–SWC2 and JEW1–JEW4 approval and publication prerequisites named +during review are now satisfied by their canonical incorporation above. +Affected collision contracts still require their Schemas, strict loaders, +dependency resolvers, durable package state machines, complete State/Event +integration, crash/replay evidence, and independent P1/P2/P3-zero review +before they may claim runtime or append authority. + + + ## Compatibility This RFC refines RFC-0007's reserved Executor contract and is subordinate to diff --git a/docs/en/rfcs/RFC-0013-artifact-storage-model.md b/docs/en/rfcs/RFC-0013-artifact-storage-model.md index 0056793..40a8296 100644 --- a/docs/en/rfcs/RFC-0013-artifact-storage-model.md +++ b/docs/en/rfcs/RFC-0013-artifact-storage-model.md @@ -492,7 +492,7 @@ status, clock status and anchor, current epoch, applied event count, last event Sigil, and these sorted closed projection collections: `recoveries`, `blobs`, `replicas`, `transfer_requests`, `transfer_attempts`, -`materializations`, `quarantines`, `provenance`, `retention_policies`, +`materializations`, `quarantines`, `provenance`, `provenance_policies`, `retention_policies`, `holds`, `reference_sets`, `legacy_v1_protections`, `gc_plans`, `canonical_reference_intents`, `dispositions`, `quota_reservations`, `open_intents`, and `incidents`. It also contains derived availability and @@ -892,6 +892,7 @@ top-level field sets are: | `artifact-transfer/1.0` | `schema_version`, `transfer_id`, `direction`, `purpose`, `source`, `destination`, `expected_blob_sigil`, `bounds`, `backend`, `authorization_sigil`, `idempotency_key_sigil`, `execution`, `verification_method`, `provenance_policy_id`, `retention_policy_ids`, `created_at`, `record_sigil` | | `artifact-transfer-attempt/1.0` | `schema_version`, `transfer_attempt_id`, `transfer_id`, `attempt_number`, `state`, `staging_state`, `reservation`, `staging_object`, `commit_intent`, `residual_staging_cleanup`, `computed_blob_sigil`, `computed_size_bytes`, `selected_replica_id`, `quarantine_id`, `terminal_reason`, `started_at`, `terminal_at`, `revision`, `record_sigil` | | `artifact-provenance/1.0` | `schema_version`, `provenance_id`, `relation`, `blob`, `source`, `destination`, `actor_id`, `authorization_sigil`, `execution`, `backend`, `transfer`, `verification_sigils`, `transformation`, `times`, `terminal_reason`, `record_sigil` | +| `artifact-provenance-policy/1.0` | `schema_version`, `provenance_policy_id`, `policy_version`, `scope`, `allowed_directions`, `allowed_purposes`, `allowed_source_kinds`, `allowed_destination_kinds`, `allowed_relations`, `execution_requirement`, `allowed_verification_methods`, `minimum_verification_evidence`, `transformation_mode`, `required_retention_policy_ids`, `authorization_sigil`, `registered_at`, `record_sigil` | | `artifact-materialization/1.0` | `schema_version`, `materialization_id`, `source_blob_sigil`, `source_replica_id`, `source_verification_sigil`, `destination_class`, `destination_sigil`, `task_id`, `attempt_id`, `access_mode`, `bounds`, `reservation`, `destination_staging_object`, `commit_intent`, `residual_staging_cleanup`, `state`, `verification`, `cleanup`, `created_at`, `terminal_at`, `revision`, `record_sigil` | | `artifact-storage-backend/1.0` | `schema_version`, `backend_id`, `adapter_id`, `adapter_version`, `protocol_version`, `adapter_sigil`, `configuration_sigil`, `namespace_sigil`, `isolation`, `limits`, `consistency`, `durability`, `verification_methods`, `range_resume`, `conditional_operations`, `deletion_capabilities`, `credential_class`, `fencing`, `conformance`, `record_sigil` | | `artifact-retention-policy/1.0` | `schema_version`, `policy_id`, `scope`, `minimum_replica_count`, `required_backends`, `required_failure_domains`, `maximum_integrity_age_seconds`, `deletion_grace_seconds`, `retain_until`, `automatic_gc_allowed`, `authorization_sigil`, `registered_at`, `record_sigil` | @@ -902,7 +903,7 @@ top-level field sets are: | `artifact-storage-disposition/1.0` | `schema_version`, `disposition_id`, `target_kind`, `target_id`, `target_generation`, `expected_blob_sigil`, `expected_size_or_bound`, `reason_code`, `actor_id`, `policy_sigil`, `approval_evidence_sigil`, `authorization_sigil`, `authorized_at`, `expires_at`, `idempotency_key_sigil`, `record_sigil` | | `artifact-storage-journal-event/1.0` | `schema_version`, `journal_id`, `event_id`, `sequence`, `event_type`, `coordinator_id`, `epoch`, `recorded_at`, `observed_at`, `entity_revisions`, `causation_event_id`, `idempotency_key_sigil`, `quota_effects`, `payload`, `previous_event_sigil`, `event_sigil` | | `artifact-storage-journal-head/1.0` | `schema_version`, `journal_id`, `storage_format_version`, `event_count`, `last_sequence`, `last_event_sigil`, `committed_byte_length`, `current_epoch`, `state_sigil`, `updated_at` | -| `artifact-storage-state/1.0` | `schema_version`, `journal_id`, `storage_format_version`, `project_id`, `backend_profile_id`, `backend_profile_sigil`, `conformance_profile_id`, `conformance_suite_sigil`, `store_status`, `active_recovery_id`, `recovery_origin_status`, `clock_status`, `clock_anchor`, `current_epoch`, `applied_event_count`, `last_event_sigil`, `recoveries`, `blobs`, `replicas`, `transfer_requests`, `transfer_attempts`, `materializations`, `quarantines`, `provenance`, `retention_policies`, `holds`, `reference_sets`, `legacy_v1_protections`, `gc_plans`, `canonical_reference_intents`, `dispositions`, `quota_reservations`, `open_intents`, `incidents`, `availability_counters`, `quota_counters`, `state_sigil` | +| `artifact-storage-state/1.0` | `schema_version`, `journal_id`, `storage_format_version`, `project_id`, `backend_profile_id`, `backend_profile_sigil`, `conformance_profile_id`, `conformance_suite_sigil`, `store_status`, `active_recovery_id`, `recovery_origin_status`, `clock_status`, `clock_anchor`, `current_epoch`, `applied_event_count`, `last_event_sigil`, `recoveries`, `blobs`, `replicas`, `transfer_requests`, `transfer_attempts`, `materializations`, `quarantines`, `provenance`, `provenance_policies`, `retention_policies`, `holds`, `reference_sets`, `legacy_v1_protections`, `gc_plans`, `canonical_reference_intents`, `dispositions`, `quota_reservations`, `open_intents`, `incidents`, `availability_counters`, `quota_counters`, `state_sigil` | | `artifact-storage-tail-evidence/1.0` | `schema_version`, `evidence_id`, `recovery_id`, `journal_id`, `kind`, `frame_start`, `observed_size`, `observed_bytes_sigil`, `previous_evidence_record_sigil`, `created_at`, `record_sigil` | | `artifact-storage-recovery-marker/1.0` | `schema_version`, `recovery_id`, `journal_id`, `prior_head_sigil`, `old_committed_byte_length`, `last_complete_byte_length`, `discarded_suffix_size`, `discarded_suffix_sigil`, `evidence_record_sigil`, `phase`, `recovery_event_id`, `recovery_event_sigil`, `recovery_event_seed_record_sigil`, `recovery_frame_start`, `recovery_frame_size`, `recovery_frame_sigil`, `prepared_frame_evidence_record_sigil`, `retry_count`, `latest_retry_evidence_record_sigil`, `created_at`, `updated_at`, `record_sigil` | | `artifact-storage-doctor-report/1.0` | `schema_version`, `report_id`, `mode`, `project_id`, `storage_journal_id`, `journal_head_sigil`, `chronicle_head_sigil`, `storage_format_version`, `backend_profile_id`, `backend_profile_sigil`, `conformance_profile_id`, `conformance_suite_sigil`, `coordinator_epoch`, `journal_verification`, `state_verification`, `backend_inventory`, `replica_checks`, `legacy_checks`, `quarantine_checks`, `quota_checks`, `reference_checks`, `open_intent_checks`, `bounds`, `incomplete_reasons`, `overall_status`, `started_at`, `completed_at`, `report_sigil` | @@ -1228,6 +1229,7 @@ State collections are not generic maps. Their item shapes are exactly: | `materializations` | `record: artifact-materialization/1.0`, `last_event_sigil: Sigil` | | `quarantines` | `quarantine_id: SQ-ID`, `owner_kind: TRANSFER_ATTEMPT\|MATERIALIZATION`, `owner_id: Opaque`, `state: INTENT_RECORDED\|HELD\|INSPECTING\|DISPOSING\|DISPOSED\|DISPOSAL_FAILED\|FAILED`, `source_object: BackendObjectRef\|null`, `destination_object: BackendObjectRef\|null`, `source_cleanup: ResidualStagingCleanup`, `reservation: ReservationRef`, `reason: Reason`, `revision: PositiveU63`, `last_event_sigil: Sigil`, `record_sigil: Sigil`; `owner_id` is `SA-ID` or `SM-ID` exactly as selected by `owner_kind` | | `provenance` | `provenance_id: Opaque`, `record_sigil: Sigil`, `revision: 1`, `last_event_sigil: Sigil` | +| `provenance_policies` | `provenance_policy_id: SPP-ID`, `record_sigil: Sigil`, `revision: 1`, `last_event_sigil: Sigil` | | `retention_policies` | `policy_id: SP-ID`, `record_sigil: Sigil`, `revision: 1`, `last_event_sigil: Sigil` | | `holds` | `hold_id: SH-ID`, `target_kind: BLOB\|REPLICA\|REFERENCE_SET`, `target_id: Opaque`, `policy_id: SP-ID`, `state: ACTIVE\|RELEASED`, `set_authorization_sigil: Sigil`, `release_authorization_sigil: Sigil\|null`, `revision: PositiveU63`, `last_event_sigil: Sigil` | | `reference_sets` | `reference_set_id: RS-ID`, `reference_set_sigil: Sigil`, `source_identity: Opaque`, `revision: 1`, `last_event_sigil: Sigil` | @@ -3944,6 +3946,191 @@ Storage authorization does not authorize external disclosure. An export to a remote or external party requires the exact destination and disclosure policy to be approved under the applicable Review or future transport contract. +## Approved 2026-08-06 Result Authority Closure AC1 v0.1 + +The user approved AC1 through AC4 as one synchronized cross-RFC decision +bundle. This RFC owns AC1's namespace replacement-index root, row, protected +Head, legal-delta comparison, and sole visibility boundary. RFC-0012 owns +AC2–AC4's OWR subject, authority, and evidence-substrate rules. Neither side +is independently sufficient authority. + +### AC1 — namespace replacement-index root + +RFC-0013 owns three new closed contracts: +`artifact-storage-execution-namespace-index-row/1.0` and +`artifact-storage-execution-namespace-index/1.0`, plus the protected +`artifact-storage-execution-namespace-index-head/1.0`. They are storage-private +control records. They are not Worker inputs, Result fields, Journal Events, or +standalone leaf visibility paths. + +### AC1.1 closed row + +The row has exactly these required members: + +```text +schema_version +reservation +activation +abort +consumption_intent +consumption +row_sigil +``` + +`schema_version` is constant +`artifact-storage-execution-namespace-index-row/1.0`. `reservation` is one +complete `artifact-storage-execution-namespace-reservation/1.0` object. The +other four members are either null or one complete object from the matching +activation, abort, consumption-intent, or consumption leaf contract. The only +legal null/presence branches are: + +| Derived state | activation | abort | consumption_intent | consumption | +| --- | --- | --- | --- | --- | +| `PENDING_EVENT` | null | null | null | null | +| `ACTIVE` | object | null | null | null | +| `ABORTED` | null | object | null | null | +| `CONSUMING` | object | null | object | null | +| `CONSUMED` | object | null | object | object | + +Every present leaf resolves byte-for-byte to the row reservation through the +already canonical owner/equality matrix. A row contains no independent status, +timestamp, mutable projection, path, or backend locator. Its self-Sigil is: + +```text +row_sigil = Sigil([ + "artifact-storage-execution-namespace-index-row/1.0", + reservation, + activation, + abort, + consumption_intent, + consumption +]) +``` + +### AC1.2 closed root and order + +The root has exactly: + +```text +schema_version +anchor_profile_sigil +index_generation +previous_index_sigil +rows +index_sigil +``` + +`schema_version` is constant +`artifact-storage-execution-namespace-index/1.0`. `index_generation` is U64. +`anchor_profile_sigil` selects the installed monotonic-anchor protection and +resolver profile and is byte-equal in every generation. `previous_index_sigil` +is Sigil or null. `rows` contains 0..4,096 members and +is strictly increasing by the unsigned-ASCII bytes of +`reservation.namespace_reservation_id`. No second order or map-key +serialization is permitted. A full index applies durable fail-closed +backpressure: no new reservation is admitted. Deletion, wraparound, or an +implementation-selected larger bound is forbidden; any future compaction or +checkpoint format requires a separately approved protocol. + +Across all rows, each of the following is independently unique: reservation +key Sigil, reservation ID, `(job_id, attempt_id, output_handle_id)`, ST-ID, +SA-ID, consumption-intent ID, and prepared Storage Event ID. Every present +activation, abort, intent, or consumption leaf is also unique by its own +ordinary self-Sigil and its canonical owner slot. A duplicate under any one +class is invalid even when another class differs. + +The unique empty initial root has `index_generation: 0`, +`previous_index_sigil: null`, and `rows: []`. Every successor has checked +`index_generation = prior.index_generation + 1`, rejects U64 overflow, and has +`previous_index_sigil = prior.index_sigil`. Its self-Sigil is: + +```text +index_sigil = Sigil([ + "artifact-storage-execution-namespace-index/1.0", + anchor_profile_sigil, + index_generation, + previous_index_sigil, + rows +]) +``` + +### AC1.3 protected Head, replacement comparison, and visibility + +The independently protected Head has exactly: + +```text +schema_version +anchor_profile_sigil +index_generation +index_sigil +previous_head_sigil +anchored_at +head_sigil +``` + +The Schema constant is +`artifact-storage-execution-namespace-index-head/1.0`. The initial Head names +the exact generation-zero root and has `previous_head_sigil: null`. Every +successor has checked Head and index generation equal to prior generation plus +one, has `anchor_profile_sigil` equal to the root and prior Head, names the +exact installed root Sigil, and has +`previous_head_sigil = prior.head_sigil`. `head_sigil` is +`Sigil(["artifact-storage-execution-namespace-index-head/1.0", +anchor_profile_sigil, index_generation, index_sigil, previous_head_sigil, +anchored_at])`. + +The Head is installed in the configured trusted monotonic anchor store, +separate from the replaceable index object. That store is append-only, +single-writer under the namespace lock, rejects generation rollback or a +second unequal successor, and resolves its current Head without accepting a +caller path or Head candidate. A self-Sigil or predecessor chain in the +replaceable root is not an anti-rollback substitute. + +A non-retry replacement performs exactly one legal delta: + +- insert one new `PENDING_EVENT` row; or +- change one row `PENDING_EVENT -> ACTIVE` or + `PENDING_EVENT -> ABORTED`; or +- change one row `ACTIVE -> CONSUMING`; or +- change one row `CONSUMING -> CONSUMED`. + +Every earlier leaf remains byte-for-byte unchanged. Rows cannot be deleted, +reordered, reassigned, compacted, or rewritten. An exact retry returns the +already installed root and does not increment the generation. Equal generation +with unequal bytes, a skipped generation, the wrong predecessor Sigil, an +illegal branch, a changed historical leaf, or a unique-key conflict is +`INTEGRITY_FAILURE`, not last-writer-wins repair. + +Before replacement, the writer requires the trusted current Head to name the +reopened prior root. It then file-syncs the candidate, atomically replaces the +one configured descriptor-relative canonical index object, directory-syncs +it, reopens and validates it, and advances the monotonic Head to that exact +root before releasing authority. Protocol visibility is the conjunction of +the durable reopened root and its protected Head. A private transaction file, +standalone leaf, directory listing, prefix match, unanchored newer root, +current/latest caller lookup, or in-memory row is never authoritative. + +A crash with the exact generation `n+1` root durable while the Head remains at +`n` gates allocators; recovery under the same lock may advance only when the +new root names the anchored root as predecessor and is its one legal delta. A +Head ahead of the root, a root more than one generation ahead, a root older +than the Head, or any unequal bytes is rollback/integrity failure. Failure to +prove any step retains the evidence and gates both allocators. + +AC1 selects the wire, checked compare, and visibility boundary. It does not +implement the lock, filesystem transaction, allocator, append, replay, or +crash-repair procedures already required by RFC-0013. + + +Conformance additionally requires the AC1 root/row/Head Schemas, strict +literal-byte loader, checked comparator, durable replacement and allocator +integration, lock-order tests, crash cuts, replay, recovery, and independent +cross-RFC review. Until all reciprocal RFC-0012 prerequisites also resolve, +both namespace allocators and Result admission fail closed. A valid leaf, +root self-Sigil, or unanchored replacement never establishes visibility. + + + ## Compatibility and migration This RFC does not reinterpret or rewrite an already accepted diff --git a/docs/en/rfcs/RFC-0015-experiment-executor-api.md b/docs/en/rfcs/RFC-0015-experiment-executor-api.md index 41da6f0..4da4961 100644 --- a/docs/en/rfcs/RFC-0015-experiment-executor-api.md +++ b/docs/en/rfcs/RFC-0015-experiment-executor-api.md @@ -408,9 +408,14 @@ Quarantine members are unique and ordered by `(subject_kind, subject_id)`; logs are unique and ordered by the fixed stream-kind order `STDOUT`, `STDERR`, `STRUCTURED` and then `stream_id`; and next actions use the printed action order. -The top-level Attempt-derived views select the current unresolved Attempt, or -the Job terminal event's selected Attempt after Job terminalization. When no -Attempt exists they use `LeaseView.NONE`, `PublicFenceView.NONE`, an +The top-level Attempt-derived views use one `projection_attempt_id` from the +verified fixed-prefix replay. For a terminal Job they use the terminal Job +Event's exact `selected_attempt_binding`, or null for its canonical `NONE` +branch. For a nonterminal Job with non-null RFC-0012 `current_attempt_id`, they +use that Attempt. For a nonterminal Job with null `current_attempt_id` and one +or more historical Attempts, including `RETRY_WAIT`, they use the Attempt with +the greatest `retry_ordinal`. When no Attempt exists they use +`LeaseView.NONE`, `PublicFenceView.NONE`, an `AssuranceView` containing the requested tuple, `attempt_binding: NONE`, and the current Job assurance binding, the fixed pre-attempt cleanup defaults, and empty Quarantine and log arrays. Otherwise the top-level logs are exactly @@ -420,9 +425,11 @@ views equal that Attempt's entry byte-for-byte and never select a different retry. `CancellationView` uses a closed selector. If any state-changing -`job.cancellation_requested` exists in the fixed prefix, it selects the -lowest-sequence such event and remains `REQUESTED`; later terminal -observations do not replace it. Otherwise, if one or more state-neutral +`job.stop_latched` Event in the fixed prefix has +`transition_cause.code = CANCEL_REQUESTED` and +`request_binding.kind = CANCELLATION`, it selects the lowest-sequence such +Event and remains `REQUESTED`; later terminal observations do not replace it. +Otherwise, if one or more state-neutral `job.cancellation_observed` events exist, it selects the lowest-sequence one as `OBSERVED_TERMINAL`. It is `NONE` only when neither event exists. Thus arbitrarily many idempotency-distinct terminal observations cannot make the @@ -660,6 +667,65 @@ Observe is read-only. A missing, corrupt, or replay-inconsistent journal fails closed rather than reporting inferred state from live processes, queues, or Crucible paths. +### Approved 2026-08-06 Observation projection clarification OP1–OP2 v0.1 + +The user approved OP1 and OP2 as one synchronized selector decision. These +rules replace the nonexistent cancellation selector and close the projection +Attempt during the historical-Attempt/no-current-Attempt interval. They are +normative for a live `execution-observation/1.0` projection. + +#### Approved synchronized selector rules + +#### OP1 — Cancellation selector + +Replace the nonexistent state-changing selector input with the canonical +RFC-0012 representation: + +1. If the fixed prefix contains one or more `job.stop_latched` Events whose + payload has `transition_cause.code = CANCEL_REQUESTED` and + `request_binding.kind = CANCELLATION`, select the lowest-sequence such + Event and emit `CancellationView.REQUESTED`. +2. Otherwise, if the prefix contains one or more state-neutral + `job.cancellation_observed` Events, select the lowest-sequence such Event + and emit `CancellationView.OBSERVED_TERMINAL`. +3. Otherwise emit `CancellationView.NONE`. +4. Later observations never replace a selected state-changing request, and no + new Event type is introduced. + +#### OP2 — Projection Attempt selector + +Define one `projection_attempt_id` from the verified fixed-prefix replay: + +1. For a terminal Job, use the terminal Job Event's exact + `selected_attempt_binding`, or null for its canonical `NONE` branch. +2. For a nonterminal Job with non-null RFC-0012 `current_attempt_id`, use that + Attempt. +3. For a nonterminal Job with null `current_attempt_id` and one or more + historical Attempts, use the Attempt with the greatest `retry_ordinal`. + This includes `RETRY_WAIT` between finalization and the next allocation. +4. If no Attempt exists, use null and the already specified no-Attempt + defaults. +5. When non-null, top-level Lease, public fence, assurance, cleanup, + quarantine, and the three Log views copy the selected Attempt projection + byte-for-byte. The selector is derived only from replayed canonical state; + it is not caller-controlled and does not add a field to the 23-field wire. + +#### Remaining live-projection prerequisites + +OP1–OP2 do not define the complete `NextAction` state/reason precedence +matrix, the exact `ObservationEvent.related_entity_ids` derivation, the +membership policy for historical Worker Sessions, or the Event-to-view +formula for nonterminal cleanup and Log closure progress. Those must be +closed before a live RFC-0015 projection can claim conformance. + +#### Authority boundary + +OP1–OP2 amend only the two RFC-0015 selector rules above. It would not +publish a Journal replayer, validate retained frames, authenticate a Cursor, +derive a page, expose runtime records, register an MCP tool, mutate execution +state, accept a Result, issue a Receipt, or confer scientific authority. + + ## Cancel `benchwork_cancel_job` accepts a closed diff --git a/schemas/agent-result-2.0.json b/schemas/agent-result-2.0.json new file mode 100644 index 0000000..eaa2396 --- /dev/null +++ b/schemas/agent-result-2.0.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/agent-result/2.0", + "title": "Agent Result v2", + "description": "Closed RFC-0015 deterministic acceptance proposal. Schema validation alone does not derive an Outcome, validate Storage, or authorize canonical acceptance.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version","task_id","program_id","task_capsule_sigil","host_identity_sigil","capability_binding","snapshot_binding","job_binding","execution_specification_binding","job_outcome_binding","terminal_event_sigil","selected_attempt_id","assurance_claim_sigil","terminal_source_binding","status","outputs","provenance","result_sigil"], + "properties": { + "schema_version": {"const":"agent-result/2.0"}, + "task_id": {"$ref":"https://benchwork.dev/schemas/task-capsule/2.0#/$defs/taskId"}, + "program_id": {"$ref":"https://benchwork.dev/schemas/task-capsule/2.0#/$defs/programId"}, + "task_capsule_sigil": {"$ref":"#/$defs/sigil"}, + "host_identity_sigil": {"$ref":"#/$defs/sigil"}, + "capability_binding": {"$ref":"https://benchwork.dev/schemas/execution-job-outcome/1.0#/$defs/capabilityBinding"}, + "snapshot_binding": {"$ref":"https://benchwork.dev/schemas/execution-job-outcome/1.0#/$defs/snapshotBinding"}, + "job_binding": {"$ref":"https://benchwork.dev/schemas/agent-result-acceptance-authorization/1.0#/$defs/jobBinding"}, + "execution_specification_binding": {"$ref":"https://benchwork.dev/schemas/execution-job-outcome/1.0#/$defs/specificationBinding"}, + "job_outcome_binding": {"$ref":"https://benchwork.dev/schemas/agent-result-acceptance-authorization/1.0#/$defs/jobOutcomeBinding"}, + "terminal_event_sigil": {"$ref":"#/$defs/sigil"}, + "selected_attempt_id": {"$ref":"https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "assurance_claim_sigil": {"$ref":"#/$defs/sigil"}, + "terminal_source_binding": {"$ref":"#/$defs/acceptedTerminalSourceBinding"}, + "status": {"const":"COMPLETED"}, + "outputs": {"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/output"}}, + "provenance": {"$ref":"#/$defs/provenance"}, + "result_sigil": {"$ref":"#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref":"https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"$ref":"https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "opaque": {"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","not":{"pattern":"[\\r\\n]"},"minLength":1,"maxLength":256}, + "output": {"type":"object","additionalProperties":false,"required":["task_output_id","declared_schema_id","declared_schema_sigil","blob_sigil","size_bytes","source_observation_member_sigil","storage_integrity_evidence_sigil"],"properties":{"task_output_id":{"$ref":"#/$defs/opaque"},"declared_schema_id":{"$ref":"#/$defs/opaque"},"declared_schema_sigil":{"$ref":"#/$defs/sigil"},"blob_sigil":{"$ref":"#/$defs/sigil"},"size_bytes":{"$ref":"#/$defs/u63"},"source_observation_member_sigil":{"$ref":"#/$defs/sigil"},"storage_integrity_evidence_sigil":{"$ref":"#/$defs/sigil"}}}, + "acceptedTerminalSourceBinding": {"oneOf":[{"type":"object","additionalProperties":false,"required":["kind"],"properties":{"kind":{"const":"NOT_APPLICABLE"}}},{"$ref":"https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/verified_terminal_source_binding"}]}, + "provenance": {"type":"object","additionalProperties":false,"required":["executor_instance_id","executor_epoch","executor_build_sigil","worker_id","worker_binding_sigil","worker_session_id","worker_session_binding_sigil","backend_identity","backend_configuration_sigil","requested_assurance_level","assurance_profile_sigil","conformance_suite_sigil","attempt_authorization_state","budget_settlement_event_sigil","job_budget_ledger_sigil","storage_observation_binding","control_evidence_set_binding","quarantine_binding_set_binding","terminalization_storage_manifest_binding","output_root_protection"],"properties":{"executor_instance_id":{"$ref":"https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/executorInstanceId"},"executor_epoch":{"$ref":"https://benchwork.dev/schemas/execution-state/1.0#/$defs/u64"},"executor_build_sigil":{"$ref":"#/$defs/sigil"},"worker_id":{"$ref":"https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"},"worker_binding_sigil":{"$ref":"#/$defs/sigil"},"worker_session_id":{"$ref":"https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"},"worker_session_binding_sigil":{"$ref":"#/$defs/sigil"},"backend_identity":{"$ref":"#/$defs/opaque"},"backend_configuration_sigil":{"$ref":"#/$defs/sigil"},"requested_assurance_level":{"enum":["SANCTUM-A0","SANCTUM-A1","SANCTUM-A2"]},"assurance_profile_sigil":{"$ref":"#/$defs/sigil"},"conformance_suite_sigil":{"$ref":"#/$defs/sigil"},"attempt_authorization_state":{"$ref":"https://benchwork.dev/schemas/execution-state/1.0#/$defs/attempt_authorization_state"},"budget_settlement_event_sigil":{"$ref":"#/$defs/sigil"},"job_budget_ledger_sigil":{"$ref":"#/$defs/sigil"},"storage_observation_binding":{"$ref":"https://benchwork.dev/schemas/execution-job-outcome/1.0#/$defs/outcomeStorageObservationBinding"},"control_evidence_set_binding":{"$ref":"https://benchwork.dev/schemas/execution-job-outcome/1.0#/$defs/terminalControlEvidenceSetBinding"},"quarantine_binding_set_binding":{"$ref":"https://benchwork.dev/schemas/execution-job-outcome/1.0#/$defs/terminalQuarantineBindingSetBinding"},"terminalization_storage_manifest_binding":{"$ref":"https://benchwork.dev/schemas/execution-job-outcome/1.0#/$defs/outcomeStorageManifestBinding"},"output_root_protection":{"$ref":"https://benchwork.dev/schemas/execution-job-outcome/1.0#/$defs/outcomeRootProtection"}}} + } +} diff --git a/schemas/agent-result-acceptance-authorization-1.0.json b/schemas/agent-result-acceptance-authorization-1.0.json new file mode 100644 index 0000000..35d1408 --- /dev/null +++ b/schemas/agent-result-acceptance-authorization-1.0.json @@ -0,0 +1,304 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/agent-result-acceptance-authorization/1.0", + "title": "Agent Result Acceptance Authorization v1", + "description": "Closed RFC-0015 Agent Result acceptance authorization preimage. Contract-only validation does not authenticate a live invocation, derive the raw acceptance key/request Sigils, execute Ward predicates, resolve approval/Outcome/Storage/Chronicle records, authorize acceptance, or create an Event or Receipt.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "transition_request_id", + "event_type", + "expected_chronicle_head", + "authority_subject", + "ward_pass", + "approval", + "acceptance_policy", + "acceptance_request_sigil", + "idempotency_key_sigil", + "reference_sets", + "managed_blob_sigils", + "acceptance_storage_binding", + "actor", + "host_invocation", + "chronicle_actor", + "requested_at", + "authorization_sigil" + ], + "properties": { + "schema_version": {"const": "agent-result-acceptance-authorization/1.0"}, + "transition_request_id": {"$ref": "#/$defs/transitionRequestId"}, + "event_type": {"const": "agent-result.accepted"}, + "expected_chronicle_head": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/chronicleHeadRef"}, + "authority_subject": {"$ref": "#/$defs/authoritySubject"}, + "ward_pass": {"$ref": "#/$defs/wardPass"}, + "approval": {"$ref": "#/$defs/approvalEvidence"}, + "acceptance_policy": {"$ref": "https://benchwork.dev/schemas/agent-result-acceptance-policy/1.0"}, + "acceptance_request_sigil": {"$ref": "#/$defs/sigil"}, + "idempotency_key_sigil": {"$ref": "#/$defs/sigil"}, + "reference_sets": { + "type": "array", + "minItems": 1, + "maxItems": 1, + "uniqueItems": true, + "items": {"$ref": "https://benchwork.dev/schemas/artifact-storage-reference-intent/1.0#/$defs/referenceSetRef"} + }, + "managed_blob_sigils": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "#/$defs/sigil"} + }, + "acceptance_storage_binding": {"$ref": "#/$defs/acceptanceStorageBinding"}, + "actor": {"$ref": "https://benchwork.dev/schemas/execution-cancel-request/1.0#/$defs/actor_binding"}, + "host_invocation": {"$ref": "https://benchwork.dev/schemas/execution-cancel-request/1.0#/$defs/host_invocation_binding"}, + "chronicle_actor": {"$ref": "https://benchwork.dev/schemas/actor/1.0"}, + "requested_at": {"$ref": "#/$defs/timestamp"}, + "authorization_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "opaque": { + "type": "string", + "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 1, + "maxLength": 256 + }, + "transitionRequestId": { + "type": "string", + "pattern": "^ATR-[A-F0-9]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "outcomeId": { + "type": "string", + "pattern": "^OJ-[A-F0-9]{64}$", + "minLength": 67, + "maxLength": 67 + }, + "eventId": { + "type": "string", + "pattern": "^CE-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 4, + "maxLength": 128 + }, + "receiptId": { + "type": "string", + "pattern": "^RC-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 4, + "maxLength": 128 + }, + "jobBinding": { + "type": "object", + "additionalProperties": false, + "required": ["job_id", "job_binding_sigil"], + "properties": { + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "job_binding_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "taskBinding": { + "type": "object", + "additionalProperties": false, + "required": ["task_id", "task_capsule_sigil"], + "properties": { + "task_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/taskId"}, + "task_capsule_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "capabilityBinding": { + "type": "object", + "additionalProperties": false, + "required": ["capability_id", "contract_version", "capability_contract_sigil"], + "properties": { + "capability_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/capabilityId"}, + "contract_version": {"const": "2.0"}, + "capability_contract_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "circleBinding": { + "type": "object", + "additionalProperties": false, + "required": ["circle_id", "circle_sigil"], + "properties": { + "circle_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/circleId"}, + "circle_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "specificationBinding": { + "type": "object", + "additionalProperties": false, + "required": ["specification_id", "specification_sigil"], + "properties": { + "specification_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/specificationId"}, + "specification_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "jobOutcomeBinding": { + "type": "object", + "additionalProperties": false, + "required": ["outcome_id", "outcome_sigil"], + "properties": { + "outcome_id": {"$ref": "#/$defs/outcomeId"}, + "outcome_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "authoritySubject": { + "type": "object", + "additionalProperties": false, + "required": [ + "registry_binding", + "task_binding", + "program_id", + "capability_binding", + "snapshot_binding", + "circle_binding", + "execution_specification_binding", + "job_binding", + "job_outcome_binding", + "agent_result_sigil" + ], + "properties": { + "registry_binding": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/registryBinding"}, + "task_binding": {"$ref": "#/$defs/taskBinding"}, + "program_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/programId"}, + "capability_binding": {"$ref": "#/$defs/capabilityBinding"}, + "snapshot_binding": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/snapshotBinding"}, + "circle_binding": {"$ref": "#/$defs/circleBinding"}, + "execution_specification_binding": {"$ref": "#/$defs/specificationBinding"}, + "job_binding": {"$ref": "#/$defs/jobBinding"}, + "job_outcome_binding": {"$ref": "#/$defs/jobOutcomeBinding"}, + "agent_result_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "wardPass": { + "type": "object", + "additionalProperties": false, + "required": [ + "status", + "ward_decision_id", + "ward_decision_sigil", + "resolved_permission_set_sigil", + "evaluated_chronicle_head", + "evaluated_at" + ], + "properties": { + "status": {"const": "PASS"}, + "ward_decision_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/wardDecisionId"}, + "ward_decision_sigil": {"$ref": "#/$defs/sigil"}, + "resolved_permission_set_sigil": {"$ref": "#/$defs/sigil"}, + "evaluated_chronicle_head": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/chronicleHeadRef"}, + "evaluated_at": {"$ref": "#/$defs/timestamp"} + } + }, + "approvalNotRequired": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "ward_decision_id", "ward_decision_sigil"], + "properties": { + "kind": {"const": "NOT_REQUIRED"}, + "ward_decision_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/wardDecisionId"}, + "ward_decision_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "approvalRequired": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "ward_decision_id", + "ward_decision_sigil", + "approval_policy_id", + "approval_policy_version", + "approval_policy_sigil", + "approval_subject_id", + "approval_subject_sigil", + "approval_event_id", + "approval_event_body_sigil", + "approval_receipt_id", + "approval_receipt_sigil" + ], + "properties": { + "kind": {"const": "REQUIRED"}, + "ward_decision_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/wardDecisionId"}, + "ward_decision_sigil": {"$ref": "#/$defs/sigil"}, + "approval_policy_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/approvalPolicyId"}, + "approval_policy_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, + "approval_policy_sigil": {"$ref": "#/$defs/sigil"}, + "approval_subject_id": {"$ref": "https://benchwork.dev/schemas/execution-approval-subject/1.0#/$defs/approvalSubjectId"}, + "approval_subject_sigil": {"$ref": "#/$defs/sigil"}, + "approval_event_id": {"$ref": "#/$defs/eventId"}, + "approval_event_body_sigil": {"$ref": "#/$defs/sigil"}, + "approval_receipt_id": {"$ref": "#/$defs/receiptId"}, + "approval_receipt_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "approvalEvidence": { + "oneOf": [ + {"$ref": "#/$defs/approvalNotRequired"}, + {"$ref": "#/$defs/approvalRequired"} + ] + }, + "acceptanceBlobValidation": { + "type": "object", + "additionalProperties": false, + "required": [ + "blob_sigil", + "size_bytes", + "replica_id", + "backend_id", + "backend_generation", + "availability_event", + "integrity_evidence_sigil", + "quarantine_status" + ], + "properties": { + "blob_sigil": {"$ref": "#/$defs/sigil"}, + "size_bytes": {"$ref": "#/$defs/u63"}, + "replica_id": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/replicaId"}, + "backend_id": {"$ref": "#/$defs/opaque"}, + "backend_generation": {"$ref": "#/$defs/opaque"}, + "availability_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, + "integrity_evidence_sigil": {"$ref": "#/$defs/sigil"}, + "quarantine_status": {"const": "CLEAR"} + } + }, + "acceptanceStorageBinding": { + "type": "object", + "additionalProperties": false, + "required": [ + "storage_event", + "storage_state_sigil", + "validated_blob_sigils", + "validation_evidence", + "validation_evidence_set_sigil" + ], + "properties": { + "storage_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, + "storage_state_sigil": {"$ref": "#/$defs/sigil"}, + "validated_blob_sigils": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "#/$defs/sigil"} + }, + "validation_evidence": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "#/$defs/acceptanceBlobValidation"} + }, + "validation_evidence_set_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/agent-result-acceptance-policy-1.0.json b/schemas/agent-result-acceptance-policy-1.0.json new file mode 100644 index 0000000..2328a34 --- /dev/null +++ b/schemas/agent-result-acceptance-policy-1.0.json @@ -0,0 +1,85 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/agent-result-acceptance-policy/1.0", + "title": "Agent Result Acceptance Policy v1", + "description": "Closed RFC-0015 immutable predicate inventory. Validity proves only the exact policy record and self-Sigil; it does not execute a predicate or authorize an Agent Result transition.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "policy_id", + "policy_version", + "canonical_event_type", + "transition_request_schema", + "authorization_schema", + "agent_result_schema", + "job_outcome_schema", + "reference_intent_schema", + "chronicle_event_schema", + "receipt_schema", + "ward_evaluator_profile", + "actor_authentication_profile", + "predicate_profile", + "predicates", + "policy_sigil" + ], + "properties": { + "schema_version": {"const": "agent-result-acceptance-policy/1.0"}, + "policy_id": {"const": "agent-result-acceptance"}, + "policy_version": {"const": "1.0"}, + "canonical_event_type": {"const": "agent-result.accepted"}, + "transition_request_schema": { + "const": "agent-result-acceptance-transition-request/1.0" + }, + "authorization_schema": { + "const": "agent-result-acceptance-authorization/1.0" + }, + "agent_result_schema": {"const": "agent-result/2.0"}, + "job_outcome_schema": {"const": "execution-job-outcome/1.0"}, + "reference_intent_schema": { + "const": "artifact-storage-reference-intent/1.0" + }, + "chronicle_event_schema": {"const": "chronicle-event/1.1"}, + "receipt_schema": {"const": "receipt/1.1"}, + "ward_evaluator_profile": { + "const": "sanctum-authority-intersection/1.0" + }, + "actor_authentication_profile": { + "const": "mcp-authenticated-invocation/1.0" + }, + "predicate_profile": { + "const": "agent-result-acceptance-predicates/1.0" + }, + "predicates": { + "type": "array", + "minItems": 16, + "maxItems": 16, + "prefixItems": [ + {"const": "EXPECTED_HEAD_ADMISSIBLE"}, + {"const": "AUTHENTICATED_INVOCATION_MATCH"}, + {"const": "TASK_AUTHORITY_CHAIN_VALID"}, + {"const": "CURRENT_WARD_PASS"}, + {"const": "APPROVAL_CHAIN_VALID"}, + {"const": "OUTCOME_REDERIVATION_MATCH"}, + {"const": "TERMINAL_SUCCESS_ELIGIBLE"}, + {"const": "EXECUTION_EVIDENCE_VALID"}, + {"const": "BUDGET_SETTLED"}, + {"const": "ASSURANCE_EVIDENCE_VALID"}, + {"const": "STORAGE_OBSERVATION_VALID"}, + {"const": "TERMINAL_SOURCE_VALID"}, + {"const": "EVIDENCE_SELECTION_FINAL"}, + {"const": "AGENT_RESULT_DERIVATION_MATCH"}, + {"const": "REFERENCE_SET_CLOSURE_VALID"}, + {"const": "ACCEPTANCE_STORAGE_PREFIX_VALID"} + ], + "items": false + }, + "policy_sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$", + "minLength": 71, + "maxLength": 71 + } + } +} + diff --git a/schemas/agent-result-acceptance-transition-request-1.0.json b/schemas/agent-result-acceptance-transition-request-1.0.json new file mode 100644 index 0000000..fd21e4c --- /dev/null +++ b/schemas/agent-result-acceptance-transition-request-1.0.json @@ -0,0 +1,12 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", + "$id":"https://benchwork.dev/schemas/agent-result-acceptance-transition-request/1.0", + "title":"Agent Result Acceptance Transition Request v1", + "description":"Closed RFC-0015 immutable Athanor candidate. Contract-only validation does not authenticate a live caller, resolve authority, or commit Chronicle.", + "type":"object","additionalProperties":false, + "required":["schema_version","transition_request_id","event_type","expected_chronicle_head","agent_result","job_outcome_binding","acceptance_request_sigil","idempotency_key_sigil","reference_sets","managed_blob_sigils","acceptance_storage_binding","actor","host_invocation","chronicle_actor","acceptance_authorization","authorization_sigil","requested_at","transition_request_sigil"], + "properties":{ + "schema_version":{"const":"agent-result-acceptance-transition-request/1.0"},"transition_request_id":{"$ref":"#/$defs/transitionRequestId"},"event_type":{"const":"agent-result.accepted"},"expected_chronicle_head":{"$ref":"https://benchwork.dev/schemas/execution-job/1.0#/$defs/chronicleHeadRef"},"agent_result":{"$ref":"https://benchwork.dev/schemas/agent-result/2.0"},"job_outcome_binding":{"$ref":"https://benchwork.dev/schemas/agent-result-acceptance-authorization/1.0#/$defs/jobOutcomeBinding"},"acceptance_request_sigil":{"$ref":"#/$defs/sigil"},"idempotency_key_sigil":{"$ref":"#/$defs/sigil"},"reference_sets":{"type":"array","minItems":1,"maxItems":1,"uniqueItems":true,"items":{"$ref":"https://benchwork.dev/schemas/artifact-storage-reference-intent/1.0#/$defs/referenceSetRef"}},"managed_blob_sigils":{"type":"array","minItems":1,"maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}},"acceptance_storage_binding":{"$ref":"https://benchwork.dev/schemas/agent-result-acceptance-authorization/1.0#/$defs/acceptanceStorageBinding"},"actor":{"$ref":"https://benchwork.dev/schemas/execution-cancel-request/1.0#/$defs/actor_binding"},"host_invocation":{"$ref":"https://benchwork.dev/schemas/execution-cancel-request/1.0#/$defs/host_invocation_binding"},"chronicle_actor":{"$ref":"https://benchwork.dev/schemas/actor/1.0"},"acceptance_authorization":{"$ref":"https://benchwork.dev/schemas/agent-result-acceptance-authorization/1.0"},"authorization_sigil":{"$ref":"#/$defs/sigil"},"requested_at":{"$ref":"https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"},"transition_request_sigil":{"$ref":"#/$defs/sigil"} + }, + "$defs":{"sigil":{"$ref":"https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"},"transitionRequestId":{"type":"string","pattern":"^ATR-[A-F0-9]{64}$","minLength":68,"maxLength":68}} +} diff --git a/schemas/agent-result-record-2.0.json b/schemas/agent-result-record-2.0.json new file mode 100644 index 0000000..c4d5d52 --- /dev/null +++ b/schemas/agent-result-record-2.0.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/agent-result-record/2.0", + "title": "Accepted Agent Result Record v2", + "description": "Closed RFC-0015 replay projection. Schema validation alone does not verify a Chronicle prefix or grant scientific acceptance authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "task_id", "program_id", "task_capsule_sigil", "host_identity_sigil", "capability_binding", "snapshot_binding", "job_binding", "execution_specification_binding", "job_outcome_binding", "terminal_event_sigil", "selected_attempt_id", "assurance_claim_sigil", "canonical_reference_binding", "terminal_source_binding", "outputs", "provenance", "status", "agent_result_sigil", "accepted_at", "acceptance_receipt"], + "properties": { + "schema_version": {"const": "agent-result-record/2.0"}, + "task_id": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/task_id"}, + "program_id": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/program_id"}, + "task_capsule_sigil": {"$ref": "#/$defs/sigil"}, + "host_identity_sigil": {"$ref": "#/$defs/sigil"}, + "capability_binding": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/capability_binding"}, + "snapshot_binding": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/snapshot_binding"}, + "job_binding": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/job_binding"}, + "execution_specification_binding": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/execution_specification_binding"}, + "job_outcome_binding": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/job_outcome_binding"}, + "terminal_event_sigil": {"$ref": "#/$defs/sigil"}, + "selected_attempt_id": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/selected_attempt_id"}, + "assurance_claim_sigil": {"$ref": "#/$defs/sigil"}, + "canonical_reference_binding": {"$ref": "#/$defs/canonicalReferenceBinding"}, + "terminal_source_binding": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/terminal_source_binding"}, + "outputs": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/properties/outputs"}, + "provenance": {"$ref": "https://benchwork.dev/schemas/agent-result/2.0#/$defs/provenance"}, + "status": {"const": "COMPLETED"}, + "agent_result_sigil": {"$ref": "#/$defs/sigil"}, + "accepted_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "acceptance_receipt": {"$ref": "#/$defs/receiptId"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "receiptId": {"type": "string", "pattern": "^RC-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "canonicalReferenceBinding": { + "type": "object", "additionalProperties": false, + "required": ["reference_intent_id", "reference_intent_record_sigil", "transition_request_id", "transition_request_sigil", "acceptance_storage_binding", "reference_set_id", "reference_set_sigil"], + "properties": { + "reference_intent_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-reference-intent/1.0#/$defs/intentId"}, + "reference_intent_record_sigil": {"$ref": "#/$defs/sigil"}, + "transition_request_id": {"$ref": "https://benchwork.dev/schemas/agent-result-acceptance-transition-request/1.0#/$defs/transitionRequestId"}, + "transition_request_sigil": {"$ref": "#/$defs/sigil"}, + "acceptance_storage_binding": {"$ref": "https://benchwork.dev/schemas/agent-result-acceptance-authorization/1.0#/$defs/acceptanceStorageBinding"}, + "reference_set_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-reference-intent/1.0#/$defs/referenceSetId"}, + "reference_set_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} diff --git a/schemas/artifact-blob-1.0.json b/schemas/artifact-blob-1.0.json new file mode 100644 index 0000000..8a2e340 --- /dev/null +++ b/schemas/artifact-blob-1.0.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-blob/1.0", + "title": "Artifact Blob v1", + "description": "Closed RFC-0013 artifact-blob/1.0 replay projection. This contract-only increment validates its self-contained record shape and internal collection relations; it does not read Blob bytes, resolve Storage Journal events, or calculate availability, policy, retention, integrity, or deadline state.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "blob_sigil", "size_bytes", "first_verified_at", "availability", "availability_as_of", "availability_basis_sigil", "effective_policy_set_sigil", "next_verification_due_at", "known_replica_ids", "eligible_replica_ids", "integrity_event_sigils", "media_type_observations", "filename_observations", "revision", "record_sigil"], + "properties": { + "schema_version": {"const": "artifact-blob/1.0"}, + "blob_sigil": {"$ref": "#/$defs/sigil"}, + "size_bytes": {"$ref": "#/$defs/u63"}, + "first_verified_at": {"$ref": "#/$defs/nullableTimestamp"}, + "availability": {"enum": ["AVAILABLE", "DEGRADED", "UNAVAILABLE", "INCIDENT"]}, + "availability_as_of": {"$ref": "#/$defs/eventRef"}, + "availability_basis_sigil": {"$ref": "#/$defs/sigil"}, + "effective_policy_set_sigil": {"$ref": "#/$defs/sigil"}, + "next_verification_due_at": {"$ref": "#/$defs/nullableTimestamp"}, + "known_replica_ids": {"$ref": "#/$defs/replicaIds"}, + "eligible_replica_ids": {"$ref": "#/$defs/replicaIds"}, + "integrity_event_sigils": {"$ref": "#/$defs/sigilSet"}, + "media_type_observations": {"$ref": "#/$defs/opaqueSet"}, + "filename_observations": {"$ref": "#/$defs/opaqueSet"}, + "revision": {"$ref": "#/$defs/positiveU63"}, + "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "nullableTimestamp": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, + "storageJournalId": {"type": "string", "pattern": "^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "storageEventId": {"type": "string", "pattern": "^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "replicaId": {"type": "string", "pattern": "^SR-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "opaque": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 256}, + "eventRef": { + "type": "object", "additionalProperties": false, + "required": ["journal_id", "event_id", "sequence", "event_sigil"], + "properties": { + "journal_id": {"$ref": "#/$defs/storageJournalId"}, + "event_id": {"$ref": "#/$defs/storageEventId"}, + "sequence": {"$ref": "#/$defs/positiveU63"}, + "event_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "replicaIds": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/replicaId"}}, + "sigilSet": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/sigil"}}, + "opaqueSet": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/opaque"}} + } +} + diff --git a/schemas/artifact-gc-plan-1.0.json b/schemas/artifact-gc-plan-1.0.json new file mode 100644 index 0000000..84e53ab --- /dev/null +++ b/schemas/artifact-gc-plan-1.0.json @@ -0,0 +1,17 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/artifact-gc-plan/1.0","title":"Artifact GC Plan v1","description":"Closed RFC-0013 artifact-gc-plan/1.0 contract; local shape and canonical-byte checks only.","type":"object","additionalProperties":false, + "required":["schema_version","gc_plan_id","policy_id","root_snapshot","extractor_suite_sigil","bounds","closure_proof","targets","created_at","grace_ends_at","record_sigil"], + "properties":{"schema_version":{"const":"artifact-gc-plan/1.0"},"gc_plan_id":{"$ref":"#/$defs/gcPlanId"},"policy_id":{"$ref":"#/$defs/policyId"},"root_snapshot":{"$ref":"#/$defs/gcRootSnapshot"},"extractor_suite_sigil":{"$ref":"#/$defs/sigil"},"bounds":{"$ref":"#/$defs/traversalBounds"},"closure_proof":{"$ref":"#/$defs/closureProof"},"targets":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/gcTarget"}},"created_at":{"$ref":"#/$defs/timestamp"},"grace_ends_at":{"$ref":"#/$defs/timestamp"},"record_sigil":{"$ref":"#/$defs/sigil"}}, + "$defs":{ + "sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"positiveU63":{"type":"integer","minimum":1,"maximum":9223372036854775807},"opaque":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"gcPlanId":{"type":"string","pattern":"^SG-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"policyId":{"type":"string","pattern":"^SP-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"replicaId":{"type":"string","pattern":"^SR-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"manifestId":{"type":"string","pattern":"^ESM-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"referenceSetId":{"type":"string","pattern":"^RS-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"holdId":{"type":"string","pattern":"^SH-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"journalId":{"type":"string","pattern":"^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"eventId":{"type":"string","pattern":"^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128}, + "eventRef":{"type":"object","additionalProperties":false,"required":["journal_id","event_id","sequence","event_sigil"],"properties":{"journal_id":{"$ref":"#/$defs/journalId"},"event_id":{"$ref":"#/$defs/eventId"},"sequence":{"$ref":"#/$defs/positiveU63"},"event_sigil":{"$ref":"#/$defs/sigil"}}},"chronicleHead":{"type":"object","additionalProperties":false,"required":["schema_version","event_count","terminal_receipt_sigil"],"properties":{"schema_version":{"const":"chronicle-head/1.1"},"event_count":{"$ref":"#/$defs/u63"},"terminal_receipt_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]}}}, + "executionStorageRoot":{"type":"object","additionalProperties":false,"required":["root_kind","job_id","attempt_id","storage_root_manifest_id","storage_root_manifest_sigil","reference_set_id","reference_set_sigil","hold_id","hold_set_event"],"properties":{"root_kind":{"enum":["JOB_INPUT","ATTEMPT_INPUT","ATTEMPT_OUTPUT"]},"job_id":{"$ref":"#/$defs/opaque"},"attempt_id":{"anyOf":[{"$ref":"#/$defs/opaque"},{"type":"null"}]},"storage_root_manifest_id":{"$ref":"#/$defs/manifestId"},"storage_root_manifest_sigil":{"$ref":"#/$defs/sigil"},"reference_set_id":{"$ref":"#/$defs/referenceSetId"},"reference_set_sigil":{"$ref":"#/$defs/sigil"},"hold_id":{"$ref":"#/$defs/holdId"},"hold_set_event":{"$ref":"#/$defs/eventRef"}}}, + "executionRootSnapshot":{"type":"object","additionalProperties":false,"required":["execution_journal_id","execution_event_count","execution_last_event_sigil","roots","root_set_sigil"],"properties":{"execution_journal_id":{"$ref":"#/$defs/opaque"},"execution_event_count":{"$ref":"#/$defs/u63"},"execution_last_event_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"roots":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/executionStorageRoot"}},"root_set_sigil":{"$ref":"#/$defs/sigil"}}}, + "gcRootSnapshot":{"type":"object","additionalProperties":false,"required":["chronicle_head","storage_event","execution_roots","hold_set_sigil","legacy_protection_set_sigil","reference_intent_set_sigil","reference_set_sigils","policy_set_sigil"],"properties":{"chronicle_head":{"$ref":"#/$defs/chronicleHead"},"storage_event":{"$ref":"#/$defs/eventRef"},"execution_roots":{"$ref":"#/$defs/executionRootSnapshot"},"hold_set_sigil":{"$ref":"#/$defs/sigil"},"legacy_protection_set_sigil":{"$ref":"#/$defs/sigil"},"reference_intent_set_sigil":{"$ref":"#/$defs/sigil"},"reference_set_sigils":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}},"policy_set_sigil":{"$ref":"#/$defs/sigil"}}}, + "traversalBounds":{"type":"object","additionalProperties":false,"required":["max_roots","max_nodes","max_edges","max_depth","max_control_record_bytes","max_wall_millis"],"properties":{"max_roots":{"$ref":"#/$defs/u63"},"max_nodes":{"$ref":"#/$defs/u63"},"max_edges":{"$ref":"#/$defs/u63"},"max_depth":{"$ref":"#/$defs/u63"},"max_control_record_bytes":{"$ref":"#/$defs/u63"},"max_wall_millis":{"$ref":"#/$defs/u63"}}}, + "closureProof":{"type":"object","additionalProperties":false,"required":["root_set_sigil","extractor_suite_sigil","bounds","visited_node_count","visited_edge_count","cycle_summary_sigil","reachable_blob_sigils","reachable_replica_ids","proof_sigil"],"properties":{"root_set_sigil":{"$ref":"#/$defs/sigil"},"extractor_suite_sigil":{"$ref":"#/$defs/sigil"},"bounds":{"$ref":"#/$defs/traversalBounds"},"visited_node_count":{"$ref":"#/$defs/u63"},"visited_edge_count":{"$ref":"#/$defs/u63"},"cycle_summary_sigil":{"$ref":"#/$defs/sigil"},"reachable_blob_sigils":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}},"reachable_replica_ids":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/replicaId"}},"proof_sigil":{"$ref":"#/$defs/sigil"}}}, + "blobRef":{"type":"object","additionalProperties":false,"required":["blob_sigil","size_bytes"],"properties":{"blob_sigil":{"$ref":"#/$defs/sigil"},"size_bytes":{"$ref":"#/$defs/u63"}}},"backendObjectRef":{"type":"object","additionalProperties":false,"required":["backend_id","object_identity_sigil","locator_sigil","generation","size_bytes","blob_sigil"],"properties":{"backend_id":{"$ref":"#/$defs/opaque"},"object_identity_sigil":{"$ref":"#/$defs/sigil"},"locator_sigil":{"$ref":"#/$defs/sigil"},"generation":{"$ref":"#/$defs/opaque"},"size_bytes":{"$ref":"#/$defs/u63"},"blob_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]}}}, + "gcTarget":{"type":"object","additionalProperties":false,"required":["target_id","replica_id","blob","backend_object","reason_code","expected_remaining_replica_ids"],"properties":{"target_id":{"$ref":"#/$defs/opaque"},"replica_id":{"$ref":"#/$defs/replicaId"},"blob":{"$ref":"#/$defs/blobRef"},"backend_object":{"$ref":"#/$defs/backendObjectRef"},"reason_code":{"enum":["AUTHORIZATION_DENIED","BACKEND_AMBIGUOUS","BACKEND_CONFLICT","BACKEND_UNAVAILABLE","BOUNDS_EXCEEDED","CANCELLED","CHRONICLE_REFERENCE_CHANGED","CLOCK_UNCERTAIN","CONFLICT","CORRUPT","DESTINATION_CONFLICT","DISPOSITION_EXPIRED","DURABILITY_UNVERIFIED","EXECUTION_HOLD_LIFETIME_EXPIRED","EXECUTION_ROOT_ORPHAN_ABORTED","EXECUTION_ROOT_OWNER_TERMINATED","FENCE_REJECTED","GC_ROOT_CHANGED","GENERATION_MISMATCH","HASH_MISMATCH","INTEGRITY_FAILURE","INVALID_MESSAGE","LEASE_EXPIRED","LEGACY_PROTECTION_FAILED","MINIMUM_REPLICA_VIOLATION","OPERATIONAL_ROOT_TERMINATED","PAYLOAD_LOST","POLICY_REJECTED","QUARANTINE_RESERVATION_FAILED","QUOTA_EXHAUSTED","RECOVERY_INTERRUPTED_PRECOMMIT","RECOVERY_PAYLOAD_LOST","RETENTION_BLOCKED","SOURCE_CHANGED","TAIL_INCOMPLETE","TIMEOUT","UNKNOWN_SCHEMA","UNSAFE_PATH","VERIFICATION_FAILED"]},"expected_remaining_replica_ids":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/replicaId"}}}} + } +} + diff --git a/schemas/artifact-materialization-1.0.json b/schemas/artifact-materialization-1.0.json new file mode 100644 index 0000000..6967ab2 --- /dev/null +++ b/schemas/artifact-materialization-1.0.json @@ -0,0 +1,27 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", + "$id":"https://benchwork.dev/schemas/artifact-materialization/1.0", + "title":"Artifact Materialization v1", + "description":"Closed RFC-0013 artifact-materialization/1.0 wire contract. Local validation only; referenced records, state history, capacity, and runtime effects are not resolved.", + "type":"object","additionalProperties":false, + "required":["schema_version","materialization_id","source_blob_sigil","source_replica_id","source_verification_sigil","destination_class","destination_sigil","task_id","attempt_id","access_mode","bounds","reservation","destination_staging_object","commit_intent","residual_staging_cleanup","state","verification","cleanup","created_at","terminal_at","revision","record_sigil"], + "properties":{ + "schema_version":{"const":"artifact-materialization/1.0"},"materialization_id":{"$ref":"#/$defs/materializationId"},"source_blob_sigil":{"$ref":"#/$defs/sigil"},"source_replica_id":{"$ref":"#/$defs/replicaId"},"source_verification_sigil":{"$ref":"#/$defs/sigil"},"destination_class":{"enum":["SANCTUM_INPUT","CRUCIBLE_WORKSPACE","PROJECT_EXPORT"]},"destination_sigil":{"$ref":"#/$defs/sigil"},"task_id":{"anyOf":[{"$ref":"#/$defs/opaque"},{"type":"null"}]},"attempt_id":{"anyOf":[{"$ref":"#/$defs/opaque"},{"type":"null"}]},"access_mode":{"enum":["READ_ONLY","COPY_ON_WRITE","WRITABLE_COPY"]},"bounds":{"$ref":"#/$defs/transferBounds"},"reservation":{"$ref":"#/$defs/reservationRef"},"destination_staging_object":{"anyOf":[{"$ref":"#/$defs/backendObjectRef"},{"type":"null"}]},"commit_intent":{"anyOf":[{"$ref":"#/$defs/materializationCommitIntent"},{"type":"null"}]},"residual_staging_cleanup":{"$ref":"#/$defs/residualStagingCleanup"},"state":{"enum":["PREPARED","STREAMING","VERIFYING","COMMITTING","AVAILABLE","CLEANING","CLEANED","CLEANUP_FAILED","FAILED","QUARANTINED"]},"verification":{"anyOf":[{"$ref":"#/$defs/verificationRef"},{"type":"null"}]},"cleanup":{"$ref":"#/$defs/cleanupResult"},"created_at":{"$ref":"#/$defs/timestamp"},"terminal_at":{"anyOf":[{"$ref":"#/$defs/timestamp"},{"type":"null"}]},"revision":{"$ref":"#/$defs/positiveU63"},"record_sigil":{"$ref":"#/$defs/sigil"} + }, + "$defs":{ + "sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"positiveU63":{"type":"integer","minimum":1,"maximum":9223372036854775807},"u64":{"type":"integer","minimum":0,"maximum":18446744073709551615},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"opaque":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256},"materializationId":{"type":"string","pattern":"^SM-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128},"replicaId":{"type":"string","pattern":"^SR-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, + "blobRef":{"type":"object","additionalProperties":false,"required":["blob_sigil","size_bytes"],"properties":{"blob_sigil":{"$ref":"#/$defs/sigil"},"size_bytes":{"$ref":"#/$defs/u63"}}}, + "transferBounds":{"type":"object","additionalProperties":false,"required":["max_bytes","max_duration_millis","max_file_count","max_chunk_count","buffer_bytes"],"properties":{"max_bytes":{"$ref":"#/$defs/u63"},"max_duration_millis":{"$ref":"#/$defs/u63"},"max_file_count":{"anyOf":[{"$ref":"#/$defs/u63"},{"type":"null"}]},"max_chunk_count":{"$ref":"#/$defs/u63"},"buffer_bytes":{"$ref":"#/$defs/positiveU63"}}}, + "quotaClaim":{"type":"object","additionalProperties":false,"required":["quota_class","byte_count","object_count","inode_count","stream_count","journal_bytes","control_record_bytes"],"properties":{"quota_class":{"enum":["JOURNAL","CONTROL_RECORD","STAGING","QUARANTINE","COMMITTED","MATERIALIZATION","STREAM","INODE"]},"byte_count":{"$ref":"#/$defs/u63"},"object_count":{"$ref":"#/$defs/u63"},"inode_count":{"$ref":"#/$defs/u63"},"stream_count":{"$ref":"#/$defs/u63"},"journal_bytes":{"$ref":"#/$defs/u63"},"control_record_bytes":{"$ref":"#/$defs/u63"}}}, + "capacityPlan":{"type":"object","additionalProperties":false,"required":["allowed_event_types","max_event_frame_count","max_control_record_count","max_recovery_evidence_count","max_event_frame_bytes","max_control_record_bytes","max_recovery_evidence_bytes"],"properties":{"allowed_event_types":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"type":"string","pattern":"^[a-z][a-z0-9_]*(?:[.][a-z][a-z0-9_]*)+$"}},"max_event_frame_count":{"$ref":"#/$defs/positiveU63"},"max_control_record_count":{"$ref":"#/$defs/u63"},"max_recovery_evidence_count":{"$ref":"#/$defs/u63"},"max_event_frame_bytes":{"$ref":"#/$defs/positiveU63"},"max_control_record_bytes":{"$ref":"#/$defs/positiveU63"},"max_recovery_evidence_bytes":{"$ref":"#/$defs/positiveU63"}}}, + "clockRef":{"type":"object","additionalProperties":false,"required":["utc","monotonic_anchor_id","monotonic_ticks","monotonic_frequency_hz","uncertainty_micros","observation_sigil"],"properties":{"utc":{"$ref":"#/$defs/timestamp"},"monotonic_anchor_id":{"$ref":"#/$defs/opaque"},"monotonic_ticks":{"$ref":"#/$defs/u63"},"monotonic_frequency_hz":{"$ref":"#/$defs/positiveU63"},"uncertainty_micros":{"$ref":"#/$defs/u63"},"observation_sigil":{"$ref":"#/$defs/sigil"}}}, + "reservationRef":{"type":"object","additionalProperties":false,"required":["reservation_id","claims","capacity_plan","expires_at","created_clock","remaining_micros_at_creation"],"properties":{"reservation_id":{"$ref":"#/$defs/opaque"},"claims":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/quotaClaim"}},"capacity_plan":{"$ref":"#/$defs/capacityPlan"},"expires_at":{"anyOf":[{"$ref":"#/$defs/timestamp"},{"type":"null"}]},"created_clock":{"$ref":"#/$defs/clockRef"},"remaining_micros_at_creation":{"anyOf":[{"$ref":"#/$defs/u63"},{"type":"null"}]}}}, + "backendObjectRef":{"type":"object","additionalProperties":false,"required":["backend_id","object_identity_sigil","locator_sigil","generation","size_bytes","blob_sigil"],"properties":{"backend_id":{"$ref":"#/$defs/opaque"},"object_identity_sigil":{"$ref":"#/$defs/sigil"},"locator_sigil":{"$ref":"#/$defs/sigil"},"generation":{"$ref":"#/$defs/opaque"},"size_bytes":{"$ref":"#/$defs/u63"},"blob_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]}}}, + "fence":{"type":"object","additionalProperties":false,"required":["execution_journal_id","executor_epoch","job_id","attempt_id","lease_id","fencing_generation","execution_event_sigil","job_fence_floor","tombstone_present"],"properties":{"execution_journal_id":{"$ref":"#/$defs/opaque"},"executor_epoch":{"$ref":"#/$defs/u64"},"job_id":{"$ref":"#/$defs/opaque"},"attempt_id":{"$ref":"#/$defs/opaque"},"lease_id":{"$ref":"#/$defs/opaque"},"fencing_generation":{"$ref":"#/$defs/u64"},"execution_event_sigil":{"$ref":"#/$defs/sigil"},"job_fence_floor":{"$ref":"#/$defs/u64"},"tombstone_present":{"type":"boolean"}}}, + "materializationCommitIntent":{"type":"object","additionalProperties":false,"required":["intent_id","staging_object","destination_object","expected_blob","destination_identity_sigil","execution_fence","reservation","recorded_clock"],"properties":{"intent_id":{"$ref":"#/$defs/opaque"},"staging_object":{"$ref":"#/$defs/backendObjectRef"},"destination_object":{"$ref":"#/$defs/backendObjectRef"},"expected_blob":{"$ref":"#/$defs/blobRef"},"destination_identity_sigil":{"$ref":"#/$defs/sigil"},"execution_fence":{"anyOf":[{"$ref":"#/$defs/fence"},{"type":"null"}]},"reservation":{"$ref":"#/$defs/reservationRef"},"recorded_clock":{"$ref":"#/$defs/clockRef"}}}, + "reason":{"type":"object","additionalProperties":false,"required":["code","evidence_sigils"],"properties":{"code":{"enum":["AUTHORIZATION_DENIED","BACKEND_AMBIGUOUS","BACKEND_CONFLICT","BACKEND_UNAVAILABLE","BOUNDS_EXCEEDED","CANCELLED","CHRONICLE_REFERENCE_CHANGED","CLOCK_UNCERTAIN","CONFLICT","CORRUPT","DESTINATION_CONFLICT","DISPOSITION_EXPIRED","DURABILITY_UNVERIFIED","EXECUTION_HOLD_LIFETIME_EXPIRED","EXECUTION_ROOT_ORPHAN_ABORTED","EXECUTION_ROOT_OWNER_TERMINATED","FENCE_REJECTED","GC_ROOT_CHANGED","GENERATION_MISMATCH","HASH_MISMATCH","INTEGRITY_FAILURE","INVALID_MESSAGE","LEASE_EXPIRED","LEGACY_PROTECTION_FAILED","MINIMUM_REPLICA_VIOLATION","OPERATIONAL_ROOT_TERMINATED","PAYLOAD_LOST","POLICY_REJECTED","QUARANTINE_RESERVATION_FAILED","QUOTA_EXHAUSTED","RECOVERY_INTERRUPTED_PRECOMMIT","RECOVERY_PAYLOAD_LOST","RETENTION_BLOCKED","SOURCE_CHANGED","TAIL_INCOMPLETE","TIMEOUT","UNKNOWN_SCHEMA","UNSAFE_PATH","VERIFICATION_FAILED"]},"evidence_sigils":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}}}}, + "residualStagingCleanup":{"type":"object","additionalProperties":false,"required":["state","staging_object","evidence_sigil","reason"],"properties":{"state":{"enum":["NOT_REQUIRED","PENDING","CLEANED","FAILED","HELD_FOR_DISPOSITION"]},"staging_object":{"anyOf":[{"$ref":"#/$defs/backendObjectRef"},{"type":"null"}]},"evidence_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"reason":{"anyOf":[{"$ref":"#/$defs/reason"},{"type":"null"}]}}}, + "cleanupResult":{"type":"object","additionalProperties":false,"required":["state","evidence_sigil","reason"],"properties":{"state":{"enum":["NOT_REQUIRED","PENDING","CLEANED","FAILED"]},"evidence_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"reason":{"anyOf":[{"$ref":"#/$defs/reason"},{"type":"null"}]}}}, + "verificationRef":{"type":"object","additionalProperties":false,"required":["method","evidence_sigil","verified_at","next_due_at"],"properties":{"method":{"enum":["FULL_READBACK_SHA256","CONFORMANCE_END_TO_END"]},"evidence_sigil":{"$ref":"#/$defs/sigil"},"verified_at":{"$ref":"#/$defs/timestamp"},"next_due_at":{"anyOf":[{"$ref":"#/$defs/timestamp"},{"type":"null"}]}}} + } +} diff --git a/schemas/artifact-provenance-1.0.json b/schemas/artifact-provenance-1.0.json new file mode 100644 index 0000000..64d0f86 --- /dev/null +++ b/schemas/artifact-provenance-1.0.json @@ -0,0 +1,77 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-provenance/1.0", + "title": "Artifact Provenance v1", + "description": "Closed RFC-0013 artifact-provenance/1.0 record. This contract-only increment validates local wire shape and local canonical collections; it does not resolve records, authorization, time causality, or runtime state.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "provenance_id", "relation", "blob", "source", "destination", "actor_id", "authorization_sigil", "execution", "backend", "transfer", "provenance_policy", "verifications", "transformation", "times", "terminal_reason", "record_sigil"], + "properties": { + "schema_version": {"const": "artifact-provenance/1.0"}, + "provenance_id": {"$ref": "#/$defs/opaque"}, + "relation": {"enum": ["CAPTURED", "IMPORTED", "COPIED", "DERIVED", "EXPORTED", "MATERIALIZED", "VERIFIED", "DELETED"]}, + "blob": {"$ref": "#/$defs/blobRef"}, + "source": {"$ref": "#/$defs/sourceDescriptor"}, + "destination": {"$ref": "#/$defs/destinationDescriptor"}, + "actor_id": {"$ref": "#/$defs/opaque"}, + "authorization_sigil": {"$ref": "#/$defs/sigil"}, + "execution": {"$ref": "#/$defs/executionContext"}, + "backend": {"$ref": "#/$defs/backendRef"}, + "transfer": {"$ref": "#/$defs/transferRef"}, + "provenance_policy": {"$ref": "#/$defs/provenancePolicyRef"}, + "verifications": {"type": "array", "minItems": 1, "maxItems": 4096, "items": {"$ref": "#/$defs/provenanceVerification"}}, + "transformation": {"$ref": "#/$defs/transformationRef"}, + "times": {"$ref": "#/$defs/timeSet"}, + "terminal_reason": {"anyOf": [{"$ref": "#/$defs/reason"}, {"type": "null"}]}, + "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "opaque": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 256}, + "operationalId": {"type": "string", "pattern": "^[A-Z]+-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 3, "maxLength": 128}, + "replicaId": {"type": "string", "pattern": "^SR-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "provenancePolicyId": {"type": "string", "pattern": "^SPP-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "transferId": {"type": "string", "pattern": "^ST-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, + "transferAttemptId": {"type": "string", "pattern": "^SA-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, + "journalId": {"type": "string", "pattern": "^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, + "eventId": {"type": "string", "pattern": "^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, + "materializationId": {"type": "string", "pattern": "^SM-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, + "blobRef": {"type": "object", "additionalProperties": false, "required": ["blob_sigil", "size_bytes"], "properties": {"blob_sigil": {"$ref": "#/$defs/sigil"}, "size_bytes": {"$ref": "#/$defs/u63"}}}, + "backendRef": {"type": "object", "additionalProperties": false, "required": ["backend_id", "backend_profile_version", "backend_profile_sigil"], "properties": {"backend_id": {"$ref": "#/$defs/opaque"}, "backend_profile_version": {"$ref": "#/$defs/opaque"}, "backend_profile_sigil": {"$ref": "#/$defs/sigil"}}}, + "backendObjectRef": {"type": "object", "additionalProperties": false, "required": ["backend_id", "object_identity_sigil", "locator_sigil", "generation", "size_bytes", "blob_sigil"], "properties": {"backend_id": {"$ref": "#/$defs/opaque"}, "object_identity_sigil": {"$ref": "#/$defs/sigil"}, "locator_sigil": {"$ref": "#/$defs/sigil"}, "generation": {"$ref": "#/$defs/opaque"}, "size_bytes": {"$ref": "#/$defs/u63"}, "blob_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}}}, + "executionFenceRef": {"type": "object", "additionalProperties": false, "required": ["execution_journal_id", "executor_epoch", "job_id", "attempt_id", "lease_id", "fencing_generation", "execution_event_sigil", "job_fence_floor", "tombstone_present"], "properties": {"execution_journal_id": {"$ref": "#/$defs/opaque"}, "executor_epoch": {"$ref": "#/$defs/u64"}, "job_id": {"$ref": "#/$defs/opaque"}, "attempt_id": {"$ref": "#/$defs/opaque"}, "lease_id": {"$ref": "#/$defs/opaque"}, "fencing_generation": {"$ref": "#/$defs/u64"}, "execution_event_sigil": {"$ref": "#/$defs/sigil"}, "job_fence_floor": {"$ref": "#/$defs/u64"}, "tombstone_present": {"type": "boolean"}}}, + "executionContext": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "execution_journal_id", "executor_epoch", "job_id", "attempt_id"], "properties": {"kind": {"const": "ATTEMPT"}, "execution_journal_id": {"$ref": "#/$defs/opaque"}, "executor_epoch": {"$ref": "#/$defs/u64"}, "job_id": {"$ref": "#/$defs/opaque"}, "attempt_id": {"$ref": "#/$defs/opaque"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "execution_journal_id", "executor_epoch", "job_id", "attempt_id", "lease_id", "worker_id", "worker_session_id", "fence"], "properties": {"kind": {"const": "LEASED"}, "execution_journal_id": {"$ref": "#/$defs/opaque"}, "executor_epoch": {"$ref": "#/$defs/u64"}, "job_id": {"$ref": "#/$defs/opaque"}, "attempt_id": {"$ref": "#/$defs/opaque"}, "lease_id": {"$ref": "#/$defs/opaque"}, "worker_id": {"$ref": "#/$defs/opaque"}, "worker_session_id": {"$ref": "#/$defs/opaque"}, "fence": {"$ref": "#/$defs/executionFenceRef"}}} + ]}, + "sourceDescriptor": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind", "authorization_scope_sigil", "lexical_identity_sigil", "resolved_file_identity_sigil"], "properties": {"kind": {"const": "LOCAL_FILE"}, "authorization_scope_sigil": {"$ref": "#/$defs/sigil"}, "lexical_identity_sigil": {"$ref": "#/$defs/sigil"}, "resolved_file_identity_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "blob", "replica_id", "verification_sigil"], "properties": {"kind": {"const": "REPLICA"}, "blob": {"$ref": "#/$defs/blobRef"}, "replica_id": {"$ref": "#/$defs/replicaId"}, "verification_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "execution", "output_handle_id"], "properties": {"kind": {"const": "ATTEMPT_OUTPUT"}, "execution": {"$ref": "#/$defs/executionContext"}, "output_handle_id": {"$ref": "#/$defs/opaque"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "source_class", "sanitized_identity_sigil", "authorization_sigil"], "properties": {"kind": {"const": "EXTERNAL"}, "source_class": {"$ref": "#/$defs/opaque"}, "sanitized_identity_sigil": {"$ref": "#/$defs/sigil"}, "authorization_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "transfer_attempt_id", "object"], "properties": {"kind": {"const": "STAGING"}, "transfer_attempt_id": {"$ref": "#/$defs/transferAttemptId"}, "object": {"$ref": "#/$defs/backendObjectRef"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "artifact_id", "receipt_sigil", "location_sigil"], "properties": {"kind": {"const": "LEGACY_ARTIFACT"}, "artifact_id": {"$ref": "#/$defs/opaque"}, "receipt_sigil": {"$ref": "#/$defs/sigil"}, "location_sigil": {"$ref": "#/$defs/sigil"}}} + ]}, + "destinationDescriptor": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind", "backend"], "properties": {"kind": {"const": "MANAGED_BACKEND"}, "backend": {"$ref": "#/$defs/backendRef"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "destination_class", "destination_identity_sigil", "authorization_sigil"], "properties": {"kind": {"const": "EXPORT"}, "destination_class": {"$ref": "#/$defs/opaque"}, "destination_identity_sigil": {"$ref": "#/$defs/sigil"}, "authorization_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "materialization_id", "destination_class", "destination_identity_sigil"], "properties": {"kind": {"const": "MATERIALIZATION"}, "materialization_id": {"$ref": "#/$defs/materializationId"}, "destination_class": {"$ref": "#/$defs/opaque"}, "destination_identity_sigil": {"$ref": "#/$defs/sigil"}}} + ]}, + "eventRef": {"type": "object", "additionalProperties": false, "required": ["journal_id", "event_id", "sequence", "event_sigil"], "properties": {"journal_id": {"$ref": "#/$defs/journalId"}, "event_id": {"$ref": "#/$defs/eventId"}, "sequence": {"$ref": "#/$defs/positiveU63"}, "event_sigil": {"$ref": "#/$defs/sigil"}}}, + "transferRef": {"type": "object", "additionalProperties": false, "required": ["transfer_id", "transfer_attempt_id", "request_record_sigil", "attempt_record_sigil", "terminal_event"], "properties": {"transfer_id": {"$ref": "#/$defs/transferId"}, "transfer_attempt_id": {"$ref": "#/$defs/transferAttemptId"}, "request_record_sigil": {"$ref": "#/$defs/sigil"}, "attempt_record_sigil": {"$ref": "#/$defs/sigil"}, "terminal_event": {"$ref": "#/$defs/eventRef"}}}, + "provenancePolicyRef": {"type": "object", "additionalProperties": false, "required": ["provenance_policy_id", "provenance_policy_sigil"], "properties": {"provenance_policy_id": {"$ref": "#/$defs/provenancePolicyId"}, "provenance_policy_sigil": {"$ref": "#/$defs/sigil"}}}, + "verificationRef": {"type": "object", "additionalProperties": false, "required": ["method", "evidence_sigil", "verified_at", "next_due_at"], "properties": {"method": {"enum": ["FULL_READBACK_SHA256", "CONFORMANCE_END_TO_END"]}, "evidence_sigil": {"$ref": "#/$defs/sigil"}, "verified_at": {"$ref": "#/$defs/timestamp"}, "next_due_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}}}, + "provenanceVerification": {"type": "object", "additionalProperties": false, "required": ["event", "replica_id", "blob", "backend", "backend_object", "verification"], "properties": {"event": {"$ref": "#/$defs/eventRef"}, "replica_id": {"$ref": "#/$defs/replicaId"}, "blob": {"$ref": "#/$defs/blobRef"}, "backend": {"$ref": "#/$defs/backendRef"}, "backend_object": {"$ref": "#/$defs/backendObjectRef"}, "verification": {"$ref": "#/$defs/verificationRef"}}}, + "transformationRef": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "contract_id", "contract_version", "implementation_sigil", "parameters_sigil", "input_blobs"], "properties": {"kind": {"const": "DERIVED"}, "contract_id": {"$ref": "#/$defs/opaque"}, "contract_version": {"$ref": "#/$defs/opaque"}, "implementation_sigil": {"$ref": "#/$defs/sigil"}, "parameters_sigil": {"$ref": "#/$defs/sigil"}, "input_blobs": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/blobRef"}}}} + ]}, + "timeSet": {"type": "object", "additionalProperties": false, "required": ["observed_at", "started_at", "committed_at", "verified_at", "terminal_at"], "properties": {"observed_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, "started_at": {"$ref": "#/$defs/timestamp"}, "committed_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, "verified_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, "terminal_at": {"$ref": "#/$defs/timestamp"}}}, + "reason": {"type": "object", "additionalProperties": false, "required": ["code", "evidence_sigils"], "properties": {"code": {"enum": ["AUTHORIZATION_DENIED", "BACKEND_AMBIGUOUS", "BACKEND_CONFLICT", "BACKEND_UNAVAILABLE", "BOUNDS_EXCEEDED", "CANCELLED", "CHRONICLE_REFERENCE_CHANGED", "CLOCK_UNCERTAIN", "CONFLICT", "CORRUPT", "DESTINATION_CONFLICT", "DISPOSITION_EXPIRED", "DURABILITY_UNVERIFIED", "EXECUTION_HOLD_LIFETIME_EXPIRED", "EXECUTION_ROOT_ORPHAN_ABORTED", "EXECUTION_ROOT_OWNER_TERMINATED", "FENCE_REJECTED", "GC_ROOT_CHANGED", "GENERATION_MISMATCH", "HASH_MISMATCH", "INTEGRITY_FAILURE", "INVALID_MESSAGE", "LEASE_EXPIRED", "LEGACY_PROTECTION_FAILED", "MINIMUM_REPLICA_VIOLATION", "OPERATIONAL_ROOT_TERMINATED", "PAYLOAD_LOST", "POLICY_REJECTED", "QUARANTINE_RESERVATION_FAILED", "QUOTA_EXHAUSTED", "RECOVERY_INTERRUPTED_PRECOMMIT", "RECOVERY_PAYLOAD_LOST", "RETENTION_BLOCKED", "SOURCE_CHANGED", "TAIL_INCOMPLETE", "TIMEOUT", "UNKNOWN_SCHEMA", "UNSAFE_PATH", "VERIFICATION_FAILED"]}, "evidence_sigils": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/sigil"}}}} + } +} diff --git a/schemas/artifact-provenance-policy-1.0.json b/schemas/artifact-provenance-policy-1.0.json new file mode 100644 index 0000000..1ec201e --- /dev/null +++ b/schemas/artifact-provenance-policy-1.0.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-provenance-policy/1.0", + "title": "Artifact Provenance Policy v1", + "description": "Closed RFC-0013 project-scoped managed INGEST/COPY provenance-admission policy. Registration, State resolution, and Transfer admission are semantic/runtime checks.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "provenance_policy_id", "policy_version", "scope", "allowed_directions", "allowed_purposes", "allowed_source_kinds", "allowed_destination_kinds", "allowed_relations", "execution_requirement", "allowed_verification_methods", "minimum_verification_evidence", "transformation_mode", "required_retention_policy_ids", "authorization_sigil", "registered_at", "record_sigil"], + "properties": { + "schema_version": {"const": "artifact-provenance-policy/1.0"}, + "provenance_policy_id": {"$ref": "#/$defs/provenancePolicyId"}, + "policy_version": {"const": "1.0"}, + "scope": {"$ref": "#/$defs/projectScope"}, + "allowed_directions": {"type": "array", "minItems": 1, "maxItems": 2, "uniqueItems": true, "items": {"enum": ["INGEST", "COPY"]}}, + "allowed_purposes": {"type": "array", "minItems": 1, "maxItems": 9, "uniqueItems": true, "items": {"$ref": "#/$defs/transferPurpose"}}, + "allowed_source_kinds": {"type": "array", "minItems": 1, "maxItems": 6, "uniqueItems": true, "items": {"$ref": "#/$defs/sourceKind"}}, + "allowed_destination_kinds": {"type": "array", "minItems": 1, "maxItems": 1, "uniqueItems": true, "items": {"const": "MANAGED_BACKEND"}}, + "allowed_relations": {"type": "array", "minItems": 1, "maxItems": 4, "uniqueItems": true, "items": {"$ref": "#/$defs/transferProvenanceRelation"}}, + "execution_requirement": {"enum": ["REQUIRED", "OPTIONAL", "FORBIDDEN"]}, + "allowed_verification_methods": {"type": "array", "minItems": 1, "maxItems": 2, "uniqueItems": true, "items": {"enum": ["FULL_READBACK_SHA256", "CONFORMANCE_END_TO_END"]}}, + "minimum_verification_evidence": {"type": "integer", "minimum": 1, "maximum": 4096}, + "transformation_mode": {"enum": ["NONE_ONLY", "DERIVED_ALLOWED"]}, + "required_retention_policy_ids": {"type": "array", "maxItems": 64, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/artifact-retention-policy/1.0#/$defs/policyId"}}, + "authorization_sigil": {"$ref": "https://benchwork.dev/schemas/artifact-retention-policy/1.0#/$defs/sigil"}, + "registered_at": {"$ref": "https://benchwork.dev/schemas/artifact-retention-policy/1.0#/$defs/timestamp"}, + "record_sigil": {"$ref": "https://benchwork.dev/schemas/artifact-retention-policy/1.0#/$defs/sigil"} + }, + "$defs": { + "provenancePolicyId": {"type": "string", "pattern": "^SPP-[A-Za-z0-9._:-]{1,124}$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "projectScope": {"type": "object", "additionalProperties": false, "required": ["kind", "project_id"], "properties": {"kind": {"const": "PROJECT"}, "project_id": {"$ref": "https://benchwork.dev/schemas/artifact-retention-policy/1.0#/$defs/opaque"}}}, + "transferPurpose": {"enum": ["ARTIFACT_IMPORT", "ATTEMPT_OUTPUT", "LEGACY_V1_PROTECTION", "REPLICA_COPY", "REPLICA_REPAIR", "SANCTUM_INPUT", "PATCH_BUNDLE", "USER_EXPORT", "QUARANTINE_REINSPECTION"]}, + "sourceKind": {"enum": ["LOCAL_FILE", "REPLICA", "ATTEMPT_OUTPUT", "EXTERNAL", "STAGING", "LEGACY_ARTIFACT"]}, + "transferProvenanceRelation": {"enum": ["CAPTURED", "IMPORTED", "COPIED", "DERIVED"]} + } +} + diff --git a/schemas/artifact-replica-1.0.json b/schemas/artifact-replica-1.0.json new file mode 100644 index 0000000..b55f8b8 --- /dev/null +++ b/schemas/artifact-replica-1.0.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-replica/1.0", + "title": "Artifact Replica v1", + "description": "Closed RFC-0013 artifact-replica/1.0 replay projection. This contract-only increment validates its self-contained structure and state/verification matrix; it does not read a backend or Blob, resolve Transfer, Journal, or Policy records, or establish physical availability.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "replica_id", "blob_sigil", "size_bytes", "backend", "object", "state", "created_by_transfer_attempt_id", "verification", "retention_policy_ids", "revision", "record_sigil"], + "properties": { + "schema_version": {"const": "artifact-replica/1.0"}, + "replica_id": {"$ref": "#/$defs/replicaId"}, + "blob_sigil": {"$ref": "#/$defs/sigil"}, + "size_bytes": {"$ref": "#/$defs/u63"}, + "backend": {"$ref": "#/$defs/backendRef"}, + "object": {"$ref": "#/$defs/backendObjectRef"}, + "state": {"enum": ["COMMITTING", "AVAILABLE", "VERIFYING", "STALE", "CORRUPT", "ABANDONED", "DELETING", "DELETED", "DELETE_FAILED"]}, + "created_by_transfer_attempt_id": {"$ref": "#/$defs/transferAttemptId"}, + "verification": {"anyOf": [{"$ref": "#/$defs/verificationRef"}, {"type": "null"}]}, + "retention_policy_ids": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/retentionPolicyId"}}, + "revision": {"$ref": "#/$defs/positiveU63"}, + "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"state": {"enum": ["COMMITTING", "ABANDONED"]}}, "required": ["state"]}, + "then": {"properties": {"verification": {"type": "null"}}, "required": ["verification"]} + }, + { + "if": {"properties": {"state": {"enum": ["AVAILABLE", "VERIFYING", "STALE", "DELETING", "DELETED", "DELETE_FAILED"]}}, "required": ["state"]}, + "then": {"properties": {"verification": {"$ref": "#/$defs/verificationRef"}}, "required": ["verification"]} + } + ], + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "opaque": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 256}, + "replicaId": {"type": "string", "pattern": "^SR-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "transferAttemptId": {"type": "string", "pattern": "^SA-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "retentionPolicyId": {"type": "string", "pattern": "^SP-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "backendRef": { + "type": "object", "additionalProperties": false, + "required": ["backend_id", "backend_profile_version", "backend_profile_sigil"], + "properties": { + "backend_id": {"$ref": "#/$defs/opaque"}, + "backend_profile_version": {"$ref": "#/$defs/opaque"}, + "backend_profile_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "backendObjectRef": { + "type": "object", "additionalProperties": false, + "required": ["backend_id", "object_identity_sigil", "locator_sigil", "generation", "size_bytes", "blob_sigil"], + "properties": { + "backend_id": {"$ref": "#/$defs/opaque"}, + "object_identity_sigil": {"$ref": "#/$defs/sigil"}, + "locator_sigil": {"$ref": "#/$defs/sigil"}, + "generation": {"$ref": "#/$defs/opaque"}, + "size_bytes": {"$ref": "#/$defs/u63"}, + "blob_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]} + } + }, + "verificationRef": { + "type": "object", "additionalProperties": false, + "required": ["method", "evidence_sigil", "verified_at", "next_due_at"], + "properties": { + "method": {"enum": ["FULL_READBACK_SHA256", "CONFORMANCE_END_TO_END"]}, + "evidence_sigil": {"$ref": "#/$defs/sigil"}, + "verified_at": {"$ref": "#/$defs/timestamp"}, + "next_due_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]} + } + } + } +} + diff --git a/schemas/artifact-retention-policy-1.0.json b/schemas/artifact-retention-policy-1.0.json new file mode 100644 index 0000000..e6ae220 --- /dev/null +++ b/schemas/artifact-retention-policy-1.0.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-retention-policy/1.0", + "title": "Artifact Retention Policy v1", + "description": "Closed RFC-0013 artifact-retention-policy/1.0 record. This contract-only increment validates the self-contained record shape and canonical collections only; it does not resolve scope, authorization, backends, policy applicability, or runtime retention decisions.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "policy_id", "scope", "minimum_replica_count", "required_backends", "required_failure_domains", "maximum_integrity_age_seconds", "deletion_grace_seconds", "retain_until", "automatic_gc_allowed", "authorization_sigil", "registered_at", "record_sigil"], + "properties": { + "schema_version": {"const": "artifact-retention-policy/1.0"}, + "policy_id": {"$ref": "#/$defs/policyId"}, + "scope": {"$ref": "#/$defs/policyScope"}, + "minimum_replica_count": {"$ref": "#/$defs/u63"}, + "required_backends": {"$ref": "#/$defs/opaqueSet"}, + "required_failure_domains": {"$ref": "#/$defs/opaqueSet"}, + "maximum_integrity_age_seconds": {"$ref": "#/$defs/nullableU63"}, + "deletion_grace_seconds": {"$ref": "#/$defs/nullableU63"}, + "retain_until": {"$ref": "#/$defs/nullableTimestamp"}, + "automatic_gc_allowed": {"type": "boolean"}, + "authorization_sigil": {"$ref": "#/$defs/sigil"}, + "registered_at": {"$ref": "#/$defs/timestamp"}, + "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "nullableU63": {"anyOf": [{"$ref": "#/$defs/u63"}, {"type": "null"}]}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "nullableTimestamp": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, + "opaque": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 256}, + "policyId": {"type": "string", "pattern": "^SP-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "referenceSetId": {"type": "string", "pattern": "^RS-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "opaqueSet": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/opaque"}}, + "policyScope": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind", "project_id"], "properties": {"kind": {"const": "PROJECT"}, "project_id": {"$ref": "#/$defs/opaque"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "program_id"], "properties": {"kind": {"const": "PROGRAM"}, "program_id": {"$ref": "#/$defs/opaque"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "blob_sigil"], "properties": {"kind": {"const": "BLOB"}, "blob_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "reference_set_id", "reference_set_sigil"], "properties": {"kind": {"const": "REFERENCE_SET"}, "reference_set_id": {"$ref": "#/$defs/referenceSetId"}, "reference_set_sigil": {"$ref": "#/$defs/sigil"}}} + ] + } + } +} + diff --git a/schemas/artifact-storage-backend-1.0.json b/schemas/artifact-storage-backend-1.0.json new file mode 100644 index 0000000..63d6d7a --- /dev/null +++ b/schemas/artifact-storage-backend-1.0.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-storage-backend/1.0", + "title": "Artifact Storage Backend v1", + "description": "Closed RFC-0013 artifact-storage-backend/1.0 capability record. This contract-only increment validates record shape and local consistency only; it does not probe, register, or resolve a backend, Host, configuration, conformance suite, or evidence.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "backend_id", "adapter_id", "adapter_version", "protocol_version", "adapter_sigil", "configuration_sigil", "namespace_sigil", "isolation", "limits", "consistency", "durability", "verification_methods", "range_resume", "conditional_operations", "deletion_capabilities", "credential_class", "fencing", "conformance", "record_sigil"], + "properties": { + "schema_version": {"const": "artifact-storage-backend/1.0"}, + "backend_id": {"$ref": "#/$defs/opaque"}, "adapter_id": {"$ref": "#/$defs/opaque"}, "adapter_version": {"$ref": "#/$defs/opaque"}, "protocol_version": {"$ref": "#/$defs/opaque"}, + "adapter_sigil": {"$ref": "#/$defs/sigil"}, "configuration_sigil": {"$ref": "#/$defs/sigil"}, "namespace_sigil": {"$ref": "#/$defs/sigil"}, + "isolation": {"$ref": "#/$defs/isolation"}, "limits": {"$ref": "#/$defs/limits"}, "consistency": {"$ref": "#/$defs/consistency"}, "durability": {"$ref": "#/$defs/durability"}, + "verification_methods": {"type": "array", "minItems": 1, "maxItems": 2, "uniqueItems": true, "items": {"enum": ["FULL_READBACK_SHA256", "CONFORMANCE_END_TO_END"]}}, + "range_resume": {"$ref": "#/$defs/rangeResume"}, "conditional_operations": {"$ref": "#/$defs/conditionalOperations"}, "deletion_capabilities": {"$ref": "#/$defs/deletionCapabilities"}, + "credential_class": {"enum": ["COORDINATOR_HOST_LOCAL", "COORDINATOR_SCOPED_REMOTE"]}, "fencing": {"$ref": "#/$defs/fencing"}, "conformance": {"$ref": "#/$defs/conformance"}, "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "opaque": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 256}, + "transferBounds": {"type": "object", "additionalProperties": false, "required": ["max_bytes", "max_duration_millis", "max_file_count", "max_chunk_count", "buffer_bytes"], "properties": {"max_bytes": {"$ref": "#/$defs/u63"}, "max_duration_millis": {"$ref": "#/$defs/u63"}, "max_file_count": {"anyOf": [{"$ref": "#/$defs/u63"}, {"type": "null"}]}, "max_chunk_count": {"$ref": "#/$defs/u63"}, "buffer_bytes": {"$ref": "#/$defs/positiveU63"}}}, + "isolation": {"type": "object", "additionalProperties": false, "required": ["scope", "namespace_enforcement", "worker_access", "worker_credentials_exposed"], "properties": {"scope": {"enum": ["SINGLE_PROJECT", "SINGLE_TENANT_PROJECT"]}, "namespace_enforcement": {"enum": ["DESCRIPTOR_RELATIVE_NOFOLLOW", "ADAPTER_SCOPED"]}, "worker_access": {"const": "NONE"}, "worker_credentials_exposed": {"const": false}}}, + "systemReserveLimit": {"type": "object", "additionalProperties": false, "required": ["reserve_class", "max_event_frame_count", "max_control_record_count", "max_recovery_evidence_count", "max_event_frame_bytes", "max_control_record_bytes", "max_recovery_evidence_bytes"], "properties": {"reserve_class": {"enum": ["INITIALIZATION", "COORDINATOR_LIVENESS", "CLOCK_PRESSURE", "CATALOG_ADMINISTRATION", "VERIFICATION_INCIDENT", "RETENTION_REFERENCE", "GC_ADMINISTRATION", "RECOVERY"]}, "max_event_frame_count": {"$ref": "#/$defs/positiveU63"}, "max_control_record_count": {"$ref": "#/$defs/u63"}, "max_recovery_evidence_count": {"$ref": "#/$defs/u63"}, "max_event_frame_bytes": {"type": "integer", "minimum": 56, "maximum": 8388664}, "max_control_record_bytes": {"type": "integer", "minimum": 1, "maximum": 8388664}, "max_recovery_evidence_bytes": {"type": "integer", "minimum": 1, "maximum": 8388664}}}, + "limits": {"type": "object", "additionalProperties": false, "required": ["max_object_bytes", "transfer_bounds", "max_concurrent_streams", "max_inventory_entries", "max_tail_recovery_retries", "system_reserve_limits", "system_journal_reserve_bytes", "system_control_record_reserve_bytes", "system_recovery_reserve_bytes"], "properties": {"max_object_bytes": {"$ref": "#/$defs/u63"}, "transfer_bounds": {"$ref": "#/$defs/transferBounds"}, "max_concurrent_streams": {"$ref": "#/$defs/u63"}, "max_inventory_entries": {"$ref": "#/$defs/u63"}, "max_tail_recovery_retries": {"$ref": "#/$defs/positiveU63"}, "system_reserve_limits": {"type": "array", "minItems": 8, "maxItems": 8, "prefixItems": [{"properties": {"reserve_class": {"const": "INITIALIZATION"}}}, {"properties": {"reserve_class": {"const": "COORDINATOR_LIVENESS"}}}, {"properties": {"reserve_class": {"const": "CLOCK_PRESSURE"}}}, {"properties": {"reserve_class": {"const": "CATALOG_ADMINISTRATION"}}}, {"properties": {"reserve_class": {"const": "VERIFICATION_INCIDENT"}}}, {"properties": {"reserve_class": {"const": "RETENTION_REFERENCE"}}}, {"properties": {"reserve_class": {"const": "GC_ADMINISTRATION"}}}, {"properties": {"reserve_class": {"const": "RECOVERY"}}}], "items": {"$ref": "#/$defs/systemReserveLimit"}}, "system_journal_reserve_bytes": {"$ref": "#/$defs/positiveU63"}, "system_control_record_reserve_bytes": {"$ref": "#/$defs/positiveU63"}, "system_recovery_reserve_bytes": {"$ref": "#/$defs/positiveU63"}}}, + "consistency": {"type": "object", "additionalProperties": false, "required": ["read_after_write", "list_consistency", "atomic_visibility", "immutable_generation", "exact_generation_reads"], "properties": {"read_after_write": {"enum": ["STRONG", "EVENTUAL"]}, "list_consistency": {"enum": ["STRONG", "EVENTUAL"]}, "atomic_visibility": {"type": "boolean"}, "immutable_generation": {"type": "boolean"}, "exact_generation_reads": {"type": "boolean"}}}, + "durability": {"type": "object", "additionalProperties": false, "required": ["commit_semantics", "logical_readback", "transparent_encryption", "transparent_compression"], "properties": {"commit_semantics": {"enum": ["FSYNC_FILE_AND_PARENT", "REMOTE_DURABLE_ACK"]}, "logical_readback": {"type": "boolean"}, "transparent_encryption": {"type": "boolean"}, "transparent_compression": {"type": "boolean"}}}, + "rangeResume": {"type": "object", "additionalProperties": false, "required": ["range_reads", "resumable_stage_writes", "resume_binding"], "properties": {"range_reads": {"type": "boolean"}, "resumable_stage_writes": {"type": "boolean"}, "resume_binding": {"enum": ["UNSUPPORTED", "GENERATION_OFFSET_PREFIX_SIGIL"]}}}, + "conditionalOperations": {"type": "object", "additionalProperties": false, "required": ["conditional_create", "no_overwrite_finalize", "exact_generation_stat", "exact_generation_delete"], "properties": {"conditional_create": {"type": "boolean"}, "no_overwrite_finalize": {"type": "boolean"}, "exact_generation_stat": {"type": "boolean"}, "exact_generation_delete": {"type": "boolean"}}}, + "deletionCapabilities": {"type": "object", "additionalProperties": false, "required": ["exact_generation_delete", "wildcard_delete", "retention_lock", "verification"], "properties": {"exact_generation_delete": {"type": "boolean"}, "wildcard_delete": {"const": false}, "retention_lock": {"enum": ["NONE", "ENFORCED"]}, "verification": {"enum": ["POST_DELETE_STAT", "RECEIPT_AND_RECONCILIATION"]}}}, + "fencing": {"type": "object", "additionalProperties": false, "required": ["mode", "attempt_staging_isolated", "executor_epoch_checked", "job_fence_floor_checked", "tombstone_checked"], "properties": {"mode": {"enum": ["COORDINATOR_PRECOMMIT", "BACKEND_PUBLIC_FENCE"]}, "attempt_staging_isolated": {"type": "boolean"}, "executor_epoch_checked": {"type": "boolean"}, "job_fence_floor_checked": {"type": "boolean"}, "tombstone_checked": {"type": "boolean"}}}, + "conformance": {"type": "object", "additionalProperties": false, "required": ["profile_id", "suite_version", "suite_sigil", "host_platform_sigil", "evidence_sigil"], "properties": {"profile_id": {"enum": ["LOCAL-PHASE3/1.0", "PORTABLE-PHASE4/1.0"]}, "suite_version": {"$ref": "#/$defs/opaque"}, "suite_sigil": {"$ref": "#/$defs/sigil"}, "host_platform_sigil": {"$ref": "#/$defs/sigil"}, "evidence_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/artifact-storage-disposition-1.0.json b/schemas/artifact-storage-disposition-1.0.json new file mode 100644 index 0000000..c8864c0 --- /dev/null +++ b/schemas/artifact-storage-disposition-1.0.json @@ -0,0 +1,7 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/artifact-storage-disposition/1.0","title":"Artifact Storage Disposition v1","description":"Closed RFC-0013 artifact-storage-disposition/1.0 authorization wire contract; local validation only.","type":"object","additionalProperties":false, + "required":["schema_version","disposition_id","target_kind","target_id","target_generation","expected_blob_sigil","expected_size_or_bound","reason_code","actor_id","policy_sigil","approval_evidence_sigil","authorization_sigil","authorized_at","expires_at","idempotency_key_sigil","record_sigil"], + "properties":{"schema_version":{"const":"artifact-storage-disposition/1.0"},"disposition_id":{"$ref":"#/$defs/dispositionId"},"target_kind":{"enum":["STAGING","MATERIALIZATION_STAGING","MATERIALIZATION_DESTINATION","QUARANTINE"]},"target_id":{"$ref":"#/$defs/opaque"},"target_generation":{"$ref":"#/$defs/opaque"},"expected_blob_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"expected_size_or_bound":{"$ref":"#/$defs/expectedSizeOrBound"},"reason_code":{"$ref":"#/$defs/reasonCode"},"actor_id":{"$ref":"#/$defs/opaque"},"policy_sigil":{"$ref":"#/$defs/sigil"},"approval_evidence_sigil":{"$ref":"#/$defs/sigil"},"authorization_sigil":{"$ref":"#/$defs/sigil"},"authorized_at":{"$ref":"#/$defs/timestamp"},"expires_at":{"$ref":"#/$defs/timestamp"},"idempotency_key_sigil":{"$ref":"#/$defs/sigil"},"record_sigil":{"$ref":"#/$defs/sigil"}}, + "$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"opaque":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"dispositionId":{"type":"string","pattern":"^SD-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"expectedSizeOrBound":{"oneOf":[{"type":"object","additionalProperties":false,"required":["kind","size_bytes"],"properties":{"kind":{"const":"EXACT"},"size_bytes":{"$ref":"#/$defs/u63"}}},{"type":"object","additionalProperties":false,"required":["kind","max_size_bytes"],"properties":{"kind":{"const":"UPPER_BOUND"},"max_size_bytes":{"$ref":"#/$defs/u63"}}}]},"reasonCode":{"enum":["AUTHORIZATION_DENIED","BACKEND_AMBIGUOUS","BACKEND_CONFLICT","BACKEND_UNAVAILABLE","BOUNDS_EXCEEDED","CANCELLED","CHRONICLE_REFERENCE_CHANGED","CLOCK_UNCERTAIN","CONFLICT","CORRUPT","DESTINATION_CONFLICT","DISPOSITION_EXPIRED","DURABILITY_UNVERIFIED","EXECUTION_HOLD_LIFETIME_EXPIRED","EXECUTION_ROOT_ORPHAN_ABORTED","EXECUTION_ROOT_OWNER_TERMINATED","FENCE_REJECTED","GC_ROOT_CHANGED","GENERATION_MISMATCH","HASH_MISMATCH","INTEGRITY_FAILURE","INVALID_MESSAGE","LEASE_EXPIRED","LEGACY_PROTECTION_FAILED","MINIMUM_REPLICA_VIOLATION","OPERATIONAL_ROOT_TERMINATED","PAYLOAD_LOST","POLICY_REJECTED","QUARANTINE_RESERVATION_FAILED","QUOTA_EXHAUSTED","RECOVERY_INTERRUPTED_PRECOMMIT","RECOVERY_PAYLOAD_LOST","RETENTION_BLOCKED","SOURCE_CHANGED","TAIL_INCOMPLETE","TIMEOUT","UNKNOWN_SCHEMA","UNSAFE_PATH","VERIFICATION_FAILED"]}} +} + diff --git a/schemas/artifact-storage-doctor-report-1.0.json b/schemas/artifact-storage-doctor-report-1.0.json new file mode 100644 index 0000000..3e5d7b7 --- /dev/null +++ b/schemas/artifact-storage-doctor-report-1.0.json @@ -0,0 +1,2 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/artifact-storage-doctor-report/1.0","title":"Artifact Storage Doctor Report v1","type":"object","additionalProperties":false,"required":["schema_version","report_id","mode","project_id","storage_journal_id","journal_head_sigil","chronicle_head_sigil","storage_format_version","backend_profile_id","backend_profile_sigil","conformance_profile_id","conformance_suite_sigil","coordinator_epoch","journal_verification","state_verification","backend_inventory","replica_checks","legacy_checks","quarantine_checks","quota_checks","reference_checks","open_intent_checks","bounds","incomplete_reasons","overall_status","started_at","completed_at","report_sigil"],"properties":{"schema_version":{"const":"artifact-storage-doctor-report/1.0"},"report_id":{"$ref":"#/$defs/opaque"},"mode":{"enum":["NORMAL","DEEP"]},"project_id":{"$ref":"#/$defs/opaque"},"storage_journal_id":{"anyOf":[{"$ref":"#/$defs/journalId"},{"type":"null"}]},"journal_head_sigil":{"$ref":"#/$defs/nullSigil"},"chronicle_head_sigil":{"$ref":"#/$defs/nullSigil"},"storage_format_version":{"$ref":"#/$defs/nullOpaque"},"backend_profile_id":{"$ref":"#/$defs/nullOpaque"},"backend_profile_sigil":{"$ref":"#/$defs/nullSigil"},"conformance_profile_id":{"$ref":"#/$defs/nullOpaque"},"conformance_suite_sigil":{"$ref":"#/$defs/nullSigil"},"coordinator_epoch":{"anyOf":[{"$ref":"#/$defs/u63"},{"type":"null"}]},"journal_verification":{"$ref":"#/$defs/check"},"state_verification":{"$ref":"#/$defs/check"},"backend_inventory":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/inventory"}},"replica_checks":{"$ref":"#/$defs/checks"},"legacy_checks":{"$ref":"#/$defs/checks"},"quarantine_checks":{"$ref":"#/$defs/checks"},"quota_checks":{"$ref":"#/$defs/checks"},"reference_checks":{"$ref":"#/$defs/checks"},"open_intent_checks":{"$ref":"#/$defs/checks"},"bounds":{"$ref":"#/$defs/bounds"},"incomplete_reasons":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/reason"}},"overall_status":{"enum":["HEALTHY","DEGRADED","RECOVERY_REQUIRED","INTEGRITY_FAILURE","INCOMPLETE"]},"started_at":{"$ref":"#/$defs/time"},"completed_at":{"$ref":"#/$defs/time"},"report_sigil":{"$ref":"#/$defs/sigil"}},"$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"nullSigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"opaque":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256},"nullOpaque":{"anyOf":[{"$ref":"#/$defs/opaque"},{"type":"null"}]},"time":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$"},"journalId":{"type":"string","pattern":"^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"reason":{"type":"object","additionalProperties":false,"required":["code","evidence_sigils"],"properties":{"code":{"$ref":"#/$defs/reasonCode"},"evidence_sigils":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}}}},"check":{"type":"object","additionalProperties":false,"required":["check_id","status","subject_kind","subject_id","evidence_sigils","reason"],"properties":{"check_id":{"$ref":"#/$defs/opaque"},"status":{"enum":["PASS","WARN","FAIL","INCOMPLETE"]},"subject_kind":{"enum":["JOURNAL","STATE","BACKEND_OBJECT","REPLICA","LEGACY_PROTECTION","QUARANTINE","QUOTA","REFERENCE_SET","HOLD","OPEN_INTENT","RECOVERY_EVIDENCE"]},"subject_id":{"$ref":"#/$defs/opaque"},"evidence_sigils":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}},"reason":{"anyOf":[{"$ref":"#/$defs/reason"},{"type":"null"}]}}},"checks":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/check"}},"object":{"type":"object","additionalProperties":false,"required":["backend_id","object_identity_sigil","locator_sigil","generation","size_bytes","blob_sigil"],"properties":{"backend_id":{"$ref":"#/$defs/opaque"},"object_identity_sigil":{"$ref":"#/$defs/sigil"},"locator_sigil":{"$ref":"#/$defs/sigil"},"generation":{"$ref":"#/$defs/opaque"},"size_bytes":{"$ref":"#/$defs/u63"},"blob_sigil":{"$ref":"#/$defs/nullSigil"}}},"inventory":{"type":"object","additionalProperties":false,"required":["backend_object","owner_kind","owner_id","status","evidence_sigils"],"properties":{"backend_object":{"$ref":"#/$defs/object"},"owner_kind":{"enum":["REPLICA","TRANSFER_ATTEMPT","MATERIALIZATION","QUARANTINE","UNJOURNALED"]},"owner_id":{"$ref":"#/$defs/nullOpaque"},"status":{"enum":["OWNED","UNJOURNALED","CONFLICTING","INACCESSIBLE"]},"evidence_sigils":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}}}},"bounds":{"type":"object","additionalProperties":false,"required":["max_inventory_entries","max_control_records","max_rehash_bytes","max_wall_millis","inventory_truncated","rehash_truncated"],"properties":{"max_inventory_entries":{"$ref":"#/$defs/u63"},"max_control_records":{"$ref":"#/$defs/u63"},"max_rehash_bytes":{"$ref":"#/$defs/u63"},"max_wall_millis":{"$ref":"#/$defs/u63"},"inventory_truncated":{"type":"boolean"},"rehash_truncated":{"type":"boolean"}}},"reasonCode":{"enum":["AUTHORIZATION_DENIED","BACKEND_AMBIGUOUS","BACKEND_CONFLICT","BACKEND_UNAVAILABLE","BOUNDS_EXCEEDED","CANCELLED","CHRONICLE_REFERENCE_CHANGED","CLOCK_UNCERTAIN","CONFLICT","CORRUPT","DESTINATION_CONFLICT","DISPOSITION_EXPIRED","DURABILITY_UNVERIFIED","EXECUTION_HOLD_LIFETIME_EXPIRED","EXECUTION_ROOT_ORPHAN_ABORTED","EXECUTION_ROOT_OWNER_TERMINATED","FENCE_REJECTED","GC_ROOT_CHANGED","GENERATION_MISMATCH","HASH_MISMATCH","INTEGRITY_FAILURE","INVALID_MESSAGE","LEASE_EXPIRED","LEGACY_PROTECTION_FAILED","MINIMUM_REPLICA_VIOLATION","OPERATIONAL_ROOT_TERMINATED","PAYLOAD_LOST","POLICY_REJECTED","QUARANTINE_RESERVATION_FAILED","QUOTA_EXHAUSTED","RECOVERY_INTERRUPTED_PRECOMMIT","RECOVERY_PAYLOAD_LOST","RETENTION_BLOCKED","SOURCE_CHANGED","TAIL_INCOMPLETE","TIMEOUT","UNKNOWN_SCHEMA","UNSAFE_PATH","VERIFICATION_FAILED"]}}} + diff --git a/schemas/artifact-storage-execution-namespace-abort-1.0.json b/schemas/artifact-storage-execution-namespace-abort-1.0.json new file mode 100644 index 0000000..1146185 --- /dev/null +++ b/schemas/artifact-storage-execution-namespace-abort-1.0.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-abort/1.0", + "title": "Artifact Storage Execution Namespace Abort v1", + "description": "Closed RFC-0013 E1 namespace abort leaf. Predicate evaluation, precedence selection, index visibility, Journal append, and recovery authority remain external.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "namespace_reservation_id", "namespace_reservation_record_sigil", "observed_execution_head", "reason", "evidence_sigil", "aborted_at", "abort_record_sigil"], + "properties": { + "schema_version": {"const": "artifact-storage-execution-namespace-abort/1.0"}, + "namespace_reservation_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-reservation/1.0#/$defs/namespaceReservationId"}, + "namespace_reservation_record_sigil": {"$ref": "#/$defs/sigil"}, + "observed_execution_head": {"$ref": "https://benchwork.dev/schemas/execution-journal-head/1.0"}, + "reason": {"enum": ["INTEGRITY_FAILURE", "RECOVERY_ACTIVE", "EXECUTOR_EPOCH_CHANGED", "FENCE_STALE", "OWNER_TERMINAL", "DEADLINE_DUE", "CANCEL_REQUESTED", "STOP_LATCHED", "LEASE_INACTIVE", "POLICY_INELIGIBLE", "OWNER_NOT_RUNNING"]}, + "evidence_sigil": {"$ref": "#/$defs/sigil"}, + "aborted_at": {"$ref": "#/$defs/timestamp"}, + "abort_record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27} + } +} + diff --git a/schemas/artifact-storage-execution-namespace-activation-1.0.json b/schemas/artifact-storage-execution-namespace-activation-1.0.json new file mode 100644 index 0000000..0e21ffa --- /dev/null +++ b/schemas/artifact-storage-execution-namespace-activation-1.0.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-activation/1.0", + "title": "Artifact Storage Execution Namespace Activation v1", + "description": "Closed RFC-0013 embedded namespace activation leaf including the E1 deterministic consumption seed. Index visibility, append, locking, and recovery authority are outside this contract.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "namespace_reservation_id", "namespace_reservation_record_sigil", "preallocation_event", "consumption_seed", "activated_at", "activation_record_sigil"], + "properties": { + "schema_version": {"const": "artifact-storage-execution-namespace-activation/1.0"}, + "namespace_reservation_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-reservation/1.0#/$defs/namespaceReservationId"}, + "namespace_reservation_record_sigil": {"$ref": "#/$defs/sigil"}, + "preallocation_event": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_ref"}, + "consumption_seed": {"$ref": "#/$defs/consumptionSeed"}, + "activated_at": {"$ref": "#/$defs/timestamp"}, + "activation_record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "consumptionIntentId": {"type": "string", "pattern": "^SCI-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "preparedEventId": {"type": "string", "pattern": "^SE-[0-9A-F]{64}$", "minLength": 67, "maxLength": 67}, + "consumptionSeed": { + "type": "object", + "additionalProperties": false, + "required": ["consumption_intent_id", "prepared_event_id", "seeded_at", "seed_sigil"], + "properties": { + "consumption_intent_id": {"$ref": "#/$defs/consumptionIntentId"}, + "prepared_event_id": {"$ref": "#/$defs/preparedEventId"}, + "seeded_at": {"$ref": "#/$defs/timestamp"}, + "seed_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/artifact-storage-execution-namespace-consumption-1.0.json b/schemas/artifact-storage-execution-namespace-consumption-1.0.json new file mode 100644 index 0000000..005e99b --- /dev/null +++ b/schemas/artifact-storage-execution-namespace-consumption-1.0.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-consumption/1.0", + "title": "Artifact Storage Execution Namespace Consumption v1", + "description": "Closed RFC-0013 consumed activation leaf binding the actual durable Storage EventRef. It grants no Event append, index installation, locking, recovery, or transfer authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "consumption_intent_id", "intent_sigil", "prepared_event", "consumed_at", "consumption_record_sigil"], + "properties": { + "schema_version": {"const": "artifact-storage-execution-namespace-consumption/1.0"}, + "consumption_intent_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-activation/1.0#/$defs/consumptionIntentId"}, + "intent_sigil": {"$ref": "#/$defs/sigil"}, + "prepared_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, + "consumed_at": {"$ref": "#/$defs/timestamp"}, + "consumption_record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27} + } +} + diff --git a/schemas/artifact-storage-execution-namespace-consumption-intent-1.0.json b/schemas/artifact-storage-execution-namespace-consumption-intent-1.0.json new file mode 100644 index 0000000..4d97a92 --- /dev/null +++ b/schemas/artifact-storage-execution-namespace-consumption-intent-1.0.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-consumption-intent/1.0", + "title": "Artifact Storage Execution Namespace Consumption Intent v1", + "description": "Closed RFC-0013 E1 embedded consumption-intent leaf. It grants no standalone visibility, record installation, Storage Event append, locking, recovery, or transfer authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "consumption_intent_id", "namespace_reservation_id", "namespace_reservation_record_sigil", "namespace_activation_record_sigil", "job_id", "attempt_id", "storage_subject_id", "output_handle_id", "transfer_id", "transfer_attempt_id", "transfer_request", "transfer_request_sigil", "initial_transfer_attempt", "initial_transfer_attempt_sigil", "prepared_event_id", "prepared_event_payload", "created_at", "intent_sigil"], + "properties": { + "schema_version": {"const": "artifact-storage-execution-namespace-consumption-intent/1.0"}, + "consumption_intent_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-activation/1.0#/$defs/consumptionIntentId"}, + "namespace_reservation_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-reservation/1.0#/$defs/namespaceReservationId"}, + "namespace_reservation_record_sigil": {"$ref": "#/$defs/sigil"}, + "namespace_activation_record_sigil": {"$ref": "#/$defs/sigil"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "storage_subject_id": {"$ref": "#/$defs/sigil"}, + "output_handle_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, + "transfer_id": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferId"}, + "transfer_attempt_id": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferAttemptId"}, + "transfer_request": {"$ref": "https://benchwork.dev/schemas/artifact-transfer/1.0"}, + "transfer_request_sigil": {"$ref": "#/$defs/sigil"}, + "initial_transfer_attempt": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0"}, + "initial_transfer_attempt_sigil": {"$ref": "#/$defs/sigil"}, + "prepared_event_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-activation/1.0#/$defs/preparedEventId"}, + "prepared_event_payload": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/p_transfer_prepared"}, + "created_at": {"$ref": "#/$defs/timestamp"}, + "intent_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27} + } +} + diff --git a/schemas/artifact-storage-execution-namespace-reservation-1.0.json b/schemas/artifact-storage-execution-namespace-reservation-1.0.json new file mode 100644 index 0000000..a115c38 --- /dev/null +++ b/schemas/artifact-storage-execution-namespace-reservation-1.0.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-storage-execution-namespace-reservation/1.0", + "title": "Artifact Storage Execution Namespace Reservation v1", + "description": "Closed RFC-0013 embedded ST/SA namespace reservation leaf. This contract does not define a standalone visibility path, replacement index, allocation, append, locking, or recovery authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "namespace_reservation_id", "reservation_key_sigil", "job_id", "attempt_id", "attempt_binding_sigil", "lease_id", "lease_binding_sigil", "worker_id", "worker_session_id", "worker_session_binding_sigil", "executor_epoch", "fence_tuple", "preallocation_event_id", "preallocation_binding_sigil", "storage_subject_id", "output_handle_id", "transfer_id", "transfer_attempt_id", "authorized_maximum_bytes", "reserved_at", "record_sigil"], + "properties": { + "schema_version": {"const": "artifact-storage-execution-namespace-reservation/1.0"}, + "namespace_reservation_id": {"$ref": "#/$defs/namespaceReservationId"}, + "reservation_key_sigil": {"$ref": "#/$defs/sigil"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "lease_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_epoch": {"$ref": "#/$defs/u64"}, + "fence_tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"}, + "preallocation_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "preallocation_binding_sigil": {"$ref": "#/$defs/sigil"}, + "storage_subject_id": {"$ref": "#/$defs/sigil"}, + "output_handle_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, + "transfer_id": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferId"}, + "transfer_attempt_id": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferAttemptId"}, + "authorized_maximum_bytes": {"$ref": "#/$defs/positiveU63"}, + "reserved_at": {"$ref": "#/$defs/timestamp"}, + "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "namespaceReservationId": {"type": "string", "pattern": "^SNR-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68} + } +} + diff --git a/schemas/artifact-storage-journal-event-1.0.json b/schemas/artifact-storage-journal-event-1.0.json new file mode 100644 index 0000000..4de1201 --- /dev/null +++ b/schemas/artifact-storage-journal-event-1.0.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0", + "title": "Artifact Storage Journal Event v1", + "description": "Closed RFC-0013 hash-chained Storage Journal event. Cross-record resolution, sequence adjacency, revision arithmetic, sorting, quota arithmetic, and replay are runtime checks.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version","journal_id","event_id","sequence","event_type","coordinator_id","epoch","recorded_at","observed_at","entity_revisions","causation_event_id","idempotency_key_sigil","quota_effects","payload","previous_event_sigil","event_sigil"], + "properties": { + "schema_version":{"const":"artifact-storage-journal-event/1.0"}, "journal_id":{"$ref":"#/$defs/journalId"}, "event_id":{"$ref":"#/$defs/eventId"}, "sequence":{"$ref":"#/$defs/positiveU63"}, "event_type":{"$ref":"#/$defs/eventType"}, "coordinator_id":{"$ref":"#/$defs/opaque"}, "epoch":{"$ref":"#/$defs/positiveU63"}, "recorded_at":{"$ref":"#/$defs/timestamp"}, "observed_at":{"anyOf":[{"$ref":"#/$defs/timestamp"},{"type":"null"}]}, "entity_revisions":{"$ref":"#/$defs/entityRevisions"}, "causation_event_id":{"anyOf":[{"$ref":"#/$defs/eventId"},{"type":"null"}]}, "idempotency_key_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]}, "quota_effects":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/quotaEffect"}}, "payload":{}, "previous_event_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]}, "event_sigil":{"$ref":"#/$defs/sigil"} + }, + "allOf":[ + {"if":{"properties":{"sequence":{"const":1}},"required":["sequence"]},"then":{"properties":{"previous_event_sigil":{"type":"null"}}},"else":{"properties":{"previous_event_sigil":{"$ref":"#/$defs/sigil"}}}}, + {"oneOf":[ + {"$ref":"#/$defs/e_storage_initialized"},{"$ref":"#/$defs/e_storage_activation_completed"},{"$ref":"#/$defs/e_storage_epoch_started"},{"$ref":"#/$defs/e_storage_clock_uncertain"},{"$ref":"#/$defs/e_storage_clock_restored"},{"$ref":"#/$defs/e_storage_recovery_started"},{"$ref":"#/$defs/e_storage_recovery_completed"},{"$ref":"#/$defs/e_storage_message_rejected"},{"$ref":"#/$defs/e_legacy_registered"},{"$ref":"#/$defs/e_legacy_failed"},{"$ref":"#/$defs/e_quota_entered"},{"$ref":"#/$defs/e_quota_cleared"}, + {"$ref":"#/$defs/e_transfer_prepared"},{"$ref":"#/$defs/e_transfer_streaming"},{"$ref":"#/$defs/e_transfer_verifying"},{"$ref":"#/$defs/e_transfer_intent"},{"$ref":"#/$defs/e_transfer_committed"},{"$ref":"#/$defs/e_transfer_failed"},{"$ref":"#/$defs/e_transfer_cancelled"},{"$ref":"#/$defs/e_transfer_quarantined"},{"$ref":"#/$defs/e_replica_verification_started"},{"$ref":"#/$defs/e_replica_verified"},{"$ref":"#/$defs/e_replica_expired"},{"$ref":"#/$defs/e_replica_corrupt"},{"$ref":"#/$defs/e_blob_incident"}, + {"$ref":"#/$defs/e_materialization_prepared"},{"$ref":"#/$defs/e_materialization_streaming"},{"$ref":"#/$defs/e_materialization_verifying"},{"$ref":"#/$defs/e_materialization_intent"},{"$ref":"#/$defs/e_materialization_committed"},{"$ref":"#/$defs/e_materialization_cleanup_started"},{"$ref":"#/$defs/e_materialization_cleaned"},{"$ref":"#/$defs/e_materialization_cleanup_failed"},{"$ref":"#/$defs/e_materialization_failed"},{"$ref":"#/$defs/e_materialization_quarantined"}, + {"$ref":"#/$defs/e_quarantine_intent"},{"$ref":"#/$defs/e_quarantine_recorded"},{"$ref":"#/$defs/e_quarantine_failed"},{"$ref":"#/$defs/e_quarantine_reinspection_started"},{"$ref":"#/$defs/e_quarantine_reinspection_completed"},{"$ref":"#/$defs/e_provenance_policy"},{"$ref":"#/$defs/e_provenance_recorded"},{"$ref":"#/$defs/e_retention_policy"},{"$ref":"#/$defs/e_hold_set"},{"$ref":"#/$defs/e_hold_released"},{"$ref":"#/$defs/e_reference_set"},{"$ref":"#/$defs/e_canonical_intent"},{"$ref":"#/$defs/e_canonical_committed"},{"$ref":"#/$defs/e_canonical_released"}, + {"$ref":"#/$defs/e_gc_plan_created"},{"$ref":"#/$defs/e_gc_plan_authorized"},{"$ref":"#/$defs/e_gc_execution_started"},{"$ref":"#/$defs/e_gc_target_skipped"},{"$ref":"#/$defs/e_gc_target_deletion_started"},{"$ref":"#/$defs/e_gc_target_deleted"},{"$ref":"#/$defs/e_gc_target_failed"},{"$ref":"#/$defs/e_gc_completed"},{"$ref":"#/$defs/e_gc_aborted"},{"$ref":"#/$defs/e_disposition_authorized"},{"$ref":"#/$defs/e_disposition_started"},{"$ref":"#/$defs/e_disposition_completed"},{"$ref":"#/$defs/e_disposition_failed"} + ]} + ], + "$defs": { + "sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71}, "u63":{"type":"integer","minimum":0,"maximum":9223372036854775807}, "positiveU63":{"type":"integer","minimum":1,"maximum":9223372036854775807}, "u64":{"type":"integer","minimum":0,"maximum":18446744073709551615}, "opaque":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256}, "timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27}, + "id":{"type":"string","pattern":"^[A-Z]+-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":3,"maxLength":128}, "journalId":{"type":"string","pattern":"^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "eventId":{"type":"string","pattern":"^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "transferId":{"type":"string","pattern":"^ST-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "attemptId":{"type":"string","pattern":"^SA-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "replicaId":{"type":"string","pattern":"^SR-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "materializationId":{"type":"string","pattern":"^SM-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "quarantineId":{"type":"string","pattern":"^SQ-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "policyId":{"type":"string","pattern":"^SP-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "provenancePolicyId":{"type":"string","pattern":"^SPP-[A-Za-z0-9._:-]{1,124}$","minLength":5,"maxLength":128}, "referenceSetId":{"type":"string","pattern":"^RS-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "referenceIntentId":{"type":"string","pattern":"^RI-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "gcPlanId":{"type":"string","pattern":"^SG-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, "dispositionId":{"type":"string","pattern":"^SD-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128}, + "eventType":{"enum":["storage.initialized","storage.activation_completed","storage.epoch_started","storage.clock_uncertain","storage.clock_restored","storage.recovery_started","storage.recovery_completed","storage.message_rejected","legacy_v1.protection_registered","legacy_v1.protection_failed","quota.pressure_entered","quota.pressure_cleared","transfer.prepared","transfer.streaming_started","transfer.verification_started","transfer.commit_intent_recorded","transfer.committed","transfer.failed","transfer.cancelled","transfer.quarantined","replica.verification_started","replica.verified","replica.verification_expired","replica.corrupt","blob.incident_recorded","materialization.prepared","materialization.streaming_started","materialization.verification_started","materialization.commit_intent_recorded","materialization.committed","materialization.cleanup_started","materialization.cleaned","materialization.cleanup_failed","materialization.failed","materialization.quarantined","quarantine.intent_recorded","quarantine.recorded","quarantine.failed","quarantine.reinspection_started","quarantine.reinspection_completed","provenance.policy_registered","provenance.recorded","retention.policy_registered","retention.hold_set","retention.hold_released","reference_set.registered","canonical_reference.intent_recorded","canonical_reference.committed","canonical_reference.released","gc.plan_created","gc.plan_authorized","gc.execution_started","gc.target_skipped","gc.target_deletion_started","gc.target_deleted","gc.target_failed","gc.completed","gc.aborted","disposition.authorized","disposition.started","disposition.completed","disposition.failed"]}, + "reason":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reason"}, "clock":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/clockRef"}, "object":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, "reservation":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reservationRef"}, "fence":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/fence"}, "verification":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/verificationRef"}, "cleanup":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/residualStagingCleanup"}, "cleanupResult":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/cleanupResult"}, "transferIntent":{"$ref":"https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferCommitIntent"}, "materializationIntent":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/materializationCommitIntent"}, + "controlRef":{"type":"object","additionalProperties":false,"required":["schema_version","record_id","record_sigil"],"properties":{"schema_version":{"$ref":"#/$defs/opaque"},"record_id":{"$ref":"#/$defs/opaque"},"record_sigil":{"$ref":"#/$defs/sigil"}}}, "eventRef":{"type":"object","additionalProperties":false,"required":["journal_id","event_id","sequence","event_sigil"],"properties":{"journal_id":{"$ref":"#/$defs/journalId"},"event_id":{"$ref":"#/$defs/eventId"},"sequence":{"$ref":"#/$defs/positiveU63"},"event_sigil":{"$ref":"#/$defs/sigil"}}}, + "tailRecovery":{"type":"object","additionalProperties":false,"required":["prior_head_sigil","old_committed_byte_length","last_complete_byte_length","discarded_suffix_size","discarded_suffix_sigil","evidence_record_sigil"],"properties":{"prior_head_sigil":{"$ref":"#/$defs/sigil"},"old_committed_byte_length":{"$ref":"#/$defs/u63"},"last_complete_byte_length":{"$ref":"#/$defs/u63"},"discarded_suffix_size":{"$ref":"#/$defs/positiveU63"},"discarded_suffix_sigil":{"$ref":"#/$defs/sigil"},"evidence_record_sigil":{"$ref":"#/$defs/sigil"}}}, + "quotaClaim":{"$ref":"https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/quotaClaim"}, "quotaSnapshot":{"type":"object","additionalProperties":false,"required":["quota_class","dimension","limit","used","reserved","pressure_state"],"properties":{"quota_class":{"enum":["JOURNAL","CONTROL_RECORD","STAGING","QUARANTINE","COMMITTED","MATERIALIZATION","STREAM","INODE"]},"dimension":{"enum":["BYTE","OBJECT","INODE","STREAM","JOURNAL_BYTE","CONTROL_RECORD_BYTE"]},"limit":{"$ref":"#/$defs/u63"},"used":{"$ref":"#/$defs/u63"},"reserved":{"$ref":"#/$defs/u63"},"pressure_state":{"enum":["CLEAR","PRESSURED"]}}}, + "quotaEffect":{"oneOf":[{"type":"object","additionalProperties":false,"required":["kind","snapshot"],"properties":{"kind":{"const":"INITIALIZE"},"snapshot":{"$ref":"#/$defs/quotaSnapshot"}}},{"type":"object","additionalProperties":false,"required":["kind","reservation","owner_kind","owner_id","purpose"],"properties":{"kind":{"const":"RESERVE"},"reservation":{"$ref":"#/$defs/reservation"},"owner_kind":{"enum":["TRANSFER_ATTEMPT","MATERIALIZATION","QUARANTINE","GC_TARGET","DISPOSITION","CANONICAL_REFERENCE","LEGACY_PROTECTION","RECOVERY"]},"owner_id":{"$ref":"#/$defs/opaque"},"purpose":{"enum":["PAYLOAD_LIFECYCLE","TERMINAL_OUTCOME","QUARANTINE_MOVE","DELETION_OUTCOME","CANONICAL_PIN_LIFECYCLE","RECOVERY_EVIDENCE"]}}},{"type":"object","additionalProperties":false,"required":["kind","reservation_id","state_after","consumed_claims","released_claims","remaining_claims","usage_additions","retained_for_event_types"],"properties":{"kind":{"const":"SETTLE"},"reservation_id":{"$ref":"#/$defs/opaque"},"state_after":{"enum":["RETAINED","SETTLED"]},"consumed_claims":{"$ref":"#/$defs/claimArray"},"released_claims":{"$ref":"#/$defs/claimArray"},"remaining_claims":{"$ref":"#/$defs/claimArray"},"usage_additions":{"$ref":"#/$defs/claimArray"},"retained_for_event_types":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/eventType"}}}},{"type":"object","additionalProperties":false,"required":["kind","removal","owner_kind","owner_id"],"properties":{"kind":{"const":"USAGE_REMOVED"},"removal":{"$ref":"#/$defs/quotaClaim"},"owner_kind":{"enum":["TRANSFER_ATTEMPT","MATERIALIZATION","QUARANTINE","GC_TARGET","DISPOSITION","CANONICAL_REFERENCE","LEGACY_PROTECTION","RECOVERY"]},"owner_id":{"$ref":"#/$defs/opaque"}}},{"type":"object","additionalProperties":false,"required":["kind","from_state","to_state","snapshot"],"properties":{"kind":{"const":"PRESSURE"},"from_state":{"enum":["CLEAR","PRESSURED"]},"to_state":{"enum":["CLEAR","PRESSURED"]},"snapshot":{"$ref":"#/$defs/quotaSnapshot"}}}]}, "claimArray":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/quotaClaim"}}, + "entityRevision":{"type":"object","additionalProperties":false,"required":["entity_type","entity_id","previous_revision","next_revision"],"properties":{"entity_type":{"enum":["STORE","BLOB","REPLICA","TRANSFER_REQUEST","TRANSFER_ATTEMPT","MATERIALIZATION","QUARANTINE","PROVENANCE","PROVENANCE_POLICY","RETENTION_POLICY","HOLD","REFERENCE_SET","REFERENCE_INTENT","LEGACY_PROTECTION","GC_PLAN","DISPOSITION","QUOTA","INCIDENT"]},"entity_id":{"$ref":"#/$defs/opaque"},"previous_revision":{"anyOf":[{"$ref":"#/$defs/u63"},{"type":"null"}]},"next_revision":{"$ref":"#/$defs/positiveU63"}}}, "entityRevisions":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/entityRevision"}}, + "p_storage_initialized":{"$ref":"#/$defs/p0"}, "p_storage_activation_completed":{"$ref":"#/$defs/p1"}, "p_storage_epoch_started":{"$ref":"#/$defs/p2"}, "p_storage_clock_uncertain":{"$ref":"#/$defs/p3"}, "p_storage_clock_restored":{"$ref":"#/$defs/p4"}, "p_storage_recovery_started":{"$ref":"#/$defs/p5"}, "p_storage_recovery_completed":{"$ref":"#/$defs/p6"}, "p_storage_message_rejected":{"$ref":"#/$defs/p7"}, "p_legacy_registered":{"$ref":"#/$defs/p8"}, "p_legacy_failed":{"$ref":"#/$defs/p9"}, "p_quota_entered":{"$ref":"#/$defs/p10"}, "p_quota_cleared":{"$ref":"#/$defs/p11"}, + "p0":{"type":"object","additionalProperties":false,"required":["project_id","storage_format_version","backend","conformance_profile_id","conformance_suite_sigil","quota_snapshots","tail_recovery","clock"],"properties":{"project_id":{"$ref":"#/$defs/opaque"},"storage_format_version":{"$ref":"#/$defs/opaque"},"backend":{"$ref":"#/$defs/controlRef"},"conformance_profile_id":{"$ref":"#/$defs/opaque"},"conformance_suite_sigil":{"$ref":"#/$defs/sigil"},"quota_snapshots":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/quotaSnapshot"}},"tail_recovery":{"anyOf":[{"$ref":"#/$defs/tailRecovery"},{"type":"null"}]},"clock":{"$ref":"#/$defs/clock"}}}, "p1":{"type":"object","additionalProperties":false,"required":["legacy_protection_ids","activation_evidence_sigil","clock"],"properties":{"legacy_protection_ids":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/opaque"}},"activation_evidence_sigil":{"$ref":"#/$defs/sigil"},"clock":{"$ref":"#/$defs/clock"}}}, "p2":{"type":"object","additionalProperties":false,"required":["previous_epoch","next_epoch","active_recovery_id","tail_recovery","reason","clock"],"properties":{"previous_epoch":{"$ref":"#/$defs/u63"},"next_epoch":{"$ref":"#/$defs/positiveU63"},"active_recovery_id":{"anyOf":[{"$ref":"#/$defs/opaque"},{"type":"null"}]},"tail_recovery":{"anyOf":[{"$ref":"#/$defs/tailRecovery"},{"type":"null"}]},"reason":{"$ref":"#/$defs/reason"},"clock":{"$ref":"#/$defs/clock"}}}, "p3":{"type":"object","additionalProperties":false,"required":["previous_clock","detected_clock","divergence_micros","affected_reservation_ids","reason"],"properties":{"previous_clock":{"$ref":"#/$defs/clock"},"detected_clock":{"$ref":"#/$defs/clock"},"divergence_micros":{"$ref":"#/$defs/u63"},"affected_reservation_ids":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/opaque"}},"reason":{"$ref":"#/$defs/reason"}}}, "p4":{"type":"object","additionalProperties":false,"required":["previous_observation_sigil","new_clock","expired_entity_ids","evidence_sigils"],"properties":{"previous_observation_sigil":{"$ref":"#/$defs/sigil"},"new_clock":{"$ref":"#/$defs/clock"},"expired_entity_ids":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/opaque"}},"evidence_sigils":{"$ref":"#/$defs/sigilArray"}}}, "p5":{"type":"object","additionalProperties":false,"required":["recovery_id","origin_status","previous_epoch","next_epoch","tail_recovery","open_intent_ids","clock"],"properties":{"recovery_id":{"$ref":"#/$defs/opaque"},"origin_status":{"enum":["INITIALIZING","ACTIVE"]},"previous_epoch":{"$ref":"#/$defs/u63"},"next_epoch":{"$ref":"#/$defs/positiveU63"},"tail_recovery":{"anyOf":[{"$ref":"#/$defs/tailRecovery"},{"type":"null"}]},"open_intent_ids":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/opaque"}},"clock":{"$ref":"#/$defs/clock"}}}, "p6":{"type":"object","additionalProperties":false,"required":["recovery_id","epoch","resume_status","resolved_intent_ids","evidence_sigils","clock"],"properties":{"recovery_id":{"$ref":"#/$defs/opaque"},"epoch":{"$ref":"#/$defs/positiveU63"},"resume_status":{"enum":["INITIALIZING","ACTIVE"]},"resolved_intent_ids":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/opaque"}},"evidence_sigils":{"$ref":"#/$defs/sigilArray"},"clock":{"$ref":"#/$defs/clock"}}}, "p7":{"type":"object","additionalProperties":false,"required":["message_class","message_sigil","reason"],"properties":{"message_class":{"$ref":"#/$defs/opaque"},"message_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"reason":{"$ref":"#/$defs/reason"}}}, "p8":{"type":"object","additionalProperties":false,"required":["protection","artifact_id","receipt_sigil","anchor_observation_sigil","blob_sigil","size_bytes","replica_id"],"properties":{"protection":{"$ref":"#/$defs/controlRef"},"artifact_id":{"$ref":"#/$defs/opaque"},"receipt_sigil":{"$ref":"#/$defs/sigil"},"anchor_observation_sigil":{"$ref":"#/$defs/sigil"},"blob_sigil":{"$ref":"#/$defs/sigil"},"size_bytes":{"$ref":"#/$defs/u63"},"replica_id":{"$ref":"#/$defs/replicaId"}}}, "p9":{"type":"object","additionalProperties":false,"required":["protection_id","artifact_id","receipt_sigil","reason"],"properties":{"protection_id":{"$ref":"#/$defs/opaque"},"artifact_id":{"$ref":"#/$defs/opaque"},"receipt_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"reason":{"$ref":"#/$defs/reason"}}}, "p10":{"type":"object","additionalProperties":false,"required":["snapshot","reason","clock"],"properties":{"snapshot":{"$ref":"#/$defs/quotaSnapshot"},"reason":{"$ref":"#/$defs/reason"},"clock":{"$ref":"#/$defs/clock"}}}, "p11":{"type":"object","additionalProperties":false,"required":["snapshot","evidence_sigils","clock"],"properties":{"snapshot":{"$ref":"#/$defs/quotaSnapshot"},"evidence_sigils":{"$ref":"#/$defs/sigilArray"},"clock":{"$ref":"#/$defs/clock"}}}, + "sigilArray":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}}, + "p_transfer_prepared":{"type":"object","additionalProperties":false,"required":["transfer","transfer_attempt","reservation","execution_fence"],"properties":{"transfer":{"$ref":"#/$defs/controlRef"},"transfer_attempt":{"$ref":"#/$defs/controlRef"},"reservation":{"$ref":"#/$defs/reservation"},"execution_fence":{"anyOf":[{"$ref":"#/$defs/fence"},{"type":"null"}]}}}, "p_transfer_streaming":{"type":"object","additionalProperties":false,"required":["transfer_id","transfer_attempt_id","staging_object","execution_fence","clock"],"properties":{"transfer_id":{"$ref":"#/$defs/transferId"},"transfer_attempt_id":{"$ref":"#/$defs/attemptId"},"staging_object":{"$ref":"#/$defs/object"},"execution_fence":{"anyOf":[{"$ref":"#/$defs/fence"},{"type":"null"}]},"clock":{"$ref":"#/$defs/clock"}}}, "p_transfer_verifying":{"type":"object","additionalProperties":false,"required":["transfer_id","transfer_attempt_id","staging_object","computed_blob_sigil","computed_size_bytes","verification_method","execution_fence"],"properties":{"transfer_id":{"$ref":"#/$defs/transferId"},"transfer_attempt_id":{"$ref":"#/$defs/attemptId"},"staging_object":{"$ref":"#/$defs/object"},"computed_blob_sigil":{"$ref":"#/$defs/sigil"},"computed_size_bytes":{"$ref":"#/$defs/u63"},"verification_method":{"enum":["FULL_READBACK_SHA256","CONFORMANCE_END_TO_END"]},"execution_fence":{"anyOf":[{"$ref":"#/$defs/fence"},{"type":"null"}]}}}, "p_transfer_intent":{"type":"object","additionalProperties":false,"required":["transfer_id","transfer_attempt_id","commit_intent","provisional_replica"],"properties":{"transfer_id":{"$ref":"#/$defs/transferId"},"transfer_attempt_id":{"$ref":"#/$defs/attemptId"},"commit_intent":{"$ref":"#/$defs/transferIntent"},"provisional_replica":{"$ref":"#/$defs/controlRef"}}}, "p_transfer_committed":{"type":"object","additionalProperties":false,"required":["transfer_id","transfer_attempt_id","outcome","provisional_replica_id","provisional_target_absence_evidence_sigil","blob_sigil","size_bytes","replica","backend_object","verification","residual_staging_cleanup","execution_fence"],"properties":{"transfer_id":{"$ref":"#/$defs/transferId"},"transfer_attempt_id":{"$ref":"#/$defs/attemptId"},"outcome":{"enum":["NEW_REPLICA","DEDUPLICATED_REPLICA"]},"provisional_replica_id":{"$ref":"#/$defs/replicaId"},"provisional_target_absence_evidence_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"blob_sigil":{"$ref":"#/$defs/sigil"},"size_bytes":{"$ref":"#/$defs/u63"},"replica":{"$ref":"#/$defs/controlRef"},"backend_object":{"$ref":"#/$defs/object"},"verification":{"$ref":"#/$defs/verification"},"residual_staging_cleanup":{"$ref":"#/$defs/cleanup"},"execution_fence":{"anyOf":[{"$ref":"#/$defs/fence"},{"type":"null"}]}}}, + "p_transfer_failed":{"$ref":"#/$defs/p_transfer_terminal"}, "p_transfer_cancelled":{"$ref":"#/$defs/p_transfer_terminal"}, "p_transfer_terminal":{"type":"object","additionalProperties":false,"required":["transfer_id","transfer_attempt_id","reason","staging_object","staging_state","residual_staging_cleanup","provisional_replica_id","provisional_target_absence_evidence_sigil","blob_sigil","execution_fence"],"properties":{"transfer_id":{"$ref":"#/$defs/transferId"},"transfer_attempt_id":{"$ref":"#/$defs/attemptId"},"reason":{"$ref":"#/$defs/reason"},"staging_object":{"anyOf":[{"$ref":"#/$defs/object"},{"type":"null"}]},"staging_state":{"enum":["NOT_CREATED","MISSING","HELD_FOR_DISPOSITION"]},"residual_staging_cleanup":{"$ref":"#/$defs/cleanup"},"provisional_replica_id":{"anyOf":[{"$ref":"#/$defs/replicaId"},{"type":"null"}]},"provisional_target_absence_evidence_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"blob_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"execution_fence":{"anyOf":[{"$ref":"#/$defs/fence"},{"type":"null"}]}}}, "p_transfer_quarantined":{"type":"object","additionalProperties":false,"required":["transfer_id","transfer_attempt_id","quarantine_id","quarantine_event","residual_staging_cleanup","reason","provisional_replica_id","provisional_target_absence_evidence_sigil","blob_sigil","execution_fence"],"properties":{"transfer_id":{"$ref":"#/$defs/transferId"},"transfer_attempt_id":{"$ref":"#/$defs/attemptId"},"quarantine_id":{"$ref":"#/$defs/quarantineId"},"quarantine_event":{"$ref":"#/$defs/eventRef"},"residual_staging_cleanup":{"$ref":"#/$defs/cleanup"},"reason":{"$ref":"#/$defs/reason"},"provisional_replica_id":{"anyOf":[{"$ref":"#/$defs/replicaId"},{"type":"null"}]},"provisional_target_absence_evidence_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"blob_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"execution_fence":{"anyOf":[{"$ref":"#/$defs/fence"},{"type":"null"}]}}}, + "p_replica_verification_started":{"$ref":"#/$defs/p_replica_start"}, "p_replica_start":{"type":"object","additionalProperties":false,"required":["replica_id","backend_object","method","clock"],"properties":{"replica_id":{"$ref":"#/$defs/replicaId"},"backend_object":{"$ref":"#/$defs/object"},"method":{"enum":["FULL_READBACK_SHA256","CONFORMANCE_END_TO_END"]},"clock":{"$ref":"#/$defs/clock"}}}, "p_replica_verified":{"type":"object","additionalProperties":false,"required":["replica_id","backend_object","verification","clock"],"properties":{"replica_id":{"$ref":"#/$defs/replicaId"},"backend_object":{"$ref":"#/$defs/object"},"verification":{"$ref":"#/$defs/verification"},"clock":{"$ref":"#/$defs/clock"}}}, "p_replica_expired":{"type":"object","additionalProperties":false,"required":["replica_id","due_at","clock"],"properties":{"replica_id":{"$ref":"#/$defs/replicaId"},"due_at":{"$ref":"#/$defs/timestamp"},"clock":{"$ref":"#/$defs/clock"}}}, "p_replica_corrupt":{"type":"object","additionalProperties":false,"required":["replica_id","backend_object","reason","verification"],"properties":{"replica_id":{"$ref":"#/$defs/replicaId"},"backend_object":{"$ref":"#/$defs/object"},"reason":{"$ref":"#/$defs/reason"},"verification":{"anyOf":[{"$ref":"#/$defs/verification"},{"type":"null"}]}}}, "p_blob_incident":{"type":"object","additionalProperties":false,"required":["blob_sigil","incident_id","reason","conflicting_record_sigils"],"properties":{"blob_sigil":{"$ref":"#/$defs/sigil"},"incident_id":{"$ref":"#/$defs/opaque"},"reason":{"$ref":"#/$defs/reason"},"conflicting_record_sigils":{"$ref":"#/$defs/sigilArray"}}}, + "p_materialization_prepared":{"type":"object","additionalProperties":false,"required":["materialization","source_replica_id","source_verification_sigil","reservation","execution_fence"],"properties":{"materialization":{"$ref":"#/$defs/controlRef"},"source_replica_id":{"$ref":"#/$defs/replicaId"},"source_verification_sigil":{"$ref":"#/$defs/sigil"},"reservation":{"$ref":"#/$defs/reservation"},"execution_fence":{"anyOf":[{"$ref":"#/$defs/fence"},{"type":"null"}]}}}, "p_materialization_streaming":{"type":"object","additionalProperties":false,"required":["materialization_id","destination_staging_object","clock"],"properties":{"materialization_id":{"$ref":"#/$defs/materializationId"},"destination_staging_object":{"$ref":"#/$defs/object"},"clock":{"$ref":"#/$defs/clock"}}}, "p_materialization_verifying":{"type":"object","additionalProperties":false,"required":["materialization_id","destination_staging_object","expected_blob_sigil","expected_size_bytes"],"properties":{"materialization_id":{"$ref":"#/$defs/materializationId"},"destination_staging_object":{"$ref":"#/$defs/object"},"expected_blob_sigil":{"$ref":"#/$defs/sigil"},"expected_size_bytes":{"$ref":"#/$defs/u63"}}}, "p_materialization_intent":{"type":"object","additionalProperties":false,"required":["materialization_id","commit_intent"],"properties":{"materialization_id":{"$ref":"#/$defs/materializationId"},"commit_intent":{"$ref":"#/$defs/materializationIntent"}}}, "p_materialization_committed":{"type":"object","additionalProperties":false,"required":["materialization_id","commit_intent_id","destination_object","destination_identity_sigil","verification","residual_staging_cleanup","execution_fence"],"properties":{"materialization_id":{"$ref":"#/$defs/materializationId"},"commit_intent_id":{"$ref":"#/$defs/opaque"},"destination_object":{"$ref":"#/$defs/object"},"destination_identity_sigil":{"$ref":"#/$defs/sigil"},"verification":{"$ref":"#/$defs/verification"},"residual_staging_cleanup":{"$ref":"#/$defs/cleanup"},"execution_fence":{"anyOf":[{"$ref":"#/$defs/fence"},{"type":"null"}]}}}, "p_materialization_cleanup_started":{"type":"object","additionalProperties":false,"required":["materialization_id","destination_identity_sigil","authorization_sigil","clock"],"properties":{"materialization_id":{"$ref":"#/$defs/materializationId"},"destination_identity_sigil":{"$ref":"#/$defs/sigil"},"authorization_sigil":{"$ref":"#/$defs/sigil"},"clock":{"$ref":"#/$defs/clock"}}}, "p_materialization_cleaned":{"type":"object","additionalProperties":false,"required":["materialization_id","destination_identity_sigil","cleanup_evidence_sigil","clock"],"properties":{"materialization_id":{"$ref":"#/$defs/materializationId"},"destination_identity_sigil":{"$ref":"#/$defs/sigil"},"cleanup_evidence_sigil":{"$ref":"#/$defs/sigil"},"clock":{"$ref":"#/$defs/clock"}}}, "p_materialization_cleanup_failed":{"type":"object","additionalProperties":false,"required":["materialization_id","destination_identity_sigil","cleanup_evidence_sigil","reason","clock"],"properties":{"materialization_id":{"$ref":"#/$defs/materializationId"},"destination_identity_sigil":{"$ref":"#/$defs/sigil"},"cleanup_evidence_sigil":{"$ref":"#/$defs/sigil"},"reason":{"$ref":"#/$defs/reason"},"clock":{"$ref":"#/$defs/clock"}}}, + "p_materialization_failed":{"type":"object","additionalProperties":false,"required":["materialization_id","reason","destination_staging_object","staging_state","residual_staging_cleanup","destination_object","destination_state","destination_cleanup"],"properties":{"materialization_id":{"$ref":"#/$defs/materializationId"},"reason":{"$ref":"#/$defs/reason"},"destination_staging_object":{"anyOf":[{"$ref":"#/$defs/object"},{"type":"null"}]},"staging_state":{"enum":["NOT_CREATED","MISSING","HELD_FOR_DISPOSITION"]},"residual_staging_cleanup":{"$ref":"#/$defs/cleanup"},"destination_object":{"anyOf":[{"$ref":"#/$defs/object"},{"type":"null"}]},"destination_state":{"enum":["NOT_CREATED","MISSING","HELD_FOR_DISPOSITION"]},"destination_cleanup":{"$ref":"#/$defs/cleanupResult"}}}, "p_materialization_quarantined":{"type":"object","additionalProperties":false,"required":["materialization_id","quarantine_id","quarantine_event","residual_staging_cleanup","reason"],"properties":{"materialization_id":{"$ref":"#/$defs/materializationId"},"quarantine_id":{"$ref":"#/$defs/quarantineId"},"quarantine_event":{"$ref":"#/$defs/eventRef"},"residual_staging_cleanup":{"$ref":"#/$defs/cleanup"},"reason":{"$ref":"#/$defs/reason"}}}, + "p_quarantine_intent":{"type":"object","additionalProperties":false,"required":["quarantine_id","owner_kind","owner_id","source_object","destination_object","reservation","expected_blob_sigil","expected_size_bytes","reason"],"properties":{"quarantine_id":{"$ref":"#/$defs/quarantineId"},"owner_kind":{"enum":["TRANSFER_ATTEMPT","MATERIALIZATION"]},"owner_id":{"$ref":"#/$defs/opaque"},"source_object":{"$ref":"#/$defs/object"},"destination_object":{"$ref":"#/$defs/object"},"reservation":{"$ref":"#/$defs/reservation"},"expected_blob_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"expected_size_bytes":{"anyOf":[{"$ref":"#/$defs/u63"},{"type":"null"}]},"reason":{"$ref":"#/$defs/reason"}}}, "p_quarantine_recorded":{"type":"object","additionalProperties":false,"required":["quarantine_id","owner_kind","owner_id","destination_object","verification","source_cleanup"],"properties":{"quarantine_id":{"$ref":"#/$defs/quarantineId"},"owner_kind":{"enum":["TRANSFER_ATTEMPT","MATERIALIZATION"]},"owner_id":{"$ref":"#/$defs/opaque"},"destination_object":{"$ref":"#/$defs/object"},"verification":{"$ref":"#/$defs/verification"},"source_cleanup":{"$ref":"#/$defs/cleanup"}}}, "p_quarantine_failed":{"type":"object","additionalProperties":false,"required":["quarantine_id","owner_kind","owner_id","source_object","source_cleanup","destination_object","destination_state","reason"],"properties":{"quarantine_id":{"$ref":"#/$defs/quarantineId"},"owner_kind":{"enum":["TRANSFER_ATTEMPT","MATERIALIZATION"]},"owner_id":{"$ref":"#/$defs/opaque"},"source_object":{"anyOf":[{"$ref":"#/$defs/object"},{"type":"null"}]},"source_cleanup":{"$ref":"#/$defs/cleanup"},"destination_object":{"anyOf":[{"$ref":"#/$defs/object"},{"type":"null"}]},"destination_state":{"enum":["NOT_CREATED","MISSING","HELD_FOR_DISPOSITION"]},"reason":{"$ref":"#/$defs/reason"}}}, "p_quarantine_reinspection_started":{"type":"object","additionalProperties":false,"required":["quarantine_id","reinspection_id","authorization_sigil","reservation","clock"],"properties":{"quarantine_id":{"$ref":"#/$defs/quarantineId"},"reinspection_id":{"$ref":"#/$defs/opaque"},"authorization_sigil":{"$ref":"#/$defs/sigil"},"reservation":{"$ref":"#/$defs/reservation"},"clock":{"$ref":"#/$defs/clock"}}}, "p_quarantine_reinspection_completed":{"type":"object","additionalProperties":false,"required":["quarantine_id","reinspection_id","outcome","evidence_sigils","new_transfer_id"],"properties":{"quarantine_id":{"$ref":"#/$defs/quarantineId"},"reinspection_id":{"$ref":"#/$defs/opaque"},"outcome":{"enum":["REMAINS_HELD","NEW_TRANSFER_PREPARED"]},"evidence_sigils":{"$ref":"#/$defs/sigilArray"},"new_transfer_id":{"anyOf":[{"$ref":"#/$defs/transferId"},{"type":"null"}]}}}, + "p_provenance_policy":{"type":"object","additionalProperties":false,"required":["provenance_policy"],"properties":{"provenance_policy":{"$ref":"#/$defs/controlRef"}}}, "p_provenance_recorded":{"type":"object","additionalProperties":false,"required":["provenance","blob_sigil","relation"],"properties":{"provenance":{"$ref":"#/$defs/controlRef"},"blob_sigil":{"$ref":"#/$defs/sigil"},"relation":{"enum":["IMPORTED","COPIED","CAPTURED","EXPORTED","MATERIALIZED","VERIFIED","DELETED"]}}}, "p_retention_policy":{"type":"object","additionalProperties":false,"required":["policy"],"properties":{"policy":{"$ref":"#/$defs/controlRef"}}}, "p_hold_set":{"type":"object","additionalProperties":false,"required":["hold_id","target_kind","target_id","policy_id","authorization_sigil"],"properties":{"hold_id":{"$ref":"#/$defs/id"},"target_kind":{"enum":["BLOB","REPLICA","REFERENCE_SET"]},"target_id":{"$ref":"#/$defs/opaque"},"policy_id":{"$ref":"#/$defs/policyId"},"authorization_sigil":{"$ref":"#/$defs/sigil"}}}, "p_hold_released":{"type":"object","additionalProperties":false,"required":["hold_id","release_authority","authorization_sigil","reason","clock"],"properties":{"hold_id":{"$ref":"#/$defs/id"},"release_authority":{"$ref":"#/$defs/holdReleaseAuthority"},"authorization_sigil":{"$ref":"#/$defs/sigil"},"reason":{"$ref":"#/$defs/reason"},"clock":{"$ref":"#/$defs/clock"}}}, "p_reference_set":{"type":"object","additionalProperties":false,"required":["reference_set_id","reference_set_sigil","source_identity","source_sigil"],"properties":{"reference_set_id":{"$ref":"#/$defs/referenceSetId"},"reference_set_sigil":{"$ref":"#/$defs/sigil"},"source_identity":{"$ref":"#/$defs/opaque"},"source_sigil":{"$ref":"#/$defs/sigil"}}}, + "chronicleHead":{"type":"object","additionalProperties":false,"required":["schema_version","event_count","terminal_receipt_sigil"],"properties":{"schema_version":{"const":"chronicle-head/1.1"},"event_count":{"$ref":"#/$defs/u63"},"terminal_receipt_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]}}}, "chronicleCommit":{"type":"object","additionalProperties":false,"required":["event_id","event_body_sigil","receipt_id","receipt_sigil","head"],"properties":{"event_id":{"$ref":"#/$defs/opaque"},"event_body_sigil":{"$ref":"#/$defs/sigil"},"receipt_id":{"$ref":"#/$defs/opaque"},"receipt_sigil":{"$ref":"#/$defs/sigil"},"head":{"$ref":"#/$defs/chronicleHead"}}}, "p_canonical_intent":{"type":"object","additionalProperties":false,"required":["reference_intent","expected_chronicle_head","blob_sigils","reference_set_sigils","lifecycle_reservation"],"properties":{"reference_intent":{"$ref":"#/$defs/controlRef"},"expected_chronicle_head":{"$ref":"#/$defs/chronicleHead"},"blob_sigils":{"$ref":"#/$defs/sigilArray"},"reference_set_sigils":{"$ref":"#/$defs/sigilArray"},"lifecycle_reservation":{"$ref":"#/$defs/reservation"}}}, "p_canonical_committed":{"type":"object","additionalProperties":false,"required":["reference_intent_id","chronicle_commit"],"properties":{"reference_intent_id":{"$ref":"#/$defs/referenceIntentId"},"chronicle_commit":{"$ref":"#/$defs/chronicleCommit"}}}, "p_canonical_released":{"type":"object","additionalProperties":false,"required":["reference_intent_id","release_kind","chronicle_commit","abort_authority","reason"],"properties":{"reference_intent_id":{"$ref":"#/$defs/referenceIntentId"},"release_kind":{"const":"ABORTED_BEFORE_CANONICAL_COMMIT"},"chronicle_commit":{"type":"null"},"abort_authority":{"$ref":"#/$defs/canonicalAbortAuthority"},"reason":{"$ref":"#/$defs/reason"}}}, + "canonicalAbortAuthority":{"type":"object","additionalProperties":false,"required":["kind","reference_intent_id","reference_intent_record_sigil","transition_request_id","transition_request_sigil","expected_chronicle_head","verified_chronicle_head","absence_evidence_sigil","authority_sigil"],"properties":{"kind":{"const":"HEAD_SUPERSEDED_WITHOUT_BOUND_EVENT"},"reference_intent_id":{"$ref":"#/$defs/referenceIntentId"},"reference_intent_record_sigil":{"$ref":"#/$defs/sigil"},"transition_request_id":{"$ref":"#/$defs/opaque"},"transition_request_sigil":{"$ref":"#/$defs/sigil"},"expected_chronicle_head":{"$ref":"#/$defs/chronicleHead"},"verified_chronicle_head":{"$ref":"#/$defs/chronicleHead"},"absence_evidence_sigil":{"$ref":"#/$defs/sigil"},"authority_sigil":{"$ref":"#/$defs/sigil"}}}, "holdReleaseAuthority":{"oneOf":[{"type":"object","additionalProperties":false,"required":["kind","authorization"],"properties":{"kind":{"const":"EXECUTION_ROOT"},"authorization":{"$ref":"#/$defs/controlRef"}}},{"type":"object","additionalProperties":false,"required":["kind","protocol_id","protocol_version","operational_journal_id","operational_root_id","operational_root_sigil","operational_root_plan","reference_set","hold_set_event","activation_event","inactivation_event","release_condition","terminal_authority","release_evidence","validator_id","validator_version","validator_sigil","authority_sigil"],"properties":{"kind":{"const":"PATCH_OPERATIONAL_ROOT"},"protocol_id":{"const":"benchwork.patch-promotion"},"protocol_version":{"const":"1.0"},"operational_journal_id":{"$ref":"#/$defs/opaque"},"operational_root_id":{"$ref":"#/$defs/opaque"},"operational_root_sigil":{"$ref":"#/$defs/sigil"},"operational_root_plan":{"$ref":"#/$defs/controlRef"},"reference_set":{"type":"object","additionalProperties":false,"required":["reference_set_id","reference_set_sigil"],"properties":{"reference_set_id":{"$ref":"#/$defs/referenceSetId"},"reference_set_sigil":{"$ref":"#/$defs/sigil"}}},"hold_set_event":{"$ref":"#/$defs/eventRef"},"activation_event":{"$ref":"#/$defs/controlRef"},"inactivation_event":{"$ref":"#/$defs/controlRef"},"release_condition":{"enum":["NON_PARTIAL_OUTCOME_OBSERVED","RESOLVED_RECOVERY_OBSERVED","ABANDONED_WITH_DISPOSITION","JOURNAL_RECOVERY_COMPLETED"]},"terminal_authority":{"$ref":"#/$defs/controlRef"},"release_evidence":{"$ref":"#/$defs/controlRef"},"validator_id":{"const":"benchwork.patch-operational-root-release"},"validator_version":{"const":"1.1"},"validator_sigil":{"$ref":"#/$defs/sigil"},"authority_sigil":{"$ref":"#/$defs/sigil"}}}]}, + "p_gc_plan_created":{"type":"object","additionalProperties":false,"required":["gc_plan","root_snapshot_sigil","closure_proof_sigil","target_ids"],"properties":{"gc_plan":{"$ref":"#/$defs/controlRef"},"root_snapshot_sigil":{"$ref":"#/$defs/sigil"},"closure_proof_sigil":{"$ref":"#/$defs/sigil"},"target_ids":{"$ref":"#/$defs/opaqueArray"}}}, "p_gc_plan_authorized":{"type":"object","additionalProperties":false,"required":["gc_plan_id","authorization_sigil","authorized_target_ids","expires_at","clock"],"properties":{"gc_plan_id":{"$ref":"#/$defs/gcPlanId"},"authorization_sigil":{"$ref":"#/$defs/sigil"},"authorized_target_ids":{"$ref":"#/$defs/opaqueArray"},"expires_at":{"$ref":"#/$defs/timestamp"},"clock":{"$ref":"#/$defs/clock"}}}, "p_gc_execution_started":{"type":"object","additionalProperties":false,"required":["gc_plan_id","root_revalidation_sigil","clock"],"properties":{"gc_plan_id":{"$ref":"#/$defs/gcPlanId"},"root_revalidation_sigil":{"$ref":"#/$defs/sigil"},"clock":{"$ref":"#/$defs/clock"}}}, "p_gc_target_skipped":{"type":"object","additionalProperties":false,"required":["gc_plan_id","target_id","replica_id","backend_object","reason","root_revalidation_sigil"],"properties":{"gc_plan_id":{"$ref":"#/$defs/gcPlanId"},"target_id":{"$ref":"#/$defs/opaque"},"replica_id":{"$ref":"#/$defs/replicaId"},"backend_object":{"$ref":"#/$defs/object"},"reason":{"$ref":"#/$defs/reason"},"root_revalidation_sigil":{"$ref":"#/$defs/sigil"}}}, "p_gc_target_deletion_started":{"type":"object","additionalProperties":false,"required":["gc_plan_id","target_id","deletion_intent_id","replica_id","backend_object","root_revalidation_sigil","authorization_sigil","outcome_reservation"],"properties":{"gc_plan_id":{"$ref":"#/$defs/gcPlanId"},"target_id":{"$ref":"#/$defs/opaque"},"deletion_intent_id":{"$ref":"#/$defs/opaque"},"replica_id":{"$ref":"#/$defs/replicaId"},"backend_object":{"$ref":"#/$defs/object"},"root_revalidation_sigil":{"$ref":"#/$defs/sigil"},"authorization_sigil":{"$ref":"#/$defs/sigil"},"outcome_reservation":{"$ref":"#/$defs/reservation"}}}, "p_gc_target_deleted":{"type":"object","additionalProperties":false,"required":["gc_plan_id","target_id","deletion_intent_id","replica_id","backend_object","deletion_evidence_sigil","clock"],"properties":{"gc_plan_id":{"$ref":"#/$defs/gcPlanId"},"target_id":{"$ref":"#/$defs/opaque"},"deletion_intent_id":{"$ref":"#/$defs/opaque"},"replica_id":{"$ref":"#/$defs/replicaId"},"backend_object":{"$ref":"#/$defs/object"},"deletion_evidence_sigil":{"$ref":"#/$defs/sigil"},"clock":{"$ref":"#/$defs/clock"}}}, "p_gc_target_failed":{"type":"object","additionalProperties":false,"required":["gc_plan_id","target_id","deletion_intent_id","replica_id","backend_object","reason","clock"],"properties":{"gc_plan_id":{"$ref":"#/$defs/gcPlanId"},"target_id":{"$ref":"#/$defs/opaque"},"deletion_intent_id":{"$ref":"#/$defs/opaque"},"replica_id":{"$ref":"#/$defs/replicaId"},"backend_object":{"$ref":"#/$defs/object"},"reason":{"$ref":"#/$defs/reason"},"clock":{"$ref":"#/$defs/clock"}}}, "p_gc_completed":{"type":"object","additionalProperties":false,"required":["gc_plan_id","deleted_target_ids","skipped_target_ids","failed_target_ids","outcome_sigil","clock"],"properties":{"gc_plan_id":{"$ref":"#/$defs/gcPlanId"},"deleted_target_ids":{"$ref":"#/$defs/opaqueArray"},"skipped_target_ids":{"$ref":"#/$defs/opaqueArray"},"failed_target_ids":{"$ref":"#/$defs/opaqueArray"},"outcome_sigil":{"$ref":"#/$defs/sigil"},"clock":{"$ref":"#/$defs/clock"}}}, "p_gc_aborted":{"type":"object","additionalProperties":false,"required":["gc_plan_id","reason","clock"],"properties":{"gc_plan_id":{"$ref":"#/$defs/gcPlanId"},"reason":{"$ref":"#/$defs/reason"},"clock":{"$ref":"#/$defs/clock"}}}, + "targetKind":{"enum":["STAGING","MATERIALIZATION_STAGING","MATERIALIZATION_DESTINATION","QUARANTINE"]}, "p_disposition_authorized":{"type":"object","additionalProperties":false,"required":["disposition","target_kind","target_id","target_object","outcome_reservation","clock"],"properties":{"disposition":{"$ref":"#/$defs/controlRef"},"target_kind":{"$ref":"#/$defs/targetKind"},"target_id":{"$ref":"#/$defs/opaque"},"target_object":{"$ref":"#/$defs/object"},"outcome_reservation":{"$ref":"#/$defs/reservation"},"clock":{"$ref":"#/$defs/clock"}}}, "p_disposition_started":{"type":"object","additionalProperties":false,"required":["disposition_id","execution_intent_id","target_kind","target_id","target_object","authorization_sigil","clock"],"properties":{"disposition_id":{"$ref":"#/$defs/dispositionId"},"execution_intent_id":{"$ref":"#/$defs/opaque"},"target_kind":{"$ref":"#/$defs/targetKind"},"target_id":{"$ref":"#/$defs/opaque"},"target_object":{"$ref":"#/$defs/object"},"authorization_sigil":{"$ref":"#/$defs/sigil"},"clock":{"$ref":"#/$defs/clock"}}}, "p_disposition_completed":{"type":"object","additionalProperties":false,"required":["disposition_id","execution_intent_id","target_kind","target_id","target_object","deletion_evidence_sigil","clock"],"properties":{"disposition_id":{"$ref":"#/$defs/dispositionId"},"execution_intent_id":{"$ref":"#/$defs/opaque"},"target_kind":{"$ref":"#/$defs/targetKind"},"target_id":{"$ref":"#/$defs/opaque"},"target_object":{"$ref":"#/$defs/object"},"deletion_evidence_sigil":{"$ref":"#/$defs/sigil"},"clock":{"$ref":"#/$defs/clock"}}}, "p_disposition_failed":{"type":"object","additionalProperties":false,"required":["disposition_id","execution_intent_id","target_kind","target_id","target_object","reason","clock"],"properties":{"disposition_id":{"$ref":"#/$defs/dispositionId"},"execution_intent_id":{"anyOf":[{"$ref":"#/$defs/opaque"},{"type":"null"}]},"target_kind":{"$ref":"#/$defs/targetKind"},"target_id":{"$ref":"#/$defs/opaque"},"target_object":{"$ref":"#/$defs/object"},"reason":{"$ref":"#/$defs/reason"},"clock":{"$ref":"#/$defs/clock"}}}, "opaqueArray":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/opaque"}}, + "e_storage_initialized":{"properties":{"event_type":{"const":"storage.initialized"},"payload":{"$ref":"#/$defs/p_storage_initialized"}}},"e_storage_activation_completed":{"properties":{"event_type":{"const":"storage.activation_completed"},"payload":{"$ref":"#/$defs/p_storage_activation_completed"}}},"e_storage_epoch_started":{"properties":{"event_type":{"const":"storage.epoch_started"},"payload":{"$ref":"#/$defs/p_storage_epoch_started"}}},"e_storage_clock_uncertain":{"properties":{"event_type":{"const":"storage.clock_uncertain"},"payload":{"$ref":"#/$defs/p_storage_clock_uncertain"}}},"e_storage_clock_restored":{"properties":{"event_type":{"const":"storage.clock_restored"},"payload":{"$ref":"#/$defs/p_storage_clock_restored"}}},"e_storage_recovery_started":{"properties":{"event_type":{"const":"storage.recovery_started"},"payload":{"$ref":"#/$defs/p_storage_recovery_started"}}},"e_storage_recovery_completed":{"properties":{"event_type":{"const":"storage.recovery_completed"},"payload":{"$ref":"#/$defs/p_storage_recovery_completed"}}},"e_storage_message_rejected":{"properties":{"event_type":{"const":"storage.message_rejected"},"payload":{"$ref":"#/$defs/p_storage_message_rejected"}}},"e_legacy_registered":{"properties":{"event_type":{"const":"legacy_v1.protection_registered"},"payload":{"$ref":"#/$defs/p_legacy_registered"}}},"e_legacy_failed":{"properties":{"event_type":{"const":"legacy_v1.protection_failed"},"payload":{"$ref":"#/$defs/p_legacy_failed"}}},"e_quota_entered":{"properties":{"event_type":{"const":"quota.pressure_entered"},"payload":{"$ref":"#/$defs/p_quota_entered"}}},"e_quota_cleared":{"properties":{"event_type":{"const":"quota.pressure_cleared"},"payload":{"$ref":"#/$defs/p_quota_cleared"}}}, + "e_transfer_prepared":{"properties":{"event_type":{"const":"transfer.prepared"},"payload":{"$ref":"#/$defs/p_transfer_prepared"}}},"e_transfer_streaming":{"properties":{"event_type":{"const":"transfer.streaming_started"},"payload":{"$ref":"#/$defs/p_transfer_streaming"}}},"e_transfer_verifying":{"properties":{"event_type":{"const":"transfer.verification_started"},"payload":{"$ref":"#/$defs/p_transfer_verifying"}}},"e_transfer_intent":{"properties":{"event_type":{"const":"transfer.commit_intent_recorded"},"payload":{"$ref":"#/$defs/p_transfer_intent"}}},"e_transfer_committed":{"properties":{"event_type":{"const":"transfer.committed"},"payload":{"$ref":"#/$defs/p_transfer_committed"}}},"e_transfer_failed":{"properties":{"event_type":{"const":"transfer.failed"},"payload":{"$ref":"#/$defs/p_transfer_failed"}}},"e_transfer_cancelled":{"properties":{"event_type":{"const":"transfer.cancelled"},"payload":{"$ref":"#/$defs/p_transfer_cancelled"}}},"e_transfer_quarantined":{"properties":{"event_type":{"const":"transfer.quarantined"},"payload":{"$ref":"#/$defs/p_transfer_quarantined"}}},"e_replica_verification_started":{"properties":{"event_type":{"const":"replica.verification_started"},"payload":{"$ref":"#/$defs/p_replica_verification_started"}}},"e_replica_verified":{"properties":{"event_type":{"const":"replica.verified"},"payload":{"$ref":"#/$defs/p_replica_verified"}}},"e_replica_expired":{"properties":{"event_type":{"const":"replica.verification_expired"},"payload":{"$ref":"#/$defs/p_replica_expired"}}},"e_replica_corrupt":{"properties":{"event_type":{"const":"replica.corrupt"},"payload":{"$ref":"#/$defs/p_replica_corrupt"}}},"e_blob_incident":{"properties":{"event_type":{"const":"blob.incident_recorded"},"payload":{"$ref":"#/$defs/p_blob_incident"}}}, + "e_materialization_prepared":{"properties":{"event_type":{"const":"materialization.prepared"},"payload":{"$ref":"#/$defs/p_materialization_prepared"}}},"e_materialization_streaming":{"properties":{"event_type":{"const":"materialization.streaming_started"},"payload":{"$ref":"#/$defs/p_materialization_streaming"}}},"e_materialization_verifying":{"properties":{"event_type":{"const":"materialization.verification_started"},"payload":{"$ref":"#/$defs/p_materialization_verifying"}}},"e_materialization_intent":{"properties":{"event_type":{"const":"materialization.commit_intent_recorded"},"payload":{"$ref":"#/$defs/p_materialization_intent"}}},"e_materialization_committed":{"properties":{"event_type":{"const":"materialization.committed"},"payload":{"$ref":"#/$defs/p_materialization_committed"}}},"e_materialization_cleanup_started":{"properties":{"event_type":{"const":"materialization.cleanup_started"},"payload":{"$ref":"#/$defs/p_materialization_cleanup_started"}}},"e_materialization_cleaned":{"properties":{"event_type":{"const":"materialization.cleaned"},"payload":{"$ref":"#/$defs/p_materialization_cleaned"}}},"e_materialization_cleanup_failed":{"properties":{"event_type":{"const":"materialization.cleanup_failed"},"payload":{"$ref":"#/$defs/p_materialization_cleanup_failed"}}},"e_materialization_failed":{"properties":{"event_type":{"const":"materialization.failed"},"payload":{"$ref":"#/$defs/p_materialization_failed"}}},"e_materialization_quarantined":{"properties":{"event_type":{"const":"materialization.quarantined"},"payload":{"$ref":"#/$defs/p_materialization_quarantined"}}}, + "e_quarantine_intent":{"properties":{"event_type":{"const":"quarantine.intent_recorded"},"payload":{"$ref":"#/$defs/p_quarantine_intent"}}},"e_quarantine_recorded":{"properties":{"event_type":{"const":"quarantine.recorded"},"payload":{"$ref":"#/$defs/p_quarantine_recorded"}}},"e_quarantine_failed":{"properties":{"event_type":{"const":"quarantine.failed"},"payload":{"$ref":"#/$defs/p_quarantine_failed"}}},"e_quarantine_reinspection_started":{"properties":{"event_type":{"const":"quarantine.reinspection_started"},"payload":{"$ref":"#/$defs/p_quarantine_reinspection_started"}}},"e_quarantine_reinspection_completed":{"properties":{"event_type":{"const":"quarantine.reinspection_completed"},"payload":{"$ref":"#/$defs/p_quarantine_reinspection_completed"}}}, + "e_provenance_policy":{"properties":{"event_type":{"const":"provenance.policy_registered"},"payload":{"$ref":"#/$defs/p_provenance_policy"}}},"e_provenance_recorded":{"properties":{"event_type":{"const":"provenance.recorded"},"payload":{"$ref":"#/$defs/p_provenance_recorded"}}},"e_retention_policy":{"properties":{"event_type":{"const":"retention.policy_registered"},"payload":{"$ref":"#/$defs/p_retention_policy"}}},"e_hold_set":{"properties":{"event_type":{"const":"retention.hold_set"},"payload":{"$ref":"#/$defs/p_hold_set"}}},"e_hold_released":{"properties":{"event_type":{"const":"retention.hold_released"},"payload":{"$ref":"#/$defs/p_hold_released"}}},"e_reference_set":{"properties":{"event_type":{"const":"reference_set.registered"},"payload":{"$ref":"#/$defs/p_reference_set"}}},"e_canonical_intent":{"properties":{"event_type":{"const":"canonical_reference.intent_recorded"},"payload":{"$ref":"#/$defs/p_canonical_intent"}}},"e_canonical_committed":{"properties":{"event_type":{"const":"canonical_reference.committed"},"payload":{"$ref":"#/$defs/p_canonical_committed"}}},"e_canonical_released":{"properties":{"event_type":{"const":"canonical_reference.released"},"payload":{"$ref":"#/$defs/p_canonical_released"}}}, + "e_gc_plan_created":{"properties":{"event_type":{"const":"gc.plan_created"},"payload":{"$ref":"#/$defs/p_gc_plan_created"}}},"e_gc_plan_authorized":{"properties":{"event_type":{"const":"gc.plan_authorized"},"payload":{"$ref":"#/$defs/p_gc_plan_authorized"}}},"e_gc_execution_started":{"properties":{"event_type":{"const":"gc.execution_started"},"payload":{"$ref":"#/$defs/p_gc_execution_started"}}},"e_gc_target_skipped":{"properties":{"event_type":{"const":"gc.target_skipped"},"payload":{"$ref":"#/$defs/p_gc_target_skipped"}}},"e_gc_target_deletion_started":{"properties":{"event_type":{"const":"gc.target_deletion_started"},"payload":{"$ref":"#/$defs/p_gc_target_deletion_started"}}},"e_gc_target_deleted":{"properties":{"event_type":{"const":"gc.target_deleted"},"payload":{"$ref":"#/$defs/p_gc_target_deleted"}}},"e_gc_target_failed":{"properties":{"event_type":{"const":"gc.target_failed"},"payload":{"$ref":"#/$defs/p_gc_target_failed"}}},"e_gc_completed":{"properties":{"event_type":{"const":"gc.completed"},"payload":{"$ref":"#/$defs/p_gc_completed"}}},"e_gc_aborted":{"properties":{"event_type":{"const":"gc.aborted"},"payload":{"$ref":"#/$defs/p_gc_aborted"}}},"e_disposition_authorized":{"properties":{"event_type":{"const":"disposition.authorized"},"payload":{"$ref":"#/$defs/p_disposition_authorized"}}},"e_disposition_started":{"properties":{"event_type":{"const":"disposition.started"},"payload":{"$ref":"#/$defs/p_disposition_started"}}},"e_disposition_completed":{"properties":{"event_type":{"const":"disposition.completed"},"payload":{"$ref":"#/$defs/p_disposition_completed"}}},"e_disposition_failed":{"properties":{"event_type":{"const":"disposition.failed"},"payload":{"$ref":"#/$defs/p_disposition_failed"}}} + } +} diff --git a/schemas/artifact-storage-journal-head-1.0.json b/schemas/artifact-storage-journal-head-1.0.json new file mode 100644 index 0000000..98b96b2 --- /dev/null +++ b/schemas/artifact-storage-journal-head-1.0.json @@ -0,0 +1,2 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/artifact-storage-journal-head/1.0","title":"Artifact Storage Journal Head v1","description":"Closed RFC-0013 replaceable Journal Head wire contract; it has no self-Sigil field.","type":"object","additionalProperties":false,"required":["schema_version","journal_id","storage_format_version","event_count","last_sequence","last_event_sigil","committed_byte_length","current_epoch","state_sigil","updated_at"],"properties":{"schema_version":{"const":"artifact-storage-journal-head/1.0"},"journal_id":{"$ref":"#/$defs/journalId"},"storage_format_version":{"$ref":"#/$defs/opaque"},"event_count":{"$ref":"#/$defs/u63"},"last_sequence":{"$ref":"#/$defs/u63"},"last_event_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"committed_byte_length":{"$ref":"#/$defs/u63"},"current_epoch":{"$ref":"#/$defs/u63"},"state_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"updated_at":{"$ref":"#/$defs/timestamp"}},"$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"opaque":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"journalId":{"type":"string","pattern":"^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128}}} + diff --git a/schemas/artifact-storage-legacy-protection-1.0.json b/schemas/artifact-storage-legacy-protection-1.0.json new file mode 100644 index 0000000..7a2ab08 --- /dev/null +++ b/schemas/artifact-storage-legacy-protection-1.0.json @@ -0,0 +1,2 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/artifact-storage-legacy-protection/1.0","type":"object","additionalProperties":false,"required":["schema_version","protection_id","artifact_id","program_id","artifact_receipt_sigil","recorded_uri_sigil","lexical_identity_sigil","resolved_file_identity_sigil","anchor_observation_sigil","blob","protected_replica_id","transfer","verification","exclusion","registered_at","record_sigil"],"properties":{"schema_version":{"const":"artifact-storage-legacy-protection/1.0"},"protection_id":{"$ref":"#/$defs/o"},"artifact_id":{"$ref":"#/$defs/o"},"program_id":{"$ref":"#/$defs/o"},"artifact_receipt_sigil":{"$ref":"#/$defs/s"},"recorded_uri_sigil":{"$ref":"#/$defs/s"},"lexical_identity_sigil":{"$ref":"#/$defs/s"},"resolved_file_identity_sigil":{"$ref":"#/$defs/s"},"anchor_observation_sigil":{"$ref":"#/$defs/s"},"blob":{"$ref":"#/$defs/blob"},"protected_replica_id":{"$ref":"#/$defs/sr"},"transfer":{"$ref":"#/$defs/tr"},"verification":{"$ref":"#/$defs/ver"},"exclusion":{"$ref":"#/$defs/ex"},"registered_at":{"$ref":"#/$defs/t"},"record_sigil":{"$ref":"#/$defs/s"}},"$defs":{"s":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"o":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256},"u":{"type":"integer","minimum":0,"maximum":9223372036854775807},"p":{"type":"integer","minimum":1,"maximum":9223372036854775807},"t":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$"},"sr":{"type":"string","pattern":"^SR-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128},"st":{"type":"string","pattern":"^ST-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128},"sa":{"type":"string","pattern":"^SA-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128},"sj":{"type":"string","pattern":"^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128},"se":{"type":"string","pattern":"^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128},"sp":{"type":"string","pattern":"^SP-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128},"blob":{"type":"object","additionalProperties":false,"required":["blob_sigil","size_bytes"],"properties":{"blob_sigil":{"$ref":"#/$defs/s"},"size_bytes":{"$ref":"#/$defs/u"}}},"event":{"type":"object","additionalProperties":false,"required":["journal_id","event_id","sequence","event_sigil"],"properties":{"journal_id":{"$ref":"#/$defs/sj"},"event_id":{"$ref":"#/$defs/se"},"sequence":{"$ref":"#/$defs/p"},"event_sigil":{"$ref":"#/$defs/s"}}},"tr":{"type":"object","additionalProperties":false,"required":["transfer_id","transfer_attempt_id","request_record_sigil","attempt_record_sigil","terminal_event"],"properties":{"transfer_id":{"$ref":"#/$defs/st"},"transfer_attempt_id":{"$ref":"#/$defs/sa"},"request_record_sigil":{"$ref":"#/$defs/s"},"attempt_record_sigil":{"$ref":"#/$defs/s"},"terminal_event":{"$ref":"#/$defs/event"}}},"ver":{"type":"object","additionalProperties":false,"required":["method","evidence_sigil","verified_at","next_due_at"],"properties":{"method":{"enum":["FULL_READBACK_SHA256","CONFORMANCE_END_TO_END"]},"evidence_sigil":{"$ref":"#/$defs/s"},"verified_at":{"$ref":"#/$defs/t"},"next_due_at":{"anyOf":[{"$ref":"#/$defs/t"},{"type":"null"}]}}},"ex":{"type":"object","additionalProperties":false,"required":["anchor_disposition","managed_copy_gc","policy_id","authorization_sigil"],"properties":{"anchor_disposition":{"const":"PERMANENTLY_EXCLUDED"},"managed_copy_gc":{"const":"PERMANENTLY_PROTECTED"},"policy_id":{"$ref":"#/$defs/sp"},"authorization_sigil":{"$ref":"#/$defs/s"}}}}} + diff --git a/schemas/artifact-storage-recovery-marker-1.0.json b/schemas/artifact-storage-recovery-marker-1.0.json new file mode 100644 index 0000000..1720e16 --- /dev/null +++ b/schemas/artifact-storage-recovery-marker-1.0.json @@ -0,0 +1,2 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/artifact-storage-recovery-marker/1.0","title":"Artifact Storage Recovery Marker v1","description":"Closed RFC-0013 Recovery Marker wire contract; raw bytes, frame decoding, evidence chains, and replay are outside this local contract.","type":"object","additionalProperties":false,"required":["schema_version","recovery_id","journal_id","prior_head_sigil","old_committed_byte_length","last_complete_byte_length","discarded_suffix_size","discarded_suffix_sigil","evidence_record_sigil","phase","recovery_event_id","recovery_event_sigil","recovery_event_seed_record_sigil","recovery_frame_start","recovery_frame_size","recovery_frame_sigil","prepared_frame_evidence_record_sigil","retry_count","latest_retry_evidence_record_sigil","created_at","updated_at","record_sigil"],"properties":{"schema_version":{"const":"artifact-storage-recovery-marker/1.0"},"recovery_id":{"$ref":"#/$defs/opaque"},"journal_id":{"$ref":"#/$defs/journalId"},"prior_head_sigil":{"$ref":"#/$defs/sigil"},"old_committed_byte_length":{"$ref":"#/$defs/u63"},"last_complete_byte_length":{"$ref":"#/$defs/u63"},"discarded_suffix_size":{"$ref":"#/$defs/positiveU63"},"discarded_suffix_sigil":{"$ref":"#/$defs/sigil"},"evidence_record_sigil":{"$ref":"#/$defs/sigil"},"phase":{"enum":["EVIDENCE_DURABLE","TAIL_TRUNCATED","RECOVERY_EVENT_ID_DURABLE","RECOVERY_EVENT_PREPARED","RECOVERY_EVENT_RETRY_EVIDENCE_DURABLE","RECOVERY_EVENT_COMMITTED"]},"recovery_event_id":{"anyOf":[{"$ref":"#/$defs/eventId"},{"type":"null"}]},"recovery_event_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"recovery_event_seed_record_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"recovery_frame_start":{"anyOf":[{"$ref":"#/$defs/u63"},{"type":"null"}]},"recovery_frame_size":{"anyOf":[{"$ref":"#/$defs/positiveU63"},{"type":"null"}]},"recovery_frame_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"prepared_frame_evidence_record_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"retry_count":{"$ref":"#/$defs/u63"},"latest_retry_evidence_record_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"created_at":{"$ref":"#/$defs/timestamp"},"updated_at":{"$ref":"#/$defs/timestamp"},"record_sigil":{"$ref":"#/$defs/sigil"}},"$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"positiveU63":{"type":"integer","minimum":1,"maximum":9223372036854775807},"opaque":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"journalId":{"type":"string","pattern":"^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"eventId":{"type":"string","pattern":"^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128}}} + diff --git a/schemas/artifact-storage-reference-intent-1.0.json b/schemas/artifact-storage-reference-intent-1.0.json new file mode 100644 index 0000000..d41fcee --- /dev/null +++ b/schemas/artifact-storage-reference-intent-1.0.json @@ -0,0 +1,2 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/artifact-storage-reference-intent/1.0","title":"Artifact Storage Reference Intent v1","description":"Closed RFC-0013 artifact-storage-reference-intent/1.0 record. Contract-only validation does not resolve Reference Sets, graph closure, Chronicle, authorization, actor, or intent state.","type":"object","additionalProperties":false,"required":["schema_version","reference_intent_id","transition_request_id","transition_request_sigil","canonical_event_type","expected_chronicle_head","reference_sets","blob_sigils","actor_id","authorization_sigil","idempotency_key_sigil","requested_at","record_sigil"],"properties":{"schema_version":{"const":"artifact-storage-reference-intent/1.0"},"reference_intent_id":{"$ref":"#/$defs/intentId"},"transition_request_id":{"$ref":"#/$defs/opaque"},"transition_request_sigil":{"$ref":"#/$defs/sigil"},"canonical_event_type":{"enum":["agent-result.accepted","patch.proposed","patch.validation.recorded","patch.promotion.authorized","patch.promotion.rejected","patch.promotion.outcome-recorded","patch.promotion.recovery-recorded"]},"expected_chronicle_head":{"$ref":"#/$defs/chronicleHeadRef"},"reference_sets":{"type":"array","minItems":1,"maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/referenceSetRef"}},"blob_sigils":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}},"actor_id":{"$ref":"#/$defs/opaque"},"authorization_sigil":{"$ref":"#/$defs/sigil"},"idempotency_key_sigil":{"$ref":"#/$defs/sigil"},"requested_at":{"$ref":"#/$defs/timestamp"},"record_sigil":{"$ref":"#/$defs/sigil"}},"$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"opaque":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256},"intentId":{"type":"string","pattern":"^RI-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128},"referenceSetId":{"type":"string","pattern":"^RS-[A-Za-z0-9][A-Za-z0-9._:-]*$","minLength":4,"maxLength":128},"referenceSetRef":{"type":"object","additionalProperties":false,"required":["reference_set_id","reference_set_sigil"],"properties":{"reference_set_id":{"$ref":"#/$defs/referenceSetId"},"reference_set_sigil":{"$ref":"#/$defs/sigil"}}},"chronicleHeadRef":{"type":"object","additionalProperties":false,"required":["schema_version","event_count","terminal_receipt_sigil"],"properties":{"schema_version":{"const":"chronicle-head/1.1"},"event_count":{"$ref":"#/$defs/u63"},"terminal_receipt_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]}}}}} + diff --git a/schemas/artifact-storage-reference-set-1.0.json b/schemas/artifact-storage-reference-set-1.0.json new file mode 100644 index 0000000..946aa80 --- /dev/null +++ b/schemas/artifact-storage-reference-set-1.0.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-storage-reference-set/1.0", + "title": "Artifact Storage Reference Set v1", + "description": "Closed RFC-0013 artifact-storage-reference-set/1.0 record. This contract-only increment validates self-contained structure, deterministic local identifiers, and edge consistency; it does not resolve sources, events, extractors, validators, or graph closure.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "reference_set_id", "source", "extractor", "edges", "validation", "registration_event_id", "created_at", "reference_set_sigil"], + "properties": { + "schema_version": {"const": "artifact-storage-reference-set/1.0"}, + "reference_set_id": {"$ref": "#/$defs/referenceSetId"}, + "source": {"$ref": "#/$defs/referenceSource"}, + "extractor": {"$ref": "#/$defs/referenceExtractor"}, + "edges": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/referenceEdge"}}, + "validation": {"$ref": "#/$defs/referenceValidation"}, + "registration_event_id": {"$ref": "#/$defs/storageEventId"}, + "created_at": {"$ref": "#/$defs/timestamp"}, + "reference_set_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "opaque": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 256}, + "referenceSetId": {"type": "string", "pattern": "^RS-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "holdId": {"type": "string", "pattern": "^SH-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "storageEventId": {"type": "string", "pattern": "^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "replicaId": {"type": "string", "pattern": "^SR-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "referenceSource": {"type": "object", "additionalProperties": false, "required": ["kind", "identity", "schema_version", "sigil"], "properties": {"kind": {"enum": ["CANONICAL_OBJECT", "OPERATIONAL_CONTROL_RECORD", "BLOB_MANIFEST"]}, "identity": {"$ref": "#/$defs/opaque"}, "schema_version": {"$ref": "#/$defs/opaque"}, "sigil": {"$ref": "#/$defs/sigil"}}}, + "referenceExtractor": {"type": "object", "additionalProperties": false, "required": ["extractor_id", "extractor_version", "extractor_sigil"], "properties": {"extractor_id": {"$ref": "#/$defs/opaque"}, "extractor_version": {"$ref": "#/$defs/opaque"}, "extractor_sigil": {"$ref": "#/$defs/sigil"}}}, + "referenceValidation": {"type": "object", "additionalProperties": false, "required": ["validator_id", "validator_version", "validator_sigil", "source_validation_sigil", "evidence_sigils"], "properties": {"validator_id": {"$ref": "#/$defs/opaque"}, "validator_version": {"$ref": "#/$defs/opaque"}, "validator_sigil": {"$ref": "#/$defs/sigil"}, "source_validation_sigil": {"$ref": "#/$defs/sigil"}, "evidence_sigils": {"type": "array", "minItems": 1, "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/sigil"}}}}, + "referenceEdge": {"type": "object", "additionalProperties": false, "required": ["relationship", "target_kind", "target_identity", "target_sigil"], "properties": {"relationship": {"enum": ["BUNDLE_RETAINS_MEMBER", "CANONICAL_BINDS_BLOB", "CANONICAL_RETAINS_OBJECT", "CONTROL_RETAINS_BLOB", "CONTROL_RETAINS_CONTROL", "HOLD_PROTECTS_BLOB", "JOB_REQUIRES_BLOB", "PATCH_RETAINS_BASE", "PATCH_RETAINS_POSTIMAGE", "REFERENCE_SET_RETAINS_SET", "TRANSFER_PINS_REPLICA"]}, "target_kind": {"enum": ["BLOB", "REPLICA", "REFERENCE_SET", "CANONICAL_OBJECT", "OPERATIONAL_CONTROL_RECORD"]}, "target_identity": {"$ref": "#/$defs/opaque"}, "target_sigil": {"$ref": "#/$defs/sigil"}}, "allOf": [{"if": {"properties": {"target_kind": {"const": "BLOB"}}}, "then": {"properties": {"target_identity": {"$ref": "#/$defs/sigil"}}}}, {"if": {"properties": {"target_kind": {"const": "REPLICA"}}}, "then": {"properties": {"target_identity": {"$ref": "#/$defs/replicaId"}}}}, {"if": {"properties": {"target_kind": {"const": "REFERENCE_SET"}}}, "then": {"properties": {"target_identity": {"$ref": "#/$defs/referenceSetId"}}}}]} + } +} diff --git a/schemas/artifact-storage-state-1.0.json b/schemas/artifact-storage-state-1.0.json new file mode 100644 index 0000000..2500829 --- /dev/null +++ b/schemas/artifact-storage-state-1.0.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-storage-state/1.0", + "title": "Artifact Storage State v1", + "description": "Closed RFC-0013 deterministic Storage Journal replay projection. Replay relations, ordering, derived counters, and self-Sigil computation are semantic checks.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "journal_id", "storage_format_version", "project_id", "backend_profile_id", "backend_profile_sigil", "conformance_profile_id", "conformance_suite_sigil", "store_status", "active_recovery_id", "recovery_origin_status", "clock_status", "clock_anchor", "current_epoch", "applied_event_count", "last_event_sigil", "recoveries", "blobs", "replicas", "transfer_requests", "transfer_attempts", "materializations", "quarantines", "provenance", "provenance_policies", "retention_policies", "holds", "reference_sets", "legacy_v1_protections", "gc_plans", "canonical_reference_intents", "dispositions", "quota_reservations", "open_intents", "incidents", "availability_counters", "quota_counters", "state_sigil"], + "properties": { + "schema_version": {"const": "artifact-storage-state/1.0"}, + "journal_id": {"$ref": "#/$defs/journalId"}, "storage_format_version": {"$ref": "#/$defs/opaque"}, "project_id": {"$ref": "#/$defs/opaque"}, + "backend_profile_id": {"$ref": "#/$defs/opaque"}, "backend_profile_sigil": {"$ref": "#/$defs/sigil"}, "conformance_profile_id": {"$ref": "#/$defs/opaque"}, "conformance_suite_sigil": {"$ref": "#/$defs/sigil"}, + "store_status": {"enum": ["INITIALIZING", "ACTIVE", "RECOVERING"]}, "active_recovery_id": {"anyOf": [{"$ref": "#/$defs/opaque"}, {"type": "null"}]}, "recovery_origin_status": {"enum": ["INITIALIZING", "ACTIVE", null]}, + "clock_status": {"enum": ["TRUSTED", "UNCERTAIN"]}, "clock_anchor": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/clockRef"}, "current_epoch": {"$ref": "#/$defs/u63"}, "applied_event_count": {"$ref": "#/$defs/u63"}, "last_event_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, + "recoveries": {"$ref": "#/$defs/recoveries"}, "blobs": {"$ref": "#/$defs/blobWrappers"}, "replicas": {"$ref": "#/$defs/replicaWrappers"}, "transfer_requests": {"$ref": "#/$defs/transferRequests"}, "transfer_attempts": {"$ref": "#/$defs/transferAttemptWrappers"}, "materializations": {"$ref": "#/$defs/materializationWrappers"}, "quarantines": {"$ref": "#/$defs/quarantines"}, "provenance": {"$ref": "#/$defs/provenance"}, "provenance_policies": {"$ref": "#/$defs/provenancePolicies"}, "retention_policies": {"$ref": "#/$defs/retentionPolicies"}, "holds": {"$ref": "#/$defs/holds"}, "reference_sets": {"$ref": "#/$defs/referenceSets"}, "legacy_v1_protections": {"$ref": "#/$defs/legacyProtections"}, "gc_plans": {"$ref": "#/$defs/gcPlans"}, "canonical_reference_intents": {"$ref": "#/$defs/canonicalReferenceIntents"}, "dispositions": {"$ref": "#/$defs/dispositions"}, "quota_reservations": {"$ref": "#/$defs/quotaReservations"}, "open_intents": {"$ref": "#/$defs/openIntents"}, "incidents": {"$ref": "#/$defs/incidents"}, + "availability_counters": {"$ref": "#/$defs/availabilityCounters"}, "quota_counters": {"$ref": "#/$defs/quotaCounters"}, "state_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + {"if": {"properties": {"store_status": {"const": "RECOVERING"}}, "required": ["store_status"]}, "then": {"properties": {"active_recovery_id": {"$ref": "#/$defs/opaque"}, "recovery_origin_status": {"enum": ["INITIALIZING", "ACTIVE"]}}}, "else": {"properties": {"active_recovery_id": {"type": "null"}, "recovery_origin_status": {"type": "null"}}}} + ], + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "opaque": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 256}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "journalId": {"type": "string", "pattern": "^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "transferId": {"type": "string", "pattern": "^ST-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "attemptId": {"type": "string", "pattern": "^SA-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "materializationId": {"type": "string", "pattern": "^SM-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "quarantineId": {"type": "string", "pattern": "^SQ-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "gcPlanId": {"type": "string", "pattern": "^SG-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "dispositionId": {"type": "string", "pattern": "^SD-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "policyId": {"type": "string", "pattern": "^SP-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "provenancePolicyId": {"type": "string", "pattern": "^SPP-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "holdId": {"type": "string", "pattern": "^SH-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "referenceSetId": {"type": "string", "pattern": "^RS-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "referenceIntentId": {"type": "string", "pattern": "^RI-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "array": {"type": "array", "maxItems": 4096, "uniqueItems": true}, + "reason": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reason"}, "reservation": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reservationRef"}, "quotaClaim": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/quotaClaim"}, "backendObject": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, "residualCleanup": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/residualStagingCleanup"}, + "eventRef": {"type": "object", "additionalProperties": false, "required": ["journal_id", "event_id", "sequence", "event_sigil"], "properties": {"journal_id": {"$ref": "#/$defs/journalId"}, "event_id": {"$ref": "#/$defs/opaque"}, "sequence": {"$ref": "#/$defs/positiveU63"}, "event_sigil": {"$ref": "#/$defs/sigil"}}}, + "recoveries": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/recovery"}}, + "recovery": {"type": "object", "additionalProperties": false, "required": ["recovery_id", "origin_status", "state", "started_event_sigil", "epoch_ids", "tail_recovery_evidence_record_sigils", "completed_event_sigil", "resume_status"], "properties": {"recovery_id": {"$ref": "#/$defs/opaque"}, "origin_status": {"enum": ["INITIALIZING", "ACTIVE"]}, "state": {"enum": ["ACTIVE", "COMPLETED"]}, "started_event_sigil": {"$ref": "#/$defs/sigil"}, "epoch_ids": {"type": "array", "minItems": 1, "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/u63"}}, "tail_recovery_evidence_record_sigils": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/sigil"}}, "completed_event_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "resume_status": {"enum": ["INITIALIZING", "ACTIVE", null]}}, "allOf": [{"if": {"properties": {"state": {"const": "ACTIVE"}}, "required": ["state"]}, "then": {"properties": {"completed_event_sigil": {"type": "null"}, "resume_status": {"type": "null"}}}, "else": {"properties": {"completed_event_sigil": {"$ref": "#/$defs/sigil"}, "resume_status": {"enum": ["INITIALIZING", "ACTIVE"]}}}}]}, + "recordWrapper": {"type": "object", "additionalProperties": false, "required": ["record", "last_event_sigil"], "properties": {"record": {}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "blobWrappers": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"allOf": [{"$ref": "#/$defs/recordWrapper"}, {"properties": {"record": {"$ref": "https://benchwork.dev/schemas/artifact-blob/1.0"}}}]}}, + "replicaWrappers": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"allOf": [{"$ref": "#/$defs/recordWrapper"}, {"properties": {"record": {"$ref": "https://benchwork.dev/schemas/artifact-replica/1.0"}}}]}}, + "transferAttemptWrappers": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"allOf": [{"$ref": "#/$defs/recordWrapper"}, {"properties": {"record": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0"}}}]}}, + "materializationWrappers": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"allOf": [{"$ref": "#/$defs/recordWrapper"}, {"properties": {"record": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0"}}}]}}, + "transferRequests": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["transfer_id", "request_record_sigil", "state", "attempt_ids", "selected_attempt_id", "revision", "last_event_sigil"], "properties": {"transfer_id": {"$ref": "#/$defs/transferId"}, "request_record_sigil": {"$ref": "#/$defs/sigil"}, "state": {"enum": ["ACTIVE", "SATISFIED"]}, "attempt_ids": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/attemptId"}}, "selected_attempt_id": {"anyOf": [{"$ref": "#/$defs/attemptId"}, {"type": "null"}]}, "revision": {"$ref": "#/$defs/positiveU63"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}}, + "quarantines": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/quarantine"}}, + "quarantine": {"type": "object", "additionalProperties": false, "required": ["quarantine_id", "owner_kind", "owner_id", "state", "source_object", "destination_object", "source_cleanup", "reservation", "reason", "revision", "last_event_sigil", "record_sigil"], "properties": {"quarantine_id": {"$ref": "#/$defs/quarantineId"}, "owner_kind": {"enum": ["TRANSFER_ATTEMPT", "MATERIALIZATION"]}, "owner_id": {"$ref": "#/$defs/opaque"}, "state": {"enum": ["INTENT_RECORDED", "HELD", "INSPECTING", "DISPOSING", "DISPOSED", "DISPOSAL_FAILED", "FAILED"]}, "source_object": {"anyOf": [{"$ref": "#/$defs/backendObject"}, {"type": "null"}]}, "destination_object": {"anyOf": [{"$ref": "#/$defs/backendObject"}, {"type": "null"}]}, "source_cleanup": {"$ref": "#/$defs/residualCleanup"}, "reservation": {"$ref": "#/$defs/reservation"}, "reason": {"$ref": "#/$defs/reason"}, "revision": {"$ref": "#/$defs/positiveU63"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}, "record_sigil": {"$ref": "#/$defs/sigil"}}, "allOf": [{"if": {"properties": {"owner_kind": {"const": "TRANSFER_ATTEMPT"}}, "required": ["owner_kind"]}, "then": {"properties": {"owner_id": {"$ref": "#/$defs/attemptId"}}}, "else": {"properties": {"owner_id": {"$ref": "#/$defs/materializationId"}}}}]}, + "provenance": {"$ref": "#/$defs/immutableRefs"}, "provenancePolicies": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["provenance_policy_id", "record_sigil", "revision", "last_event_sigil"], "properties": {"provenance_policy_id": {"$ref": "#/$defs/provenancePolicyId"}, "record_sigil": {"$ref": "#/$defs/sigil"}, "revision": {"const": 1}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}}, + "immutableRefs": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["provenance_id", "record_sigil", "revision", "last_event_sigil"], "properties": {"provenance_id": {"$ref": "#/$defs/opaque"}, "record_sigil": {"$ref": "#/$defs/sigil"}, "revision": {"const": 1}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}}, + "retentionPolicies": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["policy_id", "record_sigil", "revision", "last_event_sigil"], "properties": {"policy_id": {"$ref": "#/$defs/policyId"}, "record_sigil": {"$ref": "#/$defs/sigil"}, "revision": {"const": 1}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}}, + "holds": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["hold_id", "target_kind", "target_id", "policy_id", "state", "set_authorization_sigil", "release_authorization_sigil", "revision", "last_event_sigil"], "properties": {"hold_id": {"$ref": "#/$defs/holdId"}, "target_kind": {"enum": ["BLOB", "REPLICA", "REFERENCE_SET"]}, "target_id": {"$ref": "#/$defs/opaque"}, "policy_id": {"$ref": "#/$defs/policyId"}, "state": {"enum": ["ACTIVE", "RELEASED"]}, "set_authorization_sigil": {"$ref": "#/$defs/sigil"}, "release_authorization_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "revision": {"$ref": "#/$defs/positiveU63"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}}, + "referenceSets": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["reference_set_id", "reference_set_sigil", "source_identity", "revision", "last_event_sigil"], "properties": {"reference_set_id": {"$ref": "#/$defs/referenceSetId"}, "reference_set_sigil": {"$ref": "#/$defs/sigil"}, "source_identity": {"$ref": "#/$defs/opaque"}, "revision": {"const": 1}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}}, + "legacyProtections": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["protection_id", "artifact_id", "state", "record", "receipt_sigil", "reason", "revision", "last_event_sigil"], "properties": {"protection_id": {"$ref": "#/$defs/opaque"}, "artifact_id": {"$ref": "#/$defs/opaque"}, "state": {"const": "PROTECTED"}, "record": {"$ref": "https://benchwork.dev/schemas/artifact-storage-legacy-protection/1.0"}, "receipt_sigil": {"$ref": "#/$defs/sigil"}, "reason": {"type": "null"}, "revision": {"$ref": "#/$defs/positiveU63"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}, {"type": "object", "additionalProperties": false, "required": ["protection_id", "artifact_id", "state", "record", "receipt_sigil", "reason", "revision", "last_event_sigil"], "properties": {"protection_id": {"$ref": "#/$defs/opaque"}, "artifact_id": {"$ref": "#/$defs/opaque"}, "state": {"const": "FAILED"}, "record": {"type": "null"}, "receipt_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "reason": {"$ref": "#/$defs/reason"}, "revision": {"$ref": "#/$defs/positiveU63"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}]}}, + "gcPlans": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["gc_plan_id", "record_sigil", "state", "authorization_sigil", "authorized_at", "authorization_expires_at", "target_states", "revision", "last_event_sigil"], "properties": {"gc_plan_id": {"$ref": "#/$defs/gcPlanId"}, "record_sigil": {"$ref": "#/$defs/sigil"}, "state": {"enum": ["DRAFT", "AUTHORIZED", "EXECUTING", "COMPLETED", "PARTIAL", "ABORTED"]}, "authorization_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "authorized_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, "authorization_expires_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, "target_states": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/gcTargetState"}}, "revision": {"$ref": "#/$defs/positiveU63"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}}, + "gcTargetState": {"type": "object", "additionalProperties": false, "required": ["target_id", "state", "deletion_intent_id", "outcome_reservation", "root_revalidation_sigil", "deletion_evidence_sigil", "terminal_reason"], "properties": {"target_id": {"$ref": "#/$defs/opaque"}, "state": {"enum": ["PLANNED", "SKIPPED", "DELETING", "DELETED", "FAILED"]}, "deletion_intent_id": {"anyOf": [{"$ref": "#/$defs/opaque"}, {"type": "null"}]}, "outcome_reservation": {"anyOf": [{"$ref": "#/$defs/reservation"}, {"type": "null"}]}, "root_revalidation_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "deletion_evidence_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "terminal_reason": {"anyOf": [{"$ref": "#/$defs/reason"}, {"type": "null"}]}}, "allOf": [{"if": {"properties": {"state": {"const": "PLANNED"}}, "required": ["state"]}, "then": {"properties": {"deletion_intent_id": {"type": "null"}, "outcome_reservation": {"type": "null"}, "root_revalidation_sigil": {"type": "null"}, "deletion_evidence_sigil": {"type": "null"}, "terminal_reason": {"type": "null"}}}}, {"if": {"properties": {"state": {"const": "SKIPPED"}}, "required": ["state"]}, "then": {"properties": {"deletion_intent_id": {"type": "null"}, "outcome_reservation": {"type": "null"}, "root_revalidation_sigil": {"$ref": "#/$defs/sigil"}, "deletion_evidence_sigil": {"type": "null"}, "terminal_reason": {"$ref": "#/$defs/reason"}}}}, {"if": {"properties": {"state": {"enum": ["DELETING", "DELETED", "FAILED"]}}, "required": ["state"]}, "then": {"properties": {"deletion_intent_id": {"$ref": "#/$defs/opaque"}, "outcome_reservation": {"$ref": "#/$defs/reservation"}, "root_revalidation_sigil": {"$ref": "#/$defs/sigil"}}}}, {"if": {"properties": {"state": {"const": "DELETED"}}, "required": ["state"]}, "then": {"properties": {"deletion_evidence_sigil": {"$ref": "#/$defs/sigil"}, "terminal_reason": {"type": "null"}}}}, {"if": {"properties": {"state": {"enum": ["DELETING"]}}, "required": ["state"]}, "then": {"properties": {"deletion_evidence_sigil": {"type": "null"}, "terminal_reason": {"type": "null"}}}}, {"if": {"properties": {"state": {"const": "FAILED"}}, "required": ["state"]}, "then": {"properties": {"deletion_evidence_sigil": {"type": "null"}, "terminal_reason": {"$ref": "#/$defs/reason"}}}}]}, + "chronicleCommit": {"type": "object", "additionalProperties": false, "required": ["event_id", "event_body_sigil", "receipt_id", "receipt_sigil", "head"], "properties": {"event_id": {"$ref": "#/$defs/opaque"}, "event_body_sigil": {"$ref": "#/$defs/sigil"}, "receipt_id": {"$ref": "#/$defs/opaque"}, "receipt_sigil": {"$ref": "#/$defs/sigil"}, "head": {"$ref": "https://benchwork.dev/schemas/artifact-storage-reference-intent/1.0#/$defs/chronicleHeadRef"}}}, + "canonicalReferenceIntents": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["reference_intent_id", "record_sigil", "state", "chronicle_commit", "release_kind", "release_authority_sigil", "release_reason", "revision", "last_event_sigil"], "properties": {"reference_intent_id": {"$ref": "#/$defs/referenceIntentId"}, "record_sigil": {"$ref": "#/$defs/sigil"}, "state": {"enum": ["OPEN", "COMMITTED", "RELEASED"]}, "chronicle_commit": {"anyOf": [{"$ref": "#/$defs/chronicleCommit"}, {"type": "null"}]}, "release_kind": {"enum": ["ABORTED_BEFORE_CANONICAL_COMMIT", null]}, "release_authority_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "release_reason": {"anyOf": [{"$ref": "#/$defs/reason"}, {"type": "null"}]}, "revision": {"$ref": "#/$defs/positiveU63"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}, "allOf": [{"if": {"properties": {"state": {"const": "OPEN"}}, "required": ["state"]}, "then": {"properties": {"chronicle_commit": {"type": "null"}, "release_kind": {"type": "null"}, "release_authority_sigil": {"type": "null"}, "release_reason": {"type": "null"}}}}, {"if": {"properties": {"state": {"const": "COMMITTED"}}, "required": ["state"]}, "then": {"properties": {"chronicle_commit": {"$ref": "#/$defs/chronicleCommit"}, "release_kind": {"type": "null"}, "release_authority_sigil": {"type": "null"}, "release_reason": {"type": "null"}}}}, {"if": {"properties": {"state": {"const": "RELEASED"}}, "required": ["state"]}, "then": {"properties": {"chronicle_commit": {"type": "null"}, "release_kind": {"const": "ABORTED_BEFORE_CANONICAL_COMMIT"}, "release_authority_sigil": {"$ref": "#/$defs/sigil"}, "release_reason": {"$ref": "#/$defs/reason"}}}}]}}, + "dispositions": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["disposition_id", "record_sigil", "state", "execution_intent_id", "outcome_sigil", "revision", "last_event_sigil"], "properties": {"disposition_id": {"$ref": "#/$defs/dispositionId"}, "record_sigil": {"$ref": "#/$defs/sigil"}, "state": {"enum": ["AUTHORIZED", "EXECUTING", "COMPLETED", "FAILED"]}, "execution_intent_id": {"anyOf": [{"$ref": "#/$defs/opaque"}, {"type": "null"}]}, "outcome_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "revision": {"$ref": "#/$defs/positiveU63"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}, "allOf": [{"if": {"properties": {"state": {"const": "AUTHORIZED"}}, "required": ["state"]}, "then": {"properties": {"execution_intent_id": {"type": "null"}, "outcome_sigil": {"type": "null"}}}}, {"if": {"properties": {"state": {"const": "EXECUTING"}}, "required": ["state"]}, "then": {"properties": {"execution_intent_id": {"$ref": "#/$defs/opaque"}, "outcome_sigil": {"type": "null"}}}}, {"if": {"properties": {"state": {"const": "COMPLETED"}}, "required": ["state"]}, "then": {"properties": {"execution_intent_id": {"$ref": "#/$defs/opaque"}, "outcome_sigil": {"$ref": "#/$defs/sigil"}}}}, {"if": {"properties": {"state": {"const": "FAILED"}}, "required": ["state"]}, "then": {"properties": {"outcome_sigil": {"$ref": "#/$defs/sigil"}}}}]}}, + "quotaReservations": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["reservation", "owner_kind", "owner_id", "purpose", "state", "consumed_claims", "released_claims", "remaining_claims", "retained_for_event_types", "revision", "last_event_sigil"], "properties": {"reservation": {"$ref": "#/$defs/reservation"}, "owner_kind": {"enum": ["TRANSFER_ATTEMPT", "MATERIALIZATION", "QUARANTINE", "GC_TARGET", "DISPOSITION", "CANONICAL_REFERENCE", "LEGACY_PROTECTION", "RECOVERY"]}, "owner_id": {"$ref": "#/$defs/opaque"}, "purpose": {"enum": ["PAYLOAD_LIFECYCLE", "TERMINAL_OUTCOME", "QUARANTINE_MOVE", "DELETION_OUTCOME", "CANONICAL_PIN_LIFECYCLE", "RECOVERY_EVIDENCE"]}, "state": {"enum": ["ACTIVE", "RETAINED", "SETTLED"]}, "consumed_claims": {"$ref": "#/$defs/quotaClaims"}, "released_claims": {"$ref": "#/$defs/quotaClaims"}, "remaining_claims": {"$ref": "#/$defs/quotaClaims"}, "retained_for_event_types": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/storageEventType"}}, "revision": {"$ref": "#/$defs/positiveU63"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}}, + "quotaClaims": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/quotaClaim"}}, + "storageEventType": {"enum": ["storage.initialized", "storage.activation_completed", "storage.epoch_started", "storage.clock_uncertain", "storage.clock_restored", "storage.recovery_started", "storage.recovery_completed", "storage.message_rejected", "legacy_v1.protection_registered", "legacy_v1.protection_failed", "quota.pressure_entered", "quota.pressure_cleared", "transfer.prepared", "transfer.streaming_started", "transfer.verification_started", "transfer.commit_intent_recorded", "transfer.committed", "transfer.failed", "transfer.cancelled", "transfer.quarantined", "replica.verification_started", "replica.verified", "replica.verification_expired", "replica.corrupt", "blob.incident_recorded", "materialization.prepared", "materialization.streaming_started", "materialization.verification_started", "materialization.commit_intent_recorded", "materialization.committed", "materialization.cleanup_started", "materialization.cleaned", "materialization.cleanup_failed", "materialization.failed", "materialization.quarantined", "quarantine.intent_recorded", "quarantine.recorded", "quarantine.failed", "quarantine.reinspection_started", "quarantine.reinspection_completed", "provenance.policy_registered", "provenance.recorded", "retention.policy_registered", "retention.hold_set", "retention.hold_released", "reference_set.registered", "canonical_reference.intent_recorded", "canonical_reference.committed", "canonical_reference.released", "gc.plan_created", "gc.plan_authorized", "gc.execution_started", "gc.target_skipped", "gc.target_deletion_started", "gc.target_deleted", "gc.target_failed", "gc.completed", "gc.aborted", "disposition.authorized", "disposition.started", "disposition.completed", "disposition.failed"]}, + "openIntents": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/openIntent"}}, + "openIntent": {"oneOf": [{"$ref": "#/$defs/transferIntent"}, {"$ref": "#/$defs/materializationIntent"}, {"$ref": "#/$defs/quarantineIntent"}, {"$ref": "#/$defs/gcIntent"}, {"$ref": "#/$defs/dispositionIntent"}, {"$ref": "#/$defs/canonicalIntent"}]}, + "openIntentBase": {"type": "object", "required": ["intent_kind", "intent_id", "owner_id", "source_event", "intent_sigil", "revision", "last_event_sigil", "authorization_expires_at"], "properties": {"intent_kind": {}, "intent_id": {"$ref": "#/$defs/opaque"}, "owner_id": {"$ref": "#/$defs/opaque"}, "source_event": {"$ref": "#/$defs/eventRef"}, "intent_sigil": {"$ref": "#/$defs/sigil"}, "revision": {"const": 1}, "last_event_sigil": {"$ref": "#/$defs/sigil"}, "authorization_expires_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}}}, + "transferIntent": {"unevaluatedProperties": false, "allOf": [{"$ref": "#/$defs/openIntentBase"}, {"properties": {"intent_kind": {"const": "TRANSFER_COMMIT"}, "owner_id": {"$ref": "#/$defs/attemptId"}, "authorization_expires_at": {"type": "null"}, "staging_object": {"$ref": "#/$defs/backendObject"}, "target_object": {"$ref": "#/$defs/backendObject"}}, "required": ["staging_object", "target_object"]}]}, + "materializationIntent": {"unevaluatedProperties": false, "allOf": [{"$ref": "#/$defs/openIntentBase"}, {"properties": {"intent_kind": {"const": "MATERIALIZATION_COMMIT"}, "owner_id": {"$ref": "#/$defs/materializationId"}, "authorization_expires_at": {"type": "null"}, "staging_object": {"$ref": "#/$defs/backendObject"}, "target_object": {"$ref": "#/$defs/backendObject"}}, "required": ["staging_object", "target_object"]}]}, + "quarantineIntent": {"unevaluatedProperties": false, "allOf": [{"$ref": "#/$defs/openIntentBase"}, {"properties": {"intent_kind": {"const": "QUARANTINE_MOVE"}, "intent_id": {"$ref": "#/$defs/quarantineId"}, "owner_id": {"anyOf": [{"$ref": "#/$defs/attemptId"}, {"$ref": "#/$defs/materializationId"}]}, "authorization_expires_at": {"type": "null"}, "source_object": {"$ref": "#/$defs/backendObject"}, "target_object": {"$ref": "#/$defs/backendObject"}}, "required": ["source_object", "target_object"]}]}, + "gcIntent": {"unevaluatedProperties": false, "allOf": [{"$ref": "#/$defs/openIntentBase"}, {"properties": {"intent_kind": {"const": "GC_DELETE"}, "owner_id": {"$ref": "#/$defs/gcPlanId"}, "target_id": {"$ref": "#/$defs/opaque"}, "target_object": {"$ref": "#/$defs/backendObject"}, "authorization_expires_at": {"$ref": "#/$defs/timestamp"}}, "required": ["target_id", "target_object"]}]}, + "dispositionIntent": {"unevaluatedProperties": false, "allOf": [{"$ref": "#/$defs/openIntentBase"}, {"properties": {"intent_kind": {"const": "DISPOSITION"}, "owner_id": {"$ref": "#/$defs/dispositionId"}, "target_kind": {"enum": ["STAGING", "MATERIALIZATION_STAGING", "MATERIALIZATION_DESTINATION", "QUARANTINE"]}, "target_object": {"$ref": "#/$defs/backendObject"}, "authorization_expires_at": {"$ref": "#/$defs/timestamp"}}, "required": ["target_kind", "target_object"]}]}, + "canonicalIntent": {"unevaluatedProperties": false, "allOf": [{"$ref": "#/$defs/openIntentBase"}, {"properties": {"intent_kind": {"const": "CANONICAL_REFERENCE"}, "intent_id": {"$ref": "#/$defs/referenceIntentId"}, "owner_id": {"$ref": "#/$defs/referenceIntentId"}, "expected_chronicle_head": {"$ref": "https://benchwork.dev/schemas/artifact-storage-reference-intent/1.0#/$defs/chronicleHeadRef"}, "blob_sigils": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/sigil"}}, "reference_set_sigils": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/sigil"}}, "authorization_expires_at": {"type": "null"}}, "required": ["expected_chronicle_head", "blob_sigils", "reference_set_sigils"]}]}, + "incidents": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["incident_id", "subject_kind", "subject_id", "reason", "state", "revision", "last_event_sigil"], "properties": {"incident_id": {"$ref": "#/$defs/opaque"}, "subject_kind": {"enum": ["BLOB", "REPLICA", "TRANSFER_ATTEMPT", "MATERIALIZATION", "QUARANTINE", "BACKEND_OBJECT", "JOURNAL", "LEGACY_PROTECTION"]}, "subject_id": {"$ref": "#/$defs/opaque"}, "reason": {"$ref": "#/$defs/reason"}, "state": {"const": "OPEN"}, "revision": {"const": 1}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}}, + "availabilityCounters": {"type": "object", "additionalProperties": false, "required": ["available_blobs", "degraded_blobs", "unavailable_blobs", "incident_blobs"], "properties": {"available_blobs": {"$ref": "#/$defs/u63"}, "degraded_blobs": {"$ref": "#/$defs/u63"}, "unavailable_blobs": {"$ref": "#/$defs/u63"}, "incident_blobs": {"$ref": "#/$defs/u63"}}}, + "quotaCounters": {"type": "array", "minItems": 12, "maxItems": 12, "prefixItems": [{"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "JOURNAL"}, "dimension": {"const": "JOURNAL_BYTE"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "CONTROL_RECORD"}, "dimension": {"const": "CONTROL_RECORD_BYTE"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "STAGING"}, "dimension": {"const": "BYTE"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "STAGING"}, "dimension": {"const": "OBJECT"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "QUARANTINE"}, "dimension": {"const": "BYTE"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "QUARANTINE"}, "dimension": {"const": "OBJECT"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "COMMITTED"}, "dimension": {"const": "BYTE"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "COMMITTED"}, "dimension": {"const": "OBJECT"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "MATERIALIZATION"}, "dimension": {"const": "BYTE"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "MATERIALIZATION"}, "dimension": {"const": "OBJECT"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "STREAM"}, "dimension": {"const": "STREAM"}}}]}, {"allOf": [{"$ref": "#/$defs/quotaSnapshot"}, {"properties": {"quota_class": {"const": "INODE"}, "dimension": {"const": "INODE"}}}]}], "items": false}, + "quotaSnapshot": {"type": "object", "additionalProperties": false, "required": ["quota_class", "dimension", "limit", "used", "reserved", "pressure_state"], "properties": {"quota_class": {"enum": ["JOURNAL", "CONTROL_RECORD", "STAGING", "QUARANTINE", "COMMITTED", "MATERIALIZATION", "STREAM", "INODE"]}, "dimension": {"enum": ["BYTE", "OBJECT", "INODE", "STREAM", "JOURNAL_BYTE", "CONTROL_RECORD_BYTE"]}, "limit": {"$ref": "#/$defs/u63"}, "used": {"$ref": "#/$defs/u63"}, "reserved": {"$ref": "#/$defs/u63"}, "pressure_state": {"enum": ["CLEAR", "PRESSURED"]}}} + } +} diff --git a/schemas/artifact-storage-tail-evidence-1.0.json b/schemas/artifact-storage-tail-evidence-1.0.json new file mode 100644 index 0000000..3f04afc --- /dev/null +++ b/schemas/artifact-storage-tail-evidence-1.0.json @@ -0,0 +1,2 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/artifact-storage-tail-evidence/1.0","title":"Artifact Storage Tail Evidence v1","description":"Closed RFC-0013 Tail Evidence record contract. Raw evidence bytes are deliberately outside this record wire contract.","type":"object","additionalProperties":false,"required":["schema_version","evidence_id","recovery_id","journal_id","kind","frame_start","observed_size","observed_bytes_sigil","previous_evidence_record_sigil","created_at","record_sigil"],"properties":{"schema_version":{"const":"artifact-storage-tail-evidence/1.0"},"evidence_id":{"$ref":"#/$defs/opaque"},"recovery_id":{"$ref":"#/$defs/opaque"},"journal_id":{"$ref":"#/$defs/journalId"},"kind":{"enum":["ORIGINAL_INTERRUPTED_APPEND","RECOVERY_EVENT_SEED","RECOVERY_FRAME_TEMPLATE","RECOVERY_FRAME_RETRY_SUFFIX"]},"frame_start":{"$ref":"#/$defs/u63"},"observed_size":{"$ref":"#/$defs/positiveU63"},"observed_bytes_sigil":{"$ref":"#/$defs/sigil"},"previous_evidence_record_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"created_at":{"$ref":"#/$defs/timestamp"},"record_sigil":{"$ref":"#/$defs/sigil"}},"$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"positiveU63":{"type":"integer","minimum":1,"maximum":9223372036854775807},"opaque":{"type":"string","pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","minLength":1,"maxLength":256},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"journalId":{"type":"string","pattern":"^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128}}} + diff --git a/schemas/artifact-transfer-1.0.json b/schemas/artifact-transfer-1.0.json new file mode 100644 index 0000000..f0c88b6 --- /dev/null +++ b/schemas/artifact-transfer-1.0.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-transfer/1.0", + "title": "Artifact Transfer v1", + "description": "Closed RFC-0013 immutable transfer request. Policy resolution, Journal admission, State replay, and backend effects are semantic/runtime checks.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "transfer_id", "direction", "purpose", "source", "destination", "expected_blob_sigil", "bounds", "backend", "authorization_sigil", "idempotency_key_sigil", "execution", "verification_method", "provenance_policy", "retention_policy_ids", "created_at", "record_sigil"], + "properties": { + "schema_version": {"const": "artifact-transfer/1.0"}, + "transfer_id": {"$ref": "#/$defs/transferId"}, + "direction": {"enum": ["INGEST", "COPY", "EXPORT", "MATERIALIZE"]}, + "purpose": {"$ref": "https://benchwork.dev/schemas/artifact-provenance-policy/1.0#/$defs/transferPurpose"}, + "source": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/sourceDescriptor"}, + "destination": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/destinationDescriptor"}, + "expected_blob_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, + "bounds": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/transferBounds"}, + "backend": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/backendRef"}, + "authorization_sigil": {"$ref": "#/$defs/sigil"}, + "idempotency_key_sigil": {"$ref": "#/$defs/sigil"}, + "execution": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/executionContext"}, + "verification_method": {"enum": ["FULL_READBACK_SHA256", "CONFORMANCE_END_TO_END"]}, + "provenance_policy": {"$ref": "#/$defs/provenancePolicyBinding"}, + "retention_policy_ids": {"type": "array", "maxItems": 64, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/artifact-retention-policy/1.0#/$defs/policyId"}}, + "created_at": {"$ref": "#/$defs/timestamp"}, + "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "transferId": {"type": "string", "pattern": "^ST-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "provenancePolicyBinding": { + "type": "object", "additionalProperties": false, + "required": ["provenance_policy_id", "provenance_policy_sigil"], + "properties": { + "provenance_policy_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance-policy/1.0#/$defs/provenancePolicyId"}, + "provenance_policy_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/artifact-transfer-attempt-1.0.json b/schemas/artifact-transfer-attempt-1.0.json new file mode 100644 index 0000000..62fbcd8 --- /dev/null +++ b/schemas/artifact-transfer-attempt-1.0.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0", + "title": "Artifact Transfer Attempt v1", + "description": "Closed RFC-0013 transfer execution record. Journal transition legality, reservations, State replay, and backend effects are semantic/runtime checks.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "transfer_attempt_id", "transfer_id", "attempt_number", "state", "staging_state", "reservation", "staging_object", "commit_intent", "residual_staging_cleanup", "computed_blob_sigil", "computed_size_bytes", "selected_replica_id", "quarantine_id", "terminal_reason", "started_at", "terminal_at", "revision", "record_sigil"], + "properties": { + "schema_version": {"const": "artifact-transfer-attempt/1.0"}, + "transfer_attempt_id": {"$ref": "#/$defs/transferAttemptId"}, + "transfer_id": {"$ref": "#/$defs/transferId"}, + "attempt_number": {"$ref": "#/$defs/positiveU63"}, + "state": {"enum": ["PREPARED", "STREAMING", "VERIFYING", "COMMITTING", "COMMITTED", "FAILED", "CANCELLED", "QUARANTINED"]}, + "staging_state": {"enum": ["NOT_CREATED", "PRESENT", "MISSING", "HELD_FOR_DISPOSITION"]}, + "reservation": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reservationRef"}, + "staging_object": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, {"type": "null"}]}, + "commit_intent": {"anyOf": [{"$ref": "#/$defs/transferCommitIntent"}, {"type": "null"}]}, + "residual_staging_cleanup": {"$ref": "#/$defs/residualStagingCleanup"}, + "computed_blob_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, + "computed_size_bytes": {"anyOf": [{"$ref": "#/$defs/u63"}, {"type": "null"}]}, + "selected_replica_id": {"anyOf": [{"$ref": "#/$defs/replicaId"}, {"type": "null"}]}, + "quarantine_id": {"anyOf": [{"$ref": "#/$defs/quarantineId"}, {"type": "null"}]}, + "terminal_reason": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reason"}, {"type": "null"}]}, + "started_at": {"$ref": "#/$defs/timestamp"}, + "terminal_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, + "revision": {"$ref": "#/$defs/positiveU63"}, + "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + {"if": {"properties": {"state": {"const": "PREPARED"}}, "required": ["state"]}, "then": {"properties": {"staging_state": {"const": "NOT_CREATED"}, "staging_object": {"type": "null"}, "commit_intent": {"type": "null"}, "terminal_at": {"type": "null"}, "selected_replica_id": {"type": "null"}, "quarantine_id": {"type": "null"}, "terminal_reason": {"type": "null"}}}}, + {"if": {"properties": {"state": {"enum": ["STREAMING", "VERIFYING"]}}, "required": ["state"]}, "then": {"properties": {"staging_state": {"const": "PRESENT"}, "staging_object": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, "terminal_at": {"type": "null"}, "selected_replica_id": {"type": "null"}, "quarantine_id": {"type": "null"}, "terminal_reason": {"type": "null"}}}}, + {"if": {"properties": {"state": {"const": "COMMITTING"}}, "required": ["state"]}, "then": {"properties": {"staging_state": {"const": "PRESENT"}, "staging_object": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, "commit_intent": {"$ref": "#/$defs/transferCommitIntent"}, "terminal_at": {"type": "null"}, "selected_replica_id": {"type": "null"}, "quarantine_id": {"type": "null"}, "terminal_reason": {"type": "null"}}}}, + {"if": {"properties": {"state": {"const": "COMMITTED"}}, "required": ["state"]}, "then": {"properties": {"commit_intent": {"$ref": "#/$defs/transferCommitIntent"}, "selected_replica_id": {"$ref": "#/$defs/replicaId"}, "quarantine_id": {"type": "null"}, "terminal_reason": {"type": "null"}, "terminal_at": {"$ref": "#/$defs/timestamp"}, "residual_staging_cleanup": {"$ref": "#/$defs/terminalCleanup"}}}}, + {"if": {"properties": {"state": {"const": "QUARANTINED"}}, "required": ["state"]}, "then": {"properties": {"selected_replica_id": {"type": "null"}, "quarantine_id": {"$ref": "#/$defs/quarantineId"}, "terminal_reason": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reason"}, "terminal_at": {"$ref": "#/$defs/timestamp"}, "residual_staging_cleanup": {"$ref": "#/$defs/terminalCleanup"}}}}, + {"if": {"properties": {"state": {"enum": ["FAILED", "CANCELLED"]}}, "required": ["state"]}, "then": {"properties": {"selected_replica_id": {"type": "null"}, "quarantine_id": {"type": "null"}, "terminal_reason": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reason"}, "terminal_at": {"$ref": "#/$defs/timestamp"}, "residual_staging_cleanup": {"$ref": "#/$defs/terminalCleanup"}}}} + ], + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "transferId": {"type": "string", "pattern": "^ST-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "transferAttemptId": {"type": "string", "pattern": "^SA-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "replicaId": {"type": "string", "pattern": "^SR-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "quarantineId": {"type": "string", "pattern": "^SQ-[A-Za-z0-9][A-Za-z0-9._:-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "blobRef": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}, + "transferCommitIntent": { + "type": "object", "additionalProperties": false, + "required": ["intent_id", "provisional_replica_id", "staging_object", "target_object", "computed_blob", "execution_fence", "reservation", "recorded_clock"], + "properties": { + "intent_id": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/opaque"}, + "provisional_replica_id": {"$ref": "#/$defs/replicaId"}, + "staging_object": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, + "target_object": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, + "computed_blob": {"$ref": "#/$defs/blobRef"}, + "execution_fence": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/fence"}, {"type": "null"}]}, + "reservation": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reservationRef"}, + "recorded_clock": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/clockRef"} + } + }, + "residualStagingCleanup": { + "type": "object", "additionalProperties": false, + "required": ["state", "staging_object", "evidence_sigil", "reason"], + "properties": { + "state": {"enum": ["NOT_REQUIRED", "PENDING", "CLEANED", "FAILED", "HELD_FOR_DISPOSITION"]}, + "staging_object": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, {"type": "null"}]}, + "evidence_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, + "reason": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reason"}, {"type": "null"}]} + }, + "allOf": [ + {"if": {"properties": {"state": {"const": "NOT_REQUIRED"}}, "required": ["state"]}, "then": {"properties": {"staging_object": {"type": "null"}, "evidence_sigil": {"type": "null"}, "reason": {"type": "null"}}}}, + {"if": {"properties": {"state": {"const": "PENDING"}}, "required": ["state"]}, "then": {"properties": {"staging_object": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, "evidence_sigil": {"type": "null"}, "reason": {"type": "null"}}}}, + {"if": {"properties": {"state": {"const": "CLEANED"}}, "required": ["state"]}, "then": {"properties": {"staging_object": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, "evidence_sigil": {"$ref": "#/$defs/sigil"}, "reason": {"type": "null"}}}}, + {"if": {"properties": {"state": {"enum": ["FAILED", "HELD_FOR_DISPOSITION"]}}, "required": ["state"]}, "then": {"properties": {"staging_object": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/backendObjectRef"}, "evidence_sigil": {"$ref": "#/$defs/sigil"}, "reason": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reason"}}}} + ] + }, + "terminalCleanup": {"allOf": [{"$ref": "#/$defs/residualStagingCleanup"}, {"properties": {"state": {"enum": ["NOT_REQUIRED", "CLEANED", "HELD_FOR_DISPOSITION"]}}, "required": ["state"]}]} + } +} + diff --git a/schemas/attempt-authorization-subject-1.0.json b/schemas/attempt-authorization-subject-1.0.json new file mode 100644 index 0000000..a38cc4d --- /dev/null +++ b/schemas/attempt-authorization-subject-1.0.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0", + "title": "Attempt Authorization Subject v1", + "description": "Closed RFC-0012 per-Attempt authorization subject. Effect ordering, content-derived ID, and self-Sigil are semantic requirements.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "authorization_subject_id", "job_id", "job_binding_sigil", "attempt_id", "attempt_binding_sigil", "retry_ordinal", "specification_id", "specification_sigil", "effects", "authorization_subject_sigil"], + "properties": { + "schema_version": {"const": "attempt-authorization-subject/1.0"}, + "authorization_subject_id": {"$ref": "#/$defs/authorizationSubjectId"}, + "job_id": {"$ref": "#/$defs/jobId"}, + "job_binding_sigil": {"$ref": "#/$defs/sigil"}, + "attempt_id": {"$ref": "#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "retry_ordinal": {"$ref": "#/$defs/positiveU63"}, + "specification_id": {"$ref": "#/$defs/specificationId"}, + "specification_sigil": {"$ref": "#/$defs/sigil"}, + "effects": {"type": "array", "minItems": 1, "maxItems": 128, "items": {"$ref": "#/$defs/effect"}}, + "authorization_subject_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "authorizationSubjectId": {"type": "string", "pattern": "^AA-[0-9A-F]{64}$", "minLength": 67, "maxLength": 67}, + "subjectId": {"$ref": "#/$defs/authorizationSubjectId"}, + "jobId": {"type": "string", "pattern": "^JB-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "attemptId": {"type": "string", "pattern": "^AT-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "specificationId": {"type": "string", "pattern": "^ES-[A-Z0-9]+$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "sideEffectId": {"type": "string", "pattern": "^SE-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "effect": {"type": "object", "additionalProperties": false, "required": ["side_effect_id", "authority_sigil"], "properties": {"side_effect_id": {"$ref": "#/$defs/sideEffectId"}, "authority_sigil": {"$ref": "#/$defs/sigil"}}} + } +} diff --git a/schemas/attempt-authorization-transition-request-1.0.json b/schemas/attempt-authorization-transition-request-1.0.json new file mode 100644 index 0000000..40381e7 --- /dev/null +++ b/schemas/attempt-authorization-transition-request-1.0.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/attempt-authorization-transition-request/1.0", + "title": "Attempt Authorization Transition Request v1", + "description": "Closed RFC-0012 Athanor request for one exact per-Attempt authorization subject. Authenticated invocation-context resolution, durable single assignment, and Event/Receipt resolution remain external conformance checks.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "transition_request_id", "event_type", "expected_chronicle_head", "authorization_subject", "authority_evidence", "actor", "host_invocation", "chronicle_actor", "idempotency_key_sigil", "requested_at", "transition_request_sigil"], + "properties": { + "schema_version": {"const": "attempt-authorization-transition-request/1.0"}, + "transition_request_id": {"$ref": "#/$defs/transitionRequestId"}, + "event_type": {"const": "attempt.authorization.granted"}, + "expected_chronicle_head": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/chronicleHeadRef"}, + "authorization_subject": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0"}, + "authority_evidence": {"$ref": "#/$defs/authorityEvidence"}, + "actor": {"$ref": "https://benchwork.dev/schemas/execution-cancel-request/1.0#/$defs/actor_binding"}, + "host_invocation": {"$ref": "https://benchwork.dev/schemas/execution-cancel-request/1.0#/$defs/host_invocation_binding"}, + "chronicle_actor": {"$ref": "https://benchwork.dev/schemas/actor/1.0"}, + "idempotency_key_sigil": {"$ref": "#/$defs/sigil"}, + "requested_at": {"$ref": "#/$defs/timestamp"}, + "transition_request_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "transitionRequestId": {"type": "string", "pattern": "^AAT-[A-F0-9]{64}$", "not": {"pattern": "[\\r\\n]"}, "minLength": 68, "maxLength": 68}, + "requestId": {"$ref": "#/$defs/transitionRequestId"}, + "authorityEvidence": { + "type": "object", + "additionalProperties": false, + "required": ["purpose", "ward_decision_id", "ward_decision_sigil", "authorization_policy_sigil", "effects"], + "properties": { + "purpose": {"const": "ATTEMPT_AUTHORIZATION"}, + "ward_decision_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/wardDecisionId", "not": {"pattern": "[\\r\\n]"}}, + "ward_decision_sigil": {"$ref": "#/$defs/sigil"}, + "authorization_policy_sigil": {"$ref": "#/$defs/sigil"}, + "effects": {"type": "array", "minItems": 1, "maxItems": 128, "items": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/effect"}} + } + } + } +} diff --git a/schemas/benchwork-local-execution-lease-0.1.json b/schemas/benchwork-local-execution-lease-0.1.json new file mode 100644 index 0000000..807d089 --- /dev/null +++ b/schemas/benchwork-local-execution-lease-0.1.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/benchwork-local-execution-lease/0.1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "lease_id", + "job_id", + "attempt_id", + "worker_id", + "worker_binding_sigil", + "worker_session_id", + "worker_session_binding_sigil", + "executor_instance_id", + "executor_epoch", + "fencing_generation", + "offered_at", + "claim_due_at", + "lease_binding_sigil" + ], + "properties": { + "schema_version": {"const": "benchwork-local-execution-lease/0.1"}, + "lease_id": {"type": "string", "pattern": "^LS-[A-Z0-9][A-Z0-9._-]*$"}, + "job_id": {"type": "string", "pattern": "^JB-[A-F0-9]{64}$"}, + "attempt_id": {"type": "string", "pattern": "^AT-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_id": {"type": "string", "pattern": "^WK-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "worker_session_id": {"type": "string", "pattern": "^WS-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_session_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "executor_instance_id": {"type": "string", "pattern": "^XI-[A-Z0-9][A-Z0-9._-]*$"}, + "executor_epoch": {"type": "integer", "minimum": 1}, + "fencing_generation": {"type": "integer", "minimum": 1}, + "offered_at": {"type": "string", "format": "date-time"}, + "claim_due_at": {"type": "string", "format": "date-time"}, + "lease_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"} + } +} + diff --git a/schemas/benchwork-local-execution-log-chunk-0.1.json b/schemas/benchwork-local-execution-log-chunk-0.1.json new file mode 100644 index 0000000..4bdfc24 --- /dev/null +++ b/schemas/benchwork-local-execution-log-chunk-0.1.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/benchwork-local-execution-log-chunk/0.1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "job_id", + "attempt_id", + "lease_id", + "worker_id", + "worker_session_id", + "job_binding_sigil", + "attempt_binding_sigil", + "lease_binding_sigil", + "worker_session_binding_sigil", + "executor_epoch", + "fencing_generation", + "expected_lease_revision", + "stream", + "sequence", + "prior_accepted_sequence", + "blob_sigil", + "byte_length", + "media_type", + "message_sigil" + ], + "properties": { + "schema_version": {"const": "benchwork-local-execution-log-chunk/0.1"}, + "job_id": {"type": "string", "pattern": "^JB-[A-F0-9]{64}$"}, + "attempt_id": {"type": "string", "pattern": "^AT-[A-Z0-9][A-Z0-9._-]*$"}, + "lease_id": {"type": "string", "pattern": "^LS-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_id": {"type": "string", "pattern": "^WK-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_session_id": {"type": "string", "pattern": "^WS-[A-Z0-9][A-Z0-9._-]*$"}, + "job_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "attempt_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "lease_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "worker_session_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "executor_epoch": {"type": "integer", "minimum": 1}, + "fencing_generation": {"type": "integer", "minimum": 1}, + "expected_lease_revision": {"type": "integer", "minimum": 1}, + "stream": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, + "sequence": {"type": "integer", "minimum": 0}, + "prior_accepted_sequence": {"type": ["integer", "null"], "minimum": 0}, + "blob_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "byte_length": {"type": "integer", "minimum": 0, "maximum": 65536}, + "media_type": {"enum": ["text/plain; charset=utf-8", "application/x-ndjson"]}, + "message_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"} + } +} + diff --git a/schemas/benchwork-local-execution-specification-0.1.json b/schemas/benchwork-local-execution-specification-0.1.json new file mode 100644 index 0000000..cc2627e --- /dev/null +++ b/schemas/benchwork-local-execution-specification-0.1.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/benchwork-local-execution-specification/0.1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "specification_id", + "task_binding", + "specification_sigil" + ], + "properties": { + "schema_version": { + "const": "benchwork-local-execution-specification/0.1" + }, + "specification_id": { + "type": "string", + "pattern": "^ES-[A-Z0-9][A-Z0-9._-]*$" + }, + "task_binding": { + "type": "object", + "additionalProperties": false, + "required": ["task_id", "task_capsule_sigil"], + "properties": { + "task_id": { + "type": "string", + "minLength": 1 + }, + "task_capsule_sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$" + } + } + }, + "specification_sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$" + } + } +} + diff --git a/schemas/benchwork-local-execution-worker-0.1.json b/schemas/benchwork-local-execution-worker-0.1.json new file mode 100644 index 0000000..de886ab --- /dev/null +++ b/schemas/benchwork-local-execution-worker-0.1.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/benchwork-local-execution-worker/0.1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "worker_id", + "definition_revision", + "implementation_name", + "implementation_version", + "maximum_concurrency", + "worker_binding_sigil" + ], + "properties": { + "schema_version": {"const": "benchwork-local-execution-worker/0.1"}, + "worker_id": {"type": "string", "pattern": "^WK-[A-Z0-9][A-Z0-9._-]*$"}, + "definition_revision": {"type": "integer", "minimum": 0}, + "implementation_name": {"type": "string", "minLength": 1, "maxLength": 128}, + "implementation_version": {"type": "string", "minLength": 1, "maxLength": 128}, + "maximum_concurrency": {"const": 1}, + "worker_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"} + } +} + diff --git a/schemas/benchwork-local-execution-worker-heartbeat-0.1.json b/schemas/benchwork-local-execution-worker-heartbeat-0.1.json new file mode 100644 index 0000000..07c55cc --- /dev/null +++ b/schemas/benchwork-local-execution-worker-heartbeat-0.1.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/benchwork-local-execution-worker-heartbeat/0.1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "scope", + "worker_id", + "worker_session_id", + "worker_session_binding_sigil", + "executor_epoch", + "sequence", + "prior_accepted_sequence", + "message_sigil" + ], + "properties": { + "schema_version": {"const": "benchwork-local-execution-worker-heartbeat/0.1"}, + "scope": {"const": "WORKER"}, + "worker_id": {"type": "string", "pattern": "^WK-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_session_id": {"type": "string", "pattern": "^WS-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_session_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "executor_epoch": {"type": "integer", "minimum": 1}, + "sequence": {"type": "integer", "minimum": 0}, + "prior_accepted_sequence": {"type": ["integer", "null"], "minimum": 0}, + "message_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"} + } +} + diff --git a/schemas/benchwork-local-execution-worker-result-0.1.json b/schemas/benchwork-local-execution-worker-result-0.1.json new file mode 100644 index 0000000..c38d182 --- /dev/null +++ b/schemas/benchwork-local-execution-worker-result-0.1.json @@ -0,0 +1,50 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/benchwork-local-execution-worker-result/0.1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "job_id", + "attempt_id", + "lease_id", + "worker_id", + "worker_session_id", + "job_binding_sigil", + "attempt_binding_sigil", + "lease_binding_sigil", + "worker_session_binding_sigil", + "executor_epoch", + "fencing_generation", + "expected_lease_revision", + "outcome", + "summary", + "output_blob_sigils", + "message_sigil" + ], + "properties": { + "schema_version": {"const": "benchwork-local-execution-worker-result/0.1"}, + "job_id": {"type": "string", "pattern": "^JB-[A-F0-9]{64}$"}, + "attempt_id": {"type": "string", "pattern": "^AT-[A-Z0-9][A-Z0-9._-]*$"}, + "lease_id": {"type": "string", "pattern": "^LS-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_id": {"type": "string", "pattern": "^WK-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_session_id": {"type": "string", "pattern": "^WS-[A-Z0-9][A-Z0-9._-]*$"}, + "job_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "attempt_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "lease_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "worker_session_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "executor_epoch": {"type": "integer", "minimum": 1}, + "fencing_generation": {"type": "integer", "minimum": 1}, + "expected_lease_revision": {"type": "integer", "minimum": 1}, + "outcome": {"enum": ["COMPLETED", "FAILED"]}, + "summary": {"type": "string", "minLength": 1, "maxLength": 4096}, + "output_blob_sigils": { + "type": "array", + "maxItems": 16, + "uniqueItems": true, + "items": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"} + }, + "message_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"} + } +} + diff --git a/schemas/benchwork-local-execution-worker-session-0.1.json b/schemas/benchwork-local-execution-worker-session-0.1.json new file mode 100644 index 0000000..ce5a6ac --- /dev/null +++ b/schemas/benchwork-local-execution-worker-session-0.1.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/benchwork-local-execution-worker-session/0.1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "worker_session_id", + "worker_id", + "worker_binding_sigil", + "executor_instance_id", + "executor_epoch", + "maximum_concurrency", + "opened_at", + "worker_session_binding_sigil" + ], + "properties": { + "schema_version": {"const": "benchwork-local-execution-worker-session/0.1"}, + "worker_session_id": {"type": "string", "pattern": "^WS-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_id": {"type": "string", "pattern": "^WK-[A-Z0-9][A-Z0-9._-]*$"}, + "worker_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"}, + "executor_instance_id": {"type": "string", "pattern": "^XI-[A-Z0-9][A-Z0-9._-]*$"}, + "executor_epoch": {"type": "integer", "minimum": 1}, + "maximum_concurrency": {"const": 1}, + "opened_at": {"type": "string", "format": "date-time"}, + "worker_session_binding_sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"} + } +} + diff --git a/schemas/benchwork-source-tree-1.0.json b/schemas/benchwork-source-tree-1.0.json new file mode 100644 index 0000000..d56ba3b --- /dev/null +++ b/schemas/benchwork-source-tree-1.0.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/benchwork-source-tree/1.0", + "title": "Benchwork Source Tree v1", + "description": "Closed RFC-0012 canonical retained-source manifest and BWSOURCE1 bundle identity. Filesystem scan completeness, hard-link/sparse-file detection, Specification resolution, Storage durability, and terminal-source binding remain external conformance checks.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "source_tree_id", "manifest", "bundle_blob", "verified_at", "source_tree_sigil"], + "properties": { + "schema_version": {"const": "benchwork-source-tree/1.0"}, + "source_tree_id": {"$ref": "#/$defs/sourceTreeId"}, + "manifest": {"$ref": "#/$defs/manifest"}, + "bundle_blob": {"$ref": "#/$defs/blobRef"}, + "verified_at": {"$ref": "#/$defs/timestamp"}, + "source_tree_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "sourceTreeId": {"type": "string", "pattern": "^BTS-[A-F0-9]{64}$", "not": {"pattern": "[\\r\\n]"}, "minLength": 68, "maxLength": 68}, + "jobId": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attemptId": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, + "baseIdentity": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/token"}, + "blobRef": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}, + "path": {"type": "string", "minLength": 1, "maxLength": 4096, "pattern": "^[^/\\u0000-\\u001F\\u007F-\\u009F]+(?:/[^/\\u0000-\\u001F\\u007F-\\u009F]+)*$", "not": {"pattern": "[\\r\\n]"}}, + "symlinkTarget": {"type": "string", "maxLength": 4096, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, + "scope": { + "type": "object", + "additionalProperties": false, + "required": ["root_kind", "included_paths", "excluded_paths"], + "properties": { + "root_kind": {"const": "CRUCIBLE"}, + "included_paths": {"type": "array", "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/path"}}, + "excluded_paths": {"type": "array", "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/path"}} + } + }, + "pathSemantics": { + "type": "object", + "additionalProperties": false, + "required": ["separator", "unicode_normalization", "case_mode", "dot_segments", "link_traversal", "reserved_name_policy"], + "properties": { + "separator": {"const": "SLASH"}, + "unicode_normalization": {"const": "NFC"}, + "case_mode": {"enum": ["SENSITIVE", "INSENSITIVE_REJECT_COLLISIONS"]}, + "dot_segments": {"const": "REJECT"}, + "link_traversal": {"const": "NOFOLLOW"}, + "reserved_name_policy": {"const": "REJECT"} + } + }, + "directoryEntry": {"type": "object", "additionalProperties": false, "required": ["path", "kind", "entry_sigil"], "properties": {"path": {"$ref": "#/$defs/path"}, "kind": {"const": "DIRECTORY"}, "entry_sigil": {"$ref": "#/$defs/sigil"}}}, + "fileEntry": {"type": "object", "additionalProperties": false, "required": ["path", "kind", "blob", "executable"], "properties": {"path": {"$ref": "#/$defs/path"}, "kind": {"const": "FILE"}, "blob": {"$ref": "#/$defs/blobRef"}, "executable": {"type": "boolean"}}}, + "symlinkEntry": {"type": "object", "additionalProperties": false, "required": ["path", "kind", "target", "target_sigil"], "properties": {"path": {"$ref": "#/$defs/path"}, "kind": {"const": "SYMLINK"}, "target": {"$ref": "#/$defs/symlinkTarget"}, "target_sigil": {"$ref": "#/$defs/sigil"}}}, + "entry": {"oneOf": [{"$ref": "#/$defs/directoryEntry"}, {"$ref": "#/$defs/fileEntry"}, {"$ref": "#/$defs/symlinkEntry"}]}, + "manifest": { + "type": "object", + "additionalProperties": false, + "required": ["format_version", "job_id", "attempt_id", "attempt_binding_sigil", "crucible_base_identity", "crucible_base_sigil", "scope", "path_semantics", "entries", "file_count", "byte_count", "manifest_sigil"], + "properties": { + "format_version": {"const": "BENCHWORK_SOURCE_TREE_V1"}, + "job_id": {"$ref": "#/$defs/jobId"}, + "attempt_id": {"$ref": "#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "crucible_base_identity": {"$ref": "#/$defs/baseIdentity"}, + "crucible_base_sigil": {"$ref": "#/$defs/sigil"}, + "scope": {"$ref": "#/$defs/scope"}, + "path_semantics": {"$ref": "#/$defs/pathSemantics"}, + "entries": {"type": "array", "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/entry"}}, + "file_count": {"type": "integer", "minimum": 0, "maximum": 100000}, + "byte_count": {"$ref": "#/$defs/u63"}, + "manifest_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/capability-contract-2.0.json b/schemas/capability-contract-2.0.json new file mode 100644 index 0000000..ba8117d --- /dev/null +++ b/schemas/capability-contract-2.0.json @@ -0,0 +1,253 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/capability-contract/2.0", + "title": "Sanctum Capability Contract v2", + "description": "Structural contract for RFC-0011 capability-contract/2.0. Canonical ordering, UTF-8 byte/NFC checks, self-Sigil verification, and cross-authority narrowing are semantic validation requirements.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", "capability_id", "contract_version", "display_name", "purpose", + "tools", "filesystem", "executable", "process", "network", "environment", + "credential", "resource", "input", "output", "runtime", "lifecycle", + "side_effects", "assurance", "approval", "issued_at", "expires_at", "contract_sigil" + ], + "properties": { + "schema_version": {"const": "capability-contract/2.0"}, + "capability_id": {"$ref": "#/$defs/capabilityId"}, + "contract_version": {"const": "2.0"}, + "display_name": {"$ref": "#/$defs/humanText128"}, + "purpose": {"$ref": "#/$defs/humanText4096"}, + "tools": {"$ref": "#/$defs/toolAuthority"}, + "filesystem": {"$ref": "#/$defs/filesystemAuthority"}, + "executable": {"$ref": "#/$defs/executableAuthority"}, + "process": {"$ref": "#/$defs/processAuthority"}, + "network": {"$ref": "#/$defs/networkAuthority"}, + "environment": {"$ref": "#/$defs/environmentAuthority"}, + "credential": {"$ref": "#/$defs/credentialAuthority"}, + "resource": {"$ref": "#/$defs/resourceAuthority"}, + "input": {"$ref": "#/$defs/inputAuthority"}, + "output": {"$ref": "#/$defs/outputAuthority"}, + "runtime": {"$ref": "#/$defs/runtimeAuthority"}, + "lifecycle": {"$ref": "#/$defs/lifecycleAuthority"}, + "side_effects": {"$ref": "#/$defs/sideEffectAuthority"}, + "assurance": {"$ref": "#/$defs/assuranceAuthority"}, + "approval": {"$ref": "#/$defs/approvalAuthority"}, + "issued_at": {"$ref": "#/$defs/timestamp"}, + "expires_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, + "contract_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "timestamp": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$", "minLength": 20, "maxLength": 20}, + "version": {"type": "string", "pattern": "^[0-9]+[.][0-9]+(?:[.][0-9]+)?$", "minLength": 3, "maxLength": 32}, + "capabilityId": {"type": "string", "pattern": "^bench[.][a-z0-9]+(?:[.][a-z0-9]+)+$", "minLength": 9, "maxLength": 128}, + "token": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 1, "maxLength": 128}, + "logicalName": {"type": "string", "pattern": "^[a-z][a-z0-9_-]*$", "minLength": 1, "maxLength": 64}, + "schemaId": {"type": "string", "pattern": "^[a-z][a-z0-9-]*/[0-9]+[.][0-9]+$", "minLength": 5, "maxLength": 128}, + "mediaType": {"type": "string", "pattern": "^[a-z0-9!#$&^_.+-]+/[a-z0-9!#$&^_.+-]+$", "minLength": 3, "maxLength": 128}, + "relativePath": {"type": "string", "pattern": "^(?!/)(?!.*//)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*\\/$)[^\\u0000]+$", "minLength": 1, "maxLength": 1024}, + "hostName": {"type": "string", "pattern": "^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:[.](?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?))*$", "minLength": 1, "maxLength": 253}, + "environmentName": {"type": "string", "pattern": "^[A-Z_][A-Z0-9_]*$", "minLength": 1, "maxLength": 128}, + "humanText128": {"type": "string", "pattern": "^[^\\u0000]+$", "minLength": 1, "maxLength": 128}, + "humanText4096": {"type": "string", "pattern": "^[^\\u0000]+$", "minLength": 1, "maxLength": 4096}, + "toolId": {"type": "string", "pattern": "^TL-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "executableId": {"type": "string", "pattern": "^EX-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "runtimeId": {"type": "string", "pattern": "^RT-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "filesystemGrantId": {"type": "string", "pattern": "^FS-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "destinationId": {"type": "string", "pattern": "^ND-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "credentialHandleId": {"type": "string", "pattern": "^CH-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "sideEffectId": {"type": "string", "pattern": "^SE-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "approvalPolicyId": {"type": "string", "pattern": "^AP-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "conformanceSuiteId": {"type": "string", "pattern": "^CS-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "storagePolicyId": {"type": "string", "pattern": "^SP-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 3, "maxLength": 128}, + + "toolGrant": { + "type": "object", "additionalProperties": false, + "required": ["tool_id", "tool_version", "tool_sigil", "maximum_invocations", "side_effect_id"], + "properties": {"tool_id": {"$ref": "#/$defs/toolId"}, "tool_version": {"$ref": "#/$defs/version"}, "tool_sigil": {"$ref": "#/$defs/sigil"}, "maximum_invocations": {"$ref": "#/$defs/positiveU63"}, "side_effect_id": {"$ref": "#/$defs/sideEffectId"}} + }, + "toolAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "grants"], "properties": {"mode": {"const": "DENY"}, "grants": {"type": "array", "maxItems": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "grants"], "properties": {"mode": {"const": "ALLOWLIST"}, "grants": {"type": "array", "minItems": 1, "maxItems": 256, "items": {"$ref": "#/$defs/toolGrant"}, "uniqueItems": true}}} + ] + }, + "filesystemGrant": { + "type": "object", "additionalProperties": false, + "required": ["grant_id", "root_kind", "path_prefix", "operations", "maximum_read_bytes", "maximum_write_bytes", "maximum_entries", "maximum_depth", "symlink_policy", "mount_policy"], + "properties": { + "grant_id": {"$ref": "#/$defs/filesystemGrantId"}, "root_kind": {"enum": ["SNAPSHOT_INPUT", "CRUCIBLE", "DECLARED_OUTPUT", "EPHEMERAL"]}, "path_prefix": {"$ref": "#/$defs/relativePath"}, + "operations": {"type": "array", "minItems": 1, "maxItems": 8, "items": {"enum": ["STAT", "READ", "LIST", "CREATE", "WRITE", "RENAME", "DELETE", "EXECUTE"]}, "uniqueItems": true}, + "maximum_read_bytes": {"$ref": "#/$defs/u63"}, "maximum_write_bytes": {"$ref": "#/$defs/u63"}, "maximum_entries": {"$ref": "#/$defs/u63"}, "maximum_depth": {"$ref": "#/$defs/u63"}, "symlink_policy": {"const": "NOFOLLOW"}, "mount_policy": {"const": "NO_NEW_MOUNTS"} + } + }, + "filesystemAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "grants"], "properties": {"mode": {"const": "DENY"}, "grants": {"type": "array", "maxItems": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "grants"], "properties": {"mode": {"const": "ALLOWLIST"}, "grants": {"type": "array", "minItems": 1, "maxItems": 256, "items": {"$ref": "#/$defs/filesystemGrant"}, "uniqueItems": true}}} + ] + }, + "executableGrant": { + "type": "object", "additionalProperties": false, + "required": ["executable_id", "executable_version", "executable_sigil", "runtime_id", "runtime_version", "runtime_sigil", "entrypoint", "argument_schema_id", "argument_schema_sigil", "maximum_starts", "side_effect_id"], + "properties": {"executable_id": {"$ref": "#/$defs/executableId"}, "executable_version": {"$ref": "#/$defs/version"}, "executable_sigil": {"$ref": "#/$defs/sigil"}, "runtime_id": {"$ref": "#/$defs/runtimeId"}, "runtime_version": {"$ref": "#/$defs/version"}, "runtime_sigil": {"$ref": "#/$defs/sigil"}, "entrypoint": {"$ref": "#/$defs/relativePath"}, "argument_schema_id": {"$ref": "#/$defs/schemaId"}, "argument_schema_sigil": {"$ref": "#/$defs/sigil"}, "maximum_starts": {"$ref": "#/$defs/positiveU63"}, "side_effect_id": {"$ref": "#/$defs/sideEffectId"}} + }, + "executableAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "grants"], "properties": {"mode": {"const": "DENY"}, "grants": {"type": "array", "maxItems": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "grants"], "properties": {"mode": {"const": "ALLOWLIST"}, "grants": {"type": "array", "minItems": 1, "maxItems": 128, "items": {"$ref": "#/$defs/executableGrant"}, "uniqueItems": true}}} + ] + }, + "processAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "maximum_processes", "maximum_tree_depth", "child_executable_ids", "process_group_signals", "dynamic_loading"], "properties": {"mode": {"const": "DENY"}, "maximum_processes": {"const": 0}, "maximum_tree_depth": {"const": 0}, "child_executable_ids": {"type": "array", "maxItems": 0}, "process_group_signals": {"const": false}, "dynamic_loading": {"const": false}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "maximum_processes", "maximum_tree_depth", "child_executable_ids", "process_group_signals", "dynamic_loading"], "properties": {"mode": {"const": "ALLOWLIST"}, "maximum_processes": {"$ref": "#/$defs/positiveU63"}, "maximum_tree_depth": {"$ref": "#/$defs/positiveU63"}, "child_executable_ids": {"type": "array", "maxItems": 128, "items": {"$ref": "#/$defs/executableId"}, "uniqueItems": true}, "process_group_signals": {"type": "boolean"}, "dynamic_loading": {"type": "boolean"}}} + ] + }, + "networkDestination": { + "type": "object", "additionalProperties": false, + "required": ["destination_id", "protocol", "host", "ports", "address_policy_sigil", "redirect_policy", "side_effect_id"], + "properties": {"destination_id": {"$ref": "#/$defs/destinationId"}, "protocol": {"enum": ["TCP", "UDP", "HTTP", "HTTPS"]}, "host": {"$ref": "#/$defs/hostName"}, "ports": {"type": "array", "minItems": 1, "maxItems": 32, "items": {"type": "integer", "minimum": 1, "maximum": 65535}, "uniqueItems": true}, "address_policy_sigil": {"$ref": "#/$defs/sigil"}, "redirect_policy": {"enum": ["DENY", "SAME_DESTINATION"]}, "side_effect_id": {"$ref": "#/$defs/sideEffectId"}} + }, + "networkAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "dns_mode", "destinations", "maximum_connections", "maximum_requests", "maximum_egress_bytes"], "properties": {"mode": {"const": "DENY"}, "dns_mode": {"const": "DENY"}, "destinations": {"type": "array", "maxItems": 0}, "maximum_connections": {"const": 0}, "maximum_requests": {"const": 0}, "maximum_egress_bytes": {"const": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "dns_mode", "destinations", "maximum_connections", "maximum_requests", "maximum_egress_bytes"], "properties": {"mode": {"const": "ALLOWLIST"}, "dns_mode": {"const": "PINNED_ANSWER"}, "destinations": {"type": "array", "minItems": 1, "maxItems": 256, "items": {"$ref": "#/$defs/networkDestination"}, "uniqueItems": true}, "maximum_connections": {"$ref": "#/$defs/positiveU63"}, "maximum_requests": {"$ref": "#/$defs/positiveU63"}, "maximum_egress_bytes": {"$ref": "#/$defs/positiveU63"}}} + ] + }, + "environmentVariable": { + "type": "object", "additionalProperties": false, "required": ["name", "source_kind", "source_binding_id", "source_sigil", "required"], + "properties": {"name": {"$ref": "#/$defs/environmentName"}, "source_kind": {"enum": ["CONSTANT", "SNAPSHOT_METADATA", "RUNTIME_METADATA", "CREDENTIAL_HANDLE"]}, "source_binding_id": {"$ref": "#/$defs/token"}, "source_sigil": {"$ref": "#/$defs/sigil"}, "required": {"type": "boolean"}} + }, + "environmentAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "inheritance", "variables"], "properties": {"mode": {"const": "DENY"}, "inheritance": {"const": "NONE"}, "variables": {"type": "array", "maxItems": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "inheritance", "variables"], "properties": {"mode": {"const": "ALLOWLIST"}, "inheritance": {"const": "NONE"}, "variables": {"type": "array", "minItems": 1, "maxItems": 256, "items": {"$ref": "#/$defs/environmentVariable"}, "uniqueItems": true}}} + ] + }, + "credentialHandle": { + "type": "object", "additionalProperties": false, "required": ["handle_id", "credential_class", "scope_sigil", "maximum_uses", "side_effect_id"], + "properties": {"handle_id": {"$ref": "#/$defs/credentialHandleId"}, "credential_class": {"$ref": "#/$defs/token"}, "scope_sigil": {"$ref": "#/$defs/sigil"}, "maximum_uses": {"$ref": "#/$defs/positiveU63"}, "side_effect_id": {"$ref": "#/$defs/sideEffectId"}} + }, + "credentialAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "ambient_credentials", "value_exposure", "handles"], "properties": {"mode": {"const": "DENY"}, "ambient_credentials": {"const": false}, "value_exposure": {"const": "NEVER"}, "handles": {"type": "array", "maxItems": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "ambient_credentials", "value_exposure", "handles"], "properties": {"mode": {"const": "OPAQUE_HANDLES"}, "ambient_credentials": {"const": false}, "value_exposure": {"const": "NEVER"}, "handles": {"type": "array", "minItems": 1, "maxItems": 64, "items": {"$ref": "#/$defs/credentialHandle"}, "uniqueItems": true}}} + ] + }, + "attemptBudget": { + "type": "object", "additionalProperties": false, "required": ["cpu_time_seconds", "peak_memory_bytes", "storage_bytes_written", "output_bytes", "log_bytes", "process_starts", "network_egress_bytes", "network_requests"], + "properties": {"cpu_time_seconds": {"$ref": "#/$defs/u63"}, "peak_memory_bytes": {"$ref": "#/$defs/u63"}, "storage_bytes_written": {"$ref": "#/$defs/u63"}, "output_bytes": {"$ref": "#/$defs/u63"}, "log_bytes": {"$ref": "#/$defs/u63"}, "process_starts": {"$ref": "#/$defs/u63"}, "network_egress_bytes": {"$ref": "#/$defs/u63"}, "network_requests": {"$ref": "#/$defs/u63"}} + }, + "jobBudget": { + "type": "object", "additionalProperties": false, "required": ["attempts", "cpu_time_seconds", "storage_bytes_written", "output_bytes", "log_bytes", "process_starts", "network_egress_bytes", "network_requests"], + "properties": {"attempts": {"$ref": "#/$defs/positiveU63"}, "cpu_time_seconds": {"$ref": "#/$defs/u63"}, "storage_bytes_written": {"$ref": "#/$defs/u63"}, "output_bytes": {"$ref": "#/$defs/u63"}, "log_bytes": {"$ref": "#/$defs/u63"}, "process_starts": {"$ref": "#/$defs/u63"}, "network_egress_bytes": {"$ref": "#/$defs/u63"}, "network_requests": {"$ref": "#/$defs/u63"}} + }, + "resourceAuthority": { + "type": "object", "additionalProperties": false, "required": ["attempt_budget", "job_budget", "maximum_open_files", "maximum_file_count", "maximum_concurrent_threads"], + "properties": {"attempt_budget": {"$ref": "#/$defs/attemptBudget"}, "job_budget": {"$ref": "#/$defs/jobBudget"}, "maximum_open_files": {"$ref": "#/$defs/u63"}, "maximum_file_count": {"$ref": "#/$defs/u63"}, "maximum_concurrent_threads": {"$ref": "#/$defs/u63"}} + }, + "inputAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "maximum_inputs", "maximum_aggregate_bytes", "allowed_object_types", "allowed_media_types", "require_immutable_identity", "require_content_sigil"], "properties": {"mode": {"const": "DENY"}, "maximum_inputs": {"const": 0}, "maximum_aggregate_bytes": {"const": 0}, "allowed_object_types": {"type": "array", "maxItems": 0}, "allowed_media_types": {"type": "array", "maxItems": 0}, "require_immutable_identity": {"const": true}, "require_content_sigil": {"const": true}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "maximum_inputs", "maximum_aggregate_bytes", "allowed_object_types", "allowed_media_types", "require_immutable_identity", "require_content_sigil"], "properties": {"mode": {"const": "ALLOWLIST"}, "maximum_inputs": {"$ref": "#/$defs/positiveU63"}, "maximum_aggregate_bytes": {"$ref": "#/$defs/positiveU63"}, "allowed_object_types": {"type": "array", "minItems": 1, "maxItems": 17, "items": {"$ref": "#/$defs/snapshotObjectType"}, "uniqueItems": true}, "allowed_media_types": {"type": "array", "minItems": 1, "maxItems": 64, "items": {"$ref": "#/$defs/mediaType"}, "uniqueItems": true}, "require_immutable_identity": {"const": true}, "require_content_sigil": {"const": true}}} + ] + }, + "snapshotObjectType": {"enum": ["research-program", "evidence", "claim", "hypothesis", "protocol", "working", "experiment", "run", "result-bundle", "assessment", "decision", "artifact", "issue", "deviation", "reproduction-record", "review-request", "review-artifact"]}, + "pathRule": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind", "relative_path"], "properties": {"kind": {"const": "FIXED"}, "relative_path": {"$ref": "#/$defs/relativePath"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "relative_prefix", "maximum_depth"], "properties": {"kind": {"const": "PREFIX"}, "relative_prefix": {"$ref": "#/$defs/relativePath"}, "maximum_depth": {"$ref": "#/$defs/u63"}}} + ] + }, + "outputGrant": { + "type": "object", "additionalProperties": false, "required": ["logical_name", "schema_id", "schema_sigil", "maximum_bytes", "maximum_count", "path_rule", "side_effect_id"], + "properties": {"logical_name": {"$ref": "#/$defs/logicalName"}, "schema_id": {"$ref": "#/$defs/schemaId"}, "schema_sigil": {"$ref": "#/$defs/sigil"}, "maximum_bytes": {"$ref": "#/$defs/positiveU63"}, "maximum_count": {"$ref": "#/$defs/positiveU63"}, "path_rule": {"$ref": "#/$defs/pathRule"}, "side_effect_id": {"$ref": "#/$defs/sideEffectId"}} + }, + "outputAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "maximum_outputs", "maximum_aggregate_bytes", "grants"], "properties": {"mode": {"const": "DENY"}, "maximum_outputs": {"const": 0}, "maximum_aggregate_bytes": {"const": 0}, "grants": {"type": "array", "maxItems": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "maximum_outputs", "maximum_aggregate_bytes", "grants"], "properties": {"mode": {"const": "ALLOWLIST"}, "maximum_outputs": {"$ref": "#/$defs/positiveU63"}, "maximum_aggregate_bytes": {"$ref": "#/$defs/positiveU63"}, "grants": {"type": "array", "minItems": 1, "maxItems": 256, "items": {"$ref": "#/$defs/outputGrant"}, "uniqueItems": true}}} + ] + }, + "identityBinding": { + "type": "object", "additionalProperties": false, "required": ["identity_id", "identity_version", "identity_sigil"], + "properties": {"identity_id": {"$ref": "#/$defs/token"}, "identity_version": {"$ref": "#/$defs/version"}, "identity_sigil": {"$ref": "#/$defs/sigil"}} + }, + "constraintBinding": { + "type": "object", "additionalProperties": false, "required": ["constraint_id", "constraint_sigil"], + "properties": {"constraint_id": {"$ref": "#/$defs/token"}, "constraint_sigil": {"$ref": "#/$defs/sigil"}} + }, + "runtimeAuthority": { + "type": "object", "additionalProperties": false, "required": ["runtime_identities", "backend_identities", "host_constraints", "identity_requirements"], + "properties": { + "runtime_identities": {"type": "array", "minItems": 1, "maxItems": 64, "items": {"$ref": "#/$defs/identityBinding"}, "uniqueItems": true}, + "backend_identities": {"type": "array", "minItems": 1, "maxItems": 64, "items": {"$ref": "#/$defs/identityBinding"}, "uniqueItems": true}, + "host_constraints": {"type": "array", "maxItems": 64, "items": {"$ref": "#/$defs/constraintBinding"}, "uniqueItems": true}, + "identity_requirements": {"type": "object", "additionalProperties": false, "required": ["require_host_identity", "require_backend_configuration_identity", "require_runtime_content_identity"], "properties": {"require_host_identity": {"type": "boolean"}, "require_backend_configuration_identity": {"type": "boolean"}, "require_runtime_content_identity": {"type": "boolean"}}} + } + }, + "deadlineAuthority": { + "type": "object", "additionalProperties": false, "required": ["lease_duration_seconds", "heartbeat_interval_seconds", "heartbeat_timeout_seconds", "lease_claim_timeout_seconds", "attempt_wall_time_seconds", "cancellation_grace_seconds", "job_wall_time_seconds", "clock_uncertainty_tolerance_seconds"], + "properties": {"lease_duration_seconds": {"$ref": "#/$defs/positiveU63"}, "heartbeat_interval_seconds": {"$ref": "#/$defs/positiveU63"}, "heartbeat_timeout_seconds": {"$ref": "#/$defs/positiveU63"}, "lease_claim_timeout_seconds": {"$ref": "#/$defs/positiveU63"}, "attempt_wall_time_seconds": {"$ref": "#/$defs/positiveU63"}, "cancellation_grace_seconds": {"$ref": "#/$defs/u63"}, "job_wall_time_seconds": {"$ref": "#/$defs/positiveU63"}, "clock_uncertainty_tolerance_seconds": {"$ref": "#/$defs/u63"}} + }, + "retryAuthority": { + "type": "object", "additionalProperties": false, "required": ["maximum_attempts", "allowed_retryable_terminal_reasons", "allowed_backoff_kinds", "maximum_backoff_base_seconds", "maximum_backoff_cap_seconds", "allowed_resume_policies"], + "properties": {"maximum_attempts": {"$ref": "#/$defs/positiveU63"}, "allowed_retryable_terminal_reasons": {"type": "array", "maxItems": 25, "items": {"$ref": "#/$defs/retryableTerminalReason"}, "uniqueItems": true}, "allowed_backoff_kinds": {"type": "array", "minItems": 1, "maxItems": 3, "items": {"enum": ["NONE", "FIXED", "EXPONENTIAL"]}, "uniqueItems": true}, "maximum_backoff_base_seconds": {"$ref": "#/$defs/u63"}, "maximum_backoff_cap_seconds": {"$ref": "#/$defs/u63"}, "allowed_resume_policies": {"type": "array", "minItems": 1, "maxItems": 2, "items": {"enum": ["FRESH_ONLY", "ALLOW_IMMUTABLE_RESUME"]}, "uniqueItems": true}} + }, + "retryableTerminalReason": {"enum": ["ATTEMPT_DEADLINE", "HEARTBEAT_TIMEOUT", "LEASE_CLAIM_EXPIRED", "LEASE_ACTIVE_EXPIRED", "LEASE_REVOKED", "RECOVERY_FENCE", "CLOCK_UNCERTAIN", "EXECUTOR_EPOCH_CHANGED", "SESSION_CHANNEL_LOST", "PREFLIGHT_REJECTED", "START_FAILED", "COMPUTATION_FAILED", "VALIDATION_FAILED", "RESULT_CONFLICT", "RESULT_REQUIREMENT_FAILED", "OUTPUT_VALIDATION_FAILED", "TERMINAL_SOURCE_RETENTION_FAILED", "TERMINATION_FAILED", "CLEANUP_FAILED", "LOST_OWNERSHIP", "ASSURANCE_UNMET", "ASSURANCE_UNVERIFIABLE", "BUDGET_EXHAUSTED", "ATTEMPT_REJECTED", "FATAL_INFRASTRUCTURE"]}, + "loggingAuthority": { + "type": "object", "additionalProperties": false, "required": ["stdout_maximum_bytes", "stderr_maximum_bytes", "structured_maximum_bytes", "aggregate_maximum_bytes", "chunk_maximum_bytes", "allowed_overflow_behaviors"], + "properties": {"stdout_maximum_bytes": {"$ref": "#/$defs/u63"}, "stderr_maximum_bytes": {"$ref": "#/$defs/u63"}, "structured_maximum_bytes": {"$ref": "#/$defs/u63"}, "aggregate_maximum_bytes": {"$ref": "#/$defs/u63"}, "chunk_maximum_bytes": {"$ref": "#/$defs/u63"}, "allowed_overflow_behaviors": {"type": "array", "minItems": 1, "maxItems": 2, "items": {"enum": ["TRUNCATE", "TERMINATE"]}, "uniqueItems": true}} + }, + "resultAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["allowed_worker_result_modes"], "properties": {"allowed_worker_result_modes": {"const": ["REQUIRED"]}}}, + {"type": "object", "additionalProperties": false, "required": ["allowed_worker_result_modes"], "properties": {"allowed_worker_result_modes": {"const": ["OPTIONAL"]}}}, + {"type": "object", "additionalProperties": false, "required": ["allowed_worker_result_modes"], "properties": {"allowed_worker_result_modes": {"const": ["FORBIDDEN"]}}}, + {"type": "object", "additionalProperties": false, "required": ["allowed_worker_result_modes"], "properties": {"allowed_worker_result_modes": {"const": ["REQUIRED", "FORBIDDEN"]}}} + ] + }, + "retentionPolicyBinding": { + "type": "object", "additionalProperties": false, "required": ["retention_policy_id", "retention_policy_version", "retention_policy_sigil"], + "properties": {"retention_policy_id": {"$ref": "#/$defs/storagePolicyId"}, "retention_policy_version": {"const": "1.0"}, "retention_policy_sigil": {"$ref": "#/$defs/sigil"}} + }, + "postTerminalAuthority": { + "type": "object", "additionalProperties": false, "required": ["allowed_modes", "retention_policies", "terminal_source_maximum_files", "terminal_source_maximum_bytes", "retention_duration_seconds", "source_identity_profiles"], + "properties": {"allowed_modes": {"type": "array", "minItems": 1, "maxItems": 2, "items": {"enum": ["NONE", "CODE_MODIFICATION"]}, "uniqueItems": true}, "retention_policies": {"type": "array", "maxItems": 32, "items": {"$ref": "#/$defs/retentionPolicyBinding"}, "uniqueItems": true}, "terminal_source_maximum_files": {"$ref": "#/$defs/u63"}, "terminal_source_maximum_bytes": {"$ref": "#/$defs/u63"}, "retention_duration_seconds": {"$ref": "#/$defs/u63"}, "source_identity_profiles": {"type": "array", "maxItems": 1, "items": {"const": "BENCHWORK_SOURCE_TREE_V1"}, "uniqueItems": true}} + }, + "lifecycleAuthority": { + "type": "object", "additionalProperties": false, "required": ["deadlines", "retry", "logging", "result", "post_terminal"], + "properties": {"deadlines": {"$ref": "#/$defs/deadlineAuthority"}, "retry": {"$ref": "#/$defs/retryAuthority"}, "logging": {"$ref": "#/$defs/loggingAuthority"}, "result": {"$ref": "#/$defs/resultAuthority"}, "post_terminal": {"$ref": "#/$defs/postTerminalAuthority"}} + }, + "sideEffectGrant": { + "type": "object", "additionalProperties": false, "required": ["side_effect_id", "kind", "authority_sigil", "maximum_invocations", "retry_mode", "idempotency_scope_sigil", "requires_approval"], + "properties": {"side_effect_id": {"$ref": "#/$defs/sideEffectId"}, "kind": {"enum": ["READ_ONLY", "IDEMPOTENT_WRITE", "SINGLE_USE_EXTERNAL"]}, "authority_sigil": {"$ref": "#/$defs/sigil"}, "maximum_invocations": {"$ref": "#/$defs/positiveU63"}, "retry_mode": {"enum": ["NO_RETRY", "SAME_IDEMPOTENCY_KEY", "NEW_AUTHORIZATION_EACH_ATTEMPT"]}, "idempotency_scope_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "requires_approval": {"type": "boolean"}}, + "allOf": [ + {"if": {"properties": {"retry_mode": {"const": "SAME_IDEMPOTENCY_KEY"}}, "required": ["retry_mode"]}, "then": {"properties": {"idempotency_scope_sigil": {"$ref": "#/$defs/sigil"}}}, "else": {"properties": {"idempotency_scope_sigil": {"type": "null"}}}}, + {"if": {"properties": {"kind": {"const": "SINGLE_USE_EXTERNAL"}}, "required": ["kind"]}, "then": {"properties": {"maximum_invocations": {"const": 1}, "retry_mode": {"enum": ["NO_RETRY", "NEW_AUTHORIZATION_EACH_ATTEMPT"]}}}} + ] + }, + "sideEffectAuthority": {"type": "object", "additionalProperties": false, "required": ["grants"], "properties": {"grants": {"type": "array", "maxItems": 128, "items": {"$ref": "#/$defs/sideEffectGrant"}, "uniqueItems": true}}}, + "approvalAuthority": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["requirement", "policy_id", "policy_version", "policy_sigil", "binding_scope"], "properties": {"requirement": {"const": "NOT_REQUIRED"}, "policy_id": {"type": "null"}, "policy_version": {"type": "null"}, "policy_sigil": {"type": "null"}, "binding_scope": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["requirement", "policy_id", "policy_version", "policy_sigil", "binding_scope"], "properties": {"requirement": {"const": "REQUIRED"}, "policy_id": {"$ref": "#/$defs/approvalPolicyId"}, "policy_version": {"$ref": "#/$defs/version"}, "policy_sigil": {"$ref": "#/$defs/sigil"}, "binding_scope": {"const": "EXACT_EXECUTION_POLICY"}}} + ] + }, + "controlRequirement": { + "type": "object", "additionalProperties": false, "required": ["control_dimension", "required_state", "required_evidence_kinds", "requirement_evidence_profile_sigil"], + "properties": {"control_dimension": {"$ref": "#/$defs/controlDimension"}, "required_state": {"enum": ["ANY_RECORDED", "OBSERVED", "VERIFIED", "ENFORCED"]}, "required_evidence_kinds": {"type": "array", "minItems": 1, "maxItems": 29, "items": {"$ref": "#/$defs/evidenceKind"}, "uniqueItems": true}, "requirement_evidence_profile_sigil": {"$ref": "#/$defs/sigil"}} + }, + "controlDimension": {"enum": ["IDENTITY_AUTHORIZATION", "FILESYSTEM", "NETWORK", "PROCESS_EXECUTABLE", "RESOURCE", "ENVIRONMENT_CREDENTIAL", "LOG_OUTPUT_CAPTURE", "RUNTIME_INPUT_OUTPUT_IDENTITY", "CANCELLATION_FENCING", "TERMINATION_CLEANUP"]}, + "evidenceKind": {"enum": ["TASK_BINDING", "CAPABILITY_BINDING", "SNAPSHOT_BINDING", "WARD_DECISION", "APPROVAL_RECEIPT", "BACKEND_CONFIGURATION", "HOST_IDENTITY", "POLICY_RESOLUTION", "BASE_IDENTITY", "INPUT_IDENTITY", "MATERIALIZATION_IDENTITY", "ENVIRONMENT_CONSTRUCTION", "FILESYSTEM_POLICY", "NETWORK_POLICY", "EXECUTABLE_SELECTION", "PROCESS_TREE", "WALL_TIME_ENFORCEMENT", "RESOURCE_ACCOUNTING", "CREDENTIAL_NONINHERITANCE", "LOG_CAPTURE", "OUTPUT_VALIDATION", "STORAGE_OBSERVATION", "FENCE_TOMBSTONE", "TERMINATION", "HANDLE_REVOCATION", "CLEANUP", "QUARANTINE", "TERMINAL_SOURCE_VERIFICATION", "CONFORMANCE_FIXTURE"]}, + "assuranceGrant": { + "type": "object", "additionalProperties": false, "required": ["requested_level", "profile_version", "profile_sigil", "conformance_suite_id", "conformance_suite_sigil", "control_requirements"], + "properties": {"requested_level": {"enum": ["SANCTUM-A0", "SANCTUM-A1", "SANCTUM-A2"]}, "profile_version": {"$ref": "#/$defs/version"}, "profile_sigil": {"$ref": "#/$defs/sigil"}, "conformance_suite_id": {"$ref": "#/$defs/conformanceSuiteId"}, "conformance_suite_sigil": {"$ref": "#/$defs/sigil"}, "control_requirements": {"type": "array", "minItems": 10, "maxItems": 10, "items": {"$ref": "#/$defs/controlRequirement"}, "uniqueItems": true}} + }, + "assuranceAuthority": {"type": "object", "additionalProperties": false, "required": ["grants"], "properties": {"grants": {"type": "array", "minItems": 1, "maxItems": 64, "items": {"$ref": "#/$defs/assuranceGrant"}, "uniqueItems": true}}} + } +} + diff --git a/schemas/capability-registry-2.0.json b/schemas/capability-registry-2.0.json new file mode 100644 index 0000000..8bca893 --- /dev/null +++ b/schemas/capability-registry-2.0.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/capability-registry/2.0", + "title": "Sanctum Capability Registry v2", + "description": "Structural contract for RFC-0011 capability-registry/2.0. Map-key order, self-Sigil validation, embedded Capability semantics, and prior-revision resolution are semantic requirements.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "registry_id", "registry_revision", "created_at", "supersedes_registry_sigil", "capabilities", "registry_sigil"], + "properties": { + "schema_version": {"const": "capability-registry/2.0"}, + "registry_id": {"$ref": "#/$defs/registryId"}, + "registry_revision": {"$ref": "#/$defs/u63"}, + "created_at": {"$ref": "#/$defs/timestamp"}, + "supersedes_registry_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, + "capabilities": { + "type": "object", + "minProperties": 1, + "maxProperties": 4096, + "propertyNames": {"$ref": "#/$defs/capabilityId"}, + "additionalProperties": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0"} + }, + "registry_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"registry_revision": {"const": 0}}, "required": ["registry_revision"]}, + "then": {"properties": {"supersedes_registry_sigil": {"type": "null"}}}, + "else": {"properties": {"supersedes_registry_sigil": {"$ref": "#/$defs/sigil"}}} + } + ], + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9]Z$", "minLength": 20, "maxLength": 20}, + "capabilityId": {"type": "string", "pattern": "^bench[.][a-z0-9]+(?:[.][a-z0-9]+)+$", "not": {"pattern": "[\\r\\n]"}, "minLength": 9, "maxLength": 128}, + "registryId": {"type": "string", "pattern": "^CR-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128} + } +} + diff --git a/schemas/execution-accept-result-request-1.0.json b/schemas/execution-accept-result-request-1.0.json new file mode 100644 index 0000000..49d2168 --- /dev/null +++ b/schemas/execution-accept-result-request-1.0.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-accept-result-request/1.0", + "title": "Execution Accept Result Request", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "job_id", + "execution_job_outcome_sigil", + "idempotency_key" + ], + "properties": { + "schema_version": {"const": "execution-accept-result-request/1.0"}, + "job_id": {"$ref": "#/$defs/job_id"}, + "execution_job_outcome_sigil": {"$ref": "#/$defs/sigil"}, + "idempotency_key": {"$ref": "#/$defs/opaque"} + }, + "$defs": { + "job_id": { + "type": "string", + "pattern": "^JB-[A-F0-9]{64}$", + "minLength": 67, + "maxLength": 67 + }, + "sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$", + "minLength": 71, + "maxLength": 71 + }, + "opaque": { + "type": "string", + "not": {"pattern": "[\\u0000-\\u001F\\u007F-\\u009F]"}, + "minLength": 1, + "maxLength": 256 + } + } +} + diff --git a/schemas/execution-approval-subject-1.0.json b/schemas/execution-approval-subject-1.0.json new file mode 100644 index 0000000..e37639d --- /dev/null +++ b/schemas/execution-approval-subject-1.0.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-approval-subject/1.0", + "title": "Execution Approval Subject v1", + "description": "Closed RFC-0011 pre-approval Execution Specification subject. Candidate binding, content-derived identity, permission-set Sigil, and self-Sigil are semantic requirements.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "approval_subject_id", + "specification_id", + "preapproval_specification_sigil", + "registry_binding", + "task_id", + "task_capsule_sigil", + "capability_binding", + "snapshot_binding", + "circle_id", + "circle_sigil", + "ward_decision_id", + "ward_decision_sigil", + "approval_policy_id", + "approval_policy_version", + "approval_policy_sigil", + "assurance_requirement", + "resolved_permission_set_sigil", + "approval_subject_sigil" + ], + "properties": { + "schema_version": {"const": "execution-approval-subject/1.0"}, + "approval_subject_id": {"$ref": "#/$defs/approvalSubjectId"}, + "specification_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/specificationId"}, + "preapproval_specification_sigil": {"$ref": "#/$defs/sigil"}, + "registry_binding": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/registryBinding"}, + "task_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/taskId"}, + "task_capsule_sigil": {"$ref": "#/$defs/sigil"}, + "capability_binding": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/capabilityBinding"}, + "snapshot_binding": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/snapshotBinding"}, + "circle_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/circleId"}, + "circle_sigil": {"$ref": "#/$defs/sigil"}, + "ward_decision_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/wardDecisionId"}, + "ward_decision_sigil": {"$ref": "#/$defs/sigil"}, + "approval_policy_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/approvalPolicyId"}, + "approval_policy_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, + "approval_policy_sigil": {"$ref": "#/$defs/sigil"}, + "assurance_requirement": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/assuranceRequirement"}, + "resolved_permission_set_sigil": {"$ref": "#/$defs/sigil"}, + "approval_subject_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "approvalSubjectId": { + "type": "string", + "pattern": "^EA-[A-F0-9]{64}$", + "minLength": 67, + "maxLength": 67 + } + } +} + diff --git a/schemas/execution-approval-transition-request-1.0.json b/schemas/execution-approval-transition-request-1.0.json new file mode 100644 index 0000000..489bfe2 --- /dev/null +++ b/schemas/execution-approval-transition-request-1.0.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-approval-transition-request/1.0", + "title": "Execution Approval Transition Request v1", + "description": "Closed RFC-0011 Athanor request for one exact Execution approval subject. Authenticated invocation resolution, durable single assignment, canonical Event, Receipt, and final Specification binding remain external conformance checks.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "transition_request_id", + "event_type", + "purpose", + "expected_chronicle_head", + "approval_subject", + "actor", + "host_invocation", + "chronicle_actor", + "idempotency_key_sigil", + "requested_at", + "transition_request_sigil" + ], + "properties": { + "schema_version": {"const": "execution-approval-transition-request/1.0"}, + "transition_request_id": {"$ref": "#/$defs/transitionRequestId"}, + "event_type": {"const": "execution.approval.granted"}, + "purpose": {"const": "EXECUTION_APPROVAL"}, + "expected_chronicle_head": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/chronicleHeadRef"}, + "approval_subject": {"$ref": "https://benchwork.dev/schemas/execution-approval-subject/1.0"}, + "actor": {"$ref": "https://benchwork.dev/schemas/execution-cancel-request/1.0#/$defs/actor_binding"}, + "host_invocation": {"$ref": "https://benchwork.dev/schemas/execution-cancel-request/1.0#/$defs/host_invocation_binding"}, + "chronicle_actor": {"$ref": "https://benchwork.dev/schemas/actor/1.0"}, + "idempotency_key_sigil": {"$ref": "#/$defs/sigil"}, + "requested_at": {"$ref": "#/$defs/timestamp"}, + "transition_request_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "transitionRequestId": { + "type": "string", + "pattern": "^EAT-[A-F0-9]{64}$", + "minLength": 68, + "maxLength": 68 + } + } +} + diff --git a/schemas/execution-attempt-1.0.json b/schemas/execution-attempt-1.0.json new file mode 100644 index 0000000..92c0530 --- /dev/null +++ b/schemas/execution-attempt-1.0.json @@ -0,0 +1,189 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-attempt/1.0", + "title": "Execution Attempt", + "description": "Closed FRESH-only immutable RFC-0012 Attempt allocation record. Shape and local integrity only; it grants no allocation, Host, Lease, or execution authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "attempt_id", + "job_id", + "job_binding_sigil", + "retry_ordinal", + "fencing_generation", + "assurance_requirement", + "backend_identity", + "backend_version", + "backend_implementation_sigil", + "backend_configuration_sigil", + "base_identity", + "base_sigil", + "input_identities", + "resume_mode", + "crucible_id", + "output_namespace_id", + "log_stream_ids", + "budget_reservation", + "attempt_authorization_requirement", + "created_at", + "deadline_due_at", + "attempt_binding_sigil" + ], + "properties": { + "schema_version": {"const": "execution-attempt/1.0"}, + "attempt_id": {"$ref": "#/$defs/attemptId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "job_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "retry_ordinal": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, + "fencing_generation": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/u64"}, + "assurance_requirement": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/assuranceRequirement"}, + "backend_identity": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/token"}, + "backend_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, + "backend_implementation_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "backend_configuration_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "base_identity": { + "anyOf": [ + {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/token"}, + {"type": "null"} + ] + }, + "base_sigil": { + "anyOf": [ + {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + {"type": "null"} + ] + }, + "input_identities": { + "type": "array", + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/visibleInput"} + }, + "resume_mode": {"const": "FRESH"}, + "crucible_id": {"$ref": "#/$defs/crucibleId"}, + "output_namespace_id": {"$ref": "#/$defs/outputNamespaceId"}, + "log_stream_ids": {"$ref": "#/$defs/logStreamIds"}, + "budget_reservation": {"$ref": "#/$defs/budgetReservation"}, + "attempt_authorization_requirement": {"$ref": "#/$defs/attemptAuthorizationRequirement"}, + "created_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "deadline_due_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "attempt_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + }, + "oneOf": [ + { + "properties": { + "base_identity": {"type": "null"}, + "base_sigil": {"type": "null"} + } + }, + { + "properties": { + "base_identity": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/token"}, + "base_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + } + ], + "$defs": { + "attemptId": { + "type": "string", + "pattern": "^AT-[A-Z0-9]+$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 4, + "maxLength": 128 + }, + "logStreamId": { + "type": "string", + "pattern": "^LG-[A-Z0-9]+$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 4, + "maxLength": 128 + }, + "crucibleId": { + "type": "string", + "pattern": "^CU-[A-Z0-9]+$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 4, + "maxLength": 128 + }, + "outputNamespaceId": { + "type": "string", + "pattern": "^ON-[A-Z0-9]+$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 4, + "maxLength": 128 + }, + "logStreamIds": { + "type": "object", + "additionalProperties": false, + "required": ["STDOUT", "STDERR", "STRUCTURED"], + "properties": { + "STDOUT": {"$ref": "#/$defs/logStreamId"}, + "STDERR": {"$ref": "#/$defs/logStreamId"}, + "STRUCTURED": {"$ref": "#/$defs/logStreamId"} + } + }, + "budgetReservation": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempts", + "cpu_time_seconds", + "storage_bytes_written", + "output_bytes", + "log_bytes", + "process_starts", + "network_egress_bytes", + "network_requests" + ], + "properties": { + "attempts": {"const": 1}, + "cpu_time_seconds": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "storage_bytes_written": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "output_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "log_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "process_starts": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "network_egress_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "network_requests": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"} + } + }, + "attemptAuthorizationEffect": { + "type": "object", + "additionalProperties": false, + "required": ["side_effect_id", "authority_sigil"], + "properties": { + "side_effect_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectId"}, + "authority_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + }, + "attemptAuthorizationRequirement": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "effects"], + "properties": { + "kind": {"const": "NONE"}, + "effects": {"type": "array", "maxItems": 0} + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "effects"], + "properties": { + "kind": {"const": "REQUIRED"}, + "effects": { + "type": "array", + "minItems": 1, + "maxItems": 128, + "uniqueItems": true, + "items": {"$ref": "#/$defs/attemptAuthorizationEffect"} + } + } + } + ] + } + } +} + diff --git a/schemas/execution-authenticated-heartbeat-envelope-1.0.json b/schemas/execution-authenticated-heartbeat-envelope-1.0.json new file mode 100644 index 0000000..0f43593 --- /dev/null +++ b/schemas/execution-authenticated-heartbeat-envelope-1.0.json @@ -0,0 +1,70 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-authenticated-heartbeat-envelope/1.0", + "title": "Execution Authenticated Heartbeat Envelope v1", + "description": "Closed RFC-0012 H2 trusted-adapter output. Structural validity and its self-Sigil do not authenticate a channel, peer, Session, Lease, or received frame.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "scope", + "lease_id", + "worker_session_id", + "worker_session_binding_sigil", + "executor_instance_id", + "executor_epoch", + "control_channel_identity_sigil", + "transport_sequence", + "received_at", + "received_bytes_sigil", + "claimed_message_sigil", + "peer_key_identity_sigil", + "authentication_evidence_sigil" + ], + "properties": { + "schema_version": {"const": "execution-authenticated-heartbeat-envelope/1.0"}, + "scope": {"enum": ["WORKER", "LEASE"]}, + "lease_id": { + "oneOf": [ + {"type": "null"}, + {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"} + ] + }, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_instance_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/executorInstanceId"}, + "executor_epoch": {"$ref": "#/$defs/u64"}, + "control_channel_identity_sigil": {"$ref": "#/$defs/sigil"}, + "transport_sequence": {"$ref": "#/$defs/u64"}, + "received_at": {"$ref": "#/$defs/timestamp"}, + "received_bytes_sigil": {"$ref": "#/$defs/sigil"}, + "claimed_message_sigil": { + "oneOf": [ + {"type": "null"}, + {"$ref": "#/$defs/sigil"} + ] + }, + "peer_key_identity_sigil": {"$ref": "#/$defs/sigil"}, + "authentication_evidence_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"scope": {"const": "WORKER"}}, "required": ["scope"]}, + "then": {"properties": {"lease_id": {"type": "null"}}} + }, + { + "if": {"properties": {"scope": {"const": "LEASE"}}, "required": ["scope"]}, + "then": { + "properties": { + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"} + } + } + } + ], + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u64": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/u64"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"} + } +} + diff --git a/schemas/execution-cancel-request-1.0.json b/schemas/execution-cancel-request-1.0.json new file mode 100644 index 0000000..0dcab15 --- /dev/null +++ b/schemas/execution-cancel-request-1.0.json @@ -0,0 +1,90 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-cancel-request/1.0", + "title": "Execution Cancel Request", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "cancellation_request_id", + "idempotency_key", + "job_id", + "job_binding_sigil", + "expected_job_revision", + "reason", + "actor", + "host_invocation", + "caller_observed_at" + ], + "properties": { + "schema_version": {"const": "execution-cancel-request/1.0"}, + "cancellation_request_id": {"$ref": "#/$defs/opaque"}, + "idempotency_key": {"$ref": "#/$defs/opaque"}, + "job_id": {"$ref": "#/$defs/job_id"}, + "job_binding_sigil": {"$ref": "#/$defs/sigil"}, + "expected_job_revision": {"$ref": "#/$defs/u64"}, + "reason": {"$ref": "#/$defs/opaque"}, + "actor": {"$ref": "#/$defs/actor_binding"}, + "host_invocation": {"$ref": "#/$defs/host_invocation_binding"}, + "caller_observed_at": {"$ref": "#/$defs/timestamp"} + }, + "$defs": { + "job_id": { + "type": "string", + "pattern": "^JB-[A-F0-9]{64}$", + "minLength": 67, + "maxLength": 67 + }, + "sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$", + "minLength": 71, + "maxLength": 71 + }, + "opaque": { + "type": "string", + "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", + "minLength": 1, + "maxLength": 256 + }, + "u64": { + "type": "integer", + "minimum": 0, + "maximum": 18446744073709551615 + }, + "timestamp": { + "type": "string", + "format": "date-time", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", + "minLength": 20, + "maxLength": 27 + }, + "actor_binding": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "actor_id", "authentication_context_sigil", "actor_sigil"], + "properties": { + "kind": {"enum": ["USER", "AGENT", "SYSTEM"]}, + "actor_id": {"$ref": "#/$defs/opaque"}, + "authentication_context_sigil": {"$ref": "#/$defs/sigil"}, + "actor_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "host_invocation_binding": { + "type": "object", + "additionalProperties": false, + "required": [ + "host_identity_sigil", + "invocation_id", + "authentication_context_sigil", + "invocation_sigil" + ], + "properties": { + "host_identity_sigil": {"$ref": "#/$defs/sigil"}, + "invocation_id": {"$ref": "#/$defs/opaque"}, + "authentication_context_sigil": {"$ref": "#/$defs/sigil"}, + "invocation_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} diff --git a/schemas/execution-control-evidence-1.0.json b/schemas/execution-control-evidence-1.0.json new file mode 100644 index 0000000..a72c906 --- /dev/null +++ b/schemas/execution-control-evidence-1.0.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-control-evidence/1.0", + "title": "Execution Control Evidence v1", + "description": "Closed RFC-0012 Control Evidence wire contract. Local validation establishes shape, ordering, binding identity, and deficiency consistency only; it does not execute evidence predicates, resolve external records, establish assurance, or grant execution authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "control_evidence_id", "job_id", "attempt_id", "control_dimension", "required_state", "realized_state", "phase_evidence", "bindings", "deficiencies", "control_evidence_sigil"], + "properties": { + "schema_version": {"const": "execution-control-evidence/1.0"}, + "control_evidence_id": {"$ref": "#/$defs/controlEvidenceId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "control_dimension": {"$ref": "#/$defs/controlDimension"}, + "required_state": {"$ref": "#/$defs/requiredState"}, + "realized_state": {"$ref": "#/$defs/realizedState"}, + "phase_evidence": {"$ref": "#/$defs/phaseEvidence"}, + "bindings": {"$ref": "#/$defs/bindings"}, + "deficiencies": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/deficiency"}}, + "control_evidence_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "opaque": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 256}, + "controlEvidenceId": {"type": "string", "pattern": "^CVE-[0-7][0-9A-HJKMNP-TV-Z]{25}$", "minLength": 30, "maxLength": 30}, + "evidenceIdentity": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$", "minLength": 1, "maxLength": 128}, + "controlDimension": {"enum": ["IDENTITY_AUTHORIZATION", "FILESYSTEM", "NETWORK", "PROCESS_EXECUTABLE", "RESOURCE", "ENVIRONMENT_CREDENTIAL", "LOG_OUTPUT_CAPTURE", "RUNTIME_INPUT_OUTPUT_IDENTITY", "CANCELLATION_FENCING", "TERMINATION_CLEANUP"]}, + "requiredState": {"enum": ["ENFORCED", "VERIFIED", "OBSERVED", "ANY_RECORDED"]}, + "realizedState": {"enum": ["ENFORCED", "VERIFIED", "OBSERVED", "UNAVAILABLE"]}, + "phase": {"enum": ["PREFLIGHT", "RUNTIME", "TERMINATION", "CLEANUP"]}, + "evidenceKind": {"enum": ["TASK_BINDING", "CAPABILITY_BINDING", "SNAPSHOT_BINDING", "WARD_DECISION", "APPROVAL_RECEIPT", "BACKEND_CONFIGURATION", "HOST_IDENTITY", "POLICY_RESOLUTION", "BASE_IDENTITY", "INPUT_IDENTITY", "MATERIALIZATION_IDENTITY", "ENVIRONMENT_CONSTRUCTION", "FILESYSTEM_POLICY", "NETWORK_POLICY", "EXECUTABLE_SELECTION", "PROCESS_TREE", "WALL_TIME_ENFORCEMENT", "RESOURCE_ACCOUNTING", "CREDENTIAL_NONINHERITANCE", "LOG_CAPTURE", "OUTPUT_VALIDATION", "STORAGE_OBSERVATION", "FENCE_TOMBSTONE", "TERMINATION", "HANDLE_REVOCATION", "CLEANUP", "QUARANTINE", "TERMINAL_SOURCE_VERIFICATION", "CONFORMANCE_FIXTURE"]}, + "deficiency_reason_code": {"enum": ["COMPLETION_ESTABLISHED", "CANCEL_REQUESTED", "JOB_DEADLINE", "ATTEMPT_DEADLINE", "HEARTBEAT_TIMEOUT", "LEASE_CLAIM_EXPIRED", "LEASE_ACTIVE_EXPIRED", "LEASE_REVOKED", "RECOVERY_FENCE", "CLOCK_UNCERTAIN", "EXECUTOR_EPOCH_CHANGED", "SESSION_CHANNEL_LOST", "POLICY_VIOLATION", "ADMISSION_INVALID", "PREFLIGHT_REJECTED", "START_FAILED", "COMPUTATION_FAILED", "VALIDATION_FAILED", "RESULT_CONFLICT", "RESULT_REQUIREMENT_FAILED", "OUTPUT_VALIDATION_FAILED", "TERMINAL_SOURCE_RETENTION_FAILED", "TERMINATION_FAILED", "CLEANUP_FAILED", "LOST_OWNERSHIP", "ASSURANCE_UNMET", "ASSURANCE_UNVERIFIABLE", "BUDGET_EXHAUSTED", "RETRY_EXHAUSTED", "ATTEMPT_NONRETRYABLE", "ATTEMPT_REJECTED", "FATAL_INFRASTRUCTURE", "INTEGRITY_FAILURE", "ADMIN_DRAIN", "ADMIN_RETIRE", "DEFINITION_SUPERSEDED", "CAPABILITY_REVOKED", "VERIFICATION_FAILED", "CONTROL_CHANNEL_LOST", "WORKER_SHUTDOWN", "BACKEND_CLOSE_FAILED", "MALFORMED_MESSAGE", "UNKNOWN_SCHEMA", "INVALID_SIGIL", "WRONG_ENTITY", "WRONG_SESSION", "WRONG_EPOCH", "STALE_REVISION", "CONFLICTING_DUPLICATE", "SEQUENCE_GAP", "STATE_INELIGIBLE", "CREDENTIAL_INVALID", "LEASE_NOT_CURRENT", "FENCE_STALE", "DEADLINE_ALREADY_DUE", "MESSAGE_TOO_LARGE", "LIMIT_EXCEEDED", "RESULT_SCHEMA_INVALID", "OUTPUT_SCHEMA_INVALID", "EVIDENCE_MISSING", "EVIDENCE_INVALID", "PROFILE_MISMATCH", "CONFORMANCE_SUITE_MISMATCH", "CLAIM_INVALID", "ACCOUNTING_PARTIAL", "ACCOUNTING_UNAVAILABLE", "RESOURCE_AMBIGUOUS", "NO_ATTEMPT_ALLOCATED"]}, + "eventRef": {"type": "object", "additionalProperties": false, "required": ["journal_id", "event_id", "sequence", "event_sigil"], "properties": {"journal_id": {"type": "string", "pattern": "^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, "event_id": {"type": "string", "pattern": "^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, "sequence": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, "event_sigil": {"$ref": "#/$defs/sigil"}}}, + "transferRef": {"type": "object", "additionalProperties": false, "required": ["transfer_id", "transfer_attempt_id", "request_record_sigil", "attempt_record_sigil", "terminal_event"], "properties": {"transfer_id": {"type": "string", "pattern": "^ST-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, "transfer_attempt_id": {"type": "string", "pattern": "^SA-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, "request_record_sigil": {"$ref": "#/$defs/sigil"}, "attempt_record_sigil": {"$ref": "#/$defs/sigil"}, "terminal_event": {"$ref": "#/$defs/eventRef"}}}, + "stagingReference": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, {"type": "object", "additionalProperties": false, "required": ["kind", "storage_subject_id", "transfer", "provenance_id", "provenance_sigil"], "properties": {"kind": {"const": "TRANSFER"}, "storage_subject_id": {"$ref": "#/$defs/sigil"}, "transfer": {"$ref": "#/$defs/transferRef"}, "provenance_id": {"$ref": "#/$defs/opaque"}, "provenance_sigil": {"$ref": "#/$defs/sigil"}}}]}, + "phaseEvidenceEntry": {"type": "object", "additionalProperties": false, "required": ["evidence_kind", "producer_identity", "verifier_identity", "collected_at", "byte_size", "blob_sigil", "staging_reference"], "properties": {"evidence_kind": {"$ref": "#/$defs/evidenceKind"}, "producer_identity": {"$ref": "#/$defs/evidenceIdentity"}, "verifier_identity": {"$ref": "#/$defs/evidenceIdentity"}, "collected_at": {"$ref": "#/$defs/timestamp"}, "byte_size": {"anyOf": [{"$ref": "#/$defs/u63"}, {"type": "null"}]}, "blob_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "staging_reference": {"$ref": "#/$defs/stagingReference"}}}, + "phaseEvidence": {"type": "object", "additionalProperties": false, "required": ["preflight", "runtime", "termination", "cleanup"], "properties": {"preflight": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/phaseEvidenceEntry"}}, "runtime": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/phaseEvidenceEntry"}}, "termination": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/phaseEvidenceEntry"}}, "cleanup": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/phaseEvidenceEntry"}}}}, + "bindings": {"type": "object", "additionalProperties": false, "required": ["backend_sigil", "host_sigil", "runtime_sigil", "policy_set_sigil", "input_set_sigil", "output_set_sigil"], "properties": {"backend_sigil": {"$ref": "#/$defs/sigil"}, "host_sigil": {"$ref": "#/$defs/sigil"}, "runtime_sigil": {"$ref": "#/$defs/sigil"}, "policy_set_sigil": {"$ref": "#/$defs/sigil"}, "input_set_sigil": {"$ref": "#/$defs/sigil"}, "output_set_sigil": {"$ref": "#/$defs/sigil"}}}, + "deficiency": {"type": "object", "additionalProperties": false, "required": ["reason_code", "phase", "evidence_kind", "detail_sigil"], "properties": {"reason_code": {"$ref": "#/$defs/deficiency_reason_code"}, "phase": {"$ref": "#/$defs/phase"}, "evidence_kind": {"$ref": "#/$defs/evidenceKind"}, "detail_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/execution-control-evidence-set-1.0.json b/schemas/execution-control-evidence-set-1.0.json new file mode 100644 index 0000000..8adbfb6 --- /dev/null +++ b/schemas/execution-control-evidence-set-1.0.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-control-evidence-set/1.0", + "title": "Execution Control Evidence Set v1", + "description": "Closed RFC-0012 ten-dimension Control Evidence closure. This contract-only record binds exact evidence references to one Attempt; it does not resolve durable authority, execute evidence predicates, terminalize an Attempt, or establish assurance.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "control_evidence_set_id", + "job_id", + "attempt_id", + "attempt_binding_sigil", + "control_evidence_refs", + "control_evidence_set_sigil" + ], + "properties": { + "schema_version": {"const": "execution-control-evidence-set/1.0"}, + "control_evidence_set_id": {"$ref": "#/$defs/controlEvidenceSetId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/sigil"}, + "control_evidence_refs": { + "type": "array", + "minItems": 10, + "maxItems": 10, + "items": {"$ref": "#/$defs/controlEvidenceRef"} + }, + "control_evidence_set_sigil": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/sigil"} + }, + "$defs": { + "controlEvidenceSetId": { + "type": "string", + "pattern": "^CES-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "controlEvidenceRef": { + "type": "object", + "additionalProperties": false, + "required": ["control_dimension", "control_evidence_id", "control_evidence_sigil"], + "properties": { + "control_dimension": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/controlDimension"}, + "control_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/controlEvidenceId"}, + "control_evidence_sigil": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/sigil"} + } + }, + "controlEvidenceSetBinding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "PENDING"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "control_evidence_set_id", "control_evidence_set_sigil"], "properties": {"kind": {"const": "FROZEN"}, "control_evidence_set_id": {"$ref": "#/$defs/controlEvidenceSetId"}, "control_evidence_set_sigil": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/sigil"}}} + ] + } + } +} diff --git a/schemas/execution-evidence-issuer-authentication-1.0.json b/schemas/execution-evidence-issuer-authentication-1.0.json new file mode 100644 index 0000000..6a373ff --- /dev/null +++ b/schemas/execution-evidence-issuer-authentication-1.0.json @@ -0,0 +1,381 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0", + "title": "Execution Evidence Issuer Authentication v1", + "description": "Closed RFC-0012 O4 issuer-authentication record. Contract-only validation checks the immutable wire and local derivations; it does not read proof or evidence Blobs, verify a signature or attestation, resolve a registry snapshot, receipt, trusted role, profile, or authority, establish independence, append an Event, or grant evidence authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "authentication_id", + "subject", + "role_identity", + "authority_binding", + "raw_payload", + "decoder_binding", + "evidence_profile_binding", + "collection_context_sigil", + "collected_at", + "issuer_identity", + "key_binding", + "registry_snapshot_binding", + "proof", + "issued_at", + "expires_at", + "anti_replay_sigil", + "verified_at", + "authentication_record_sigil" + ], + "properties": { + "schema_version": {"const": "execution-evidence-issuer-authentication/1.0"}, + "authentication_id": {"$ref": "#/$defs/authenticationId"}, + "subject": {"$ref": "#/$defs/authenticationSubject"}, + "role_identity": {"$ref": "#/$defs/evidenceRoleIdentity"}, + "authority_binding": {"$ref": "#/$defs/authenticationAuthorityBinding"}, + "raw_payload": {"$ref": "#/$defs/rawPayloadBinding"}, + "decoder_binding": {"$ref": "#/$defs/decoderBinding"}, + "evidence_profile_binding": {"$ref": "#/$defs/evidenceProfileBinding"}, + "collection_context_sigil": {"$ref": "#/$defs/sigil"}, + "collected_at": {"$ref": "#/$defs/timestamp"}, + "issuer_identity": {"$ref": "#/$defs/issuerIdentity"}, + "key_binding": {"$ref": "#/$defs/keyBinding"}, + "registry_snapshot_binding": {"$ref": "#/$defs/registrySnapshotBinding"}, + "proof": {"$ref": "#/$defs/proof"}, + "issued_at": {"$ref": "#/$defs/timestamp"}, + "expires_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, + "anti_replay_sigil": {"$ref": "#/$defs/sigil"}, + "verified_at": {"$ref": "#/$defs/timestamp"}, + "authentication_record_sigil": {"$ref": "#/$defs/sigil"} + }, + "oneOf": [ + { + "properties": { + "subject": { + "allOf": [ + {"$ref": "#/$defs/authenticationSubject"}, + { + "properties": { + "subject_kind": {"const": "EXECUTION_OBSERVATION"}, + "raw_evidence_id": {"$ref": "#/$defs/observationRawEvidenceId"}, + "raw_evidence_kind": {"const": "PRODUCER"} + } + } + ] + }, + "role_identity": { + "allOf": [ + {"$ref": "#/$defs/evidenceRoleIdentity"}, + {"properties": {"role_kind": {"const": "WORKER_SESSION"}}} + ] + }, + "authority_binding": { + "allOf": [ + {"$ref": "#/$defs/authenticationAuthorityBinding"}, + {"properties": {"authority_kind": {"const": "RESULT_INGRESS_RECEIPT"}}} + ] + } + } + }, + { + "properties": { + "subject": { + "allOf": [ + {"$ref": "#/$defs/authenticationSubject"}, + { + "properties": { + "subject_kind": {"const": "EXECUTION_OBSERVATION"}, + "raw_evidence_id": {"$ref": "#/$defs/observationRawEvidenceId"}, + "raw_evidence_kind": {"const": "VERIFIER"} + } + } + ] + }, + "role_identity": { + "allOf": [ + {"$ref": "#/$defs/evidenceRoleIdentity"}, + { + "properties": { + "role_kind": { + "enum": [ + "EXECUTOR_SUPERVISOR", + "ENFORCEMENT_BACKEND", + "HOST_VERIFIER", + "INDEPENDENT_BACKEND_VERIFIER" + ] + } + } + } + ] + }, + "authority_binding": { + "allOf": [ + {"$ref": "#/$defs/authenticationAuthorityBinding"}, + {"properties": {"authority_kind": {"const": "TRUSTED_VERIFIER_IDENTITY"}}} + ] + } + } + }, + { + "properties": { + "subject": { + "allOf": [ + {"$ref": "#/$defs/authenticationSubject"}, + { + "properties": { + "subject_kind": {"const": "OUTPUT_WRITER_REVOCATION"}, + "raw_evidence_id": {"$ref": "#/$defs/outputWriterRawEvidenceId"}, + "raw_evidence_kind": {"const": "PRODUCER"} + } + } + ] + }, + "role_identity": { + "allOf": [ + {"$ref": "#/$defs/evidenceRoleIdentity"}, + {"properties": {"role_kind": {"enum": ["EXECUTOR_SUPERVISOR", "ENFORCEMENT_BACKEND"]}}} + ] + }, + "authority_binding": { + "allOf": [ + {"$ref": "#/$defs/authenticationAuthorityBinding"}, + {"properties": {"authority_kind": {"const": "OUTPUT_WRITER_REVOCATION_OWNER"}}} + ] + } + } + }, + { + "properties": { + "subject": { + "allOf": [ + {"$ref": "#/$defs/authenticationSubject"}, + { + "properties": { + "subject_kind": {"const": "OUTPUT_WRITER_REVOCATION"}, + "raw_evidence_id": {"$ref": "#/$defs/outputWriterRawEvidenceId"}, + "raw_evidence_kind": {"const": "VERIFIER"} + } + } + ] + }, + "role_identity": { + "allOf": [ + {"$ref": "#/$defs/evidenceRoleIdentity"}, + {"properties": {"role_kind": {"enum": ["HOST_VERIFIER", "INDEPENDENT_BACKEND_VERIFIER"]}}} + ] + }, + "authority_binding": { + "allOf": [ + {"$ref": "#/$defs/authenticationAuthorityBinding"}, + {"properties": {"authority_kind": {"const": "OUTPUT_WRITER_REVOCATION_OWNER"}}} + ] + } + } + } + ], + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/sigil"}, + "u63": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/u63"}, + "positiveU63": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/positiveU63"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "protocolIdentifier": { + "type": "string", + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:+-]{0,127}$", + "minLength": 1, + "maxLength": 128 + }, + "evidenceMediaType": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9!#$&^_.+-]{0,63}/[a-z0-9][a-z0-9!#$&^_.+-]{0,63}$", + "minLength": 3, + "maxLength": 129 + }, + "authenticationId": { + "type": "string", + "pattern": "^EIA-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "observationRawEvidenceId": { + "type": "string", + "pattern": "^ORE-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "outputWriterRawEvidenceId": { + "type": "string", + "pattern": "^OWE-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "roleKind": { + "enum": [ + "WORKER_SESSION", + "EXECUTOR_SUPERVISOR", + "ENFORCEMENT_BACKEND", + "HOST_VERIFIER", + "INDEPENDENT_BACKEND_VERIFIER" + ] + }, + "authorityKind": { + "enum": [ + "RESULT_INGRESS_RECEIPT", + "TRUSTED_VERIFIER_IDENTITY", + "OUTPUT_WRITER_REVOCATION_OWNER" + ] + }, + "evidenceRoleIdentity": { + "type": "object", + "additionalProperties": false, + "required": ["role_kind", "identity_id", "implementation_version", "implementation_sigil"], + "properties": { + "role_kind": {"$ref": "#/$defs/roleKind"}, + "identity_id": {"$ref": "#/$defs/protocolIdentifier"}, + "implementation_version": {"$ref": "#/$defs/protocolIdentifier"}, + "implementation_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "rawPayloadBinding": { + "type": "object", + "additionalProperties": false, + "required": ["media_type", "size_bytes", "blob_sigil"], + "properties": { + "media_type": {"$ref": "#/$defs/evidenceMediaType"}, + "size_bytes": {"$ref": "#/$defs/u63"}, + "blob_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "decoderBinding": { + "type": "object", + "additionalProperties": false, + "required": ["decoder_id", "decoder_version", "implementation_sigil"], + "properties": { + "decoder_id": {"$ref": "#/$defs/protocolIdentifier"}, + "decoder_version": {"$ref": "#/$defs/protocolIdentifier"}, + "implementation_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "evidenceProfileBinding": { + "type": "object", + "additionalProperties": false, + "required": ["evidence_profile_id", "evidence_profile_version", "evidence_profile_sigil"], + "properties": { + "evidence_profile_id": {"$ref": "#/$defs/protocolIdentifier"}, + "evidence_profile_version": {"$ref": "#/$defs/protocolIdentifier"}, + "evidence_profile_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "authenticationAuthorityBinding": { + "type": "object", + "additionalProperties": false, + "required": ["authority_kind", "authority_id", "authority_sigil"], + "properties": { + "authority_kind": {"$ref": "#/$defs/authorityKind"}, + "authority_id": {"$ref": "#/$defs/protocolIdentifier"}, + "authority_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "issuerAuthenticationBinding": { + "type": "object", + "additionalProperties": false, + "required": ["authentication_id", "authentication_record_sigil"], + "properties": { + "authentication_id": {"$ref": "#/$defs/authenticationId"}, + "authentication_record_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "authenticationSubject": { + "type": "object", + "additionalProperties": false, + "required": [ + "subject_kind", + "raw_evidence_id", + "raw_evidence_kind", + "owner_binding_sigil", + "decoded_observation_sigil" + ], + "properties": { + "subject_kind": {"enum": ["EXECUTION_OBSERVATION", "OUTPUT_WRITER_REVOCATION"]}, + "raw_evidence_id": { + "oneOf": [ + {"$ref": "#/$defs/observationRawEvidenceId"}, + {"$ref": "#/$defs/outputWriterRawEvidenceId"} + ] + }, + "raw_evidence_kind": {"enum": ["PRODUCER", "VERIFIER"]}, + "owner_binding_sigil": {"$ref": "#/$defs/sigil"}, + "decoded_observation_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "issuerIdentity": { + "type": "object", + "additionalProperties": false, + "required": ["issuer_id", "issuer_kind", "issuer_implementation_sigil"], + "properties": { + "issuer_id": {"$ref": "#/$defs/protocolIdentifier"}, + "issuer_kind": { + "enum": ["EXECUTOR", "ENFORCEMENT_BACKEND", "HOST_ATTESTER", "INDEPENDENT_VERIFIER"] + }, + "issuer_implementation_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "keyBinding": { + "type": "object", + "additionalProperties": false, + "required": ["registry_id", "registry_version", "key_id", "key_generation", "verification_profile_sigil"], + "properties": { + "registry_id": {"$ref": "#/$defs/protocolIdentifier"}, + "registry_version": {"$ref": "#/$defs/protocolIdentifier"}, + "key_id": {"$ref": "#/$defs/protocolIdentifier"}, + "key_generation": {"$ref": "#/$defs/positiveU63"}, + "verification_profile_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "registrySnapshotBinding": { + "type": "object", + "additionalProperties": false, + "required": ["registry_id", "registry_version", "registry_snapshot_sigil"], + "properties": { + "registry_id": {"$ref": "#/$defs/protocolIdentifier"}, + "registry_version": {"$ref": "#/$defs/protocolIdentifier"}, + "registry_snapshot_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "signatureProof": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "algorithm", "signature_payload"], + "properties": { + "kind": {"const": "SIGNATURE"}, + "algorithm": {"const": "ED25519"}, + "signature_payload": { + "allOf": [ + {"$ref": "#/$defs/rawPayloadBinding"}, + { + "properties": { + "media_type": {"const": "application/vnd.benchwork.ed25519-signature"}, + "size_bytes": {"const": 64} + } + } + ] + } + } + }, + "attestationProof": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "attestation_profile_id", "attestation_payload"], + "properties": { + "kind": {"const": "ATTESTATION"}, + "attestation_profile_id": {"$ref": "#/$defs/protocolIdentifier"}, + "attestation_payload": {"$ref": "#/$defs/rawPayloadBinding"} + } + }, + "proof": { + "oneOf": [ + {"$ref": "#/$defs/signatureProof"}, + {"$ref": "#/$defs/attestationProof"} + ] + } + } +} + diff --git a/schemas/execution-get-result-request-1.0.json b/schemas/execution-get-result-request-1.0.json new file mode 100644 index 0000000..9240348 --- /dev/null +++ b/schemas/execution-get-result-request-1.0.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-get-result-request/1.0", + "title": "Execution Get Result Request", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "job_id"], + "properties": { + "schema_version": {"const": "execution-get-result-request/1.0"}, + "job_id": { + "type": "string", + "pattern": "^JB-[A-F0-9]{64}$", + "minLength": 67, + "maxLength": 67 + } + } +} diff --git a/schemas/execution-heartbeat-authenticated-ingress-1.0.json b/schemas/execution-heartbeat-authenticated-ingress-1.0.json new file mode 100644 index 0000000..c6194f2 --- /dev/null +++ b/schemas/execution-heartbeat-authenticated-ingress-1.0.json @@ -0,0 +1,70 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-heartbeat-authenticated-ingress/1.0", + "title": "Execution Heartbeat Authenticated Ingress v1", + "description": "Closed RFC-0012 H8 immutable first-authenticated-ingress record. Structural validity and local byte checks do not prove a protected handshake, current channel or Session authority, package durability, committed visibility, Heartbeat admission, or Journal/State effects.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "authenticated_ingress_record_id", + "owner_kind", + "owner_id", + "message_kind", + "authenticated_envelope", + "envelope_canonical_size_bytes", + "envelope_canonical_bytes_sigil", + "received_frame_size_bytes", + "received_frame_bytes_sigil", + "created_at", + "authenticated_ingress_record_sigil" + ], + "properties": { + "schema_version": {"const": "execution-heartbeat-authenticated-ingress/1.0"}, + "authenticated_ingress_record_id": {"$ref": "#/$defs/authenticatedIngressRecordId"}, + "owner_kind": {"enum": ["WORKER_SESSION", "LEASE"]}, + "owner_id": {"type": "string"}, + "message_kind": {"enum": ["WORKER_SESSION_HEARTBEAT", "LEASE_HEARTBEAT"]}, + "authenticated_envelope": {"$ref": "https://benchwork.dev/schemas/execution-authenticated-heartbeat-envelope/1.0"}, + "envelope_canonical_size_bytes": {"$ref": "#/$defs/u63"}, + "envelope_canonical_bytes_sigil": {"$ref": "#/$defs/sigil"}, + "received_frame_size_bytes": {"$ref": "#/$defs/u63"}, + "received_frame_bytes_sigil": {"$ref": "#/$defs/sigil"}, + "created_at": {"$ref": "#/$defs/timestamp"}, + "authenticated_ingress_record_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"owner_kind": {"const": "WORKER_SESSION"}}, "required": ["owner_kind"]}, + "then": { + "properties": { + "owner_id": {"$ref": "#/$defs/workerSessionId"}, + "message_kind": {"const": "WORKER_SESSION_HEARTBEAT"} + } + } + }, + { + "if": {"properties": {"owner_kind": {"const": "LEASE"}}, "required": ["owner_kind"]}, + "then": { + "properties": { + "owner_id": {"$ref": "#/$defs/leaseId"}, + "message_kind": {"const": "LEASE_HEARTBEAT"} + } + } + } + ], + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "workerSessionId": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "leaseId": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "authenticatedIngressRecordId": { + "type": "string", + "pattern": "^HAI-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + } + } +} + diff --git a/schemas/execution-heartbeat-canonical-message-1.0.json b/schemas/execution-heartbeat-canonical-message-1.0.json new file mode 100644 index 0000000..532960f --- /dev/null +++ b/schemas/execution-heartbeat-canonical-message-1.0.json @@ -0,0 +1,66 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-heartbeat-canonical-message/1.0", + "title": "Execution Heartbeat Canonical Message v1", + "description": "Closed RFC-0012 H8 immutable canonical Heartbeat-message record. This contract-only record binds routed identity and canonical-byte facts; it does not validate the referenced Heartbeat, prove protected transport, install a committed-visible package, append a Journal Event, update State, or grant authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "canonical_message_record_id", + "owner_kind", + "owner_id", + "message_kind", + "message_sigil", + "message_canonical_size_bytes", + "message_canonical_bytes_sigil", + "created_at", + "canonical_message_record_sigil" + ], + "properties": { + "schema_version": {"const": "execution-heartbeat-canonical-message/1.0"}, + "canonical_message_record_id": {"$ref": "#/$defs/canonicalMessageRecordId"}, + "owner_kind": {"enum": ["WORKER_SESSION", "LEASE"]}, + "owner_id": {"type": "string"}, + "message_kind": {"enum": ["WORKER_SESSION_HEARTBEAT", "LEASE_HEARTBEAT"]}, + "message_sigil": {"$ref": "#/$defs/sigil"}, + "message_canonical_size_bytes": {"$ref": "#/$defs/u63"}, + "message_canonical_bytes_sigil": {"$ref": "#/$defs/sigil"}, + "created_at": {"$ref": "#/$defs/timestamp"}, + "canonical_message_record_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"owner_kind": {"const": "WORKER_SESSION"}}, "required": ["owner_kind"]}, + "then": { + "properties": { + "owner_id": {"$ref": "#/$defs/workerSessionId"}, + "message_kind": {"const": "WORKER_SESSION_HEARTBEAT"} + } + } + }, + { + "if": {"properties": {"owner_kind": {"const": "LEASE"}}, "required": ["owner_kind"]}, + "then": { + "properties": { + "owner_id": {"$ref": "#/$defs/leaseId"}, + "message_kind": {"const": "LEASE_HEARTBEAT"} + } + } + } + ], + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "workerSessionId": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "leaseId": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "canonicalMessageRecordId": { + "type": "string", + "pattern": "^HCM-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + } + } +} + diff --git a/schemas/execution-heartbeat-disposition-index-row-1.0.json b/schemas/execution-heartbeat-disposition-index-row-1.0.json new file mode 100644 index 0000000..0570c63 --- /dev/null +++ b/schemas/execution-heartbeat-disposition-index-row-1.0.json @@ -0,0 +1,128 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-heartbeat-disposition-index-row/1.0", + "title": "Execution Heartbeat Disposition Index Row v1", + "description": "Closed RFC-0012 H8 durable Heartbeat disposition lookup row. Structural validity and supplied immutable-record equality do not prove committed package visibility, a canonical Journal Event, replayed State, protected transport, historical disposition authority, or live Heartbeat admission.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "disposition_row_id", + "owner_kind", + "owner_id", + "message_kind", + "disposition_message_sigil", + "identity_binding", + "outcome", + "disposition_event_id", + "disposition_event_sigil", + "disposition_row_sigil" + ], + "properties": { + "schema_version": {"const": "execution-heartbeat-disposition-index-row/1.0"}, + "disposition_row_id": {"$ref": "#/$defs/dispositionRowId"}, + "owner_kind": {"enum": ["WORKER_SESSION", "LEASE"]}, + "owner_id": {"type": "string"}, + "message_kind": {"enum": ["WORKER_SESSION_HEARTBEAT", "LEASE_HEARTBEAT"]}, + "disposition_message_sigil": {"$ref": "#/$defs/sigil"}, + "identity_binding": {"$ref": "#/$defs/identityBinding"}, + "outcome": {"enum": ["ACCEPTED", "REJECTED"]}, + "disposition_event_id": {"$ref": "#/$defs/eventId"}, + "disposition_event_sigil": {"$ref": "#/$defs/sigil"}, + "disposition_row_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"owner_kind": {"const": "WORKER_SESSION"}}, "required": ["owner_kind"]}, + "then": { + "properties": { + "owner_id": {"$ref": "#/$defs/workerSessionId"}, + "message_kind": {"const": "WORKER_SESSION_HEARTBEAT"} + } + } + }, + { + "if": {"properties": {"owner_kind": {"const": "LEASE"}}, "required": ["owner_kind"]}, + "then": { + "properties": { + "owner_id": {"$ref": "#/$defs/leaseId"}, + "message_kind": {"const": "LEASE_HEARTBEAT"} + } + } + } + ], + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "workerSessionId": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "leaseId": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "eventId": {"$ref": "https://benchwork.dev/schemas/execution-journal-head/1.0#/$defs/eventId"}, + "canonicalMessageRecordId": {"$ref": "https://benchwork.dev/schemas/execution-heartbeat-canonical-message/1.0#/$defs/canonicalMessageRecordId"}, + "rawFrameRecordId": {"$ref": "https://benchwork.dev/schemas/execution-heartbeat-raw-frame/1.0#/$defs/rawFrameRecordId"}, + "installManifestId": {"$ref": "https://benchwork.dev/schemas/execution-heartbeat-message-store-install-manifest/1.0#/$defs/installManifestId"}, + "dispositionRowId": { + "type": "string", + "pattern": "^HDP-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "canonicalMessageBinding": { + "type": "object", + "additionalProperties": false, + "required": [ + "canonical_message_record_id", + "canonical_message_record_sigil", + "message_canonical_bytes_sigil", + "install_manifest_id", + "install_manifest_sigil" + ], + "properties": { + "canonical_message_record_id": {"$ref": "#/$defs/canonicalMessageRecordId"}, + "canonical_message_record_sigil": {"$ref": "#/$defs/sigil"}, + "message_canonical_bytes_sigil": {"$ref": "#/$defs/sigil"}, + "install_manifest_id": {"$ref": "#/$defs/installManifestId"}, + "install_manifest_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "rawFrameBinding": { + "type": "object", + "additionalProperties": false, + "required": [ + "raw_frame_record_id", + "raw_frame_record_sigil", + "received_bytes_sigil", + "install_manifest_id", + "install_manifest_sigil" + ], + "properties": { + "raw_frame_record_id": {"$ref": "#/$defs/rawFrameRecordId"}, + "raw_frame_record_sigil": {"$ref": "#/$defs/sigil"}, + "received_bytes_sigil": {"$ref": "#/$defs/sigil"}, + "install_manifest_id": {"$ref": "#/$defs/installManifestId"}, + "install_manifest_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "identityBinding": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "canonical_message_binding"], + "properties": { + "kind": {"const": "CANONICAL_MESSAGE"}, + "canonical_message_binding": {"$ref": "#/$defs/canonicalMessageBinding"} + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "raw_frame_binding"], + "properties": { + "kind": {"const": "RAW_FRAME"}, + "raw_frame_binding": {"$ref": "#/$defs/rawFrameBinding"} + } + } + ] + } + } +} + diff --git a/schemas/execution-heartbeat-forensic-package-reservation-index-row-1.0.json b/schemas/execution-heartbeat-forensic-package-reservation-index-row-1.0.json new file mode 100644 index 0000000..0fd038c --- /dev/null +++ b/schemas/execution-heartbeat-forensic-package-reservation-index-row-1.0.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-heartbeat-forensic-package-reservation-index-row/1.0", + "title": "Execution Heartbeat Forensic Package Reservation Index Row v1", + "description": "Closed RFC-0012 H8 deterministic source-to-forensic-package reservation row. Structural validity and supplied marker/source equality do not prove a committed collision gate, candidate-inventory authority, reservation package durability, filesystem visibility, forensic package installation, Journal replay, State closure, or execution authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "forensic_reservation_id", + "collision_gate_marker_id", + "collision_gate_marker_sigil", + "source_candidate_id", + "source_candidate_inventory_entry_sigil", + "forensic_package_id", + "reservation_state", + "reserved_at", + "forensic_reservation_sigil" + ], + "properties": { + "schema_version": {"const": "execution-heartbeat-forensic-package-reservation-index-row/1.0"}, + "forensic_reservation_id": {"$ref": "#/$defs/forensicReservationId"}, + "collision_gate_marker_id": {"$ref": "#/$defs/collisionGateMarkerId"}, + "collision_gate_marker_sigil": {"$ref": "#/$defs/sigil"}, + "source_candidate_id": {"$ref": "#/$defs/sourceCandidateId"}, + "source_candidate_inventory_entry_sigil": {"$ref": "#/$defs/sigil"}, + "forensic_package_id": {"$ref": "#/$defs/forensicPackageId"}, + "reservation_state": {"const": "RESERVED"}, + "reserved_at": {"$ref": "#/$defs/timestamp"}, + "forensic_reservation_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "forensicReservationId": { + "type": "string", + "pattern": "^HPR-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "collisionGateMarkerId": { + "type": "string", + "pattern": "^HCG-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "sourceCandidateId": { + "type": "string", + "pattern": "^HOC-[0-7][0-9A-HJKMNP-TV-Z]{25}$", + "minLength": 30, + "maxLength": 30 + }, + "forensicPackageId": { + "type": "string", + "pattern": "^HFP-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + } + } +} + diff --git a/schemas/execution-heartbeat-message-store-install-manifest-1.0.json b/schemas/execution-heartbeat-message-store-install-manifest-1.0.json new file mode 100644 index 0000000..618ab05 --- /dev/null +++ b/schemas/execution-heartbeat-message-store-install-manifest-1.0.json @@ -0,0 +1,86 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-heartbeat-message-store-install-manifest/1.0", + "title": "Execution Heartbeat Message Store Install Manifest v1", + "description": "Closed RFC-0012 immutable Heartbeat message-store package manifest. This contract-only record binds one record identity to exact stored-byte facts; it does not select a path, write or fsync files, rename a candidate, acquire a lock, prove durable or committed visibility, validate a record branch, append an Event, or establish authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "install_manifest_id", + "record_kind", + "record_id", + "record_sigil", + "stored_size_bytes", + "stored_bytes_sigil", + "storage_profile", + "install_manifest_sigil" + ], + "properties": { + "schema_version": {"const": "execution-heartbeat-message-store-install-manifest/1.0"}, + "install_manifest_id": {"$ref": "#/$defs/installManifestId"}, + "record_kind": {"$ref": "#/$defs/recordKind"}, + "record_id": {"type": "string"}, + "record_sigil": {"$ref": "#/$defs/sigil"}, + "stored_size_bytes": {"$ref": "#/$defs/u63"}, + "stored_bytes_sigil": {"$ref": "#/$defs/sigil"}, + "storage_profile": {"const": "DESCRIPTOR_RELATIVE_ATOMIC_DIRECTORY_V1"}, + "install_manifest_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"record_kind": {"const": "CANONICAL_MESSAGE"}}, "required": ["record_kind"]}, + "then": {"properties": {"record_id": {"$ref": "#/$defs/canonicalMessageRecordId"}}} + }, + { + "if": {"properties": {"record_kind": {"const": "AUTHENTICATED_INGRESS"}}, "required": ["record_kind"]}, + "then": {"properties": {"record_id": {"$ref": "#/$defs/authenticatedIngressRecordId"}}} + }, + { + "if": {"properties": {"record_kind": {"const": "RAW_FRAME"}}, "required": ["record_kind"]}, + "then": {"properties": {"record_id": {"$ref": "#/$defs/rawFrameRecordId"}}} + }, + { + "if": {"properties": {"record_kind": {"const": "COLLISION_EVIDENCE"}}, "required": ["record_kind"]}, + "then": {"properties": {"record_id": {"$ref": "#/$defs/collisionEvidenceId"}}} + } + ], + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "recordKind": { + "enum": ["CANONICAL_MESSAGE", "AUTHENTICATED_INGRESS", "RAW_FRAME", "COLLISION_EVIDENCE"] + }, + "installManifestId": { + "type": "string", + "pattern": "^HMI-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "canonicalMessageRecordId": { + "type": "string", + "pattern": "^HCM-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "authenticatedIngressRecordId": { + "type": "string", + "pattern": "^HAI-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "rawFrameRecordId": { + "type": "string", + "pattern": "^HFR-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "collisionEvidenceId": { + "type": "string", + "pattern": "^HCE-[0-7][0-9A-HJKMNP-TV-Z]{25}$", + "minLength": 30, + "maxLength": 30 + } + } +} + diff --git a/schemas/execution-heartbeat-raw-frame-1.0.json b/schemas/execution-heartbeat-raw-frame-1.0.json new file mode 100644 index 0000000..239d5d9 --- /dev/null +++ b/schemas/execution-heartbeat-raw-frame-1.0.json @@ -0,0 +1,96 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-heartbeat-raw-frame/1.0", + "title": "Execution Heartbeat Raw Frame v1", + "description": "Closed RFC-0012 H8 immutable raw-frame record. Structural validity and pure resolution do not prove protected-channel authority, committed package visibility, collision-gate disposition, Heartbeat admission, or Journal/State effects.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "raw_frame_record_id", + "owner_kind", + "owner_id", + "message_kind", + "received_bytes_sigil", + "received_size_bytes", + "first_received_at", + "first_authenticated_ingress_binding", + "raw_frame_record_sigil" + ], + "properties": { + "schema_version": {"const": "execution-heartbeat-raw-frame/1.0"}, + "raw_frame_record_id": {"$ref": "#/$defs/rawFrameRecordId"}, + "owner_kind": {"enum": ["WORKER_SESSION", "LEASE"]}, + "owner_id": {"type": "string"}, + "message_kind": {"enum": ["WORKER_SESSION_HEARTBEAT", "LEASE_HEARTBEAT"]}, + "received_bytes_sigil": {"$ref": "#/$defs/sigil"}, + "received_size_bytes": {"$ref": "#/$defs/u63"}, + "first_received_at": {"$ref": "#/$defs/timestamp"}, + "first_authenticated_ingress_binding": {"$ref": "#/$defs/firstAuthenticatedIngressBinding"}, + "raw_frame_record_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"owner_kind": {"const": "WORKER_SESSION"}}, "required": ["owner_kind"]}, + "then": { + "properties": { + "owner_id": {"$ref": "#/$defs/workerSessionId"}, + "message_kind": {"const": "WORKER_SESSION_HEARTBEAT"} + } + } + }, + { + "if": {"properties": {"owner_kind": {"const": "LEASE"}}, "required": ["owner_kind"]}, + "then": { + "properties": { + "owner_id": {"$ref": "#/$defs/leaseId"}, + "message_kind": {"const": "LEASE_HEARTBEAT"} + } + } + } + ], + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "workerSessionId": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "leaseId": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "rawFrameRecordId": { + "type": "string", + "pattern": "^HFR-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "authenticatedIngressRecordId": { + "type": "string", + "pattern": "^HAI-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "installManifestId": { + "type": "string", + "pattern": "^HMI-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "firstAuthenticatedIngressBinding": { + "type": "object", + "additionalProperties": false, + "required": [ + "authenticated_ingress_record_id", + "authenticated_ingress_record_sigil", + "envelope_canonical_bytes_sigil", + "install_manifest_id", + "install_manifest_sigil" + ], + "properties": { + "authenticated_ingress_record_id": {"$ref": "#/$defs/authenticatedIngressRecordId"}, + "authenticated_ingress_record_sigil": {"$ref": "#/$defs/sigil"}, + "envelope_canonical_bytes_sigil": {"$ref": "#/$defs/sigil"}, + "install_manifest_id": {"$ref": "#/$defs/installManifestId"}, + "install_manifest_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/execution-job-1.0.json b/schemas/execution-job-1.0.json new file mode 100644 index 0000000..7d13842 --- /dev/null +++ b/schemas/execution-job-1.0.json @@ -0,0 +1,86 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-job/1.0", + "title": "Execution Job v1", + "description": "Closed RFC-0012 execution-job/1.0 contract-only record. This increment validates only self-contained Job structure and bindings. job_storage_roots is deliberately limited to an empty array until execution-journal-event/1.0 publishes the canonical storage_root_binding definition; external Task, Specification, Chronicle, Ward, assurance, and Storage resolution are outside this contract.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "job_id", "submitted_at", "submission_idempotency_key_sigil", "start_request_sigil", "task_id", "task_capsule_sigil", "specification_id", "specification_sigil", "admission_chronicle_head", "admission_chronicle_head_evidence", "assurance_requirement", "deadline_due_at", "job_budget", "job_storage_roots", "job_binding_sigil"], + "properties": { + "schema_version": {"const": "execution-job/1.0"}, + "job_id": {"$ref": "#/$defs/jobId"}, + "submitted_at": {"$ref": "#/$defs/timestamp"}, + "submission_idempotency_key_sigil": {"$ref": "#/$defs/sigil"}, + "start_request_sigil": {"$ref": "#/$defs/sigil"}, + "task_id": {"$ref": "#/$defs/taskId"}, + "task_capsule_sigil": {"$ref": "#/$defs/sigil"}, + "specification_id": {"$ref": "#/$defs/specificationId"}, + "specification_sigil": {"$ref": "#/$defs/sigil"}, + "admission_chronicle_head": {"$ref": "#/$defs/chronicleHeadRef"}, + "admission_chronicle_head_evidence": {"$ref": "#/$defs/admissionChronicleHeadEvidence"}, + "assurance_requirement": {"$ref": "#/$defs/assuranceRequirement"}, + "deadline_due_at": {"$ref": "#/$defs/timestamp"}, + "job_budget": {"$ref": "#/$defs/jobBudget"}, + "job_storage_roots": {"type": "array", "maxItems": 0}, + "job_binding_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "jobId": {"type": "string", "pattern": "^JB-[0-9A-F]{64}$", "minLength": 67, "maxLength": 67}, + "taskId": {"type": "string", "pattern": "^TK-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "specificationId": {"type": "string", "pattern": "^ES-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "suiteId": {"type": "string", "pattern": "^CS-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "version": {"type": "string", "pattern": "^[0-9]+[.][0-9]+(?:[.][0-9]+)?$", "not": {"pattern": "[\\r\\n]"}, "minLength": 3, "maxLength": 32}, + "chronicleHeadRef": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "event_count", "terminal_receipt_sigil"], + "properties": { + "schema_version": {"const": "chronicle-head/1.1"}, + "event_count": {"$ref": "#/$defs/u63"}, + "terminal_receipt_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]} + } + }, + "admissionChronicleHeadEvidence": { + "type": "object", "additionalProperties": false, + "required": ["profile", "job_id", "start_request_sigil", "observed_chronicle_head", "observed_at", "validator_build_sigil", "evidence_sigil"], + "properties": { + "profile": {"const": "PHASE3_CHRONICLE_HEAD_ADMISSION_V1"}, + "job_id": {"$ref": "#/$defs/jobId"}, + "start_request_sigil": {"$ref": "#/$defs/sigil"}, + "observed_chronicle_head": {"$ref": "#/$defs/chronicleHeadRef"}, + "observed_at": {"$ref": "#/$defs/timestamp"}, + "validator_build_sigil": {"$ref": "#/$defs/sigil"}, + "evidence_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "assuranceRequirement": { + "type": "object", "additionalProperties": false, + "required": ["requested_level", "profile_version", "profile_sigil", "conformance_suite_id", "conformance_suite_sigil"], + "properties": { + "requested_level": {"enum": ["SANCTUM-A0", "SANCTUM-A1", "SANCTUM-A2"]}, + "profile_version": {"$ref": "#/$defs/version"}, + "profile_sigil": {"$ref": "#/$defs/sigil"}, + "conformance_suite_id": {"$ref": "#/$defs/suiteId"}, + "conformance_suite_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "jobBudget": { + "type": "object", "additionalProperties": false, + "required": ["attempts", "cpu_time_seconds", "storage_bytes_written", "output_bytes", "log_bytes", "process_starts", "network_egress_bytes", "network_requests"], + "properties": { + "attempts": {"$ref": "#/$defs/positiveU63"}, + "cpu_time_seconds": {"$ref": "#/$defs/u63"}, + "storage_bytes_written": {"$ref": "#/$defs/u63"}, + "output_bytes": {"$ref": "#/$defs/u63"}, + "log_bytes": {"$ref": "#/$defs/u63"}, + "process_starts": {"$ref": "#/$defs/u63"}, + "network_egress_bytes": {"$ref": "#/$defs/u63"}, + "network_requests": {"$ref": "#/$defs/u63"} + } + } + } +} + diff --git a/schemas/execution-job-outcome-1.0.json b/schemas/execution-job-outcome-1.0.json new file mode 100644 index 0000000..503e54c --- /dev/null +++ b/schemas/execution-job-outcome-1.0.json @@ -0,0 +1,616 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-job-outcome/1.0", + "title": "Execution Job Outcome v1", + "description": "Closed RFC-0015 contract-only terminal Job Outcome wire. Structural validation does not derive a terminal prefix, resolve Result or Storage authority, evaluate acceptance eligibility, or confer execution or scientific authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "outcome_id", + "job_id", + "job_binding_sigil", + "job_terminal", + "task_binding", + "program_id", + "capability_binding", + "snapshot_binding", + "circle_binding", + "approval_binding", + "execution_specification_binding", + "attempt_summaries", + "selected_attempt_binding", + "result_binding", + "completion_anchor_binding", + "first_stop_or_fence_binding", + "lease_terminal_binding", + "authority_binding", + "final_fence_binding", + "runtime_outcome", + "terminal_source_binding", + "terminal_source_observation", + "assurance_context_binding", + "attempt_assurance_binding", + "job_assurance_binding", + "control_evidence_set_binding", + "quarantine_binding_set_binding", + "terminalization_storage_manifest_binding", + "output_root_protection", + "budget_binding", + "outputs", + "storage_observation_binding", + "logs", + "resource_evidence", + "acceptance_eligible", + "ineligibility_reasons", + "derivation_profile", + "terminal_recorded_at", + "outcome_sigil" + ], + "properties": { + "schema_version": {"const": "execution-job-outcome/1.0"}, + "outcome_id": {"$ref": "#/$defs/outcomeId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "job_binding_sigil": {"$ref": "#/$defs/sigil"}, + "job_terminal": {"$ref": "#/$defs/jobTerminal"}, + "task_binding": {"$ref": "#/$defs/taskBinding"}, + "program_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/programId"}, + "capability_binding": {"$ref": "#/$defs/capabilityBinding"}, + "snapshot_binding": {"$ref": "#/$defs/snapshotBinding"}, + "circle_binding": {"$ref": "#/$defs/circleBinding"}, + "approval_binding": {"$ref": "#/$defs/approvalBinding"}, + "execution_specification_binding": {"$ref": "#/$defs/specificationBinding"}, + "attempt_summaries": { + "type": "array", + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/attempt_summary"} + }, + "selected_attempt_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/selected_attempt_binding"}, + "result_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/result_binding"}, + "completion_anchor_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/completion_anchor_binding"}, + "first_stop_or_fence_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/first_stop_or_fence_binding"}, + "lease_terminal_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/lease_terminal_binding"}, + "authority_binding": {"$ref": "#/$defs/authority_binding"}, + "final_fence_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/final_fence_binding"}, + "runtime_outcome": {"$ref": "#/$defs/runtimeOutcome"}, + "terminal_source_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/terminal_source_binding"}, + "terminal_source_observation": {"$ref": "#/$defs/terminalSourceObservation"}, + "assurance_context_binding": {"$ref": "#/$defs/assurance_context_binding"}, + "attempt_assurance_binding": {"$ref": "#/$defs/terminalAttemptAssuranceBinding"}, + "job_assurance_binding": {"$ref": "#/$defs/terminalJobAssuranceBinding"}, + "control_evidence_set_binding": {"$ref": "#/$defs/terminalControlEvidenceSetBinding"}, + "quarantine_binding_set_binding": {"$ref": "#/$defs/terminalQuarantineBindingSetBinding"}, + "terminalization_storage_manifest_binding": {"$ref": "#/$defs/outcomeStorageManifestBinding"}, + "output_root_protection": {"$ref": "#/$defs/outcomeRootProtection"}, + "budget_binding": {"$ref": "#/$defs/budgetBinding"}, + "outputs": { + "type": "array", + "maxItems": 4096, + "uniqueItems": true, + "items": { + "oneOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0#/$defs/attempt_outputs_none_member"}, + {"$ref": "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0#/$defs/attempt_output_member"} + ] + }, + "allOf": [ + { + "if": {"contains": {"properties": {"kind": {"const": "ATTEMPT_OUTPUTS_NONE"}}, "required": ["kind"]}}, + "then": {"maxItems": 1} + } + ] + }, + "storage_observation_binding": {"$ref": "#/$defs/outcomeStorageObservationBinding"}, + "logs": { + "type": "array", + "maxItems": 3, + "uniqueItems": true, + "items": {"$ref": "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0#/$defs/log_stream_member"} + }, + "resource_evidence": { + "type": "array", + "maxItems": 4096, + "uniqueItems": true, + "items": { + "oneOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0#/$defs/resource_evidence_none_member"}, + {"$ref": "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0#/$defs/resource_evidence_member"} + ] + }, + "allOf": [ + { + "if": {"contains": {"properties": {"kind": {"const": "RESOURCE_EVIDENCE_NONE"}}, "required": ["kind"]}}, + "then": {"maxItems": 1} + } + ] + }, + "acceptance_eligible": {"type": "boolean"}, + "ineligibility_reasons": { + "type": "array", + "maxItems": 27, + "uniqueItems": true, + "items": {"$ref": "#/$defs/ineligibilityReason"} + }, + "derivation_profile": {"$ref": "#/$defs/derivationProfile"}, + "terminal_recorded_at": {"$ref": "#/$defs/timestamp"}, + "outcome_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + { + "if": { + "properties": {"selected_attempt_binding": {"properties": {"kind": {"const": "NONE"}}, "required": ["kind"]}}, + "required": ["selected_attempt_binding"] + }, + "then": { + "properties": { + "attempt_summaries": {"maxItems": 0}, + "result_binding": {"properties": {"kind": {"const": "NONE"}}, "required": ["kind"]}, + "completion_anchor_binding": {"properties": {"kind": {"const": "NOT_ESTABLISHED"}}, "required": ["kind"]}, + "lease_terminal_binding": {"properties": {"kind": {"const": "NONE"}}, "required": ["kind"]}, + "authority_binding": {"properties": {"kind": {"const": "NO_ATTEMPT"}}, "required": ["kind"]}, + "final_fence_binding": {"properties": {"kind": {"const": "NO_ATTEMPT"}}, "required": ["kind"]}, + "runtime_outcome": {"properties": {"kind": {"const": "NO_ATTEMPT"}}, "required": ["kind"]}, + "terminal_source_observation": {"properties": {"kind": {"const": "NO_ATTEMPT"}}, "required": ["kind"]}, + "assurance_context_binding": {"properties": {"kind": {"const": "NO_ATTEMPT"}}, "required": ["kind"]}, + "attempt_assurance_binding": {"properties": {"kind": {"const": "NONE"}}, "required": ["kind"]}, + "job_assurance_binding": {"properties": {"kind": {"const": "NOT_APPLICABLE"}}, "required": ["kind"]}, + "control_evidence_set_binding": {"properties": {"kind": {"const": "NOT_APPLICABLE"}}, "required": ["kind"]}, + "quarantine_binding_set_binding": {"properties": {"kind": {"const": "NOT_APPLICABLE"}}, "required": ["kind"]}, + "terminalization_storage_manifest_binding": {"properties": {"kind": {"const": "NOT_APPLICABLE"}}, "required": ["kind"]}, + "output_root_protection": {"properties": {"kind": {"const": "NOT_APPLICABLE"}}, "required": ["kind"]}, + "outputs": {"maxItems": 0}, + "storage_observation_binding": {"properties": {"kind": {"const": "NOT_APPLICABLE"}}, "required": ["kind"]}, + "logs": {"maxItems": 0}, + "resource_evidence": {"maxItems": 0}, + "budget_binding": { + "properties": { + "selected_attempt_settlement": {"properties": {"kind": {"const": "NONE"}}, "required": ["kind"]} + }, + "required": ["selected_attempt_settlement"] + } + } + }, + "else": { + "properties": { + "attempt_summaries": {"minItems": 1}, + "authority_binding": {"not": {"properties": {"kind": {"const": "NO_ATTEMPT"}}, "required": ["kind"]}}, + "final_fence_binding": {"not": {"properties": {"kind": {"const": "NO_ATTEMPT"}}, "required": ["kind"]}}, + "runtime_outcome": {"properties": {"kind": {"const": "ATTEMPT"}}, "required": ["kind"]}, + "terminal_source_observation": {"not": {"properties": {"kind": {"const": "NO_ATTEMPT"}}, "required": ["kind"]}}, + "assurance_context_binding": {"properties": {"kind": {"const": "ATTEMPT"}}, "required": ["kind"]}, + "attempt_assurance_binding": {"not": {"properties": {"kind": {"const": "NONE"}}, "required": ["kind"]}}, + "job_assurance_binding": {"not": {"properties": {"kind": {"const": "NOT_APPLICABLE"}}, "required": ["kind"]}}, + "control_evidence_set_binding": {"properties": {"kind": {"const": "FROZEN"}}, "required": ["kind"]}, + "quarantine_binding_set_binding": {"properties": {"kind": {"const": "FROZEN"}}, "required": ["kind"]}, + "terminalization_storage_manifest_binding": {"properties": {"kind": {"const": "FROZEN"}}, "required": ["kind"]}, + "output_root_protection": {"properties": {"kind": {"enum": ["NO_HOLD", "HELD"]}}, "required": ["kind"]}, + "outputs": {"minItems": 1}, + "storage_observation_binding": {"properties": {"kind": {"const": "FROZEN"}}, "required": ["kind"]}, + "logs": {"minItems": 3}, + "resource_evidence": {"minItems": 1}, + "budget_binding": { + "properties": { + "selected_attempt_settlement": {"properties": {"kind": {"const": "SETTLED"}}, "required": ["kind"]} + }, + "required": ["selected_attempt_settlement"] + }, + "selected_attempt_binding": { + "properties": { + "storage_observation_binding": {"properties": {"kind": {"const": "FROZEN"}}, "required": ["kind"]} + }, + "required": ["storage_observation_binding"] + } + } + } + }, + { + "if": { + "properties": {"authority_binding": {"properties": {"kind": {"const": "ASSIGNED_NO_LEASE"}}, "required": ["kind"]}}, + "required": ["authority_binding"] + }, + "then": { + "properties": { + "selected_attempt_binding": { + "properties": { + "kind": {"const": "SELECTED"}, + "worker_session_binding": {"properties": {"kind": {"const": "NONE"}}, "required": ["kind"]} + }, + "required": ["kind", "worker_session_binding"] + }, + "lease_terminal_binding": {"properties": {"kind": {"const": "NONE"}}, "required": ["kind"]}, + "final_fence_binding": {"properties": {"kind": {"const": "ASSIGNED_NO_LEASE"}}, "required": ["kind"]} + } + } + }, + { + "if": { + "properties": {"authority_binding": {"properties": {"kind": {"const": "LEASED"}}, "required": ["kind"]}}, + "required": ["authority_binding"] + }, + "then": { + "properties": { + "selected_attempt_binding": { + "properties": { + "kind": {"const": "SELECTED"}, + "worker_session_binding": {"properties": {"kind": {"const": "BOUND"}}, "required": ["kind"]} + }, + "required": ["kind", "worker_session_binding"] + }, + "lease_terminal_binding": {"properties": {"kind": {"const": "TERMINAL"}}, "required": ["kind"]}, + "final_fence_binding": {"properties": {"kind": {"const": "TOMBSTONE"}}, "required": ["kind"]} + } + } + }, + { + "if": {"properties": {"acceptance_eligible": {"const": true}}, "required": ["acceptance_eligible"]}, + "then": {"properties": {"ineligibility_reasons": {"maxItems": 0}}}, + "else": {"properties": {"ineligibility_reasons": {"minItems": 1}}} + } + ], + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "timestamp": { + "type": "string", + "format": "date-time", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", + "minLength": 20, + "maxLength": 27 + }, + "outcomeId": {"type": "string", "pattern": "^OJ-[0-9A-F]{64}$", "minLength": 67, "maxLength": 67}, + "jobTerminal": { + "type": "object", + "additionalProperties": false, + "required": ["job_revision", "state", "transition_cause", "event_id", "event_sequence", "event_sigil"], + "properties": { + "job_revision": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/u64"}, + "state": {"enum": ["SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATION"]}, + "transition_cause": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/transition_cause"}, + "event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "event_sequence": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/positive_u63"}, + "event_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "taskBinding": { + "type": "object", + "additionalProperties": false, + "required": ["task_id", "task_capsule_sigil"], + "properties": { + "task_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/taskId"}, + "task_capsule_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "capabilityBinding": { + "type": "object", + "additionalProperties": false, + "required": ["capability_id", "contract_version", "capability_contract_sigil"], + "properties": { + "capability_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/capabilityId"}, + "contract_version": {"const": "2.0"}, + "capability_contract_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "snapshotBinding": { + "type": "object", + "additionalProperties": false, + "required": ["snapshot_id", "snapshot_sigil"], + "properties": { + "snapshot_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/snapshotId"}, + "snapshot_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "circleBinding": { + "type": "object", + "additionalProperties": false, + "required": ["circle_id", "circle_sigil"], + "properties": { + "circle_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/circleId"}, + "circle_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "specificationBinding": { + "type": "object", + "additionalProperties": false, + "required": ["specification_id", "specification_sigil"], + "properties": { + "specification_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/specificationId"}, + "specification_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "approvalBinding": {"oneOf": [{"$ref": "#/$defs/approvalNotRequired"}, {"$ref": "#/$defs/approvalRequired"}]}, + "approvalNotRequired": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "ward_decision_id", "ward_decision_sigil"], + "properties": { + "kind": {"const": "NOT_REQUIRED"}, + "ward_decision_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/wardDecisionId"}, + "ward_decision_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "approvalRequired": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "ward_decision_id", "ward_decision_sigil", "approval_receipt_id", "approval_receipt_sigil"], + "properties": { + "kind": {"const": "REQUIRED"}, + "ward_decision_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/wardDecisionId"}, + "ward_decision_sigil": {"$ref": "#/$defs/sigil"}, + "approval_receipt_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/receiptId"}, + "approval_receipt_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "authority_binding": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NO_ATTEMPT"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "allocation_executor_instance_id", "allocation_executor_epoch", "allocation_executor_build_sigil", "job_id", "attempt_id", "fencing_generation"], + "properties": { + "kind": {"const": "ASSIGNED_NO_LEASE"}, + "allocation_executor_instance_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/executorInstanceId"}, + "allocation_executor_epoch": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/u64"}, + "allocation_executor_build_sigil": {"$ref": "#/$defs/sigil"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "fencing_generation": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/u64"} + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "executor_instance_id", "executor_epoch", "executor_build_sigil", "public_fence_tuple"], + "properties": { + "kind": {"const": "LEASED"}, + "executor_instance_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/executorInstanceId"}, + "executor_epoch": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/u64"}, + "executor_build_sigil": {"$ref": "#/$defs/sigil"}, + "public_fence_tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"} + } + } + ] + }, + "assurance_context_binding": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "requested_level", "profile_version", "profile_sigil", "conformance_suite_id", "conformance_suite_sigil"], + "properties": { + "kind": {"const": "NO_ATTEMPT"}, + "requested_level": {"enum": ["SANCTUM-A0", "SANCTUM-A1", "SANCTUM-A2"]}, + "profile_version": {"$ref": "https://benchwork.dev/schemas/sanctum-assurance-profile/1.0#/$defs/version"}, + "profile_sigil": {"$ref": "#/$defs/sigil"}, + "conformance_suite_id": {"$ref": "https://benchwork.dev/schemas/sanctum-assurance-profile/1.0#/$defs/suiteId"}, + "conformance_suite_sigil": {"$ref": "#/$defs/sigil"} + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "requested_level", "profile_version", "profile_sigil", "conformance_suite_id", "conformance_suite_sigil", "backend_identity", "backend_configuration_sigil", "host_identity_sigil"], + "properties": { + "kind": {"const": "ATTEMPT"}, + "requested_level": {"enum": ["SANCTUM-A0", "SANCTUM-A1", "SANCTUM-A2"]}, + "profile_version": {"$ref": "https://benchwork.dev/schemas/sanctum-assurance-profile/1.0#/$defs/version"}, + "profile_sigil": {"$ref": "#/$defs/sigil"}, + "conformance_suite_id": {"$ref": "https://benchwork.dev/schemas/sanctum-assurance-profile/1.0#/$defs/suiteId"}, + "conformance_suite_sigil": {"$ref": "#/$defs/sigil"}, + "backend_identity": {"$ref": "https://benchwork.dev/schemas/sanctum-assurance-claim/1.0#/$defs/token"}, + "backend_configuration_sigil": {"$ref": "#/$defs/sigil"}, + "host_identity_sigil": {"$ref": "#/$defs/sigil"} + } + } + ] + }, + "worker_session_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/worker_session_binding"}, + "runtimeOutcome": {"oneOf": [{"$ref": "#/$defs/noAttemptRuntimeOutcome"}, {"$ref": "#/$defs/attemptRuntimeOutcome"}]}, + "noAttemptRuntimeOutcome": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "computation_status", "worker_status", "process_termination_status", "handle_revocation_status", "cleanup_status", "mutable_resource_isolation_status", "output_publication_status", "quarantine_status", "termination_evidence_sigil", "handle_disposition_evidence_sigil", "cleanup_summary_sigil", "quarantine_evidence_sigil", "log_closure_sigil", "output_closure_sigil", "accounting_capture_event_id", "accounting_capture_event_sigil"], + "properties": { + "kind": {"const": "NO_ATTEMPT"}, + "computation_status": {"const": "NOT_STARTED"}, + "worker_status": {"const": "NOT_REPORTED"}, + "process_termination_status": {"const": "NOT_STARTED"}, + "handle_revocation_status": {"const": "NOT_APPLICABLE"}, + "cleanup_status": {"const": "NOT_APPLICABLE"}, + "mutable_resource_isolation_status": {"const": "NOT_APPLICABLE"}, + "output_publication_status": {"const": "NOT_APPLICABLE"}, + "quarantine_status": {"const": "NOT_REQUIRED"}, + "termination_evidence_sigil": {"type": "null"}, + "handle_disposition_evidence_sigil": {"type": "null"}, + "cleanup_summary_sigil": {"type": "null"}, + "quarantine_evidence_sigil": {"type": "null"}, + "log_closure_sigil": {"type": "null"}, + "output_closure_sigil": {"type": "null"}, + "accounting_capture_event_id": {"type": "null"}, + "accounting_capture_event_sigil": {"type": "null"} + } + }, + "attemptRuntimeOutcome": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "computation_status", "worker_status", "process_termination_status", "handle_revocation_status", "cleanup_status", "mutable_resource_isolation_status", "output_publication_status", "quarantine_status", "termination_evidence_sigil", "handle_disposition_evidence_sigil", "cleanup_summary_sigil", "quarantine_evidence_sigil", "log_closure_sigil", "output_closure_sigil", "accounting_capture_event_id", "accounting_capture_event_sigil"], + "properties": { + "kind": {"const": "ATTEMPT"}, + "computation_status": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/computation_status"}, + "worker_status": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/worker_status"}, + "process_termination_status": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/process_termination_status"}, + "handle_revocation_status": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/handle_revocation_status"}, + "cleanup_status": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/cleanup_status"}, + "mutable_resource_isolation_status": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/mutable_resource_isolation_status"}, + "output_publication_status": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/output_publication_status"}, + "quarantine_status": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/quarantine_status"}, + "termination_evidence_sigil": {"$ref": "#/$defs/sigil"}, + "handle_disposition_evidence_sigil": {"$ref": "#/$defs/sigil"}, + "cleanup_summary_sigil": {"$ref": "#/$defs/sigil"}, + "quarantine_evidence_sigil": {"$ref": "#/$defs/sigil"}, + "log_closure_sigil": {"$ref": "#/$defs/sigil"}, + "output_closure_sigil": {"$ref": "#/$defs/sigil"}, + "accounting_capture_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "accounting_capture_event_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "terminalAttemptAssuranceBinding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + { + "allOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/attempt_assurance_binding"}, + {"not": {"properties": {"kind": {"const": "PENDING"}}, "required": ["kind"]}} + ] + } + ] + }, + "terminalJobAssuranceBinding": { + "allOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/job_assurance_binding"}, + {"not": {"properties": {"kind": {"const": "PENDING"}}, "required": ["kind"]}} + ] + }, + "notApplicableBinding": { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NOT_APPLICABLE"}} + }, + "terminalControlEvidenceSetBinding": { + "oneOf": [ + {"$ref": "#/$defs/notApplicableBinding"}, + { + "allOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-control-evidence-set/1.0#/$defs/controlEvidenceSetBinding"}, + {"properties": {"kind": {"const": "FROZEN"}}, "required": ["kind"]} + ] + } + ] + }, + "terminalQuarantineBindingSetBinding": { + "oneOf": [ + {"$ref": "#/$defs/notApplicableBinding"}, + { + "allOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-quarantine-binding-set/1.0#/$defs/quarantineBindingSetBinding"}, + {"properties": {"kind": {"const": "FROZEN"}}, "required": ["kind"]} + ] + } + ] + }, + "outcomeStorageManifestBinding": { + "oneOf": [ + {"$ref": "#/$defs/notApplicableBinding"}, + { + "allOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/terminalization_storage_manifest_binding"}, + {"properties": {"kind": {"const": "FROZEN"}}, "required": ["kind"]} + ] + } + ] + }, + "outcomeRootProtection": { + "oneOf": [ + {"$ref": "#/$defs/notApplicableBinding"}, + { + "allOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/output_root_protection"}, + { + "properties": { + "kind": {"enum": ["NO_HOLD", "HELD"]}, + "terminalization_storage_manifest_binding": { + "properties": {"kind": {"const": "FROZEN"}}, + "required": ["kind"] + } + }, + "required": ["kind", "terminalization_storage_manifest_binding"] + } + ] + } + ] + }, + "outcomeStorageObservationBinding": { + "allOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/storage_observation_binding"}, + {"properties": {"kind": {"enum": ["NOT_APPLICABLE", "FROZEN"]}}, "required": ["kind"]} + ] + }, + "selectedSettlement": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + { + "allOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/budget_settlement_binding"}, + {"properties": {"kind": {"const": "SETTLED"}}, "required": ["kind"]} + ] + } + ] + }, + "budgetBinding": { + "type": "object", + "additionalProperties": false, + "required": ["job_budget_ledger", "selected_attempt_settlement"], + "properties": { + "job_budget_ledger": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/budget_ledger"}, + "selected_attempt_settlement": {"$ref": "#/$defs/selectedSettlement"} + } + }, + "terminalSourceObservation": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NO_ATTEMPT"}}}, + {"$ref": "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0#/$defs/terminal_source_not_applicable_member"}, + {"$ref": "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0#/$defs/terminal_source_none_member"}, + {"$ref": "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0#/$defs/terminal_source_member"} + ] + }, + "ineligibilityReason": { + "enum": [ + "JOB_NOT_SUCCEEDED", + "ATTEMPT_ABSENT", + "ATTEMPT_NOT_SUCCEEDED", + "RESULT_REQUIREMENT_UNMET", + "COMPLETION_NOT_ESTABLISHED", + "AUTHORITY_LOST_BEFORE_COMPLETION", + "ATTEMPT_AUTHORIZATION_INVALID", + "WORKER_SESSION_EVIDENCE_MISSING", + "LEASE_TERMINAL_EVIDENCE_MISSING", + "FINAL_FENCE_EVIDENCE_MISSING", + "BUDGET_UNSETTLED", + "BUDGET_EXCEEDED", + "ACCOUNTING_UNVERIFIED", + "TERMINATION_UNVERIFIED", + "HANDLE_REVOCATION_UNVERIFIED", + "CLEANUP_UNVERIFIED", + "MUTABLE_RESOURCE_UNSAFE", + "OUTPUT_INVALID", + "OUTPUT_UNAVAILABLE", + "OUTPUT_QUARANTINED", + "TERMINAL_SOURCE_INVALID", + "TERMINAL_SOURCE_QUARANTINED", + "ASSURANCE_UNMET", + "ASSURANCE_UNVERIFIABLE", + "CONTROL_EVIDENCE_INVALID", + "STORAGE_OBSERVATION_INVALID", + "INTEGRITY_FAILURE" + ] + }, + "derivationProfile": { + "type": "object", + "additionalProperties": false, + "required": ["profile_id", "profile_version", "algorithm_sigil", "outcome_schema_sigil", "imported_schema_set_sigil"], + "properties": { + "profile_id": {"const": "execution-job-outcome-v1"}, + "profile_version": {"const": "1.0"}, + "algorithm_sigil": {"$ref": "#/$defs/sigil"}, + "outcome_schema_sigil": {"$ref": "#/$defs/sigil"}, + "imported_schema_set_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} diff --git a/schemas/execution-journal-event-1.0.json b/schemas/execution-journal-event-1.0.json new file mode 100644 index 0000000..6b0fbc9 --- /dev/null +++ b/schemas/execution-journal-event-1.0.json @@ -0,0 +1,3864 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-journal-event/1.0", + "title": "Execution Journal Event v1", + "description": "Closed RFC-0012 contract-only Event wire. Validation grants no append, replay, recovery, mutation, storage, or scientific authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "journal_id", + "event_id", + "sequence", + "event_type", + "executor_instance_id", + "executor_epoch", + "executor_build_sigil", + "recorded_at", + "observed_at", + "entity_revisions", + "causation_event_id", + "idempotency_key_sigil", + "recovery_action_binding", + "payload", + "previous_event_sigil", + "event_sigil" + ], + "properties": { + "schema_version": { + "const": "execution-journal-event/1.0" + }, + "journal_id": { + "$ref": "#/$defs/journal_id" + }, + "event_id": { + "$ref": "#/$defs/event_id" + }, + "sequence": { + "$ref": "#/$defs/positive_u63" + }, + "event_type": { + "$ref": "#/$defs/event_type" + }, + "executor_instance_id": { + "$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/executorInstanceId" + }, + "executor_epoch": { + "$ref": "#/$defs/u64" + }, + "executor_build_sigil": { + "$ref": "#/$defs/sigil" + }, + "recorded_at": { + "$ref": "#/$defs/timestamp" + }, + "observed_at": { + "oneOf": [ + { + "$ref": "#/$defs/timestamp" + }, + { + "type": "null" + } + ] + }, + "entity_revisions": { + "type": "array", + "minItems": 1, + "maxItems": 5, + "items": { + "$ref": "#/$defs/entity_revision" + } + }, + "causation_event_id": { + "oneOf": [ + { + "$ref": "#/$defs/event_id" + }, + { + "type": "null" + } + ] + }, + "idempotency_key_sigil": { + "oneOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "recovery_action_binding": { + "oneOf": [ + { + "$ref": "#/$defs/recovery_action_binding" + }, + { + "type": "null" + } + ] + }, + "payload": { + "type": "object" + }, + "previous_event_sigil": { + "oneOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "event_sigil": { + "$ref": "#/$defs/sigil" + } + }, + "allOf": [ + { + "if": { + "properties": { + "event_type": { + "const": "executor.epoch_started" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "prior_epoch", + "new_epoch", + "startup_reason", + "host_identity_sigil", + "executor_build_binding" + ], + "properties": { + "prior_epoch": true, + "new_epoch": true, + "startup_reason": true, + "host_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "executor_build_binding": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "executor.clock_uncertain" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "last_trusted_utc", + "detected_utc", + "monotonic_status", + "divergence_seconds", + "affected_lease_ids" + ], + "properties": { + "last_trusted_utc": { + "$ref": "#/$defs/timestamp" + }, + "detected_utc": { + "$ref": "#/$defs/timestamp" + }, + "monotonic_status": true, + "divergence_seconds": true, + "affected_lease_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "executor.clock_restored" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "trusted_time_source_sigil", + "restored_utc", + "fenced_lease_ids", + "new_anchor_evidence_sigil" + ], + "properties": { + "trusted_time_source_sigil": { + "$ref": "#/$defs/sigil" + }, + "restored_utc": { + "$ref": "#/$defs/timestamp" + }, + "fenced_lease_ids": { + "type": "array" + }, + "new_anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "execution.heartbeat_collision_authority_closed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "collision_gate_marker_id", + "owner_kind", + "owner_id", + "message_kind", + "identity_kind", + "identity_sigil", + "candidate_inventory_bytes_sigil", + "authority_effect", + "transition_cause" + ], + "properties": { + "collision_gate_marker_id": true, + "owner_kind": true, + "owner_id": true, + "message_kind": true, + "identity_kind": true, + "identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "candidate_inventory_bytes_sigil": { + "$ref": "#/$defs/sigil" + }, + "authority_effect": true, + "transition_cause": { + "$ref": "#/$defs/transition_cause" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "recovery.started" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_id", + "prior_recovery_id", + "replay_through_sequence", + "replay_through_event_sigil", + "old_epoch", + "new_epoch", + "nonterminal_job_ids", + "nonterminal_attempt_ids", + "nonterminal_lease_ids", + "nonterminal_worker_session_ids", + "initial_action_set_sigil" + ], + "properties": { + "recovery_id": true, + "prior_recovery_id": true, + "replay_through_sequence": true, + "replay_through_event_sigil": { + "$ref": "#/$defs/sigil" + }, + "old_epoch": true, + "new_epoch": true, + "nonterminal_job_ids": { + "type": "array" + }, + "nonterminal_attempt_ids": { + "type": "array" + }, + "nonterminal_lease_ids": { + "type": "array" + }, + "nonterminal_worker_session_ids": { + "type": "array" + }, + "initial_action_set_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "recovery.action_set_rebased" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_id", + "phase", + "prior_action_set_sigil", + "replacement_action_set_sigil", + "reason_event_id", + "new_epoch", + "carried_completion_event_ids" + ], + "properties": { + "recovery_id": true, + "phase": true, + "prior_action_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "replacement_action_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "reason_event_id": true, + "new_epoch": true, + "carried_completion_event_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "recovery.phase_advanced" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_id", + "from_phase", + "to_phase", + "completed_action_set_sigil", + "next_action_set_sigil", + "completed_entity_ids", + "quarantined_entity_ids" + ], + "properties": { + "recovery_id": true, + "from_phase": true, + "to_phase": true, + "completed_action_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "next_action_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "completed_entity_ids": { + "type": "array" + }, + "quarantined_entity_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "recovery.completed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_id", + "completed_action_set_sigil", + "finalizing_state_sigil", + "fence_tombstone_event_ids", + "quarantined_entity_ids", + "resumable_job_ids" + ], + "properties": { + "recovery_id": true, + "completed_action_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "finalizing_state_sigil": { + "$ref": "#/$defs/sigil" + }, + "fence_tombstone_event_ids": { + "type": "array" + }, + "quarantined_entity_ids": { + "type": "array" + }, + "resumable_job_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker.definition_registered" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "worker_binding_sigil", + "definition_revision", + "supersedes_worker_binding_sigil" + ], + "properties": { + "worker_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "definition_revision": true, + "supersedes_worker_binding_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker.enabled" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "worker_binding_sigil", + "verification_evidence_set_sigil" + ], + "properties": { + "worker_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "verification_evidence_set_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker.draining" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "reason_code", + "affected_worker_session_ids" + ], + "properties": { + "reason_code": true, + "affected_worker_session_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker.quarantined" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "reason_codes", + "evidence_set_sigil", + "affected_worker_session_ids" + ], + "properties": { + "reason_codes": { + "type": "array" + }, + "evidence_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "affected_worker_session_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker.retired" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "reason_code", + "closed_worker_session_ids" + ], + "properties": { + "reason_code": true, + "closed_worker_session_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker_session.registered" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "worker_session_binding_sigil", + "worker_binding_sigil", + "backend_session_identity", + "control_channel_identity_sigil" + ], + "properties": { + "worker_session_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "worker_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "backend_session_identity": true, + "control_channel_identity_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker_session.ready" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "verification_evidence_set_sigil", + "capacity", + "worker_session_heartbeat_policy_id", + "worker_session_heartbeat_policy_sigil", + "initial_heartbeat_due_at" + ], + "properties": { + "verification_evidence_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "capacity": true, + "worker_session_heartbeat_policy_id": { + "type": "string", + "pattern": "^WSHP-[0-9A-F]{64}$" + }, + "worker_session_heartbeat_policy_sigil": { + "$ref": "#/$defs/sigil" + }, + "initial_heartbeat_due_at": { + "$ref": "#/$defs/timestamp" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker_session.draining" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "reason_code", + "active_lease_ids" + ], + "properties": { + "reason_code": true, + "active_lease_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker_session.offline" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "last_heartbeat_sequence", + "active_lease_ids" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "last_heartbeat_sequence": true, + "active_lease_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker_session.quarantined" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "reason_codes", + "evidence_set_sigil", + "active_lease_ids" + ], + "properties": { + "reason_codes": { + "type": "array" + }, + "evidence_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "active_lease_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker_session.closed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "reason_code", + "terminal_lease_ids", + "backend_close_evidence_sigil" + ], + "properties": { + "reason_code": true, + "terminal_lease_ids": { + "type": "array" + }, + "backend_close_evidence_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker_session.heartbeat_accepted" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "heartbeat_message_sigil", + "sequence", + "prior_accepted_sequence", + "received_at", + "next_heartbeat_due_at", + "worker_session_heartbeat_policy_id", + "worker_session_heartbeat_policy_sigil", + "resource_sample_sigil", + "resource_counter_floors_after" + ], + "properties": { + "heartbeat_message_sigil": { + "$ref": "#/$defs/sigil" + }, + "sequence": true, + "prior_accepted_sequence": true, + "received_at": { + "$ref": "#/$defs/timestamp" + }, + "next_heartbeat_due_at": { + "$ref": "#/$defs/timestamp" + }, + "worker_session_heartbeat_policy_id": { + "type": "string", + "pattern": "^WSHP-[0-9A-F]{64}$" + }, + "worker_session_heartbeat_policy_sigil": { + "$ref": "#/$defs/sigil" + }, + "resource_sample_sigil": { + "$ref": "#/$defs/sigil" + }, + "resource_counter_floors_after": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "worker_session.message_rejected" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "message_kind", + "message_sigil", + "identity_binding", + "reason_codes", + "historical_disposition_event_id" + ], + "properties": { + "message_kind": true, + "message_sigil": { + "$ref": "#/$defs/sigil" + }, + "identity_binding": true, + "reason_codes": { + "type": "array" + }, + "historical_disposition_event_id": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.submitted" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "job_binding_sigil", + "start_request_sigil", + "submission_idempotency_key_sigil", + "admission_chronicle_head", + "admission_chronicle_head_evidence", + "deadline_due_at", + "job_budget", + "job_storage_roots" + ], + "properties": { + "job_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "start_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "submission_idempotency_key_sigil": { + "$ref": "#/$defs/sigil" + }, + "admission_chronicle_head": true, + "admission_chronicle_head_evidence": true, + "deadline_due_at": { + "$ref": "#/$defs/timestamp" + }, + "job_budget": true, + "job_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.queued" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "admission_evidence_sigil", + "queue_key" + ], + "properties": { + "admission_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "queue_key": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.attempt_allocated" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_binding_sigil", + "retry_ordinal", + "fencing_generation", + "prior_fencing_counter", + "resulting_fence_floor", + "budget_reservation", + "resulting_budget_ledger_sigil" + ], + "properties": { + "attempt_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "retry_ordinal": true, + "fencing_generation": true, + "prior_fencing_counter": true, + "resulting_fence_floor": true, + "budget_reservation": true, + "resulting_budget_ledger_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.budget_settled" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "reservation", + "accounting_capture_event_id", + "accounting_capture_event_sigil", + "usage_status", + "measured", + "charged", + "accounting_started_at", + "accounting_ended_at", + "supervisor_identity", + "accounting_evidence_set_sigil", + "resulting_budget_ledger_sigil" + ], + "properties": { + "attempt_id": true, + "reservation": true, + "accounting_capture_event_id": true, + "accounting_capture_event_sigil": { + "$ref": "#/$defs/sigil" + }, + "usage_status": true, + "measured": true, + "charged": true, + "accounting_started_at": { + "$ref": "#/$defs/timestamp" + }, + "accounting_ended_at": { + "$ref": "#/$defs/timestamp" + }, + "supervisor_identity": true, + "accounting_evidence_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "resulting_budget_ledger_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.retry_scheduled" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "preceding_attempt_id", + "terminal_reason", + "eligible_due_at", + "backoff_ordinal", + "post_settlement_budget_ledger_sigil" + ], + "properties": { + "preceding_attempt_id": true, + "terminal_reason": true, + "eligible_due_at": { + "$ref": "#/$defs/timestamp" + }, + "backoff_ordinal": true, + "post_settlement_budget_ledger_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.retry_ready" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "eligible_due_at", + "deadline_check_sigil", + "freshness_evidence_sigil", + "queue_key" + ], + "properties": { + "eligible_due_at": { + "$ref": "#/$defs/timestamp" + }, + "deadline_check_sigil": { + "$ref": "#/$defs/sigil" + }, + "freshness_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "queue_key": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.stop_latched" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "request_binding" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "request_binding": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.cancellation_observed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "cancellation_request_id", + "idempotency_key_sigil", + "cancel_request_sigil", + "actor_sigil", + "host_provenance_sigil", + "reason", + "expected_job_revision", + "terminal_event_id", + "terminal_event_sigil" + ], + "properties": { + "cancellation_request_id": true, + "idempotency_key_sigil": { + "$ref": "#/$defs/sigil" + }, + "cancel_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "actor_sigil": { + "$ref": "#/$defs/sigil" + }, + "host_provenance_sigil": { + "$ref": "#/$defs/sigil" + }, + "reason": true, + "expected_job_revision": true, + "terminal_event_id": true, + "terminal_event_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.assurance_evaluated" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "evaluation", + "attempt_id", + "attempt_assurance_event_sigil", + "assurance_claim_sigil", + "reason_codes", + "evidence_set_sigil" + ], + "properties": { + "evaluation": true, + "attempt_id": true, + "attempt_assurance_event_sigil": { + "anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}] + }, + "assurance_claim_sigil": { + "anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}] + }, + "reason_codes": { + "type": "array" + }, + "evidence_set_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.succeeded" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "attempt_summaries", + "selected_attempt_binding", + "completion_anchor_binding", + "first_stop_or_fence_binding", + "job_assurance_event_sigil", + "budget_ledger_sigil", + "final_fence_binding", + "cleanup_summary_sigil", + "storage_observation_binding", + "terminal_source_binding", + "output_hold_release_schedules" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "attempt_summaries": { + "type": "array" + }, + "selected_attempt_binding": true, + "completion_anchor_binding": true, + "first_stop_or_fence_binding": true, + "job_assurance_event_sigil": { + "$ref": "#/$defs/sigil" + }, + "budget_ledger_sigil": { + "$ref": "#/$defs/sigil" + }, + "final_fence_binding": true, + "cleanup_summary_sigil": { + "$ref": "#/$defs/sigil" + }, + "storage_observation_binding": true, + "terminal_source_binding": true, + "output_hold_release_schedules": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.failed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "attempt_summaries", + "selected_attempt_binding", + "completion_anchor_binding", + "first_stop_or_fence_binding", + "job_assurance_event_sigil", + "budget_ledger_sigil", + "final_fence_binding", + "cleanup_summary_sigil", + "storage_observation_binding", + "terminal_source_binding", + "output_hold_release_schedules" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "attempt_summaries": { + "type": "array" + }, + "selected_attempt_binding": true, + "completion_anchor_binding": true, + "first_stop_or_fence_binding": true, + "job_assurance_event_sigil": { + "$ref": "#/$defs/sigil" + }, + "budget_ledger_sigil": { + "$ref": "#/$defs/sigil" + }, + "final_fence_binding": true, + "cleanup_summary_sigil": { + "$ref": "#/$defs/sigil" + }, + "storage_observation_binding": true, + "terminal_source_binding": true, + "output_hold_release_schedules": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.cancelled" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "attempt_summaries", + "selected_attempt_binding", + "completion_anchor_binding", + "first_stop_or_fence_binding", + "job_assurance_event_sigil", + "budget_ledger_sigil", + "final_fence_binding", + "cleanup_summary_sigil", + "storage_observation_binding", + "terminal_source_binding", + "output_hold_release_schedules" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "attempt_summaries": { + "type": "array" + }, + "selected_attempt_binding": true, + "completion_anchor_binding": true, + "first_stop_or_fence_binding": true, + "job_assurance_event_sigil": { + "$ref": "#/$defs/sigil" + }, + "budget_ledger_sigil": { + "$ref": "#/$defs/sigil" + }, + "final_fence_binding": true, + "cleanup_summary_sigil": { + "$ref": "#/$defs/sigil" + }, + "storage_observation_binding": true, + "terminal_source_binding": true, + "output_hold_release_schedules": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.timed_out" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "attempt_summaries", + "selected_attempt_binding", + "completion_anchor_binding", + "first_stop_or_fence_binding", + "job_assurance_event_sigil", + "budget_ledger_sigil", + "final_fence_binding", + "cleanup_summary_sigil", + "storage_observation_binding", + "terminal_source_binding", + "output_hold_release_schedules" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "attempt_summaries": { + "type": "array" + }, + "selected_attempt_binding": true, + "completion_anchor_binding": true, + "first_stop_or_fence_binding": true, + "job_assurance_event_sigil": { + "$ref": "#/$defs/sigil" + }, + "budget_ledger_sigil": { + "$ref": "#/$defs/sigil" + }, + "final_fence_binding": true, + "cleanup_summary_sigil": { + "$ref": "#/$defs/sigil" + }, + "storage_observation_binding": true, + "terminal_source_binding": true, + "output_hold_release_schedules": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.policy_violated" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "attempt_summaries", + "selected_attempt_binding", + "completion_anchor_binding", + "first_stop_or_fence_binding", + "job_assurance_event_sigil", + "budget_ledger_sigil", + "final_fence_binding", + "cleanup_summary_sigil", + "storage_observation_binding", + "terminal_source_binding", + "output_hold_release_schedules" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "attempt_summaries": { + "type": "array" + }, + "selected_attempt_binding": true, + "completion_anchor_binding": true, + "first_stop_or_fence_binding": true, + "job_assurance_event_sigil": { + "$ref": "#/$defs/sigil" + }, + "budget_ledger_sigil": { + "$ref": "#/$defs/sigil" + }, + "final_fence_binding": true, + "cleanup_summary_sigil": { + "$ref": "#/$defs/sigil" + }, + "storage_observation_binding": true, + "terminal_source_binding": true, + "output_hold_release_schedules": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "storage_root.hold_release_observed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "job_id", + "release_binding", + "storage_release_event" + ], + "properties": { + "job_id": true, + "release_binding": true, + "storage_release_event": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "job.message_rejected" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "message_kind", + "message_sigil", + "reason_codes", + "historical_disposition_event_id" + ], + "properties": { + "message_kind": true, + "message_sigil": { + "$ref": "#/$defs/sigil" + }, + "reason_codes": { + "type": "array" + }, + "historical_disposition_event_id": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.authorization_bound" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "authorization_subject", + "attempt_authorization_binding" + ], + "properties": { + "authorization_subject": true, + "attempt_authorization_binding": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.preflight_started" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "preflight_plan_sigil", + "freshness_evidence_sigil" + ], + "properties": { + "preflight_plan_sigil": { + "$ref": "#/$defs/sigil" + }, + "freshness_evidence_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.preflight_progressed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "step", + "progress_evidence_sigil" + ], + "properties": { + "step": true, + "progress_evidence_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.preflight_passed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "materialization_identity", + "materialization_sigil", + "preflight_evidence_set_sigil", + "input_storage_roots" + ], + "properties": { + "materialization_identity": true, + "materialization_sigil": { + "$ref": "#/$defs/sigil" + }, + "preflight_evidence_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "input_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.starting" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "backend_start_handle_sigil", + "start_request_sigil" + ], + "properties": { + "backend_start_handle_sigil": { + "$ref": "#/$defs/sigil" + }, + "start_request_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.running" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "process_tree_identity", + "process_tree_evidence_sigil", + "side_effect_handle_set_sigil" + ], + "properties": { + "process_tree_identity": true, + "process_tree_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "side_effect_handle_set_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.output_staging_preallocated" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "job_id", + "attempt_id", + "attempt_binding_sigil", + "lease_id", + "lease_binding_sigil", + "worker_id", + "worker_session_id", + "worker_session_binding_sigil", + "executor_epoch", + "fence_tuple", + "storage_subject_id", + "output_handle_id", + "transfer_id", + "transfer_attempt_id", + "authorized_maximum_bytes" + ], + "properties": { + "job_id": true, + "attempt_id": true, + "attempt_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "lease_id": true, + "lease_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "worker_id": true, + "worker_session_id": true, + "worker_session_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "executor_epoch": true, + "fence_tuple": { + "$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple" + }, + "storage_subject_id": true, + "output_handle_id": true, + "transfer_id": true, + "transfer_attempt_id": true, + "authorized_maximum_bytes": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.result_ingress_received" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "ingress_receipt_id", + "ingress_receipt_sigil", + "result_sigil", + "observation_evidence_subject_sigil", + "received_at" + ], + "properties": { + "ingress_receipt_id": true, + "ingress_receipt_sigil": { + "$ref": "#/$defs/sigil" + }, + "result_sigil": { + "$ref": "#/$defs/sigil" + }, + "observation_evidence_subject_sigil": { + "$ref": "#/$defs/sigil" + }, + "received_at": { + "$ref": "#/$defs/timestamp" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.result_accepted" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "result_sigil", + "lease_revision", + "fence_tuple", + "received_at", + "validation_evidence_sigil", + "observation_evidence_disposition_binding" + ], + "properties": { + "result_sigil": { + "$ref": "#/$defs/sigil" + }, + "lease_revision": true, + "fence_tuple": { + "$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple" + }, + "received_at": { + "$ref": "#/$defs/timestamp" + }, + "validation_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "observation_evidence_disposition_binding": { + "$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_evidence_disposition_binding" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.result_rejected" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "disposition_kind", + "message_sigil", + "claimed_result_sigil", + "received_at", + "reason_codes", + "historical_disposition_event_id", + "observation_evidence_disposition_binding" + ], + "properties": { + "disposition_kind": { + "const": "FIRST_DISPOSITION_REJECTION" + }, + "message_sigil": { + "$ref": "#/$defs/sigil" + }, + "claimed_result_sigil": { + "$ref": "#/$defs/sigil" + }, + "received_at": { + "$ref": "#/$defs/timestamp" + }, + "reason_codes": { + "type": "array" + }, + "historical_disposition_event_id": { + "type": "null" + }, + "observation_evidence_disposition_binding": { + "$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_evidence_disposition_binding" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "disposition_kind", + "message_sigil", + "claimed_result_sigil", + "received_at", + "reason_codes", + "historical_disposition_event_id" + ], + "properties": { + "disposition_kind": { + "const": "LATE_OR_CONFLICTING_REJECTION" + }, + "message_sigil": { + "$ref": "#/$defs/sigil" + }, + "claimed_result_sigil": { + "$ref": "#/$defs/sigil" + }, + "received_at": { + "$ref": "#/$defs/timestamp" + }, + "reason_codes": { + "type": "array" + }, + "historical_disposition_event_id": { + "oneOf": [ + { + "$ref": "#/$defs/event_id" + }, + { + "type": "null" + } + ] + } + } + } + ] + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.draining" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "result_binding", + "process_exit_observation_sigil" + ], + "properties": { + "result_binding": true, + "process_exit_observation_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.stop_latched" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "grace_due_at" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "grace_due_at": { + "$ref": "#/$defs/timestamp" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.stop_progressed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "step", + "termination_evidence_sigil", + "remaining_handle_ids" + ], + "properties": { + "step": true, + "termination_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "remaining_handle_ids": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.cleaning" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "log_closure_sigil", + "output_closure_sigil", + "termination_evidence_sigil", + "quarantine_plan_sigil", + "terminal_source_binding" + ], + "properties": { + "log_closure_sigil": { + "$ref": "#/$defs/sigil" + }, + "output_closure_sigil": { + "$ref": "#/$defs/sigil" + }, + "termination_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "quarantine_plan_sigil": { + "$ref": "#/$defs/sigil" + }, + "terminal_source_binding": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.cleanup_progressed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "step", + "cleanup_evidence_sigil", + "remaining_resource_ids", + "finalization_bindings" + ], + "properties": { + "step": true, + "cleanup_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "remaining_resource_ids": { + "type": "array" + }, + "finalization_bindings": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.succeeded" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_terminal_evidence", + "fencing_generation", + "final_fence_floor", + "output_storage_roots" + ], + "properties": { + "attempt_terminal_evidence": {"$ref": "#/$defs/attempt_terminal_evidence"}, + "fencing_generation": true, + "final_fence_floor": true, + "output_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.failed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_terminal_evidence", + "fencing_generation", + "final_fence_floor", + "output_storage_roots" + ], + "properties": { + "attempt_terminal_evidence": {"$ref": "#/$defs/attempt_terminal_evidence"}, + "fencing_generation": true, + "final_fence_floor": true, + "output_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.cancelled" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_terminal_evidence", + "fencing_generation", + "final_fence_floor", + "output_storage_roots" + ], + "properties": { + "attempt_terminal_evidence": {"$ref": "#/$defs/attempt_terminal_evidence"}, + "fencing_generation": true, + "final_fence_floor": true, + "output_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.timed_out" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_terminal_evidence", + "fencing_generation", + "final_fence_floor", + "output_storage_roots" + ], + "properties": { + "attempt_terminal_evidence": {"$ref": "#/$defs/attempt_terminal_evidence"}, + "fencing_generation": true, + "final_fence_floor": true, + "output_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.policy_violated" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_terminal_evidence", + "fencing_generation", + "final_fence_floor", + "output_storage_roots" + ], + "properties": { + "attempt_terminal_evidence": {"$ref": "#/$defs/attempt_terminal_evidence"}, + "fencing_generation": true, + "final_fence_floor": true, + "output_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.lease_expired" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_terminal_evidence", + "fencing_generation", + "final_fence_floor", + "output_storage_roots" + ], + "properties": { + "attempt_terminal_evidence": {"$ref": "#/$defs/attempt_terminal_evidence"}, + "fencing_generation": true, + "final_fence_floor": true, + "output_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.lost" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_terminal_evidence", + "fencing_generation", + "final_fence_floor", + "output_storage_roots" + ], + "properties": { + "attempt_terminal_evidence": {"$ref": "#/$defs/attempt_terminal_evidence"}, + "fencing_generation": true, + "final_fence_floor": true, + "output_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.fenced" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_terminal_evidence", + "fencing_generation", + "final_fence_floor", + "output_storage_roots" + ], + "properties": { + "attempt_terminal_evidence": {"$ref": "#/$defs/attempt_terminal_evidence"}, + "fencing_generation": true, + "final_fence_floor": true, + "output_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.rejected" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_terminal_evidence", + "fencing_generation", + "final_fence_floor", + "output_storage_roots" + ], + "properties": { + "attempt_terminal_evidence": {"$ref": "#/$defs/attempt_terminal_evidence"}, + "fencing_generation": true, + "final_fence_floor": true, + "output_storage_roots": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "attempt.assurance_evaluated" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "evaluation", + "assurance_claim_sigil", + "reason_codes", + "evidence_set_sigil" + ], + "properties": { + "evaluation": true, + "assurance_claim_sigil": { + "anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}] + }, + "reason_codes": { + "type": "array" + }, + "evidence_set_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.offered" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "lease_binding_sigil", + "credential_digest", + "claim_due_at", + "initial_expiry_due_at", + "maximum_expiry_due_at" + ], + "properties": { + "lease_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "credential_digest": true, + "claim_due_at": { + "$ref": "#/$defs/timestamp" + }, + "initial_expiry_due_at": { + "$ref": "#/$defs/timestamp" + }, + "maximum_expiry_due_at": { + "$ref": "#/$defs/timestamp" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.claimed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "credential_proof_sigil", + "claimed_at", + "next_heartbeat_due_at", + "session_capacity_after" + ], + "properties": { + "credential_proof_sigil": { + "$ref": "#/$defs/sigil" + }, + "claimed_at": { + "$ref": "#/$defs/timestamp" + }, + "next_heartbeat_due_at": { + "$ref": "#/$defs/timestamp" + }, + "session_capacity_after": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.heartbeat_accepted" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "heartbeat_message_sigil", + "sequence", + "prior_accepted_sequence", + "received_at", + "next_heartbeat_due_at", + "resource_sample_sigil", + "resource_counter_floors_after" + ], + "properties": { + "heartbeat_message_sigil": { + "$ref": "#/$defs/sigil" + }, + "sequence": true, + "prior_accepted_sequence": true, + "received_at": { + "$ref": "#/$defs/timestamp" + }, + "next_heartbeat_due_at": { + "$ref": "#/$defs/timestamp" + }, + "resource_sample_sigil": { + "$ref": "#/$defs/sigil" + }, + "resource_counter_floors_after": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.renewed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "renewal_request_sigil", + "prior_expiry_due_at", + "new_expiry_due_at", + "renewal_counter" + ], + "properties": { + "renewal_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "prior_expiry_due_at": { + "$ref": "#/$defs/timestamp" + }, + "new_expiry_due_at": { + "$ref": "#/$defs/timestamp" + }, + "renewal_counter": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.released" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "release_evidence_sigil", + "prior_fence_floor", + "tombstone_generation", + "tombstone_publication_sigil", + "session_capacity_after" + ], + "properties": { + "release_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "prior_fence_floor": true, + "tombstone_generation": true, + "tombstone_publication_sigil": { + "$ref": "#/$defs/sigil" + }, + "session_capacity_after": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.revoked" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "prior_fence_floor", + "tombstone_generation", + "tombstone_publication_sigil", + "session_capacity_after" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "prior_fence_floor": true, + "tombstone_generation": true, + "tombstone_publication_sigil": { + "$ref": "#/$defs/sigil" + }, + "session_capacity_after": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.expired" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "deadline_kind", + "due_at", + "prior_fence_floor", + "tombstone_generation", + "tombstone_publication_sigil", + "session_capacity_after" + ], + "properties": { + "deadline_kind": true, + "due_at": { + "$ref": "#/$defs/timestamp" + }, + "prior_fence_floor": true, + "tombstone_generation": true, + "tombstone_publication_sigil": { + "$ref": "#/$defs/sigil" + }, + "session_capacity_after": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.fenced" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "transition_cause", + "prior_fence_floor", + "tombstone_generation", + "tombstone_publication_sigil", + "session_capacity_after" + ], + "properties": { + "transition_cause": { + "$ref": "#/$defs/transition_cause" + }, + "prior_fence_floor": true, + "tombstone_generation": true, + "tombstone_publication_sigil": { + "$ref": "#/$defs/sigil" + }, + "session_capacity_after": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.tombstone_republished" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "tombstone_generation", + "original_terminal_event_sigil", + "sink_ids", + "publication_evidence_sigil" + ], + "properties": { + "tombstone_generation": true, + "original_terminal_event_sigil": { + "$ref": "#/$defs/sigil" + }, + "sink_ids": { + "type": "array" + }, + "publication_evidence_sigil": { + "$ref": "#/$defs/sigil" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "lease.message_rejected" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "message_kind", + "message_sigil", + "identity_binding", + "reason_codes", + "historical_disposition_event_id" + ], + "properties": { + "message_kind": true, + "message_sigil": { + "$ref": "#/$defs/sigil" + }, + "identity_binding": true, + "reason_codes": { + "type": "array" + }, + "historical_disposition_event_id": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "log.chunk_committed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "intake_kind", + "intake_id", + "intake_record_sigil", + "disposition_intent_id", + "log_stream_id", + "chunk_record_sigil", + "stream", + "sequence", + "blob_sigil", + "captured_bytes_after" + ], + "properties": { + "intake_kind": true, + "intake_id": true, + "intake_record_sigil": { + "$ref": "#/$defs/sigil" + }, + "disposition_intent_id": true, + "log_stream_id": true, + "chunk_record_sigil": { + "$ref": "#/$defs/sigil" + }, + "stream": true, + "sequence": true, + "blob_sigil": { + "$ref": "#/$defs/sigil" + }, + "captured_bytes_after": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "log.chunk_duplicate_observed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "intake_kind", + "intake_id", + "intake_record_sigil", + "disposition_intent_id", + "log_stream_id", + "stream", + "sequence", + "original_chunk_id", + "original_chunk_record_sigil", + "original_disposition_event" + ], + "properties": { + "intake_kind": true, + "intake_id": true, + "intake_record_sigil": { + "$ref": "#/$defs/sigil" + }, + "disposition_intent_id": true, + "log_stream_id": true, + "stream": true, + "sequence": true, + "original_chunk_id": true, + "original_chunk_record_sigil": { + "$ref": "#/$defs/sigil" + }, + "original_disposition_event": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "log.chunk_rejected" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "intake_kind", + "intake_id", + "intake_record_sigil", + "disposition_intent_id", + "log_stream_id", + "stream", + "sequence", + "message_sigil", + "reason_codes", + "historical_disposition_event_id" + ], + "properties": { + "intake_kind": true, + "intake_id": true, + "intake_record_sigil": { + "$ref": "#/$defs/sigil" + }, + "disposition_intent_id": true, + "log_stream_id": true, + "stream": true, + "sequence": true, + "message_sigil": { + "$ref": "#/$defs/sigil" + }, + "reason_codes": { + "type": "array" + }, + "historical_disposition_event_id": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "log.truncated" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "intake_kind", + "intake_id", + "intake_record_sigil", + "disposition_intent_id", + "log_stream_id", + "stream", + "limit_kind", + "limit_bytes", + "captured_bytes", + "dropped_bytes", + "overflow_behavior", + "structured_truncation_status", + "accepted_prefix_length", + "capture_cutoff_ordinal" + ], + "properties": { + "intake_kind": true, + "intake_id": true, + "intake_record_sigil": { + "$ref": "#/$defs/sigil" + }, + "disposition_intent_id": true, + "log_stream_id": true, + "stream": true, + "limit_kind": true, + "limit_bytes": true, + "captured_bytes": true, + "dropped_bytes": true, + "overflow_behavior": true, + "structured_truncation_status": true, + "accepted_prefix_length": true, + "capture_cutoff_ordinal": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "log.eof_accepted" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "eof_id", + "eof_record_sigil", + "eof_intent_id", + "stream_validation_binding" + ], + "properties": { + "eof_id": true, + "eof_record_sigil": { + "$ref": "#/$defs/sigil" + }, + "eof_intent_id": true, + "stream_validation_binding": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "log.eof_rejected" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "eof_id", + "eof_record_sigil", + "eof_intent_id", + "reason_codes" + ], + "properties": { + "eof_id": true, + "eof_record_sigil": { + "$ref": "#/$defs/sigil" + }, + "eof_intent_id": true, + "reason_codes": { + "type": "array" + } + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "log.closed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "log_stream_id", + "stream", + "final_sequence", + "captured_bytes", + "dropped_bytes", + "stream_set_sigil", + "freeze_binding", + "closure_intent_id" + ], + "properties": { + "log_stream_id": true, + "stream": true, + "final_sequence": true, + "captured_bytes": true, + "dropped_bytes": true, + "stream_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "freeze_binding": true, + "closure_intent_id": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "log.closure_recovery_closed" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "log_stream_id", + "stream", + "final_sequence", + "captured_bytes", + "dropped_bytes", + "stream_set_sigil", + "closure_recovery_id", + "old_closure_intent_id" + ], + "properties": { + "log_stream_id": true, + "stream": true, + "final_sequence": true, + "captured_bytes": true, + "dropped_bytes": true, + "stream_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "closure_recovery_id": true, + "old_closure_intent_id": true + } + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "log.intake_recovery_terminalized" + } + }, + "required": [ + "event_type" + ] + }, + "then": { + "properties": { + "payload": { + "type": "object", + "additionalProperties": false, + "required": [ + "selection_recovery_id", + "log_stream_id", + "operation_kind", + "original_intake_id", + "original_intent_id", + "surviving_event_prefix", + "terminal_delta" + ], + "properties": { + "selection_recovery_id": true, + "log_stream_id": true, + "operation_kind": true, + "original_intake_id": true, + "original_intent_id": true, + "surviving_event_prefix": { + "type": "array" + }, + "terminal_delta": true + } + } + } + } + } + ], + "$defs": { + "sigil": { + "$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil" + }, + "positive_u63": { + "$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63" + }, + "u63": { + "type": "integer", + "minimum": 0, + "maximum": 9223372036854776000 + }, + "u64": { + "type": "integer", + "minimum": 0, + "maximum": 18446744073709552000 + }, + "timestamp": { + "$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp" + }, + "journal_id": { + "type": "string", + "pattern": "^EJ-[A-Z0-9]+$", + "minLength": 4, + "maxLength": 128 + }, + "event_id": { + "type": "string", + "pattern": "^JE-[A-Z0-9]+$", + "minLength": 4, + "maxLength": 128 + }, + "event_type": { + "enum": [ + "executor.epoch_started", + "executor.clock_uncertain", + "executor.clock_restored", + "execution.heartbeat_collision_authority_closed", + "recovery.started", + "recovery.action_set_rebased", + "recovery.phase_advanced", + "recovery.completed", + "worker.definition_registered", + "worker.enabled", + "worker.draining", + "worker.quarantined", + "worker.retired", + "worker_session.registered", + "worker_session.ready", + "worker_session.draining", + "worker_session.offline", + "worker_session.quarantined", + "worker_session.closed", + "worker_session.heartbeat_accepted", + "worker_session.message_rejected", + "job.submitted", + "job.queued", + "job.attempt_allocated", + "job.budget_settled", + "job.retry_scheduled", + "job.retry_ready", + "job.stop_latched", + "job.cancellation_observed", + "job.assurance_evaluated", + "job.succeeded", + "job.failed", + "job.cancelled", + "job.timed_out", + "job.policy_violated", + "storage_root.hold_release_observed", + "job.message_rejected", + "attempt.authorization_bound", + "attempt.preflight_started", + "attempt.preflight_progressed", + "attempt.preflight_passed", + "attempt.starting", + "attempt.running", + "attempt.output_staging_preallocated", + "attempt.result_ingress_received", + "attempt.result_accepted", + "attempt.result_rejected", + "attempt.draining", + "attempt.stop_latched", + "attempt.stop_progressed", + "attempt.cleaning", + "attempt.cleanup_progressed", + "attempt.succeeded", + "attempt.failed", + "attempt.cancelled", + "attempt.timed_out", + "attempt.policy_violated", + "attempt.lease_expired", + "attempt.lost", + "attempt.fenced", + "attempt.rejected", + "attempt.assurance_evaluated", + "lease.offered", + "lease.claimed", + "lease.heartbeat_accepted", + "lease.renewed", + "lease.released", + "lease.revoked", + "lease.expired", + "lease.fenced", + "lease.tombstone_republished", + "lease.message_rejected", + "log.chunk_committed", + "log.chunk_duplicate_observed", + "log.chunk_rejected", + "log.truncated", + "log.eof_accepted", + "log.eof_rejected", + "log.closed", + "log.closure_recovery_closed", + "log.intake_recovery_terminalized" + ] + }, + "transition_cause": { + "type": "object", + "additionalProperties": false, + "required": [ + "code", + "trigger_kind", + "trigger_event_id", + "effective_sequence", + "evidence_sigil" + ], + "properties": { + "code": { + "enum": [ + "COMPLETION_ESTABLISHED", + "CANCEL_REQUESTED", + "JOB_DEADLINE", + "ATTEMPT_DEADLINE", + "HEARTBEAT_TIMEOUT", + "HEARTBEAT_IDENTITY_COLLISION", + "LEASE_CLAIM_EXPIRED", + "LEASE_ACTIVE_EXPIRED", + "LEASE_REVOKED", + "RECOVERY_FENCE", + "CLOCK_UNCERTAIN", + "EXECUTOR_EPOCH_CHANGED", + "SESSION_CHANNEL_LOST", + "POLICY_VIOLATION", + "ADMISSION_INVALID", + "PREFLIGHT_REJECTED", + "START_FAILED", + "COMPUTATION_FAILED", + "VALIDATION_FAILED", + "RESULT_CONFLICT", + "RESULT_REQUIREMENT_FAILED", + "OUTPUT_VALIDATION_FAILED", + "TERMINAL_SOURCE_RETENTION_FAILED", + "TERMINATION_FAILED", + "CLEANUP_FAILED", + "LOST_OWNERSHIP", + "ASSURANCE_UNMET", + "ASSURANCE_UNVERIFIABLE", + "BUDGET_EXHAUSTED", + "RETRY_EXHAUSTED", + "ATTEMPT_NONRETRYABLE", + "ATTEMPT_REJECTED", + "FATAL_INFRASTRUCTURE", + "INTEGRITY_FAILURE" + ] + }, + "trigger_kind": { + "enum": [ + "PRIOR_EVENT", + "CURRENT_REQUEST", + "DUE_DEADLINE", + "RECOVERY_DERIVATION" + ] + }, + "trigger_event_id": { + "$ref": "#/$defs/event_id" + }, + "effective_sequence": { + "$ref": "#/$defs/positive_u63" + }, + "evidence_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "entity_revision": { + "type": "object", + "additionalProperties": false, + "required": [ + "entity_kind", + "entity_id", + "preceding_revision", + "next_revision" + ], + "properties": { + "entity_kind": { + "enum": [ + "EXECUTOR", + "RECOVERY", + "WORKER", + "WORKER_SESSION", + "JOB", + "ATTEMPT", + "LEASE", + "LOG_STREAM" + ] + }, + "entity_id": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "preceding_revision": { + "oneOf": [ + { + "$ref": "#/$defs/u64" + }, + { + "type": "null" + } + ] + }, + "next_revision": { + "$ref": "#/$defs/u64" + } + } + }, + "recovery_action_binding": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_id", + "phase", + "action_set_sigil", + "action_ordinal" + ], + "properties": { + "recovery_id": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "phase": { + "enum": [ + "STARTED", + "FENCING", + "RECONCILING", + "FINALIZING" + ] + }, + "action_set_sigil": { + "$ref": "#/$defs/sigil" + }, + "action_ordinal": { + "$ref": "#/$defs/u63" + } + } + }, + "event_ref": { + "type": "object", "additionalProperties": false, + "required": ["journal_id", "event_id", "sequence", "event_sigil"], + "properties": {"journal_id": {"$ref": "#/$defs/journal_id"}, "event_id": {"$ref": "#/$defs/event_id"}, "sequence": {"$ref": "#/$defs/positive_u63"}, "event_sigil": {"$ref": "#/$defs/sigil"}} + }, + "budget_vector": { + "type": "object", "additionalProperties": false, + "required": ["attempts", "cpu_time_seconds", "storage_bytes_written", "output_bytes", "log_bytes", "process_starts", "network_egress_bytes", "network_requests"], + "properties": {"attempts": {"$ref": "#/$defs/u63"}, "cpu_time_seconds": {"$ref": "#/$defs/u63"}, "storage_bytes_written": {"$ref": "#/$defs/u63"}, "output_bytes": {"$ref": "#/$defs/u63"}, "log_bytes": {"$ref": "#/$defs/u63"}, "process_starts": {"$ref": "#/$defs/u63"}, "network_egress_bytes": {"$ref": "#/$defs/u63"}, "network_requests": {"$ref": "#/$defs/u63"}} + }, + "storage_root_binding": { + "type": "object", "additionalProperties": false, + "required": ["root_kind", "job_id", "attempt_id", "storage_root_manifest_id", "storage_root_manifest_sigil", "reference_set_id", "reference_set_sigil", "hold_id", "hold_set_event"], + "properties": { + "root_kind": {"enum": ["JOB_INPUT", "ATTEMPT_INPUT", "ATTEMPT_OUTPUT"]}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, {"type": "null"}]}, + "storage_root_manifest_id": {"$ref": "https://benchwork.dev/schemas/execution-storage-root-manifest/1.0#/$defs/manifestId"}, + "storage_root_manifest_sigil": {"$ref": "#/$defs/sigil"}, + "reference_set_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-reference-set/1.0#/$defs/referenceSetId"}, + "reference_set_sigil": {"$ref": "#/$defs/sigil"}, + "hold_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-reference-set/1.0#/$defs/holdId"}, + "hold_set_event": {"$ref": "#/$defs/event_ref"} + }, + "allOf": [ + {"if": {"properties": {"root_kind": {"const": "JOB_INPUT"}}}, "then": {"properties": {"attempt_id": {"type": "null"}}}}, + {"if": {"properties": {"root_kind": {"enum": ["ATTEMPT_INPUT", "ATTEMPT_OUTPUT"]}}}, "then": {"properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}}}} + ] + }, + "completion_anchor_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NOT_ESTABLISHED"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "event_id", "event_sigil", "sequence", "result_sigil"], "properties": {"kind": {"const": "RESULT_ACCEPTED"}, "event_id": {"$ref": "#/$defs/event_id"}, "event_sigil": {"$ref": "#/$defs/sigil"}, "sequence": {"$ref": "#/$defs/positive_u63"}, "result_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "event_id", "event_sigil", "sequence", "process_exit_observation_sigil"], "properties": {"kind": {"const": "NO_RESULT"}, "event_id": {"$ref": "#/$defs/event_id"}, "event_sigil": {"$ref": "#/$defs/sigil"}, "sequence": {"$ref": "#/$defs/positive_u63"}, "process_exit_observation_sigil": {"$ref": "#/$defs/sigil"}}} + ] + }, + "worker_session_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "worker_id", "worker_binding_sigil", "worker_session_id", "worker_session_binding_sigil"], "properties": {"kind": {"const": "BOUND"}, "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}}} + ] + }, + "first_stop_or_fence_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "event_id", "event_type", "event_sigil", "effective_sequence"], "properties": {"kind": {"const": "PRESENT"}, "event_id": {"$ref": "#/$defs/event_id"}, "event_type": {"$ref": "#/$defs/event_type"}, "event_sigil": {"$ref": "#/$defs/sigil"}, "effective_sequence": {"$ref": "#/$defs/positive_u63"}}} + ] + }, + "storage_observation_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NOT_APPLICABLE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "storage_journal_id", "through_sequence", "through_event_sigil", "output_storage_observation_set_id", "output_storage_observation_set_sigil"], "properties": {"kind": {"const": "FROZEN"}, "storage_journal_id": {"type": "string", "pattern": "^SJ-[A-Z0-9]+$"}, "through_sequence": {"$ref": "#/$defs/positive_u63"}, "through_event_sigil": {"$ref": "#/$defs/sigil"}, "output_storage_observation_set_id": {"$ref": "#/$defs/opaque_id"}, "output_storage_observation_set_sigil": {"$ref": "#/$defs/sigil"}}}, + {"$ref": "#/$defs/capacity_failed_binding"} + ] + }, + "selected_attempt_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "attempt_id", "attempt_binding_sigil", "attempt_terminal_event_id", "attempt_terminal_event_sigil", "attempt_authorization_state", "worker_session_binding", "result_binding", "completion_anchor_binding", "first_stop_or_fence_binding", "storage_observation_binding"], "properties": {"kind": {"const": "SELECTED"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, "attempt_terminal_event_id": {"$ref": "#/$defs/event_id"}, "attempt_terminal_event_sigil": {"$ref": "#/$defs/sigil"}, "attempt_authorization_state": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/attempt_authorization_state"}, "worker_session_binding": {"$ref": "#/$defs/worker_session_binding"}, "result_binding": {"$ref": "#/$defs/result_binding"}, "completion_anchor_binding": {"$ref": "#/$defs/completion_anchor_binding"}, "first_stop_or_fence_binding": {"$ref": "#/$defs/first_stop_or_fence_binding"}, "storage_observation_binding": {"$ref": "#/$defs/storage_observation_binding"}}} + ] + }, + "attempt_terminal_evidence": { + "type": "object", "additionalProperties": false, + "required": ["transition_cause", "computation_status", "worker_status", "process_termination_status", "handle_revocation_status", "cleanup_status", "mutable_resource_isolation_status", "output_publication_status", "quarantine_status", "termination_evidence_sigil", "handle_disposition_evidence_sigil", "cleanup_summary_sigil", "quarantine_evidence_sigil", "log_closure_sigil", "output_closure_sigil", "result_binding", "attempt_authorization_state", "completion_anchor_binding", "worker_session_binding", "lease_terminal_binding", "first_stop_or_fence_binding", "storage_observation_binding", "accounting_capture_event_id", "accounting_capture_event_sigil", "control_evidence_set_binding", "quarantine_binding_set_binding", "terminalization_storage_manifest_binding", "output_root_protection", "assurance_input_set_sigil", "terminal_source_binding"], + "properties": { + "transition_cause": {"$ref": "#/$defs/transition_cause"}, + "computation_status": {"$ref": "#/$defs/computation_status"}, "worker_status": {"$ref": "#/$defs/worker_status"}, + "process_termination_status": {"$ref": "#/$defs/process_termination_status"}, "handle_revocation_status": {"$ref": "#/$defs/handle_revocation_status"}, + "cleanup_status": {"$ref": "#/$defs/cleanup_status"}, "mutable_resource_isolation_status": {"$ref": "#/$defs/mutable_resource_isolation_status"}, + "output_publication_status": {"$ref": "#/$defs/output_publication_status"}, "quarantine_status": {"$ref": "#/$defs/quarantine_status"}, + "termination_evidence_sigil": {"$ref": "#/$defs/sigil"}, "handle_disposition_evidence_sigil": {"$ref": "#/$defs/sigil"}, + "cleanup_summary_sigil": {"$ref": "#/$defs/sigil"}, "quarantine_evidence_sigil": {"$ref": "#/$defs/sigil"}, + "log_closure_sigil": {"$ref": "#/$defs/sigil"}, "output_closure_sigil": {"$ref": "#/$defs/sigil"}, + "result_binding": {"$ref": "#/$defs/result_binding"}, "attempt_authorization_state": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/attempt_authorization_state"}, + "completion_anchor_binding": {"$ref": "#/$defs/completion_anchor_binding"}, "worker_session_binding": {"$ref": "#/$defs/worker_session_binding"}, + "lease_terminal_binding": {"$ref": "#/$defs/lease_terminal_binding"}, "first_stop_or_fence_binding": {"$ref": "#/$defs/first_stop_or_fence_binding"}, + "storage_observation_binding": {"$ref": "#/$defs/storage_observation_binding"}, "accounting_capture_event_id": {"$ref": "#/$defs/event_id"}, + "accounting_capture_event_sigil": {"$ref": "#/$defs/sigil"}, "control_evidence_set_binding": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence-set/1.0#/$defs/controlEvidenceSetBinding"}, + "quarantine_binding_set_binding": {"$ref": "https://benchwork.dev/schemas/execution-quarantine-binding-set/1.0#/$defs/quarantineBindingSetBinding"}, + "terminalization_storage_manifest_binding": {"$ref": "#/$defs/terminalization_storage_manifest_binding"}, "output_root_protection": {"$ref": "#/$defs/output_root_protection"}, + "assurance_input_set_sigil": {"$ref": "#/$defs/sigil"}, "terminal_source_binding": {"$ref": "#/$defs/terminal_source_binding"} + } + }, + "attempt_summary": { + "type": "object", "additionalProperties": false, + "required": ["attempt_id", "attempt_binding_sigil", "retry_ordinal", "terminal_state", "terminal_event_id", "terminal_event_sigil", "worker_session_binding", "attempt_authorization_requirement", "attempt_authorization_state", "budget_settlement_event_sigil", "assurance_evaluation_event_sigil"], + "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, "retry_ordinal": {"$ref": "#/$defs/u63"}, "terminal_state": {"enum": ["SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATION", "LEASE_EXPIRED", "LOST", "FENCED", "REJECTED"]}, "terminal_event_id": {"$ref": "#/$defs/event_id"}, "terminal_event_sigil": {"$ref": "#/$defs/sigil"}, "worker_session_binding": {"$ref": "#/$defs/worker_session_binding"}, "attempt_authorization_requirement": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptAuthorizationRequirement"}, "attempt_authorization_state": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/attempt_authorization_state"}, "budget_settlement_event_sigil": {"$ref": "#/$defs/sigil"}, "assurance_evaluation_event_sigil": {"$ref": "#/$defs/sigil"}} + }, + "lease_terminal_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "lease_id", "lease_state", "terminal_event_id", "terminal_event_sigil", "final_fence_floor", "tombstone_event_sigil"], "properties": {"kind": {"const": "TERMINAL"}, "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, "lease_state": {"enum": ["RELEASED", "REVOKED", "EXPIRED", "FENCED"]}, "terminal_event_id": {"$ref": "#/$defs/event_id"}, "terminal_event_sigil": {"$ref": "#/$defs/sigil"}, "final_fence_floor": {"$ref": "#/$defs/u64"}, "tombstone_event_sigil": {"$ref": "#/$defs/sigil"}}} + ] + }, + "final_fence_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind", "final_fence_floor"], "properties": {"kind": {"const": "NO_ATTEMPT"}, "final_fence_floor": {"const": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "final_fence_floor", "attempt_id", "attempt_terminal_event_sigil"], "properties": {"kind": {"const": "ASSIGNED_NO_LEASE"}, "final_fence_floor": {"$ref": "#/$defs/u64"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "attempt_terminal_event_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "final_fence_floor", "lease_id", "lease_terminal_event_sigil", "tombstone_event_sigil"], "properties": {"kind": {"const": "TOMBSTONE"}, "final_fence_floor": {"$ref": "#/$defs/u64"}, "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, "lease_terminal_event_sigil": {"$ref": "#/$defs/sigil"}, "tombstone_event_sigil": {"$ref": "#/$defs/sigil"}}} + ] + }, + "capacity_failed_binding": { + "type": "object", "additionalProperties": false, + "required": ["kind", "capacity_failure_id", "capacity_failure_sigil"], + "properties": {"kind": {"const": "CAPACITY_FAILED"}, "capacity_failure_id": {"type": "string", "pattern": "^ECF-[0-9A-F]{64}$"}, "capacity_failure_sigil": {"$ref": "#/$defs/sigil"}} + }, + "terminalization_storage_manifest_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "PENDING"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "storage_root_manifest_id", "storage_root_manifest_sigil"], "properties": {"kind": {"const": "FROZEN"}, "storage_root_manifest_id": {"$ref": "https://benchwork.dev/schemas/execution-storage-root-manifest/1.0#/$defs/manifestId"}, "storage_root_manifest_sigil": {"$ref": "#/$defs/sigil"}}}, + {"$ref": "#/$defs/capacity_failed_binding"} + ] + }, + "output_root_protection": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "PENDING"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "terminalization_storage_manifest_binding"], "properties": {"kind": {"const": "NO_HOLD"}, "terminalization_storage_manifest_binding": {"$ref": "#/$defs/terminalization_storage_manifest_binding"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "terminalization_storage_manifest_binding", "storage_root_binding"], "properties": {"kind": {"const": "HELD"}, "terminalization_storage_manifest_binding": {"$ref": "#/$defs/terminalization_storage_manifest_binding"}, "storage_root_binding": {"$ref": "#/$defs/storage_root_binding"}}}, + {"$ref": "#/$defs/capacity_failed_binding"} + ] + }, + "output_hold_release_schedule": { + "type": "object", "additionalProperties": false, + "required": ["attempt_id", "storage_root_manifest_id", "storage_root_manifest_sigil", "reference_set_id", "reference_set_sigil", "hold_id", "hold_set_event", "retention_duration_seconds", "root_inactivation_event_id", "release_due_at", "deadline_status"], + "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "storage_root_manifest_id": {"$ref": "https://benchwork.dev/schemas/execution-storage-root-manifest/1.0#/$defs/manifestId"}, "storage_root_manifest_sigil": {"$ref": "#/$defs/sigil"}, "reference_set_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-reference-set/1.0#/$defs/referenceSetId"}, "reference_set_sigil": {"$ref": "#/$defs/sigil"}, "hold_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-reference-set/1.0#/$defs/holdId"}, "hold_set_event": {"$ref": "#/$defs/event_ref"}, "retention_duration_seconds": {"$ref": "#/$defs/u63"}, "root_inactivation_event_id": {"$ref": "#/$defs/event_id"}, "release_due_at": {"$ref": "#/$defs/timestamp"}, "deadline_status": {"enum": ["EXACT", "OVERFLOW_FAIL_CLOSED"]}} + }, + "storage_cut_binding": {"type": "object", "additionalProperties": false, "required": ["schema_version", "storage_cut_id", "storage_cut_sigil"], "properties": {"schema_version": {"const": "execution-terminalization-storage-cut/1.0"}, "storage_cut_id": {"type": "string", "pattern": "^ESC-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, "storage_cut_sigil": {"$ref": "#/$defs/sigil"}}}, + "opaque_id": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._:+-]{0,127}$", "minLength": 1, "maxLength": 128}, + "result_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "result_sigil", "disposition_event_id", "disposition_event_sigil", "disposition_sequence"], "properties": {"kind": {"const": "ACCEPTED"}, "result_sigil": {"$ref": "#/$defs/sigil"}, "disposition_event_id": {"$ref": "#/$defs/event_id"}, "disposition_event_sigil": {"$ref": "#/$defs/sigil"}, "disposition_sequence": {"$ref": "#/$defs/positive_u63"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "message_sigil", "disposition_event_id", "disposition_event_sigil", "disposition_sequence", "reason_codes"], "properties": {"kind": {"const": "REJECTED"}, "message_sigil": {"$ref": "#/$defs/sigil"}, "disposition_event_id": {"$ref": "#/$defs/event_id"}, "disposition_event_sigil": {"$ref": "#/$defs/sigil"}, "disposition_sequence": {"$ref": "#/$defs/positive_u63"}, "reason_codes": {"type": "array", "minItems": 1, "maxItems": 4096, "uniqueItems": true, "items": {"type": "string"}}}} + ] + }, + "terminal_source_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NOT_APPLICABLE"}}}, + {"$ref": "#/$defs/verified_terminal_source_binding"}, + {"$ref": "#/$defs/quarantined_terminal_source_binding"} + ] + }, + "verified_terminal_source_binding": { + "type": "object", "additionalProperties": false, + "required": ["kind", "crucible_base_identity", "crucible_base_sigil", "terminal_source_identity", "terminal_source_sigil", "storage_blob", "retention_policy_sigil", "file_count", "byte_count", "storage_status", "verifier_evidence_sigil"], + "properties": {"kind": {"const": "VERIFIED"}, "crucible_base_identity": {"type": "string", "minLength": 1, "maxLength": 128}, "crucible_base_sigil": {"$ref": "#/$defs/sigil"}, "terminal_source_identity": {"$ref": "https://benchwork.dev/schemas/benchwork-source-tree/1.0#/$defs/sourceTreeId"}, "terminal_source_sigil": {"$ref": "#/$defs/sigil"}, "storage_blob": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}, "retention_policy_sigil": {"$ref": "#/$defs/sigil"}, "file_count": {"$ref": "#/$defs/u63"}, "byte_count": {"$ref": "#/$defs/u63"}, "storage_status": {"const": "DURABLE_VERIFIED"}, "verifier_evidence_sigil": {"$ref": "#/$defs/sigil"}} + }, + "quarantined_terminal_source_binding": { + "type": "object", "additionalProperties": false, + "required": ["kind", "crucible_base_identity", "crucible_base_sigil", "terminal_source_identity", "terminal_source_sigil", "storage_blob", "retention_policy_sigil", "file_count", "byte_count", "storage_status", "verifier_evidence_sigil", "reason_codes"], + "properties": {"kind": {"const": "QUARANTINED"}, "crucible_base_identity": {"type": "string", "minLength": 1, "maxLength": 128}, "crucible_base_sigil": {"$ref": "#/$defs/sigil"}, "terminal_source_identity": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/benchwork-source-tree/1.0#/$defs/sourceTreeId"}, {"type": "null"}]}, "terminal_source_sigil": {"oneOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "storage_blob": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}, {"type": "null"}]}, "retention_policy_sigil": {"$ref": "#/$defs/sigil"}, "file_count": {"$ref": "#/$defs/u63"}, "byte_count": {"$ref": "#/$defs/u63"}, "storage_status": {"const": "QUARANTINED"}, "verifier_evidence_sigil": {"$ref": "#/$defs/sigil"}, "reason_codes": {"type": "array", "minItems": 1, "maxItems": 10, "uniqueItems": true, "items": {"enum": ["BASE_BINDING_INVALID", "SOURCE_ABSENT", "SOURCE_PARTIAL", "SOURCE_MUTABLE", "SOURCE_IDENTITY_MISMATCH", "FILE_LIMIT_EXCEEDED", "BYTE_LIMIT_EXCEEDED", "STORAGE_UNVERIFIED", "RETENTION_POLICY_MISMATCH", "VERIFIER_UNAVAILABLE"]}}} + }, + "computation_status": {"enum": ["NOT_STARTED", "COMPLETED", "FAILED", "UNKNOWN"]}, + "worker_status": {"enum": ["NOT_REPORTED", "COMPLETED", "FAILED", "CANCELLED", "TIMED_OUT", "LOST"]}, + "process_termination_status": {"enum": ["NOT_STARTED", "EXITED", "TERMINATED", "QUARANTINED", "UNVERIFIABLE"]}, + "handle_revocation_status": {"enum": ["NOT_APPLICABLE", "REVOKED", "FENCED", "QUARANTINED", "UNVERIFIABLE"]}, + "cleanup_status": {"enum": ["NOT_APPLICABLE", "VERIFIED", "PARTIAL", "FAILED", "QUARANTINED"]}, + "mutable_resource_isolation_status": {"enum": ["NOT_APPLICABLE", "VERIFIED_ISOLATED", "QUARANTINED", "UNVERIFIED"]}, + "output_publication_status": {"enum": ["NOT_APPLICABLE", "VERIFIED", "QUARANTINED", "FAILED"]}, + "quarantine_status": {"enum": ["NOT_REQUIRED", "COMPLETE", "PARTIAL", "FAILED"]} + } +} diff --git a/schemas/execution-journal-head-1.0.json b/schemas/execution-journal-head-1.0.json new file mode 100644 index 0000000..862fc73 --- /dev/null +++ b/schemas/execution-journal-head-1.0.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-journal-head/1.0", + "title": "Execution Journal Head v1", + "description": "Closed RFC-0012 execution-journal-head/1.0 cache record. Exact event-prefix and replay validation are outside this contract-only Schema.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "limit_profile", "journal_id", "last_sequence", "last_event_id", "last_event_sigil", "updated_at", "head_sigil"], + "properties": { + "schema_version": {"const": "execution-journal-head/1.0"}, + "limit_profile": {"const": "EXECUTION_JOURNAL_V1_FIXED_LIMITS"}, + "journal_id": {"$ref": "#/$defs/journalId"}, + "last_sequence": {"$ref": "#/$defs/positiveU63"}, + "last_event_id": {"$ref": "#/$defs/eventId"}, + "last_event_sigil": {"$ref": "#/$defs/sigil"}, + "updated_at": {"$ref": "#/$defs/timestamp"}, + "head_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "journalId": {"type": "string", "pattern": "^EJ-[A-Z0-9]+$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "eventId": {"type": "string", "pattern": "^JE-[A-Z0-9]+$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27} + } +} + diff --git a/schemas/execution-lease-1.0.json b/schemas/execution-lease-1.0.json new file mode 100644 index 0000000..625a31b --- /dev/null +++ b/schemas/execution-lease-1.0.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-lease/1.0", + "title": "Execution Lease v1", + "description": "Closed RFC-0012 immutable Lease offer. Parent Worker, Session, Specification, and durable allocation-slot conformance require semantic resolvers.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "lease_id", "job_id", "attempt_id", "worker_id", "worker_binding_sigil", "worker_session_id", "worker_session_binding_sigil", "executor_instance_id", "executor_epoch", "fencing_generation", "offered_at", "claim_due_at", "initial_expiry_due_at", "maximum_expiry_due_at", "heartbeat_policy", "lease_credential_digest", "lease_binding_sigil"], + "properties": { + "schema_version": {"const": "execution-lease/1.0"}, + "lease_id": {"$ref": "#/$defs/leaseId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_instance_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/executorInstanceId"}, + "executor_epoch": {"$ref": "#/$defs/u64"}, + "fencing_generation": {"$ref": "#/$defs/u64"}, + "offered_at": {"$ref": "#/$defs/timestamp"}, + "claim_due_at": {"$ref": "#/$defs/timestamp"}, + "initial_expiry_due_at": {"$ref": "#/$defs/timestamp"}, + "maximum_expiry_due_at": {"$ref": "#/$defs/timestamp"}, + "heartbeat_policy": {"$ref": "#/$defs/heartbeatPolicy"}, + "lease_credential_digest": {"$ref": "#/$defs/sigil"}, + "lease_binding_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "positiveU63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "leaseId": {"type": "string", "pattern": "^LS-[0-7][0-9A-HJKMNP-TV-Z]{25}$", "not": {"pattern": "[\\r\\n]"}, "minLength": 29, "maxLength": 29}, + "heartbeatPolicy": { + "type": "object", + "additionalProperties": false, + "required": ["heartbeat_interval_seconds", "heartbeat_timeout_seconds"], + "properties": { + "heartbeat_interval_seconds": {"$ref": "#/$defs/positiveU63"}, + "heartbeat_timeout_seconds": {"$ref": "#/$defs/positiveU63"} + } + } + } +} + diff --git a/schemas/execution-log-chunk-1.0.json b/schemas/execution-log-chunk-1.0.json new file mode 100644 index 0000000..0696704 --- /dev/null +++ b/schemas/execution-log-chunk-1.0.json @@ -0,0 +1,110 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-log-chunk/1.0", + "title": "Execution Log Chunk v1", + "description": "Closed RFC-0012 L1-L12 immutable accepted-byte record. Shape and pure local validation do not authorize capture, resolve live ownership, establish sequence eligibility, consume an ingress key, append a Journal Event, acknowledge a request, or grant storage, assurance, Artifact, Run, or scientific authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "chunk_id", + "log_stream_id", + "job_id", + "attempt_id", + "lease_id", + "worker_id", + "worker_session_id", + "executor_epoch", + "attempt_binding_sigil", + "lease_binding_sigil", + "worker_session_binding_sigil", + "fence_tuple", + "stream", + "sequence", + "byte_length", + "media_type", + "encoding", + "blob_sigil", + "staging_reference", + "observed_at", + "received_at", + "split_utf8_boundary", + "split_line", + "chunk_record_sigil" + ], + "properties": { + "schema_version": {"const": "execution-log-chunk/1.0"}, + "chunk_id": {"$ref": "#/$defs/chunk_id"}, + "log_stream_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/logStreamId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "executor_epoch": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/u64"}, + "attempt_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "lease_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "worker_session_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "fence_tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"}, + "stream": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, + "sequence": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "byte_length": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, + "media_type": {"enum": ["application/octet-stream", "application/x-ndjson"]}, + "encoding": {"enum": ["BINARY", "UTF-8"]}, + "blob_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "staging_reference": {"$ref": "#/$defs/staging_reference"}, + "observed_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "received_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "split_utf8_boundary": {"type": "boolean"}, + "split_line": {"type": "boolean"}, + "chunk_record_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + }, + "$defs": { + "chunk_id": { + "type": "string", + "pattern": "^LC-[A-Z0-9]+$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 4, + "maxLength": 128 + }, + "staging_record_id": { + "type": "string", + "pattern": "^LSR-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "staging_reference": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "staging_record_id", "staging_record_sigil"], + "properties": { + "kind": {"const": "EXECUTION_LOG_SPOOL_RECORD"}, + "staging_record_id": {"$ref": "#/$defs/staging_record_id"}, + "staging_record_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + } + }, + "allOf": [ + { + "if": {"properties": {"stream": {"enum": ["STDOUT", "STDERR"]}}}, + "then": { + "properties": { + "media_type": {"const": "application/octet-stream"}, + "encoding": {"const": "BINARY"}, + "split_utf8_boundary": {"const": false}, + "split_line": {"const": false} + } + } + }, + { + "if": {"properties": {"stream": {"const": "STRUCTURED"}}}, + "then": { + "properties": { + "media_type": {"const": "application/x-ndjson"}, + "encoding": {"const": "UTF-8"} + } + } + } + ] +} + diff --git a/schemas/execution-log-staging-record-1.0.json b/schemas/execution-log-staging-record-1.0.json new file mode 100644 index 0000000..592797e --- /dev/null +++ b/schemas/execution-log-staging-record-1.0.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-log-staging-record/1.0", + "title": "Execution Log Staging Record", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "staging_record_id", + "journal_id", + "job_id", + "attempt_id", + "log_stream_id", + "stream", + "sequence", + "byte_length", + "blob_sigil", + "spool_object_generation", + "stored_at", + "staging_record_sigil" + ], + "properties": { + "schema_version": {"const": "execution-log-staging-record/1.0"}, + "staging_record_id": {"$ref": "#/$defs/stagingRecordId"}, + "journal_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/journal_id"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "log_stream_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/logStreamId"}, + "stream": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, + "sequence": {"$ref": "#/$defs/u63"}, + "byte_length": {"$ref": "#/$defs/positiveU63"}, + "blob_sigil": {"$ref": "#/$defs/sigil"}, + "spool_object_generation": {"$ref": "#/$defs/positiveU63"}, + "stored_at": {"$ref": "#/$defs/timestamp"}, + "staging_record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "stagingRecordId": { + "type": "string", + "pattern": "^LSR-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$", + "minLength": 71, + "maxLength": 71 + }, + "u63": { + "type": "integer", + "minimum": 0, + "maximum": 9223372036854775807 + }, + "positiveU63": { + "type": "integer", + "minimum": 1, + "maximum": 9223372036854775807 + }, + "timestamp": { + "type": "string", + "format": "date-time", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", + "minLength": 20, + "maxLength": 27 + } + } +} + diff --git a/schemas/execution-observation-1.0.json b/schemas/execution-observation-1.0.json new file mode 100644 index 0000000..cf2d92c --- /dev/null +++ b/schemas/execution-observation-1.0.json @@ -0,0 +1,547 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-observation/1.0", + "title": "Execution Observation", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "job_binding", + "task_binding", + "capability_binding", + "snapshot_binding", + "execution_specification_binding", + "job_state", + "job_revision", + "attempts", + "worker_sessions", + "lease_binding", + "public_fence_binding", + "assurance", + "cancellation", + "terminal", + "cleanup", + "quarantine", + "events", + "logs", + "through_journal_sequence", + "through_event_sigil", + "next_cursor", + "next_actions" + ], + "properties": { + "schema_version": {"const": "execution-observation/1.0"}, + "job_binding": {"$ref": "#/$defs/jobBinding"}, + "task_binding": {"$ref": "#/$defs/taskBinding"}, + "capability_binding": {"$ref": "#/$defs/capabilityBinding"}, + "snapshot_binding": {"$ref": "#/$defs/snapshotBinding"}, + "execution_specification_binding": {"$ref": "#/$defs/specificationBinding"}, + "job_state": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/job_state"}, + "job_revision": {"$ref": "#/$defs/u64"}, + "attempts": { + "type": "array", + "items": {"$ref": "#/$defs/observationAttempt"}, + "maxItems": 4096 + }, + "worker_sessions": { + "type": "array", + "items": {"$ref": "#/$defs/observationWorkerSession"}, + "maxItems": 4096 + }, + "lease_binding": {"$ref": "#/$defs/leaseView"}, + "public_fence_binding": {"$ref": "#/$defs/publicFenceView"}, + "assurance": {"$ref": "#/$defs/assuranceView"}, + "cancellation": {"$ref": "#/$defs/cancellationView"}, + "terminal": {"$ref": "#/$defs/terminalView"}, + "cleanup": {"$ref": "#/$defs/cleanupView"}, + "quarantine": { + "type": "array", + "items": {"$ref": "#/$defs/quarantineView"}, + "maxItems": 4096 + }, + "events": { + "type": "array", + "items": {"$ref": "#/$defs/observationEvent"}, + "maxItems": 256 + }, + "logs": { + "type": "array", + "items": {"$ref": "#/$defs/observationLog"}, + "maxItems": 3 + }, + "through_journal_sequence": {"$ref": "#/$defs/positiveU63"}, + "through_event_sigil": {"$ref": "#/$defs/sigil"}, + "next_cursor": { + "oneOf": [ + {"type": "null"}, + {"$ref": "#/$defs/observationCursor"} + ] + }, + "next_actions": { + "type": "array", + "items": {"$ref": "#/$defs/nextAction"}, + "maxItems": 6 + } + }, + "$defs": { + "sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$", + "minLength": 71, + "maxLength": 71 + }, + "opaque": { + "type": "string", + "not": {"pattern": "[\\u0000-\\u001F\\u007F-\\u009F]"}, + "minLength": 1, + "maxLength": 256 + }, + "u63": { + "type": "integer", + "minimum": 0, + "maximum": 9223372036854775807 + }, + "positiveU63": { + "type": "integer", + "minimum": 1, + "maximum": 9223372036854775807 + }, + "u64": { + "type": "integer", + "minimum": 0, + "maximum": 18446744073709551615 + }, + "timestamp": { + "type": "string", + "format": "date-time", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", + "minLength": 20, + "maxLength": 27 + }, + "jobBinding": { + "type": "object", + "additionalProperties": false, + "required": ["job_id", "job_binding_sigil"], + "properties": { + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "job_binding_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "taskBinding": { + "type": "object", + "additionalProperties": false, + "required": ["task_id", "task_capsule_sigil"], + "properties": { + "task_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/taskId"}, + "task_capsule_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "capabilityBinding": { + "type": "object", + "additionalProperties": false, + "required": ["capability_id", "contract_version", "capability_contract_sigil"], + "properties": { + "capability_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/capabilityId"}, + "contract_version": {"const": "2.0"}, + "capability_contract_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "snapshotBinding": { + "type": "object", + "additionalProperties": false, + "required": ["snapshot_id", "snapshot_sigil"], + "properties": { + "snapshot_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/snapshotId"}, + "snapshot_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "specificationBinding": { + "type": "object", + "additionalProperties": false, + "required": ["specification_id", "specification_sigil"], + "properties": { + "specification_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/specificationId"}, + "specification_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "observationCursor": { + "type": "object", + "additionalProperties": false, + "required": [ + "job_id", + "last_returned_sequence", + "through_journal_sequence", + "through_event_sigil", + "cursor_sigil" + ], + "properties": { + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "last_returned_sequence": {"$ref": "#/$defs/u63"}, + "through_journal_sequence": {"$ref": "#/$defs/positiveU63"}, + "through_event_sigil": {"$ref": "#/$defs/sigil"}, + "cursor_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "workerSessionBinding": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NONE"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "worker_id", + "worker_binding_sigil", + "worker_session_id", + "worker_session_binding_sigil" + ], + "properties": { + "kind": {"const": "BOUND"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"} + } + } + ] + }, + "leaseView": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NONE"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "lease_id", "state", "terminal_event_sigil"], + "properties": { + "kind": {"const": "PRESENT"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "state": {"enum": ["OFFERED", "ACTIVE"]}, + "terminal_event_sigil": {"type": "null"} + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "lease_id", "state", "terminal_event_sigil"], + "properties": { + "kind": {"const": "PRESENT"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "state": {"enum": ["RELEASED", "REVOKED", "EXPIRED", "FENCED"]}, + "terminal_event_sigil": {"$ref": "#/$defs/sigil"} + } + } + ] + }, + "publicFenceView": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NONE"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "tuple", "final_fence_floor", "tombstone_present"], + "properties": { + "kind": {"const": "PRESENT"}, + "tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"}, + "final_fence_floor": {"$ref": "#/$defs/u64"}, + "tombstone_present": {"type": "boolean"} + } + } + ] + }, + "assuranceView": { + "type": "object", + "additionalProperties": false, + "required": [ + "requested_level", + "profile_version", + "profile_sigil", + "conformance_suite_id", + "conformance_suite_sigil", + "attempt_binding", + "job_binding" + ], + "properties": { + "requested_level": {"enum": ["SANCTUM-A0", "SANCTUM-A1", "SANCTUM-A2"]}, + "profile_version": {"$ref": "#/$defs/opaque"}, + "profile_sigil": {"$ref": "#/$defs/sigil"}, + "conformance_suite_id": {"$ref": "#/$defs/opaque"}, + "conformance_suite_sigil": {"$ref": "#/$defs/sigil"}, + "attempt_binding": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NONE"}} + }, + {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/attempt_assurance_binding"} + ] + }, + "job_binding": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/job_assurance_binding"} + } + }, + "cancellationView": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NONE"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "cancellation_request_id", "request_event_id", "request_event_sigil", "reason"], + "properties": { + "kind": {"const": "REQUESTED"}, + "cancellation_request_id": {"$ref": "#/$defs/opaque"}, + "request_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "request_event_sigil": {"$ref": "#/$defs/sigil"}, + "reason": {"$ref": "#/$defs/opaque"} + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "cancellation_request_id", "observation_event_id", "observation_event_sigil", "reason"], + "properties": { + "kind": {"const": "OBSERVED_TERMINAL"}, + "cancellation_request_id": {"$ref": "#/$defs/opaque"}, + "observation_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "observation_event_sigil": {"$ref": "#/$defs/sigil"}, + "reason": {"$ref": "#/$defs/opaque"} + } + } + ] + }, + "terminalView": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NONTERMINAL"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "state", "event_id", "sequence", "event_sigil", "recorded_at"], + "properties": { + "kind": {"const": "TERMINAL"}, + "state": {"enum": ["SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATION"]}, + "event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "sequence": {"$ref": "#/$defs/positiveU63"}, + "event_sigil": {"$ref": "#/$defs/sigil"}, + "recorded_at": {"$ref": "#/$defs/timestamp"} + } + } + ] + }, + "attemptTerminalView": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NONTERMINAL"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "state", "event_id", "sequence", "event_sigil", "recorded_at"], + "properties": { + "kind": {"const": "TERMINAL"}, + "state": {"enum": ["SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATION", "LEASE_EXPIRED", "LOST", "FENCED", "REJECTED"]}, + "event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "sequence": {"$ref": "#/$defs/positiveU63"}, + "event_sigil": {"$ref": "#/$defs/sigil"}, + "recorded_at": {"$ref": "#/$defs/timestamp"} + } + } + ] + }, + "cleanupView": { + "type": "object", + "additionalProperties": false, + "required": [ + "termination_status", + "handle_status", + "cleanup_status", + "mutable_resource_isolation_status", + "output_publication_status", + "quarantine_status", + "termination_evidence_sigil", + "handle_disposition_evidence_sigil", + "cleanup_summary_sigil" + ], + "properties": { + "termination_status": {"enum": ["NOT_STARTED", "EXITED", "TERMINATED", "QUARANTINED", "UNVERIFIABLE"]}, + "handle_status": {"enum": ["NOT_APPLICABLE", "REVOKED", "FENCED", "QUARANTINED", "UNVERIFIABLE"]}, + "cleanup_status": {"enum": ["NOT_APPLICABLE", "VERIFIED", "PARTIAL", "FAILED", "QUARANTINED"]}, + "mutable_resource_isolation_status": {"enum": ["NOT_APPLICABLE", "VERIFIED_ISOLATED", "QUARANTINED", "UNVERIFIED"]}, + "output_publication_status": {"enum": ["NOT_APPLICABLE", "VERIFIED", "QUARANTINED", "FAILED"]}, + "quarantine_status": {"enum": ["NOT_REQUIRED", "COMPLETE", "PARTIAL", "FAILED"]}, + "termination_evidence_sigil": {"$ref": "#/$defs/nullableSigil"}, + "handle_disposition_evidence_sigil": {"$ref": "#/$defs/nullableSigil"}, + "cleanup_summary_sigil": {"$ref": "#/$defs/nullableSigil"} + } + }, + "nullableSigil": { + "oneOf": [{"type": "null"}, {"$ref": "#/$defs/sigil"}] + }, + "quarantineView": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["subject_kind", "subject_id", "status", "evidence_sigil"], + "properties": { + "subject_kind": {"enum": ["ATTEMPT_OUTPUT", "LOG", "RESOURCE_EVIDENCE", "TERMINAL_SOURCE"]}, + "subject_id": {"$ref": "#/$defs/opaque"}, + "status": {"const": "NOT_REQUIRED"}, + "evidence_sigil": {"type": "null"} + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["subject_kind", "subject_id", "status", "evidence_sigil"], + "properties": { + "subject_kind": {"enum": ["ATTEMPT_OUTPUT", "LOG", "RESOURCE_EVIDENCE", "TERMINAL_SOURCE"]}, + "subject_id": {"$ref": "#/$defs/opaque"}, + "status": {"enum": ["COMPLETE", "PARTIAL", "FAILED"]}, + "evidence_sigil": {"$ref": "#/$defs/sigil"} + } + } + ] + }, + "observationAttempt": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "attempt_binding_sigil", + "retry_ordinal", + "state", + "revision", + "attempt_authorization_state", + "worker_session_binding", + "lease_binding", + "public_fence_binding", + "assurance", + "terminal", + "cleanup", + "quarantine" + ], + "properties": { + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "retry_ordinal": {"$ref": "#/$defs/positiveU63"}, + "state": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/attempt_state"}, + "revision": {"$ref": "#/$defs/u64"}, + "attempt_authorization_state": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/attempt_authorization_state"}, + "worker_session_binding": {"$ref": "#/$defs/workerSessionBinding"}, + "lease_binding": {"$ref": "#/$defs/leaseView"}, + "public_fence_binding": {"$ref": "#/$defs/publicFenceView"}, + "assurance": {"$ref": "#/$defs/assuranceView"}, + "terminal": {"$ref": "#/$defs/attemptTerminalView"}, + "cleanup": {"$ref": "#/$defs/cleanupView"}, + "quarantine": { + "type": "array", + "items": {"$ref": "#/$defs/quarantineView"}, + "maxItems": 4096 + } + } + }, + "observationWorkerSession": { + "type": "object", + "additionalProperties": false, + "required": ["worker_id", "worker_binding_sigil", "worker_session_id", "worker_session_binding_sigil", "state"], + "properties": { + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "state": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/worker_session_state"} + } + }, + "observationEvent": { + "type": "object", + "additionalProperties": false, + "required": ["sequence", "event_id", "event_type", "recorded_at", "related_entity_ids", "event_sigil"], + "properties": { + "sequence": {"$ref": "#/$defs/positiveU63"}, + "event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "event_type": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_type"}, + "recorded_at": {"$ref": "#/$defs/timestamp"}, + "related_entity_ids": { + "type": "array", + "items": {"$ref": "#/$defs/opaque"}, + "uniqueItems": true, + "maxItems": 4096 + }, + "event_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "observationLog": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["stream_kind", "stream_id", "state", "captured_bytes", "dropped_bytes", "truncated", "blob_sigil", "closure_event_sigil"], + "properties": { + "stream_kind": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, + "stream_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/logStreamId"}, + "state": {"const": "OPEN"}, + "captured_bytes": {"$ref": "#/$defs/u63"}, + "dropped_bytes": {"$ref": "#/$defs/u63"}, + "truncated": {"type": "boolean"}, + "blob_sigil": {"type": "null"}, + "closure_event_sigil": {"type": "null"} + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["stream_kind", "stream_id", "state", "captured_bytes", "dropped_bytes", "truncated", "blob_sigil", "closure_event_sigil"], + "properties": { + "stream_kind": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, + "stream_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/logStreamId"}, + "state": {"const": "CLOSED"}, + "captured_bytes": {"$ref": "#/$defs/u63"}, + "dropped_bytes": {"$ref": "#/$defs/u63"}, + "truncated": {"type": "boolean"}, + "blob_sigil": {"$ref": "#/$defs/sigil"}, + "closure_event_sigil": {"$ref": "#/$defs/sigil"} + } + } + ] + }, + "nextAction": { + "type": "object", + "additionalProperties": false, + "required": ["action", "reason_code", "expected_job_revision"], + "properties": { + "action": {"enum": ["WAIT", "OBSERVE", "CANCEL", "GET_OUTCOME", "ACCEPT_OUTCOME", "INSPECT_FAILURE"]}, + "reason_code": {"enum": ["JOB_NONTERMINAL", "CANCELLABLE", "TERMINAL_OUTCOME_READY", "OUTCOME_ELIGIBLE", "OUTCOME_INELIGIBLE", "FAILURE_RECORDED"]}, + "expected_job_revision": {"$ref": "#/$defs/u64"} + } + } + } +} + diff --git a/schemas/execution-observation-evidence-1.0.json b/schemas/execution-observation-evidence-1.0.json new file mode 100644 index 0000000..f27bc54 --- /dev/null +++ b/schemas/execution-observation-evidence-1.0.json @@ -0,0 +1,92 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-observation-evidence/1.0", + "title": "Execution Observation Evidence v1", + "description": "Closed immutable RFC-0012 O1-O10 Result-facing observation decision. This contract does not establish acceptance, accounting completeness, assurance, or scientific truth.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "observation_evidence_id", "job_id", "job_binding_sigil", "attempt_id", "attempt_binding_sigil", "lease_id", "lease_binding_sigil", "worker_id", "worker_binding_sigil", "worker_session_id", "worker_session_binding_sigil", "executor_epoch", "fence_tuple", "result_observation_binding", "result_ingress_receipt_binding", "producer_evidence_binding", "verifier_evidence_binding", "evidence_profile_binding", "assessment", "created_at", "observation_evidence_sigil"], + "properties": { + "schema_version": {"const": "execution-observation-evidence/1.0"}, + "observation_evidence_id": {"$ref": "#/$defs/observation_evidence_id"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "job_binding_sigil": {"$ref": "#/$defs/sigil"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "lease_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_epoch": {"$ref": "#/$defs/u64"}, + "fence_tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"}, + "result_observation_binding": {"$ref": "#/$defs/result_observation_binding"}, + "result_ingress_receipt_binding": {"$ref": "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0#/$defs/result_ingress_receipt_binding"}, + "producer_evidence_binding": {"$ref": "#/$defs/raw_evidence_binding"}, + "verifier_evidence_binding": {"$ref": "#/$defs/raw_evidence_binding"}, + "evidence_profile_binding": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/evidenceProfileBinding"}, + "assessment": {"$ref": "#/$defs/assessment"}, + "created_at": {"$ref": "#/$defs/timestamp"}, + "observation_evidence_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "protocol_identifier": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._:+-]{0,127}$", "minLength": 1, "maxLength": 128}, + "observation_evidence_id": {"type": "string", "pattern": "^OVE-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "observation_owner_binding": { + "type": "object", "additionalProperties": false, + "required": ["job_id", "job_binding_sigil", "attempt_id", "attempt_binding_sigil", "lease_id", "lease_binding_sigil", "worker_id", "worker_binding_sigil", "worker_session_id", "worker_session_binding_sigil", "executor_epoch", "fence_tuple"], + "properties": {"job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "job_binding_sigil": {"$ref": "#/$defs/sigil"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, "lease_binding_sigil": {"$ref": "#/$defs/sigil"}, "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, "executor_epoch": {"$ref": "#/$defs/u64"}, "fence_tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"}} + }, + "runtime_observation": { + "type": "object", "additionalProperties": false, + "required": ["started_at", "ended_at", "cpu_time_seconds", "peak_memory_bytes", "process_count"], + "properties": {"started_at": {"$ref": "#/$defs/timestamp"}, "ended_at": {"$ref": "#/$defs/timestamp"}, "cpu_time_seconds": {"$ref": "#/$defs/u63"}, "peak_memory_bytes": {"$ref": "#/$defs/u63"}, "process_count": {"$ref": "#/$defs/u63"}} + }, + "termination_observation": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind", "exit_code", "observed_at", "observation_source"], "properties": {"kind": {"const": "EXITED"}, "exit_code": {"$ref": "#/$defs/u63"}, "observed_at": {"$ref": "#/$defs/timestamp"}, "observation_source": {"$ref": "#/$defs/termination_observation_source"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "signal", "observed_at", "observation_source"], "properties": {"kind": {"const": "SIGNALED"}, "signal": {"type": "string", "pattern": "^[A-Z][A-Z0-9_]{0,63}$", "minLength": 1, "maxLength": 64}, "observed_at": {"$ref": "#/$defs/timestamp"}, "observation_source": {"$ref": "#/$defs/termination_observation_source"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "observed_at", "observation_source"], "properties": {"kind": {"const": "UNKNOWN"}, "observed_at": {"$ref": "#/$defs/timestamp"}, "observation_source": {"$ref": "#/$defs/termination_observation_source"}}} + ] + }, + "termination_observation_source": {"enum": ["WORKER", "EXECUTOR_SUPERVISOR", "ENFORCEMENT_BACKEND"]}, + "result_observation_binding": { + "type": "object", "additionalProperties": false, + "required": ["runtime_observation", "termination_observation", "observation_evidence_subject_sigil"], + "properties": {"runtime_observation": {"$ref": "#/$defs/runtime_observation"}, "termination_observation": {"$ref": "#/$defs/termination_observation"}, "observation_evidence_subject_sigil": {"$ref": "#/$defs/sigil"}} + }, + "raw_evidence_binding": { + "type": "object", "additionalProperties": false, + "required": ["raw_evidence_id", "raw_evidence_record_sigil"], + "properties": {"raw_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/observationRawEvidenceId"}, "raw_evidence_record_sigil": {"$ref": "#/$defs/sigil"}} + }, + "observation_evidence_disposition_binding": { + "type": "object", "additionalProperties": false, + "required": ["result_ingress_receipt_binding", "observation_evidence_subject_sigil", "observation_evidence_id", "observation_evidence_sigil"], + "properties": {"result_ingress_receipt_binding": {"$ref": "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0#/$defs/result_ingress_receipt_binding"}, "observation_evidence_subject_sigil": {"$ref": "#/$defs/sigil"}, "observation_evidence_id": {"$ref": "#/$defs/observation_evidence_id"}, "observation_evidence_sigil": {"$ref": "#/$defs/sigil"}} + }, + "authenticated_observation_source": { + "type": "object", "additionalProperties": false, + "required": ["source_kind", "source_identity_id", "source_identity_sigil", "source_identity_profile_sigil", "source_channel_sigil", "source_channel_profile_sigil", "source_registry_id", "source_registry_version", "source_registry_snapshot_sigil"], + "properties": {"source_kind": {"$ref": "#/$defs/termination_observation_source"}, "source_identity_id": {"$ref": "#/$defs/protocol_identifier"}, "source_identity_sigil": {"$ref": "#/$defs/sigil"}, "source_identity_profile_sigil": {"$ref": "#/$defs/sigil"}, "source_channel_sigil": {"$ref": "#/$defs/sigil"}, "source_channel_profile_sigil": {"$ref": "#/$defs/sigil"}, "source_registry_id": {"$ref": "#/$defs/protocol_identifier"}, "source_registry_version": {"$ref": "#/$defs/protocol_identifier"}, "source_registry_snapshot_sigil": {"$ref": "#/$defs/sigil"}} + }, + "observation_field": {"enum": ["RUNTIME_STARTED_AT", "RUNTIME_ENDED_AT", "CPU_TIME_SECONDS", "PEAK_MEMORY_BYTES", "PROCESS_COUNT", "TERMINATION_KIND", "TERMINATION_EXIT_CODE", "TERMINATION_SIGNAL", "TERMINATION_OBSERVED_AT", "TERMINATION_OBSERVATION_SOURCE"]}, + "observation_reason": { + "type": "object", "additionalProperties": false, "required": ["field", "reason_code", "detail_sigil"], + "properties": {"field": {"$ref": "#/$defs/observation_field"}, "reason_code": {"enum": ["MISMATCH", "SOURCE_DATA_MISSING", "SOURCE_DATA_DECODE_FAILED", "SOURCE_AUTHENTICATION_UNAVAILABLE", "SOURCE_COUNTER_INVALID", "SOURCE_TIME_INVALID"]}, "detail_sigil": {"$ref": "#/$defs/sigil"}} + }, + "assessment": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind", "verified_runtime_observation", "verified_termination_observation", "verified_source_binding", "reason_bindings"], "properties": {"kind": {"const": "MATCHED"}, "verified_runtime_observation": {"$ref": "#/$defs/runtime_observation"}, "verified_termination_observation": {"$ref": "#/$defs/termination_observation"}, "verified_source_binding": {"$ref": "#/$defs/authenticated_observation_source"}, "reason_bindings": {"type": "array", "maxItems": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "verified_runtime_observation", "verified_termination_observation", "verified_source_binding", "reason_bindings"], "properties": {"kind": {"const": "MISMATCHED"}, "verified_runtime_observation": {"$ref": "#/$defs/runtime_observation"}, "verified_termination_observation": {"$ref": "#/$defs/termination_observation"}, "verified_source_binding": {"$ref": "#/$defs/authenticated_observation_source"}, "reason_bindings": {"type": "array", "minItems": 1, "maxItems": 4096, "items": {"$ref": "#/$defs/observation_reason"}, "uniqueItems": true}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "unavailable_fields", "reason_bindings"], "properties": {"kind": {"const": "UNAVAILABLE"}, "unavailable_fields": {"type": "array", "minItems": 1, "maxItems": 10, "items": {"$ref": "#/$defs/observation_field"}, "uniqueItems": true}, "reason_bindings": {"type": "array", "minItems": 1, "maxItems": 4096, "items": {"$ref": "#/$defs/observation_reason"}, "uniqueItems": true}}} + ] + } + } +} + diff --git a/schemas/execution-observation-evidence-profile-1.0.json b/schemas/execution-observation-evidence-profile-1.0.json new file mode 100644 index 0000000..335c6d8 --- /dev/null +++ b/schemas/execution-observation-evidence-profile-1.0.json @@ -0,0 +1,342 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-observation-evidence-profile/1.0", + "title": "Execution Observation Evidence Profile v1", + "description": "Closed RFC-0012 O8 structural profile. Contract-only validation does not install or execute a decoder, read raw evidence, authenticate an issuer or source, resolve a registry or implementation, establish counter semantics or independence, validate the evidence-graph time matrix, append a Journal Event, or grant evidence authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "evidence_profile_id", + "evidence_profile_version", + "subject_kind", + "producer_implementations", + "verifier_implementations", + "allowed_role_pairs", + "decoder_profiles", + "raw_media_profiles", + "authentication_profiles", + "source_authentication_profiles", + "process_identity_profile_sigil", + "cpu_clock_profile_sigil", + "memory_observation_profile_sigil", + "independence_profile_sigil", + "maximum_raw_payload_bytes", + "profile_sigil" + ], + "properties": { + "schema_version": {"const": "execution-observation-evidence-profile/1.0"}, + "evidence_profile_id": {"$ref": "#/$defs/protocolIdentifier"}, + "evidence_profile_version": {"$ref": "#/$defs/protocolIdentifier"}, + "subject_kind": {"const": "EXECUTION_OBSERVATION"}, + "producer_implementations": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "allOf": [ + {"$ref": "#/$defs/implementationEntry"}, + {"properties": {"role_kind": {"const": "WORKER_SESSION"}}} + ] + } + }, + "verifier_implementations": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "allOf": [ + {"$ref": "#/$defs/implementationEntry"}, + { + "properties": { + "role_kind": { + "enum": [ + "EXECUTOR_SUPERVISOR", + "ENFORCEMENT_BACKEND", + "HOST_VERIFIER", + "INDEPENDENT_BACKEND_VERIFIER" + ] + } + } + } + ] + } + }, + "allowed_role_pairs": {"$ref": "#/$defs/allowedRolePairArray"}, + "decoder_profiles": { + "type": "array", + "minItems": 2, + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "#/$defs/decoderProfile"}, + "allOf": [ + { + "contains": { + "type": "object", + "properties": {"role": {"const": "PRODUCER"}}, + "required": ["role"] + }, + "minContains": 1 + }, + { + "contains": { + "type": "object", + "properties": {"role": {"const": "VERIFIER"}}, + "required": ["role"] + }, + "minContains": 1 + } + ] + }, + "raw_media_profiles": {"$ref": "#/$defs/rawMediaProfileArray"}, + "authentication_profiles": {"$ref": "#/$defs/authenticationProfileArray"}, + "source_authentication_profiles": {"$ref": "#/$defs/sourceAuthenticationProfileArray"}, + "process_identity_profile_sigil": {"$ref": "#/$defs/sigil"}, + "cpu_clock_profile_sigil": {"$ref": "#/$defs/sigil"}, + "memory_observation_profile_sigil": {"$ref": "#/$defs/sigil"}, + "independence_profile_sigil": {"$ref": "#/$defs/sigil"}, + "maximum_raw_payload_bytes": {"$ref": "#/$defs/positiveU63"}, + "profile_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/sigil"}, + "positiveU63": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/positiveU63"}, + "protocolIdentifier": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/protocolIdentifier"}, + "evidenceMediaType": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/evidenceMediaType"}, + "roleKind": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/roleKind"}, + "authorityKind": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/authorityKind"}, + "issuerKind": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/issuerIdentity/properties/issuer_kind"}, + "decoderBinding": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/decoderBinding"}, + "evidenceRole": {"enum": ["PRODUCER", "VERIFIER"]}, + "observationSource": {"enum": ["WORKER", "EXECUTOR_SUPERVISOR", "ENFORCEMENT_BACKEND"]}, + "sourceRoleKind": {"enum": ["WORKER_SESSION", "EXECUTOR_SUPERVISOR", "ENFORCEMENT_BACKEND"]}, + "proofKind": {"enum": ["SIGNATURE", "ATTESTATION"]}, + "implementationEntry": { + "type": "object", + "additionalProperties": false, + "required": ["role_kind", "implementation_version", "implementation_sigil"], + "properties": { + "role_kind": {"$ref": "#/$defs/roleKind"}, + "implementation_version": {"$ref": "#/$defs/protocolIdentifier"}, + "implementation_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "allowedRolePair": { + "type": "object", + "additionalProperties": false, + "required": ["producer_role_kind", "observation_source", "verifier_role_kind"], + "properties": { + "producer_role_kind": {"const": "WORKER_SESSION"}, + "observation_source": {"$ref": "#/$defs/observationSource"}, + "verifier_role_kind": {"$ref": "#/$defs/roleKind"} + }, + "oneOf": [ + { + "properties": { + "observation_source": {"const": "WORKER"}, + "verifier_role_kind": { + "enum": [ + "EXECUTOR_SUPERVISOR", + "ENFORCEMENT_BACKEND", + "HOST_VERIFIER", + "INDEPENDENT_BACKEND_VERIFIER" + ] + } + } + }, + { + "properties": { + "observation_source": {"const": "EXECUTOR_SUPERVISOR"}, + "verifier_role_kind": { + "enum": ["ENFORCEMENT_BACKEND", "HOST_VERIFIER", "INDEPENDENT_BACKEND_VERIFIER"] + } + } + }, + { + "properties": { + "observation_source": {"const": "ENFORCEMENT_BACKEND"}, + "verifier_role_kind": { + "enum": ["EXECUTOR_SUPERVISOR", "HOST_VERIFIER", "INDEPENDENT_BACKEND_VERIFIER"] + } + } + } + ] + }, + "allowedRolePairArray": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "#/$defs/allowedRolePair"} + }, + "decoderProfile": { + "type": "object", + "additionalProperties": false, + "required": [ + "role", + "decoder_binding", + "media_type", + "maximum_input_bytes", + "maximum_output_bytes", + "maximum_cpu_time_milliseconds", + "maximum_memory_bytes", + "maximum_recursion_depth", + "decoded_contract_sigil" + ], + "properties": { + "role": {"$ref": "#/$defs/evidenceRole"}, + "decoder_binding": {"$ref": "#/$defs/decoderBinding"}, + "media_type": {"$ref": "#/$defs/evidenceMediaType"}, + "maximum_input_bytes": {"$ref": "#/$defs/positiveU63"}, + "maximum_output_bytes": {"$ref": "#/$defs/positiveU63"}, + "maximum_cpu_time_milliseconds": {"$ref": "#/$defs/positiveU63"}, + "maximum_memory_bytes": {"$ref": "#/$defs/positiveU63"}, + "maximum_recursion_depth": {"$ref": "#/$defs/positiveU63"}, + "decoded_contract_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "rawMediaProfile": { + "type": "object", + "additionalProperties": false, + "required": ["role", "media_type", "maximum_input_bytes"], + "properties": { + "role": {"$ref": "#/$defs/evidenceRole"}, + "media_type": {"$ref": "#/$defs/evidenceMediaType"}, + "maximum_input_bytes": {"$ref": "#/$defs/positiveU63"} + } + }, + "rawMediaProfileArray": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "#/$defs/rawMediaProfile"} + }, + "authenticationProfile": { + "type": "object", + "additionalProperties": false, + "required": [ + "subject_kind", + "evidence_kind", + "role_kind", + "authority_kind", + "issuer_kind", + "registry_id", + "registry_version", + "registry_snapshot_sigil", + "allowed_key_profile_sigil", + "verification_profile_sigil", + "allowed_proof_kind" + ], + "properties": { + "subject_kind": {"const": "EXECUTION_OBSERVATION"}, + "evidence_kind": {"$ref": "#/$defs/evidenceRole"}, + "role_kind": {"$ref": "#/$defs/roleKind"}, + "authority_kind": {"$ref": "#/$defs/authorityKind"}, + "issuer_kind": {"$ref": "#/$defs/issuerKind"}, + "registry_id": {"$ref": "#/$defs/protocolIdentifier"}, + "registry_version": {"$ref": "#/$defs/protocolIdentifier"}, + "registry_snapshot_sigil": {"$ref": "#/$defs/sigil"}, + "allowed_key_profile_sigil": {"$ref": "#/$defs/sigil"}, + "verification_profile_sigil": {"$ref": "#/$defs/sigil"}, + "allowed_proof_kind": {"$ref": "#/$defs/proofKind"} + }, + "oneOf": [ + { + "properties": { + "evidence_kind": {"const": "PRODUCER"}, + "role_kind": {"const": "WORKER_SESSION"}, + "authority_kind": {"const": "RESULT_INGRESS_RECEIPT"} + } + }, + { + "properties": { + "evidence_kind": {"const": "VERIFIER"}, + "role_kind": { + "enum": [ + "EXECUTOR_SUPERVISOR", + "ENFORCEMENT_BACKEND", + "HOST_VERIFIER", + "INDEPENDENT_BACKEND_VERIFIER" + ] + }, + "authority_kind": {"const": "TRUSTED_VERIFIER_IDENTITY"} + } + } + ] + }, + "authenticationProfileArray": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "#/$defs/authenticationProfile"} + }, + "sourceAuthenticationProfile": { + "type": "object", + "additionalProperties": false, + "required": [ + "observation_source", + "source_role_kind", + "source_identity_profile_sigil", + "source_channel_profile_sigil", + "source_registry_id", + "source_registry_profile_sigil", + "verifier_role_kind" + ], + "properties": { + "observation_source": {"$ref": "#/$defs/observationSource"}, + "source_role_kind": {"$ref": "#/$defs/sourceRoleKind"}, + "source_identity_profile_sigil": {"$ref": "#/$defs/sigil"}, + "source_channel_profile_sigil": {"$ref": "#/$defs/sigil"}, + "source_registry_id": {"$ref": "#/$defs/protocolIdentifier"}, + "source_registry_profile_sigil": {"$ref": "#/$defs/sigil"}, + "verifier_role_kind": {"$ref": "#/$defs/roleKind"} + }, + "oneOf": [ + { + "properties": { + "observation_source": {"const": "WORKER"}, + "source_role_kind": {"const": "WORKER_SESSION"}, + "verifier_role_kind": { + "enum": [ + "EXECUTOR_SUPERVISOR", + "ENFORCEMENT_BACKEND", + "HOST_VERIFIER", + "INDEPENDENT_BACKEND_VERIFIER" + ] + } + } + }, + { + "properties": { + "observation_source": {"const": "EXECUTOR_SUPERVISOR"}, + "source_role_kind": {"const": "EXECUTOR_SUPERVISOR"}, + "verifier_role_kind": { + "enum": ["ENFORCEMENT_BACKEND", "HOST_VERIFIER", "INDEPENDENT_BACKEND_VERIFIER"] + } + } + }, + { + "properties": { + "observation_source": {"const": "ENFORCEMENT_BACKEND"}, + "source_role_kind": {"const": "ENFORCEMENT_BACKEND"}, + "verifier_role_kind": { + "enum": ["EXECUTOR_SUPERVISOR", "HOST_VERIFIER", "INDEPENDENT_BACKEND_VERIFIER"] + } + } + } + ] + }, + "sourceAuthenticationProfileArray": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "#/$defs/sourceAuthenticationProfile"} + } + } +} + diff --git a/schemas/execution-observation-raw-evidence-1.0.json b/schemas/execution-observation-raw-evidence-1.0.json new file mode 100644 index 0000000..71f6a21 --- /dev/null +++ b/schemas/execution-observation-raw-evidence-1.0.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-observation-raw-evidence/1.0", + "title": "Execution Observation Raw Evidence v1", + "description": "Closed RFC-0012 O4-O10 raw Observation Evidence record. Contract-only validation does not read a Blob, execute a decoder, verify a proof, resolve an external registry, append an Event, or grant operational, assurance, or scientific authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "raw_evidence_id", "observation_evidence_id", "kind", "owner_binding", "result_observation_binding", "result_ingress_receipt_binding", "role_identity", "raw_payload", "decoder_binding", "evidence_profile_binding", "issuer_authentication_binding", "decoded_observation", "collected_at", "created_at", "record_sigil"], + "properties": { + "schema_version": {"const": "execution-observation-raw-evidence/1.0"}, + "raw_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/observationRawEvidenceId"}, + "observation_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_evidence_id"}, + "kind": {"enum": ["PRODUCER", "VERIFIER"]}, + "owner_binding": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_owner_binding"}, + "result_observation_binding": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/result_observation_binding"}, + "result_ingress_receipt_binding": {"$ref": "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0#/$defs/result_ingress_receipt_binding"}, + "role_identity": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/evidenceRoleIdentity"}, + "raw_payload": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/rawPayloadBinding"}, + "decoder_binding": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/decoderBinding"}, + "evidence_profile_binding": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/evidenceProfileBinding"}, + "issuer_authentication_binding": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/issuerAuthenticationBinding"}, + "decoded_observation": {"$ref": "#/$defs/decodedObservation"}, + "collected_at": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/timestamp"}, + "created_at": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/timestamp"}, + "record_sigil": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/sigil"} + }, + "oneOf": [ + {"properties": {"kind": {"const": "PRODUCER"}, "role_identity": {"properties": {"role_kind": {"const": "WORKER_SESSION"}}}, "decoded_observation": {"$ref": "#/$defs/producerComplete"}}}, + {"properties": {"kind": {"const": "VERIFIER"}, "role_identity": {"properties": {"role_kind": {"enum": ["EXECUTOR_SUPERVISOR", "ENFORCEMENT_BACKEND", "HOST_VERIFIER", "INDEPENDENT_BACKEND_VERIFIER"]}}}, "decoded_observation": {"$ref": "#/$defs/verifierComplete"}}}, + {"properties": {"kind": {"const": "VERIFIER"}, "role_identity": {"properties": {"role_kind": {"enum": ["EXECUTOR_SUPERVISOR", "ENFORCEMENT_BACKEND", "HOST_VERIFIER", "INDEPENDENT_BACKEND_VERIFIER"]}}}, "decoded_observation": {"$ref": "#/$defs/verifierUnavailable"}}} + ], + "$defs": { + "decodedObservation": {"oneOf": [{"$ref": "#/$defs/producerComplete"}, {"$ref": "#/$defs/verifierComplete"}, {"$ref": "#/$defs/verifierUnavailable"}]}, + "producerComplete": { + "type": "object", "additionalProperties": false, + "required": ["kind", "owner_binding", "result_ingress_receipt_binding", "runtime_observation", "termination_observation", "collection_context_sigil"], + "properties": {"kind": {"const": "PRODUCER_COMPLETE"}, "owner_binding": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_owner_binding"}, "result_ingress_receipt_binding": {"$ref": "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0#/$defs/result_ingress_receipt_binding"}, "runtime_observation": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/runtime_observation"}, "termination_observation": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/termination_observation"}, "collection_context_sigil": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/sigil"}} + }, + "verifierComplete": { + "type": "object", "additionalProperties": false, + "required": ["kind", "owner_binding", "runtime_observation", "termination_observation", "authenticated_source", "collection_context_sigil"], + "properties": {"kind": {"const": "VERIFIER_COMPLETE"}, "owner_binding": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_owner_binding"}, "runtime_observation": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/runtime_observation"}, "termination_observation": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/termination_observation"}, "authenticated_source": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/authenticated_observation_source"}, "collection_context_sigil": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/sigil"}} + }, + "verifierUnavailable": { + "type": "object", "additionalProperties": false, + "required": ["kind", "owner_binding", "authenticated_source", "unavailable_fields", "reason_bindings", "collection_context_sigil"], + "properties": {"kind": {"const": "VERIFIER_UNAVAILABLE"}, "owner_binding": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_owner_binding"}, "authenticated_source": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/authenticated_observation_source"}, {"type": "null"}]}, "unavailable_fields": {"type": "array", "minItems": 1, "maxItems": 10, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_field"}}, "reason_bindings": {"type": "array", "minItems": 1, "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_reason"}}, "collection_context_sigil": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/sigil"}} + } + } +} + diff --git a/schemas/execution-observe-request-1.0.json b/schemas/execution-observe-request-1.0.json new file mode 100644 index 0000000..38fe027 --- /dev/null +++ b/schemas/execution-observe-request-1.0.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-observe-request/1.0", + "title": "Execution Observe Request", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "job_id", "limit"], + "properties": { + "schema_version": {"const": "execution-observe-request/1.0"}, + "job_id": {"$ref": "#/$defs/job_id"}, + "limit": {"type": "integer", "minimum": 1, "maximum": 256}, + "cursor": {"$ref": "#/$defs/observation_cursor"} + }, + "$defs": { + "job_id": { + "type": "string", + "pattern": "^JB-[A-F0-9]{64}$", + "minLength": 67, + "maxLength": 67 + }, + "sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$" + }, + "observation_cursor": { + "type": "object", + "additionalProperties": false, + "required": [ + "job_id", + "last_returned_sequence", + "through_journal_sequence", + "through_event_sigil", + "cursor_sigil" + ], + "properties": { + "job_id": {"$ref": "#/$defs/job_id"}, + "last_returned_sequence": { + "type": "integer", + "minimum": 0, + "maximum": 9223372036854775807 + }, + "through_journal_sequence": { + "type": "integer", + "minimum": 1, + "maximum": 9223372036854775807 + }, + "through_event_sigil": {"$ref": "#/$defs/sigil"}, + "cursor_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/execution-output-storage-observation-set-1.0.json b/schemas/execution-output-storage-observation-set-1.0.json new file mode 100644 index 0000000..ef8d041 --- /dev/null +++ b/schemas/execution-output-storage-observation-set-1.0.json @@ -0,0 +1,105 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0", + "title": "Execution Output Storage Observation Set v1", + "description": "Closed RFC-0012 contract-only frozen output storage observation. Shape and locally provable identity only; Execution/Storage replay, immutable-record resolution, Blob bytes, Quarantine truth, Replica availability, durable allocation, Journal append, and runtime authority remain external and fail closed.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "observation_set_id", "job_id", "attempt_id", "attempt_binding_sigil", "result_binding", "log_closure_sigil", "output_closure_sigil", "control_evidence_set_binding", "quarantine_binding_set_binding", "terminalization_storage_manifest_binding", "output_root_protection", "terminal_source_binding", "storage_event", "storage_state_sigil", "members", "blob_sigils", "observation_set_sigil"], + "properties": { + "schema_version": {"const": "execution-output-storage-observation-set/1.0"}, + "observation_set_id": {"$ref": "#/$defs/outputStorageObservationSetId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "result_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/result_binding"}, + "log_closure_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "output_closure_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "control_evidence_set_binding": {"$ref": "#/$defs/control_evidence_set_binding"}, + "quarantine_binding_set_binding": {"$ref": "#/$defs/quarantine_binding_set_binding"}, + "terminalization_storage_manifest_binding": {"$ref": "#/$defs/terminalization_storage_manifest_binding"}, + "output_root_protection": {"$ref": "#/$defs/output_root_protection"}, + "terminal_source_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/terminal_source_binding"}, + "storage_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, + "storage_state_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "members": {"type": "array", "minItems": 6, "maxItems": 4096, "items": {"$ref": "#/$defs/member"}}, + "blob_sigils": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}, + "observation_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + }, + "$defs": { + "outputStorageObservationSetId": {"type": "string", "pattern": "^OS-[0-9A-F]{64}$", "minLength": 67, "maxLength": 67}, + "control_evidence_set_binding": { + "type": "object", "additionalProperties": false, + "required": ["kind", "control_evidence_set_id", "control_evidence_set_sigil"], + "properties": {"kind": {"const": "FROZEN"}, "control_evidence_set_id": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence-set/1.0#/$defs/controlEvidenceSetId"}, "control_evidence_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}} + }, + "quarantine_binding_set_binding": { + "type": "object", "additionalProperties": false, + "required": ["kind", "quarantine_binding_set_id", "quarantine_binding_set_sigil"], + "properties": {"kind": {"const": "FROZEN"}, "quarantine_binding_set_id": {"$ref": "https://benchwork.dev/schemas/execution-quarantine-binding-set/1.0#/$defs/quarantineBindingSetId"}, "quarantine_binding_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}} + }, + "terminalization_storage_manifest_binding": { + "type": "object", "additionalProperties": false, + "required": ["kind", "storage_root_manifest_id", "storage_root_manifest_sigil"], + "properties": {"kind": {"const": "FROZEN"}, "storage_root_manifest_id": {"$ref": "https://benchwork.dev/schemas/execution-storage-root-manifest/1.0#/$defs/manifestId"}, "storage_root_manifest_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}} + }, + "output_root_protection": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/output_root_protection"}, + "member": {"oneOf": [{"$ref": "#/$defs/attempt_outputs_none_member"}, {"$ref": "#/$defs/attempt_output_member"}, {"$ref": "#/$defs/log_stream_member"}, {"$ref": "#/$defs/resource_evidence_none_member"}, {"$ref": "#/$defs/resource_evidence_member"}, {"$ref": "#/$defs/terminal_source_not_applicable_member"}, {"$ref": "#/$defs/terminal_source_none_member"}, {"$ref": "#/$defs/terminal_source_member"}]}, + "attempt_outputs_none_member": { + "type": "object", "additionalProperties": false, "required": ["kind", "reason"], + "properties": {"kind": {"const": "ATTEMPT_OUTPUTS_NONE"}, "reason": {"enum": ["NO_RESULT", "RESULT_REJECTED", "OUTPUT_ARRAY_EMPTY"]}} + }, + "attempt_output_member": { + "type": "object", "additionalProperties": false, + "required": ["kind", "storage_subject_id", "manifest_entry_sigil", "logical_name", "schema_id", "schema_sigil", "staging_reference_sigil", "byte_size", "blob_sigil", "storage_origin", "storage"], + "properties": { + "kind": {"const": "ATTEMPT_OUTPUT"}, "storage_subject_id": {"$ref": "#/$defs/sigil"}, "manifest_entry_sigil": {"$ref": "#/$defs/sigil"}, + "logical_name": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/logicalName"}, "schema_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/schemaId"}, "schema_sigil": {"$ref": "#/$defs/sigil"}, "staging_reference_sigil": {"$ref": "#/$defs/sigil"}, "byte_size": {"$ref": "#/$defs/u63"}, "blob_sigil": {"$ref": "#/$defs/sigil"}, + "storage_origin": {"$ref": "https://benchwork.dev/schemas/execution-storage-root-manifest/1.0#/$defs/storageOrigin"}, "storage": {"$ref": "#/$defs/storage_observation"} + } + }, + "log_stream_member": { + "type": "object", "additionalProperties": false, + "required": ["kind", "storage_subject_id", "manifest_entry_sigil", "stream", "log_stream_id", "final_sequence", "captured_bytes", "dropped_bytes", "truncated", "stream_set_sigil", "closure_event_id", "closure_event_sigil", "storage_origin", "content"], + "properties": { + "kind": {"const": "LOG_STREAM"}, "storage_subject_id": {"$ref": "#/$defs/sigil"}, "manifest_entry_sigil": {"$ref": "#/$defs/sigil"}, "stream": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, "log_stream_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/logStreamId"}, "final_sequence": {"anyOf": [{"$ref": "#/$defs/u63"}, {"type": "null"}]}, "captured_bytes": {"$ref": "#/$defs/u63"}, "dropped_bytes": {"$ref": "#/$defs/u63"}, "truncated": {"type": "boolean"}, "stream_set_sigil": {"$ref": "#/$defs/sigil"}, "closure_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, "closure_event_sigil": {"$ref": "#/$defs/sigil"}, "storage_origin": {"$ref": "https://benchwork.dev/schemas/execution-storage-root-manifest/1.0#/$defs/storageOrigin"}, "content": {"$ref": "#/$defs/log_content"} + } + }, + "log_content": {"oneOf": [{"$ref": "#/$defs/empty_log_content"}, {"$ref": "#/$defs/captured_log_content"}]}, + "empty_log_content": {"type": "object", "additionalProperties": false, "required": ["kind", "blob_sigil", "storage"], "properties": {"kind": {"const": "EMPTY"}, "blob_sigil": {"$ref": "#/$defs/sigil"}, "storage": {"$ref": "#/$defs/storage_observation"}}}, + "captured_log_content": {"type": "object", "additionalProperties": false, "required": ["kind", "blob_sigil", "storage"], "properties": {"kind": {"const": "CAPTURED"}, "blob_sigil": {"$ref": "#/$defs/sigil"}, "storage": {"$ref": "#/$defs/storage_observation"}}}, + "resource_evidence_none_member": {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "RESOURCE_EVIDENCE_NONE"}}}, + "resource_evidence_member": { + "type": "object", "additionalProperties": false, + "required": ["kind", "storage_subject_id", "manifest_entry_sigil", "control_evidence_id", "control_evidence_sigil", "control_dimension", "phase", "phase_evidence_entry_sigil", "evidence_kind", "producer_identity", "verifier_identity", "collected_at", "byte_size", "blob_sigil", "storage_origin", "storage"], + "properties": { + "kind": {"const": "RESOURCE_EVIDENCE"}, "storage_subject_id": {"$ref": "#/$defs/sigil"}, "manifest_entry_sigil": {"$ref": "#/$defs/sigil"}, "control_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/controlEvidenceId"}, "control_evidence_sigil": {"$ref": "#/$defs/sigil"}, "control_dimension": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/controlDimension"}, "phase": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/phase"}, "phase_evidence_entry_sigil": {"$ref": "#/$defs/sigil"}, "evidence_kind": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/evidenceKind"}, "producer_identity": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/evidenceIdentity"}, "verifier_identity": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/evidenceIdentity"}, "collected_at": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/timestamp"}, "byte_size": {"$ref": "#/$defs/u63"}, "blob_sigil": {"$ref": "#/$defs/sigil"}, "storage_origin": {"$ref": "https://benchwork.dev/schemas/execution-storage-root-manifest/1.0#/$defs/storageOrigin"}, "storage": {"$ref": "#/$defs/storage_observation"} + } + }, + "terminal_source_not_applicable_member": {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "TERMINAL_SOURCE_NOT_APPLICABLE"}}}, + "terminal_source_none_member": {"type": "object", "additionalProperties": false, "required": ["kind", "reason_codes"], "properties": {"kind": {"const": "TERMINAL_SOURCE_NONE"}, "reason_codes": {"type": "array", "minItems": 1, "maxItems": 10, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/quarantined_terminal_source_binding/properties/reason_codes/items"}}}}, + "terminal_source_member": { + "type": "object", "additionalProperties": false, + "required": ["kind", "storage_subject_id", "manifest_entry_sigil", "disposition", "terminal_source_identity", "terminal_source_sigil", "storage_blob", "retention_policy_sigil", "file_count", "byte_count", "storage_origin", "storage"], + "properties": {"kind": {"const": "TERMINAL_SOURCE"}, "storage_subject_id": {"$ref": "#/$defs/sigil"}, "manifest_entry_sigil": {"$ref": "#/$defs/sigil"}, "disposition": {"enum": ["VERIFIED", "QUARANTINED"]}, "terminal_source_identity": {"$ref": "https://benchwork.dev/schemas/benchwork-source-tree/1.0#/$defs/sourceTreeId"}, "terminal_source_sigil": {"$ref": "#/$defs/sigil"}, "storage_blob": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}, "retention_policy_sigil": {"$ref": "#/$defs/sigil"}, "file_count": {"$ref": "#/$defs/u63"}, "byte_count": {"$ref": "#/$defs/u63"}, "storage_origin": {"$ref": "https://benchwork.dev/schemas/execution-storage-root-manifest/1.0#/$defs/storageOrigin"}, "storage": {"$ref": "#/$defs/storage_observation"}} + }, + "storage_observation": {"oneOf": [{"$ref": "#/$defs/no_storage"}, {"$ref": "#/$defs/blob_storage"}, {"$ref": "#/$defs/quarantined_storage"}, {"$ref": "#/$defs/quarantine_terminal_negative_storage"}]}, + "no_storage": {"type": "object", "additionalProperties": false, "required": ["kind", "terminal_storage_status"], "properties": {"kind": {"const": "NONE"}, "terminal_storage_status": {"const": "UNAVAILABLE"}}}, + "blob_storage": { + "type": "object", "additionalProperties": false, + "required": ["kind", "terminal_storage_status", "blob_sigil", "size_bytes", "blob_record_sigil", "availability", "availability_as_of", "availability_basis_sigil", "integrity_event_sigils", "quarantine", "replica"], + "properties": {"kind": {"const": "BLOB"}, "terminal_storage_status": {"enum": ["AVAILABLE", "DEGRADED", "UNAVAILABLE", "INCIDENT"]}, "blob_sigil": {"$ref": "#/$defs/sigil"}, "size_bytes": {"$ref": "#/$defs/u63"}, "blob_record_sigil": {"$ref": "#/$defs/sigil"}, "availability": {"enum": ["AVAILABLE", "DEGRADED", "UNAVAILABLE", "INCIDENT"]}, "availability_as_of": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, "availability_basis_sigil": {"$ref": "#/$defs/sigil"}, "integrity_event_sigils": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/sigil"}}, "quarantine": {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, "replica": {"$ref": "#/$defs/replica_selection"}} + }, + "replica_selection": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, {"$ref": "#/$defs/selected_replica"}]}, + "selected_replica": {"type": "object", "additionalProperties": false, "required": ["kind", "replica_id", "replica_record_sigil", "state", "backend", "object", "verification"], "properties": {"kind": {"const": "SELECTED"}, "replica_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/replicaId"}, "replica_record_sigil": {"$ref": "#/$defs/sigil"}, "state": {"const": "AVAILABLE"}, "backend": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/backendRef"}, "object": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/backendObjectRef"}, "verification": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/verificationRef"}}}, + "quarantined_storage": {"$ref": "#/$defs/quarantine_storage_base", "properties": {"kind": {"const": "QUARANTINED"}, "terminal_storage_status": {"const": "QUARANTINED"}, "state": {"enum": ["HELD", "DISPOSAL_FAILED"]}}, "required": ["kind", "terminal_storage_status", "claimed_blob_sigil", "claimed_size_bytes", "quarantine_binding_sigil", "quarantine_id", "owner_kind", "owner_id", "state", "source_object", "destination_object", "quarantine_record_sigil", "quarantine_event", "reason"]}, + "quarantine_terminal_negative_storage": {"$ref": "#/$defs/quarantine_storage_base", "properties": {"kind": {"const": "QUARANTINE_TERMINAL_NEGATIVE"}, "terminal_storage_status": {"const": "UNAVAILABLE"}, "state": {"enum": ["FAILED", "DISPOSAL_FAILED", "DISPOSED"]}}, "required": ["kind", "terminal_storage_status", "claimed_blob_sigil", "claimed_size_bytes", "quarantine_binding_sigil", "quarantine_id", "owner_kind", "owner_id", "state", "source_object", "destination_object", "quarantine_record_sigil", "origin_event", "observation_event", "reason"]}, + "quarantine_storage_base": { + "type": "object", "additionalProperties": false, + "properties": {"kind": {"enum": ["QUARANTINED", "QUARANTINE_TERMINAL_NEGATIVE"]}, "terminal_storage_status": {"enum": ["QUARANTINED", "UNAVAILABLE"]}, "claimed_blob_sigil": {"$ref": "#/$defs/sigil"}, "claimed_size_bytes": {"$ref": "#/$defs/u63"}, "quarantine_binding_sigil": {"$ref": "#/$defs/sigil"}, "quarantine_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-state/1.0#/$defs/quarantineId"}, "owner_kind": {"const": "TRANSFER_ATTEMPT"}, "owner_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/transferAttemptId"}, "state": {"enum": ["HELD", "FAILED", "DISPOSAL_FAILED", "DISPOSED"]}, "source_object": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/backendObjectRef"}, {"type": "null"}]}, "destination_object": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/backendObjectRef"}, "quarantine_record_sigil": {"$ref": "#/$defs/sigil"}, "quarantine_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, "origin_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, "observation_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, "reason": {"$ref": "https://benchwork.dev/schemas/artifact-storage-state/1.0#/$defs/reason"}} + }, + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"} + } +} + diff --git a/schemas/execution-output-writer-revocation-evidence-1.0.json b/schemas/execution-output-writer-revocation-evidence-1.0.json new file mode 100644 index 0000000..a5f0e62 --- /dev/null +++ b/schemas/execution-output-writer-revocation-evidence-1.0.json @@ -0,0 +1,174 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0", + "title": "Execution Output Writer Revocation Evidence v1", + "description": "Closed RFC-0012 R7 output-writer revocation evidence wire. Contract-only validation establishes shape, deterministic identity, self-Sigil, and local equality/order facts only; it does not authenticate evidence, establish writer-inventory completeness, prove immutable-generation semantics, execute a decoder, read raw bytes, resolve a profile or registry, seal/read/hash output bytes, append a Journal Event, or grant Result admission authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", "revocation_evidence_id", "job_id", "attempt_id", + "attempt_binding_sigil", "lease_id", "lease_binding_sigil", "worker_id", + "worker_session_id", "worker_session_binding_sigil", "executor_epoch", + "fence_tuple", "preallocation_event_id", "preallocation_event_sigil", + "preallocation_binding_sigil", "storage_subject_id", "output_handle_id", + "transfer_id", "transfer_attempt_id", "sealed_generation_binding", + "writer_handles", "revocation_started_at", "revocation_completed_at", + "producer_identity", "producer_evidence_binding", "verifier_identity", + "verifier_evidence_binding", "evidence_profile_id", + "evidence_profile_version", "evidence_profile_sigil", + "revocation_evidence_sigil" + ], + "properties": { + "schema_version": {"const": "execution-output-writer-revocation-evidence/1.0"}, + "revocation_evidence_id": {"$ref": "#/$defs/writerRevocationEvidenceId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "lease_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_epoch": {"$ref": "#/$defs/u64"}, + "fence_tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"}, + "preallocation_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "preallocation_event_sigil": {"$ref": "#/$defs/sigil"}, + "preallocation_binding_sigil": {"$ref": "#/$defs/sigil"}, + "storage_subject_id": {"$ref": "#/$defs/sigil"}, + "output_handle_id": {"$ref": "#/$defs/opaque"}, + "transfer_id": {"$ref": "#/$defs/transferId"}, + "transfer_attempt_id": {"$ref": "#/$defs/transferAttemptId"}, + "sealed_generation_binding": {"$ref": "#/$defs/sealedGenerationBinding"}, + "writer_handles": {"$ref": "#/$defs/writerHandleSet"}, + "revocation_started_at": {"$ref": "#/$defs/timestamp"}, + "revocation_completed_at": {"$ref": "#/$defs/timestamp"}, + "producer_identity": {"$ref": "#/$defs/producerIdentity"}, + "producer_evidence_binding": {"$ref": "#/$defs/rawEvidenceBinding"}, + "verifier_identity": {"$ref": "#/$defs/verifierIdentity"}, + "verifier_evidence_binding": {"$ref": "#/$defs/rawEvidenceBinding"}, + "evidence_profile_id": {"const": "EXECUTION_OUTPUT_WRITER_REVOCATION"}, + "evidence_profile_version": {"const": "1.0"}, + "evidence_profile_sigil": {"$ref": "#/$defs/sigil"}, + "revocation_evidence_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "writerRevocationEvidenceId": {"type": "string", "pattern": "^OWR-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u64": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/u64"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "opaque": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, + "transferId": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferId"}, + "transferAttemptId": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferAttemptId"}, + "sealedGenerationBinding": { + "oneOf": [ + {"$ref": "#/$defs/backendGeneration"}, + {"$ref": "#/$defs/opaqueSealedGeneration"} + ] + }, + "backendGeneration": { + "type": "object", "additionalProperties": false, + "required": ["kind", "backend_id", "backend_profile_sigil", "object_identity_sigil", "generation"], + "properties": { + "kind": {"const": "BACKEND_GENERATION"}, + "backend_id": {"$ref": "#/$defs/opaque"}, + "backend_profile_sigil": {"$ref": "#/$defs/sigil"}, + "object_identity_sigil": {"$ref": "#/$defs/sigil"}, + "generation": {"$ref": "#/$defs/opaque"} + } + }, + "opaqueSealedGeneration": { + "type": "object", "additionalProperties": false, + "required": ["kind", "backend_id", "backend_profile_sigil", "object_identity_sigil", "sealed_generation_sigil"], + "properties": { + "kind": {"const": "OPAQUE_SEALED_GENERATION"}, + "backend_id": {"$ref": "#/$defs/opaque"}, + "backend_profile_sigil": {"$ref": "#/$defs/sigil"}, + "object_identity_sigil": {"$ref": "#/$defs/sigil"}, + "sealed_generation_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "writerHandleSet": { + "type": "array", "minItems": 1, "maxItems": 4096, + "items": {"$ref": "#/$defs/writerHandle"} + }, + "writerHandle": { + "type": "object", "additionalProperties": false, + "required": ["writer_handle_id", "writer_kind", "writer_identity_sigil", "handle_generation_sigil", "revoked_at", "revocation_receipt_sigil"], + "properties": { + "writer_handle_id": {"$ref": "#/$defs/opaque"}, + "writer_kind": {"enum": ["WORKER", "BACKEND_WRITER", "EXECUTOR_DELEGATE"]}, + "writer_identity_sigil": {"$ref": "#/$defs/sigil"}, + "handle_generation_sigil": {"$ref": "#/$defs/sigil"}, + "revoked_at": {"$ref": "#/$defs/timestamp"}, + "revocation_receipt_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "producerIdentity": { + "type": "object", "additionalProperties": false, + "required": ["kind", "identity_id", "implementation_version", "implementation_sigil"], + "properties": { + "kind": {"enum": ["EXECUTOR_SUPERVISOR", "ENFORCEMENT_BACKEND"]}, + "identity_id": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/protocolIdentifier"}, + "implementation_version": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/protocolIdentifier"}, + "implementation_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "verifierIdentity": { + "type": "object", "additionalProperties": false, + "required": ["kind", "identity_id", "implementation_version", "implementation_sigil"], + "properties": { + "kind": {"enum": ["INDEPENDENT_BACKEND_VERIFIER", "HOST_VERIFIER"]}, + "identity_id": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/protocolIdentifier"}, + "implementation_version": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/protocolIdentifier"}, + "implementation_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "rawEvidenceBinding": { + "type": "object", "additionalProperties": false, + "required": ["raw_evidence_id", "raw_evidence_record_sigil"], + "properties": { + "raw_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/outputWriterRawEvidenceId"}, + "raw_evidence_record_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "ownerBinding": { + "type": "object", "additionalProperties": false, + "required": [ + "job_id", "attempt_id", "attempt_binding_sigil", "lease_id", + "lease_binding_sigil", "worker_id", "worker_session_id", + "worker_session_binding_sigil", "executor_epoch", "fence_tuple", + "preallocation_event_id", "preallocation_event_sigil", + "preallocation_binding_sigil", "storage_subject_id", "output_handle_id", + "transfer_id", "transfer_attempt_id" + ], + "properties": { + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "lease_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_epoch": {"$ref": "#/$defs/u64"}, + "fence_tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"}, + "preallocation_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "preallocation_event_sigil": {"$ref": "#/$defs/sigil"}, + "preallocation_binding_sigil": {"$ref": "#/$defs/sigil"}, + "storage_subject_id": {"$ref": "#/$defs/sigil"}, + "output_handle_id": {"$ref": "#/$defs/opaque"}, + "transfer_id": {"$ref": "#/$defs/transferId"}, + "transfer_attempt_id": {"$ref": "#/$defs/transferAttemptId"} + } + }, + "writerRevocationEvidenceBinding": { + "type": "object", "additionalProperties": false, + "required": ["revocation_evidence_id", "revocation_evidence_sigil"], + "properties": { + "revocation_evidence_id": {"$ref": "#/$defs/writerRevocationEvidenceId"}, + "revocation_evidence_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/execution-output-writer-revocation-raw-evidence-1.0.json b/schemas/execution-output-writer-revocation-raw-evidence-1.0.json new file mode 100644 index 0000000..bc53068 --- /dev/null +++ b/schemas/execution-output-writer-revocation-raw-evidence-1.0.json @@ -0,0 +1,126 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-output-writer-revocation-raw-evidence/1.0", + "title": "Execution Output Writer Revocation Raw Evidence v1", + "description": "Closed RFC-0012 R7 producer-or-verifier writer-revocation raw-evidence manifest. Contract-only validation does not authenticate the issuer, resolve raw bytes, execute or trust a decoder, install a profile, prove handle-inventory completeness or immutable generation, or grant seal/read/hash/Result authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", "raw_evidence_id", "kind", "role_identity", "job_id", + "attempt_id", "attempt_binding_sigil", "lease_id", "lease_binding_sigil", + "worker_id", "worker_session_id", "worker_session_binding_sigil", + "executor_epoch", "fence_tuple", "preallocation_event_id", + "preallocation_event_sigil", "preallocation_binding_sigil", + "storage_subject_id", "output_handle_id", "transfer_id", + "transfer_attempt_id", "sealed_generation_binding", "writer_handles", + "raw_payload", "decoder", "evidence_profile_binding", + "issuer_authentication_binding", "decoded_observation", "created_at", + "record_sigil" + ], + "properties": { + "schema_version": {"const": "execution-output-writer-revocation-raw-evidence/1.0"}, + "raw_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/outputWriterRawEvidenceId"}, + "kind": {"enum": ["PRODUCER", "VERIFIER"]}, + "role_identity": { + "oneOf": [ + {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/producerIdentity"}, + {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/verifierIdentity"} + ] + }, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "lease_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_epoch": {"$ref": "#/$defs/u64"}, + "fence_tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"}, + "preallocation_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "preallocation_event_sigil": {"$ref": "#/$defs/sigil"}, + "preallocation_binding_sigil": {"$ref": "#/$defs/sigil"}, + "storage_subject_id": {"$ref": "#/$defs/sigil"}, + "output_handle_id": {"$ref": "#/$defs/opaque"}, + "transfer_id": {"$ref": "#/$defs/transferId"}, + "transfer_attempt_id": {"$ref": "#/$defs/transferAttemptId"}, + "sealed_generation_binding": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/sealedGenerationBinding"}, + "writer_handles": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/writerHandleSet"}, + "raw_payload": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/rawPayloadBinding"}, + "decoder": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/decoderBinding"}, + "evidence_profile_binding": {"$ref": "#/$defs/outputWriterEvidenceProfileBinding"}, + "issuer_authentication_binding": {"$ref": "https://benchwork.dev/schemas/execution-evidence-issuer-authentication/1.0#/$defs/issuerAuthenticationBinding"}, + "decoded_observation": { + "oneOf": [ + {"$ref": "#/$defs/producerRevocation"}, + {"$ref": "#/$defs/verifierConfirmation"} + ] + }, + "created_at": {"$ref": "#/$defs/timestamp"}, + "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "oneOf": [ + { + "properties": { + "kind": {"const": "PRODUCER"}, + "role_identity": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/producerIdentity"}, + "decoded_observation": {"$ref": "#/$defs/producerRevocation"} + } + }, + { + "properties": { + "kind": {"const": "VERIFIER"}, + "role_identity": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/verifierIdentity"}, + "decoded_observation": {"$ref": "#/$defs/verifierConfirmation"} + } + } + ], + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u64": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/u64"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "opaque": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, + "transferId": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferId"}, + "transferAttemptId": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferAttemptId"}, + "outputWriterEvidenceProfileBinding": { + "type": "object", "additionalProperties": false, + "required": ["evidence_profile_id", "evidence_profile_version", "evidence_profile_sigil"], + "properties": { + "evidence_profile_id": {"const": "EXECUTION_OUTPUT_WRITER_REVOCATION"}, + "evidence_profile_version": {"const": "1.0"}, + "evidence_profile_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "producerRevocation": { + "type": "object", "additionalProperties": false, + "required": ["kind", "owner_binding", "producer_identity", "revocation_started_at", "revocation_completed_at", "sealed_generation_binding", "writer_handles"], + "properties": { + "kind": {"const": "PRODUCER_REVOCATION"}, + "owner_binding": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/ownerBinding"}, + "producer_identity": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/producerIdentity"}, + "revocation_started_at": {"$ref": "#/$defs/timestamp"}, + "revocation_completed_at": {"$ref": "#/$defs/timestamp"}, + "sealed_generation_binding": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/sealedGenerationBinding"}, + "writer_handles": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/writerHandleSet"} + } + }, + "verifierConfirmation": { + "type": "object", "additionalProperties": false, + "required": ["kind", "owner_binding", "verifier_identity", "observed_at", "sealed_generation_binding", "writer_handles", "all_writes_rejected", "unlisted_writer_scan", "exact_generation_reopen", "generation_immutable", "read_identity_sigil"], + "properties": { + "kind": {"const": "VERIFIER_CONFIRMATION"}, + "owner_binding": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/ownerBinding"}, + "verifier_identity": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/verifierIdentity"}, + "observed_at": {"$ref": "#/$defs/timestamp"}, + "sealed_generation_binding": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/sealedGenerationBinding"}, + "writer_handles": {"$ref": "https://benchwork.dev/schemas/execution-output-writer-revocation-evidence/1.0#/$defs/writerHandleSet"}, + "all_writes_rejected": {"const": true}, + "unlisted_writer_scan": {"const": "COMPLETE"}, + "exact_generation_reopen": {"const": "VERIFIED"}, + "generation_immutable": {"const": "VERIFIED"}, + "read_identity_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/execution-quarantine-binding-set-1.0.json b/schemas/execution-quarantine-binding-set-1.0.json new file mode 100644 index 0000000..91245bd --- /dev/null +++ b/schemas/execution-quarantine-binding-set-1.0.json @@ -0,0 +1,211 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-quarantine-binding-set/1.0", + "title": "Execution Quarantine Binding Set v1", + "description": "Closed RFC-0012 contract-only mapping from one Attempt's frozen output ESM subjects to RFC-0013 Quarantine projections. Shape and locally provable integrity only; ESM resolution, Storage replay, Event-type resolution, retained-byte authentication, durable allocation, and runtime authority remain external and fail closed.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "quarantine_binding_set_id", + "job_id", + "attempt_id", + "attempt_binding_sigil", + "quarantine_plan_sigil", + "terminalization_storage_manifest_binding", + "storage_event", + "storage_state_sigil", + "bindings", + "quarantine_binding_set_sigil" + ], + "properties": { + "schema_version": {"const": "execution-quarantine-binding-set/1.0"}, + "quarantine_binding_set_id": {"$ref": "#/$defs/quarantineBindingSetId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "quarantine_plan_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "terminalization_storage_manifest_binding": {"$ref": "#/$defs/frozenStorageManifestBinding"}, + "storage_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, + "storage_state_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "bindings": { + "type": "array", + "maxItems": 4096, + "items": {"$ref": "#/$defs/binding"} + }, + "quarantine_binding_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + }, + "$defs": { + "quarantineBindingSetId": { + "type": "string", + "pattern": "^QBS-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "storageManifestId": { + "type": "string", + "pattern": "^ESM-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "frozenStorageManifestBinding": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "storage_root_manifest_id", "storage_root_manifest_sigil"], + "properties": { + "kind": {"const": "FROZEN"}, + "storage_root_manifest_id": {"$ref": "#/$defs/storageManifestId"}, + "storage_root_manifest_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + }, + "binding": { + "type": "object", + "additionalProperties": false, + "required": [ + "storage_subject_id", + "manifest_entry_sigil", + "subject", + "storage_origin", + "quarantine_ref", + "disposition", + "quarantine_binding_sigil" + ], + "properties": { + "storage_subject_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "manifest_entry_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "subject": {"$ref": "#/$defs/subject"}, + "storage_origin": {"$ref": "#/$defs/quarantineStorageOrigin"}, + "quarantine_ref": {"$ref": "#/$defs/quarantineRef"}, + "disposition": {"enum": ["RETAINED", "TERMINAL_NEGATIVE"]}, + "quarantine_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"quarantine_ref": {"properties": {"state": {"const": "HELD"}}}}, "required": ["quarantine_ref"]}, + "then": {"properties": {"disposition": {"const": "RETAINED"}}} + }, + { + "if": {"properties": {"quarantine_ref": {"properties": {"state": {"enum": ["FAILED", "DISPOSED"]}}}}, "required": ["quarantine_ref"]}, + "then": {"properties": {"disposition": {"const": "TERMINAL_NEGATIVE"}}} + } + ] + }, + "subject": { + "oneOf": [ + {"$ref": "#/$defs/attemptOutputSubject"}, + {"$ref": "#/$defs/logStreamSubject"}, + {"$ref": "#/$defs/resourceEvidenceSubject"}, + {"$ref": "#/$defs/terminalSourceSubject"} + ] + }, + "attemptOutputSubject": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "logical_name", "schema_id", "schema_sigil", "staging_reference_sigil", "byte_size", "blob_sigil"], + "properties": { + "kind": {"const": "ATTEMPT_OUTPUT"}, + "logical_name": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/logicalName"}, + "schema_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/schemaId"}, + "schema_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "staging_reference_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "byte_size": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "blob_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + }, + "logStreamSubject": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "stream", "log_stream_id", "stream_set_sigil", "byte_size", "blob_sigil"], + "properties": { + "kind": {"const": "LOG_STREAM"}, + "stream": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, + "log_stream_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/logStreamId"}, + "stream_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "byte_size": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "blob_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + }, + "resourceEvidenceSubject": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "control_evidence_id", "control_evidence_sigil", "control_dimension", "phase", "phase_evidence_entry_sigil", "byte_size", "blob_sigil"], + "properties": { + "kind": {"const": "RESOURCE_EVIDENCE"}, + "control_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/controlEvidenceId"}, + "control_evidence_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "control_dimension": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/controlDimension"}, + "phase": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/phase"}, + "phase_evidence_entry_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "byte_size": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "blob_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + }, + "terminalSourceSubject": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "disposition", "terminal_source_identity", "terminal_source_sigil", "storage_blob", "retention_policy_sigil", "file_count", "byte_count"], + "properties": { + "kind": {"const": "TERMINAL_SOURCE"}, + "disposition": {"enum": ["VERIFIED", "QUARANTINED"]}, + "terminal_source_identity": {"$ref": "https://benchwork.dev/schemas/benchwork-source-tree/1.0#/$defs/sourceTreeId"}, + "terminal_source_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "storage_blob": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}, + "retention_policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "file_count": {"type": "integer", "minimum": 0, "maximum": 100000}, + "byte_count": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"} + } + }, + "quarantineStorageOrigin": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "transfer", "provenance_id", "provenance_sigil", "quarantine_id", "quarantine_origin_event"], + "properties": { + "kind": {"const": "QUARANTINE"}, + "transfer": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/transferRef"}, + "provenance_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, + "provenance_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "quarantine_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/quarantineId"}, + "quarantine_origin_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"} + } + }, + "quarantineRef": { + "type": "object", + "additionalProperties": false, + "required": ["quarantine_id", "owner_kind", "owner_id", "quarantine_record_sigil", "origin_event", "observation_event", "state", "source_object", "destination_object", "source_cleanup", "reason"], + "properties": { + "quarantine_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-state/1.0#/$defs/quarantine/properties/quarantine_id"}, + "owner_kind": {"const": "TRANSFER_ATTEMPT"}, + "owner_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/transferAttemptId"}, + "quarantine_record_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "origin_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, + "observation_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}, + "state": {"enum": ["HELD", "DISPOSAL_FAILED", "DISPOSED", "FAILED"]}, + "source_object": {"$ref": "https://benchwork.dev/schemas/artifact-storage-state/1.0#/$defs/quarantine/properties/source_object"}, + "destination_object": {"$ref": "https://benchwork.dev/schemas/artifact-storage-state/1.0#/$defs/quarantine/properties/destination_object"}, + "source_cleanup": {"$ref": "https://benchwork.dev/schemas/artifact-storage-state/1.0#/$defs/quarantine/properties/source_cleanup"}, + "reason": {"$ref": "https://benchwork.dev/schemas/artifact-storage-state/1.0#/$defs/quarantine/properties/reason"} + } + }, + "quarantineBindingSetBinding": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "PENDING"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "quarantine_binding_set_id", "quarantine_binding_set_sigil"], + "properties": { + "kind": {"const": "FROZEN"}, + "quarantine_binding_set_id": {"$ref": "#/$defs/quarantineBindingSetId"}, + "quarantine_binding_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + } + ] + } + } +} + diff --git a/schemas/execution-recovery-action-set-1.0.json b/schemas/execution-recovery-action-set-1.0.json new file mode 100644 index 0000000..f712719 --- /dev/null +++ b/schemas/execution-recovery-action-set-1.0.json @@ -0,0 +1,115 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-recovery-action-set/1.0", + "title": "Execution Recovery Action Set v1", + "description": "Closed RFC-0012 immutable recovery action-set wire. Contract validation does not derive the set from Journal replay, allocate target Events, install or execute actions, prove postconditions, append Events, or grant recovery, runtime, or scientific authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "recovery_id", "phase", "derived_from_journal_id", "derived_through_sequence", "derived_through_event_sigil", "supersedes_action_set_sigil", "actions", "action_set_sigil"], + "properties": { + "schema_version": {"const": "execution-recovery-action-set/1.0"}, + "recovery_id": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/recovery_id"}, + "phase": {"$ref": "#/$defs/phase"}, + "derived_from_journal_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/journal_id"}, + "derived_through_sequence": {"$ref": "#/$defs/u63"}, + "derived_through_event_sigil": {"$ref": "#/$defs/sigil"}, + "supersedes_action_set_sigil": {"oneOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, + "actions": {"type": "array", "items": {"$ref": "#/$defs/action"}}, + "action_set_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "positiveU63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "opaqueId": {"type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Z0-9][A-Z0-9_-]*$"}, + "phase": {"enum": ["STARTED", "FENCING", "RECONCILING", "FINALIZING"]}, + "actionKind": {"enum": ["COMMIT_DUE_EVENT", "RESTORE_CLOCK", "FENCE_LEASE", "REPUBLISH_TOMBSTONE", "OFFLINE_SESSION", "TERMINATE_PROCESS_TREE", "REVOKE_HANDLES", "CLOSE_SESSION", "CLOSE_LOG", "VERIFY_OUTPUT_STORAGE", "VERIFY_TERMINAL_SOURCE", "BIND_DURABLE_ATTEMPT_AUTHORIZATION", "RELEASE_INACTIVE_EXECUTION_INPUT_HOLD", "RELEASE_DUE_EXECUTION_HOLD", "QUARANTINE_RESOURCE", "ADVANCE_ATTEMPT", "CLEAN_RESOURCE", "COLLECT_ACCOUNTING", "SETTLE_BUDGET", "EVALUATE_ATTEMPT_ASSURANCE", "EVALUATE_JOB_ASSURANCE", "ADVANCE_JOB"]}, + "entityKind": {"enum": ["EXECUTOR", "RECOVERY", "WORKER", "WORKER_SESSION", "JOB", "ATTEMPT", "LEASE", "LOG_STREAM"]}, + "idArray": {"type": "array", "uniqueItems": true, "items": {"$ref": "#/$defs/opaqueId"}}, + "eventIdArray": {"type": "array", "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}}, + "action": { + "type": "object", + "additionalProperties": false, + "required": ["ordinal", "action_kind", "entity_kind", "entity_id", "expected_revision", "target_event_id", "target_sequence", "target_event_type", "prerequisite_event_ids", "parameters"], + "properties": { + "ordinal": {"$ref": "#/$defs/u63"}, + "action_kind": {"$ref": "#/$defs/actionKind"}, + "entity_kind": {"$ref": "#/$defs/entityKind"}, + "entity_id": {"$ref": "#/$defs/opaqueId"}, + "expected_revision": {"$ref": "#/$defs/u64"}, + "target_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "target_sequence": {"$ref": "#/$defs/positiveU63"}, + "target_event_type": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_type"}, + "prerequisite_event_ids": {"$ref": "#/$defs/eventIdArray"}, + "parameters": {"oneOf": [ + {"$ref": "#/$defs/commitDueEvent"}, {"$ref": "#/$defs/restoreClock"}, + {"$ref": "#/$defs/fenceLease"}, {"$ref": "#/$defs/republishTombstone"}, + {"$ref": "#/$defs/offlineSession"}, {"$ref": "#/$defs/terminateProcessTree"}, + {"$ref": "#/$defs/revokeHandles"}, {"$ref": "#/$defs/closeSession"}, + {"$ref": "#/$defs/closeLog"}, {"$ref": "#/$defs/verifyOutputStorage"}, + {"$ref": "#/$defs/verifyTerminalSource"}, {"$ref": "#/$defs/bindDurableAttemptAuthorization"}, + {"$ref": "#/$defs/releaseInactiveExecutionInputHold"}, {"$ref": "#/$defs/releaseDueExecutionHold"}, + {"$ref": "#/$defs/quarantineResource"}, {"$ref": "#/$defs/advanceAttempt"}, + {"$ref": "#/$defs/cleanResource"}, {"$ref": "#/$defs/collectAccounting"}, + {"$ref": "#/$defs/settleBudget"}, {"$ref": "#/$defs/evaluateAttemptAssurance"}, + {"$ref": "#/$defs/evaluateJobAssurance"}, {"$ref": "#/$defs/advanceJob"} + ]} + }, + "allOf": [ + {"if": {"properties": {"action_kind": {"const": "COMMIT_DUE_EVENT"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/commitDueEvent"}}}}, + {"if": {"properties": {"action_kind": {"const": "RESTORE_CLOCK"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/restoreClock"}}}}, + {"if": {"properties": {"action_kind": {"const": "FENCE_LEASE"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/fenceLease"}}}}, + {"if": {"properties": {"action_kind": {"const": "REPUBLISH_TOMBSTONE"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/republishTombstone"}}}}, + {"if": {"properties": {"action_kind": {"const": "OFFLINE_SESSION"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/offlineSession"}}}}, + {"if": {"properties": {"action_kind": {"const": "TERMINATE_PROCESS_TREE"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/terminateProcessTree"}}}}, + {"if": {"properties": {"action_kind": {"const": "REVOKE_HANDLES"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/revokeHandles"}}}}, + {"if": {"properties": {"action_kind": {"const": "CLOSE_SESSION"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/closeSession"}}}}, + {"if": {"properties": {"action_kind": {"const": "CLOSE_LOG"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/closeLog"}}}}, + {"if": {"properties": {"action_kind": {"const": "VERIFY_OUTPUT_STORAGE"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/verifyOutputStorage"}}}}, + {"if": {"properties": {"action_kind": {"const": "VERIFY_TERMINAL_SOURCE"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/verifyTerminalSource"}}}}, + {"if": {"properties": {"action_kind": {"const": "BIND_DURABLE_ATTEMPT_AUTHORIZATION"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/bindDurableAttemptAuthorization"}}}}, + {"if": {"properties": {"action_kind": {"const": "RELEASE_INACTIVE_EXECUTION_INPUT_HOLD"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/releaseInactiveExecutionInputHold"}}}}, + {"if": {"properties": {"action_kind": {"const": "RELEASE_DUE_EXECUTION_HOLD"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/releaseDueExecutionHold"}}}}, + {"if": {"properties": {"action_kind": {"const": "QUARANTINE_RESOURCE"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/quarantineResource"}}}}, + {"if": {"properties": {"action_kind": {"const": "ADVANCE_ATTEMPT"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/advanceAttempt"}}}}, + {"if": {"properties": {"action_kind": {"const": "CLEAN_RESOURCE"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/cleanResource"}}}}, + {"if": {"properties": {"action_kind": {"const": "COLLECT_ACCOUNTING"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/collectAccounting"}}}}, + {"if": {"properties": {"action_kind": {"const": "SETTLE_BUDGET"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/settleBudget"}}}}, + {"if": {"properties": {"action_kind": {"const": "EVALUATE_ATTEMPT_ASSURANCE"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/evaluateAttemptAssurance"}}}}, + {"if": {"properties": {"action_kind": {"const": "EVALUATE_JOB_ASSURANCE"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/evaluateJobAssurance"}}}}, + {"if": {"properties": {"action_kind": {"const": "ADVANCE_JOB"}}}, "then": {"properties": {"parameters": {"$ref": "#/$defs/advanceJob"}}}} + ] + }, + "commitDueEvent": {"type": "object", "additionalProperties": false, "required": ["deadline_kind", "due_at", "deadline_entity_id"], "properties": {"deadline_kind": {"enum": ["JOB_DEADLINE", "ATTEMPT_DEADLINE", "HEARTBEAT_TIMEOUT", "LEASE_EXPIRY", "LEASE_CLAIM_DEADLINE", "CANCELLATION_GRACE", "RETRY_ELIGIBILITY"]}, "due_at": {"$ref": "#/$defs/timestamp"}, "deadline_entity_id": {"$ref": "#/$defs/opaqueId"}}}, + "restoreClock": {"type": "object", "additionalProperties": false, "required": ["clock_uncertain_event_id", "trusted_time_source_sigil", "clock_uncertainty_tolerance_seconds"], "properties": {"clock_uncertain_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, "trusted_time_source_sigil": {"$ref": "#/$defs/sigil"}, "clock_uncertainty_tolerance_seconds": {"$ref": "#/$defs/u63"}}}, + "fenceLease": {"type": "object", "additionalProperties": false, "required": ["lease_id", "lease_binding_sigil", "prior_fence_floor", "tombstone_generation"], "properties": {"lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, "lease_binding_sigil": {"$ref": "#/$defs/sigil"}, "prior_fence_floor": {"$ref": "#/$defs/u64"}, "tombstone_generation": {"$ref": "#/$defs/u64"}}}, + "republishTombstone": {"type": "object", "additionalProperties": false, "required": ["lease_id", "tombstone_generation", "original_terminal_event_sigil", "sink_ids"], "properties": {"lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, "tombstone_generation": {"$ref": "#/$defs/u64"}, "original_terminal_event_sigil": {"$ref": "#/$defs/sigil"}, "sink_ids": {"$ref": "#/$defs/idArray"}}}, + "offlineSession": {"type": "object", "additionalProperties": false, "required": ["worker_session_id", "last_heartbeat_sequence", "active_lease_ids"], "properties": {"worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, "last_heartbeat_sequence": {"oneOf": [{"$ref": "#/$defs/u63"}, {"type": "null"}]}, "active_lease_ids": {"type": "array", "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}}}}, + "terminateProcessTree": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind", "attempt_id", "process_tree_identity", "backend_configuration_sigil", "termination_policy_sigil"], "properties": {"kind": {"const": "TRACKED"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "process_tree_identity": {"$ref": "#/$defs/opaqueId"}, "backend_configuration_sigil": {"$ref": "#/$defs/sigil"}, "termination_policy_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "attempt_id", "backend_start_handle_sigil", "backend_configuration_sigil", "termination_policy_sigil"], "properties": {"kind": {"const": "START_HANDLE"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "backend_start_handle_sigil": {"$ref": "#/$defs/sigil"}, "backend_configuration_sigil": {"$ref": "#/$defs/sigil"}, "termination_policy_sigil": {"$ref": "#/$defs/sigil"}}} + ]}, + "revokeHandles": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "handle_set_sigil", "sink_ids"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "handle_set_sigil": {"$ref": "#/$defs/sigil"}, "sink_ids": {"$ref": "#/$defs/idArray"}}}, + "closeSession": {"type": "object", "additionalProperties": false, "required": ["worker_session_id", "backend_session_identity", "control_channel_identity_sigil"], "properties": {"worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, "backend_session_identity": {"$ref": "#/$defs/opaqueId"}, "control_channel_identity_sigil": {"$ref": "#/$defs/sigil"}}}, + "closeLog": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "stream", "last_committed_sequence"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "stream": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, "last_committed_sequence": {"oneOf": [{"$ref": "#/$defs/u63"}, {"type": "null"}]}}}, + "verifyOutputStorage": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "expected_output_set_sigil", "storage_journal_id", "storage_through_sequence", "storage_through_event_sigil"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "expected_output_set_sigil": {"$ref": "#/$defs/sigil"}, "storage_journal_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/journalId"}, "storage_through_sequence": {"$ref": "#/$defs/positiveU63"}, "storage_through_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "verifyTerminalSource": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "crucible_base_identity", "crucible_base_sigil", "retention_policy_sigil"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "crucible_base_identity": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/token"}, "crucible_base_sigil": {"$ref": "#/$defs/sigil"}, "retention_policy_sigil": {"$ref": "#/$defs/sigil"}}}, + "bindDurableAttemptAuthorization": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "authorization_subject_id", "authorization_subject_sigil", "authorization_transition_request_id", "authorization_transition_request_sigil", "authorization_event_id", "authorization_event_body_sigil", "authorization_receipt_id", "authorization_receipt_sigil"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "authorization_subject_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/subjectId"}, "authorization_subject_sigil": {"$ref": "#/$defs/sigil"}, "authorization_transition_request_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-transition-request/1.0#/$defs/requestId"}, "authorization_transition_request_sigil": {"$ref": "#/$defs/sigil"}, "authorization_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, "authorization_event_body_sigil": {"$ref": "#/$defs/sigil"}, "authorization_receipt_id": {"$ref": "#/$defs/opaqueId"}, "authorization_receipt_sigil": {"$ref": "#/$defs/sigil"}}}, + "releaseInactiveExecutionInputHold": {"type": "object", "additionalProperties": false, "required": ["root_kind", "storage_root", "owner_terminal_basis", "release_authorization_id", "release_authorization_sigil"], "properties": {"root_kind": {"enum": ["JOB_INPUT", "ATTEMPT_INPUT"]}, "storage_root": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/storage_root_binding"}, "owner_terminal_basis": {"$ref": "https://benchwork.dev/schemas/execution-root-hold-release-authorization/1.0#/$defs/owner_terminal"}, "release_authorization_id": {"$ref": "https://benchwork.dev/schemas/execution-root-hold-release-authorization/1.0#/$defs/release_authorization_id"}, "release_authorization_sigil": {"$ref": "#/$defs/sigil"}}}, + "releaseDueExecutionHold": {"type": "object", "additionalProperties": false, "required": ["job_id", "release_schedule", "release_authorization_id", "release_authorization_sigil"], "properties": {"job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "release_schedule": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/output_hold_release_schedule"}, "release_authorization_id": {"$ref": "https://benchwork.dev/schemas/execution-root-hold-release-authorization/1.0#/$defs/release_authorization_id"}, "release_authorization_sigil": {"$ref": "#/$defs/sigil"}}}, + "quarantineResource": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "resource_ids", "reason_codes"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "resource_ids": {"$ref": "#/$defs/idArray"}, "reason_codes": {"type": "array", "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/token"}}}}, + "advanceAttempt": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "from_state", "transition_cause"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "from_state": {"enum": ["CREATED", "PREFLIGHTING", "READY", "LEASED", "STARTING", "RUNNING", "DRAINING", "STOPPING", "CLEANING", "SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATION", "LEASE_EXPIRED", "LOST", "FENCED", "REJECTED"]}, "transition_cause": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/transition_cause"}}}, + "cleanResource": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "resource_ids", "cleanup_policy_sigil"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "resource_ids": {"$ref": "#/$defs/idArray"}, "cleanup_policy_sigil": {"$ref": "#/$defs/sigil"}}}, + "collectAccounting": {"type": "object", "additionalProperties": false, "required": ["job_id", "attempt_id", "reservation", "accounting_scope_sigil", "backend_configuration_sigil", "accounting_policy_sigil"], "properties": {"job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "reservation": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/budgetReservation"}, "accounting_scope_sigil": {"$ref": "#/$defs/sigil"}, "backend_configuration_sigil": {"$ref": "#/$defs/sigil"}, "accounting_policy_sigil": {"$ref": "#/$defs/sigil"}}}, + "settleBudget": {"type": "object", "additionalProperties": false, "required": ["job_id", "attempt_id", "reservation", "accounting_capture_event_id", "accounting_capture_event_sigil"], "properties": {"job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "reservation": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/budgetReservation"}, "accounting_capture_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, "accounting_capture_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "evaluateAttemptAssurance": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "terminal_event_id", "assurance_input_event_ids"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "terminal_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, "assurance_input_event_ids": {"$ref": "#/$defs/eventIdArray"}}}, + "evaluateJobAssurance": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind", "job_id", "attempt_id", "attempt_assurance_event_id"], "properties": {"kind": {"const": "ATTEMPT"}, "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, "attempt_assurance_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "job_id", "reason"], "properties": {"kind": {"const": "NOT_APPLICABLE"}, "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "reason": {"const": "NO_ATTEMPT_ALLOCATED"}}} + ]}, + "advanceJob": {"type": "object", "additionalProperties": false, "required": ["job_id", "from_state", "selected_attempt_id", "transition_cause"], "properties": {"job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "from_state": {"enum": ["SUBMITTED", "QUEUED", "ACTIVE", "RETRY_WAIT", "STOPPING", "SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATION"]}, "selected_attempt_id": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, {"type": "null"}]}, "transition_cause": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/transition_cause"}}} + } +} + diff --git a/schemas/execution-result-ingress-event-intent-1.0.json b/schemas/execution-result-ingress-event-intent-1.0.json new file mode 100644 index 0000000..1e18cca --- /dev/null +++ b/schemas/execution-result-ingress-event-intent-1.0.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-result-ingress-event-intent/1.0", + "title": "Execution Result Ingress Event Intent v1", + "description": "Closed RFC-0012 O2 immutable Result-ingress Event candidate intent. Contract validation does not append or reserve a Journal Event, validate live ingress authority, win a CAS, or accept a Result scientifically.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "ingress_event_intent_id", "result_ingress_receipt_binding", "event_candidate", "created_at", "intent_sigil"], + "properties": { + "schema_version": {"const": "execution-result-ingress-event-intent/1.0"}, + "ingress_event_intent_id": {"$ref": "#/$defs/ingress_event_intent_id"}, + "result_ingress_receipt_binding": {"$ref": "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0#/$defs/result_ingress_receipt_binding"}, + "event_candidate": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0"}, + "created_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "intent_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + }, + "$defs": { + "ingress_event_intent_id": { + "type": "string", + "pattern": "^OII-[0-9A-F]{64}$", + "minLength": 68, + "maxLength": 68 + } + } +} + diff --git a/schemas/execution-result-ingress-index-1.0.json b/schemas/execution-result-ingress-index-1.0.json new file mode 100644 index 0000000..1458112 --- /dev/null +++ b/schemas/execution-result-ingress-index-1.0.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-result-ingress-index/1.0", + "title": "Execution Result Ingress Index v1", + "description": "Closed RFC-0012 O2 single-Attempt Result-ingress replacement row. Structural validation does not establish canonical-path visibility, Journal/CAS/due authority, live ownership, Result acceptance, or scientific authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "ingress_index_id", "attempt_id", "result_sigil", "idempotency_key_sigil", "event_id", "result_ingress_receipt", "ingress_event_intent", "status", "created_at", "index_sigil"], + "properties": { + "schema_version": {"const": "execution-result-ingress-index/1.0"}, + "ingress_index_id": {"$ref": "#/$defs/ingress_index_id"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "result_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "idempotency_key_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "result_ingress_receipt": {"$ref": "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0"}, + "ingress_event_intent": {"$ref": "https://benchwork.dev/schemas/execution-result-ingress-event-intent/1.0"}, + "status": {"oneOf": [{"$ref": "#/$defs/pending_event"}, {"$ref": "#/$defs/committed"}, {"$ref": "#/$defs/aborted"}]}, + "created_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "index_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + }, + "$defs": { + "ingress_index_id": {"type": "string", "pattern": "^OIX-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "abort_predicate": {"enum": ["EXECUTOR_EPOCH_CHANGED", "FENCE_STALE", "ATTEMPT_NOT_RUNNING", "JOB_NOT_ACTIVE", "LEASE_NOT_ACTIVE", "LEASE_EXPIRED", "LEASE_REVOKED", "WORKER_SESSION_NOT_CURRENT", "CONTROL_CHANNEL_NOT_CURRENT", "STOP_OR_DUE_ALREADY_WON", "RESULT_MODE_DISALLOWS"]}, + "pending_event": { + "type": "object", "additionalProperties": false, + "required": ["kind", "expected_prior_index_sigil", "expected_journal_head", "installed_at"], + "properties": {"kind": {"const": "PENDING_EVENT"}, "expected_prior_index_sigil": {"type": "null"}, "expected_journal_head": {"$ref": "https://benchwork.dev/schemas/execution-journal-head/1.0"}, "installed_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}} + }, + "committed": { + "type": "object", "additionalProperties": false, + "required": ["kind", "expected_prior_index_sigil", "actual_event_ref", "committed_at"], + "properties": {"kind": {"const": "COMMITTED"}, "expected_prior_index_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "actual_event_ref": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_ref"}, "committed_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}} + }, + "aborted": { + "type": "object", "additionalProperties": false, + "required": ["kind", "expected_prior_index_sigil", "recovered_journal_head", "due_cutoff_at", "failed_predicate", "aborted_at"], + "properties": {"kind": {"const": "ABORTED"}, "expected_prior_index_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "recovered_journal_head": {"$ref": "https://benchwork.dev/schemas/execution-journal-head/1.0"}, "due_cutoff_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, "failed_predicate": {"$ref": "#/$defs/abort_predicate"}, "aborted_at": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}} + } + } +} + diff --git a/schemas/execution-result-ingress-receipt-1.0.json b/schemas/execution-result-ingress-receipt-1.0.json new file mode 100644 index 0000000..ea857c1 --- /dev/null +++ b/schemas/execution-result-ingress-receipt-1.0.json @@ -0,0 +1,50 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0", + "title": "Execution Result Ingress Receipt v1", + "description": "Closed immutable RFC-0012 O2 ingress receipt. Structural and deterministic validation grants no Result acceptance or Journal append authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "ingress_receipt_id", "owner_binding", "result_sigil", "result_observation_binding", "received_at", "control_channel_identity_sigil", "credential_verification", "receiver_identity", "created_at", "ingress_receipt_sigil"], + "properties": { + "schema_version": {"const": "execution-result-ingress-receipt/1.0"}, + "ingress_receipt_id": {"$ref": "#/$defs/ingress_receipt_id"}, + "owner_binding": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_owner_binding"}, + "result_sigil": {"$ref": "#/$defs/sigil"}, + "result_observation_binding": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/result_observation_binding"}, + "received_at": {"$ref": "#/$defs/timestamp"}, + "control_channel_identity_sigil": {"$ref": "#/$defs/sigil"}, + "credential_verification": {"$ref": "#/$defs/credential_verification"}, + "receiver_identity": {"$ref": "#/$defs/receiver_identity"}, + "created_at": {"$ref": "#/$defs/timestamp"}, + "ingress_receipt_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "protocol_identifier": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._:+-]{0,127}$", "minLength": 1, "maxLength": 128}, + "ingress_receipt_id": {"type": "string", "pattern": "^OIR-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "result_ingress_receipt_binding": { + "type": "object", "additionalProperties": false, + "required": ["ingress_receipt_id", "ingress_receipt_sigil"], + "properties": {"ingress_receipt_id": {"$ref": "#/$defs/ingress_receipt_id"}, "ingress_receipt_sigil": {"$ref": "#/$defs/sigil"}} + }, + "credential_verification": { + "type": "object", "additionalProperties": false, + "required": ["kind", "lease_credential_digest", "verification_profile_sigil", "verified_at", "verification_sigil"], + "properties": {"kind": {"const": "VERIFIED"}, "lease_credential_digest": {"$ref": "#/$defs/sigil"}, "verification_profile_sigil": {"$ref": "#/$defs/sigil"}, "verified_at": {"$ref": "#/$defs/timestamp"}, "verification_sigil": {"$ref": "#/$defs/sigil"}} + }, + "receiver_identity": { + "type": "object", "additionalProperties": false, + "required": ["executor_instance_id", "executor_epoch", "implementation_sigil"], + "properties": {"executor_instance_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/executorInstanceId"}, "executor_epoch": {"$ref": "#/$defs/u64"}, "implementation_sigil": {"$ref": "#/$defs/sigil"}} + }, + "result_ingress_credential_verification_profile": { + "type": "object", "additionalProperties": false, + "required": ["profile_id", "profile_version", "receiver_implementation_sigil", "control_channel_profile_sigil", "lease_credential_class", "credential_digest_algorithm", "verification_algorithm_id", "verification_implementation_sigil", "profile_sigil"], + "properties": {"profile_id": {"$ref": "#/$defs/protocol_identifier"}, "profile_version": {"$ref": "#/$defs/protocol_identifier"}, "receiver_implementation_sigil": {"$ref": "#/$defs/sigil"}, "control_channel_profile_sigil": {"$ref": "#/$defs/sigil"}, "lease_credential_class": {"$ref": "#/$defs/protocol_identifier"}, "credential_digest_algorithm": {"const": "SHA-256"}, "verification_algorithm_id": {"$ref": "#/$defs/protocol_identifier"}, "verification_implementation_sigil": {"$ref": "#/$defs/sigil"}, "profile_sigil": {"$ref": "#/$defs/sigil"}} + } + } +} + diff --git a/schemas/execution-root-hold-release-authorization-1.0.json b/schemas/execution-root-hold-release-authorization-1.0.json new file mode 100644 index 0000000..8e479a7 --- /dev/null +++ b/schemas/execution-root-hold-release-authorization-1.0.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-root-hold-release-authorization/1.0", + "title": "Execution Root Hold Release Authorization v1", + "description": "Closed RFC-0012 execution-root hold-release authorization. Contract validation does not prove replay/current-Head/sole-Event/absence/due/CAS facts, release Storage state, delete bytes, or affect canonical or scientific authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "release_authorization_id", "execution_journal_id", "storage_root", "policy", "hold_set_authorization_sigil", "basis", "release_authorization_sigil"], + "properties": { + "schema_version": {"const": "execution-root-hold-release-authorization/1.0"}, + "release_authorization_id": {"$ref": "#/$defs/release_authorization_id"}, + "execution_journal_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/journal_id"}, + "storage_root": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/storage_root_binding"}, + "policy": {"$ref": "#/$defs/policy"}, + "hold_set_authorization_sigil": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/sigil"}, + "basis": {"oneOf": [{"$ref": "#/$defs/owner_terminal"}, {"$ref": "#/$defs/orphan_abort"}, {"$ref": "#/$defs/output_deadline"}]}, + "release_authorization_sigil": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/sigil"} + }, + "allOf": [ + {"if": {"properties": {"basis": {"properties": {"kind": {"const": "OWNER_TERMINAL"}}}}}, "then": {"properties": {"storage_root": {"properties": {"root_kind": {"enum": ["JOB_INPUT", "ATTEMPT_INPUT"]}}}}}}, + {"if": {"properties": {"basis": {"properties": {"kind": {"const": "OUTPUT_DEADLINE"}}}}}, "then": {"properties": {"storage_root": {"properties": {"root_kind": {"const": "ATTEMPT_OUTPUT"}}}}}}, + {"if": {"properties": {"storage_root": {"properties": {"root_kind": {"const": "JOB_INPUT"}}}, "basis": {"properties": {"kind": {"const": "OWNER_TERMINAL"}}}}}, "then": {"properties": {"basis": {"properties": {"terminal_event_type": {"enum": ["job.succeeded", "job.failed", "job.cancelled", "job.timed_out", "job.policy_violated"]}}}}}}, + {"if": {"properties": {"storage_root": {"properties": {"root_kind": {"const": "ATTEMPT_INPUT"}}}, "basis": {"properties": {"kind": {"const": "OWNER_TERMINAL"}}}}}, "then": {"properties": {"basis": {"properties": {"terminal_event_type": {"enum": ["attempt.succeeded", "attempt.failed", "attempt.cancelled", "attempt.timed_out", "attempt.policy_violated", "attempt.lease_expired", "attempt.lost", "attempt.fenced", "attempt.rejected"]}}}}}}, + {"if": {"properties": {"storage_root": {"properties": {"root_kind": {"const": "JOB_INPUT"}}}, "basis": {"properties": {"kind": {"const": "ORPHAN_ABORT"}}}}}, "then": {"properties": {"basis": {"properties": {"intended_activation_event_type": {"const": "job.submitted"}}}}}}, + {"if": {"properties": {"storage_root": {"properties": {"root_kind": {"const": "ATTEMPT_INPUT"}}}, "basis": {"properties": {"kind": {"const": "ORPHAN_ABORT"}}}}}, "then": {"properties": {"basis": {"properties": {"intended_activation_event_type": {"const": "attempt.preflight_passed"}}}}}}, + {"if": {"properties": {"storage_root": {"properties": {"root_kind": {"const": "ATTEMPT_OUTPUT"}}}, "basis": {"properties": {"kind": {"const": "ORPHAN_ABORT"}}}}}, "then": {"properties": {"basis": {"properties": {"intended_activation_event_type": {"enum": ["attempt.succeeded", "attempt.failed", "attempt.cancelled", "attempt.timed_out", "attempt.policy_violated", "attempt.lease_expired", "attempt.lost", "attempt.fenced", "attempt.rejected"]}}}}}} + ], + "$defs": { + "release_authorization_id": {"type": "string", "pattern": "^EHR-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "policy": {"type": "object", "additionalProperties": false, "required": ["policy_id", "policy_sigil"], "properties": {"policy_id": {"const": "SP-EXECUTION-ROOT-HOLD-V1"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/sigil"}}}, + "owner_terminal": { + "type": "object", "additionalProperties": false, + "required": ["kind", "activation_event_id", "activation_event_sequence", "activation_event_sigil", "terminal_event_id", "terminal_event_sequence", "terminal_event_sigil", "terminal_event_type", "verification_head", "verification_state_sigil"], + "properties": {"kind": {"const": "OWNER_TERMINAL"}, "activation_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, "activation_event_sequence": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/positive_u63"}, "activation_event_sigil": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/sigil"}, "terminal_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, "terminal_event_sequence": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/positive_u63"}, "terminal_event_sigil": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/sigil"}, "terminal_event_type": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_type"}, "verification_head": {"$ref": "https://benchwork.dev/schemas/execution-journal-head/1.0"}, "verification_state_sigil": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/sigil"}} + }, + "orphan_abort": { + "type": "object", "additionalProperties": false, + "required": ["kind", "intended_activation_event_type", "absence_head", "absence_state_sigil"], + "properties": {"kind": {"const": "ORPHAN_ABORT"}, "intended_activation_event_type": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_type"}, "absence_head": {"$ref": "https://benchwork.dev/schemas/execution-journal-head/1.0"}, "absence_state_sigil": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/sigil"}} + }, + "output_deadline": { + "type": "object", "additionalProperties": false, + "required": ["kind", "activation_event_id", "activation_event_sequence", "activation_event_sigil", "release_schedule", "terminal_event_sequence", "terminal_event_sigil", "verification_head", "verification_state_sigil"], + "properties": {"kind": {"const": "OUTPUT_DEADLINE"}, "activation_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, "activation_event_sequence": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/positive_u63"}, "activation_event_sigil": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/sigil"}, "release_schedule": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/output_hold_release_schedule"}, "terminal_event_sequence": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/positive_u63"}, "terminal_event_sigil": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/sigil"}, "verification_head": {"$ref": "https://benchwork.dev/schemas/execution-journal-head/1.0"}, "verification_state_sigil": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/sigil"}} + } + } +} diff --git a/schemas/execution-sealed-output-staging-binding-1.0.json b/schemas/execution-sealed-output-staging-binding-1.0.json new file mode 100644 index 0000000..4601777 --- /dev/null +++ b/schemas/execution-sealed-output-staging-binding-1.0.json @@ -0,0 +1,113 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-sealed-output-staging-binding/1.0", + "title": "Execution Sealed Output Staging Binding v1", + "description": "Closed RFC-0012 immutable sealed-output staging binding. This contract validates shape and locally derivable identity/equality only; it does not prove writer revocation, sealed bytes, immutable-generation reads, hash/length truth, durable installation, replay, Journal append, or Result admission authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "sealed_staging_binding_id", + "job_id", + "attempt_id", + "attempt_binding_sigil", + "lease_id", + "lease_binding_sigil", + "worker_id", + "worker_session_id", + "worker_session_binding_sigil", + "executor_epoch", + "fence_tuple", + "preallocation_event_id", + "preallocation_event_sigil", + "preallocation_binding_sigil", + "storage_subject_id", + "output_handle_id", + "transfer_id", + "transfer_attempt_id", + "authorized_maximum_bytes", + "byte_size", + "blob_sigil", + "sealed_generation_binding", + "writer_revocation_evidence_binding", + "sealed_at", + "binding_sigil" + ], + "properties": { + "schema_version": {"const": "execution-sealed-output-staging-binding/1.0"}, + "sealed_staging_binding_id": {"$ref": "#/$defs/sealedStagingBindingId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "lease_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_epoch": {"$ref": "#/$defs/u64"}, + "fence_tuple": {"$ref": "https://benchwork.dev/schemas/execution-state/1.0#/$defs/public_fence_tuple"}, + "preallocation_event_id": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_id"}, + "preallocation_event_sigil": {"$ref": "#/$defs/sigil"}, + "preallocation_binding_sigil": {"$ref": "#/$defs/sigil"}, + "storage_subject_id": {"$ref": "#/$defs/sigil"}, + "output_handle_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, + "transfer_id": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferId"}, + "transfer_attempt_id": {"$ref": "https://benchwork.dev/schemas/artifact-transfer-attempt/1.0#/$defs/transferAttemptId"}, + "authorized_maximum_bytes": {"$ref": "#/$defs/positiveU63"}, + "byte_size": {"$ref": "#/$defs/u63"}, + "blob_sigil": {"$ref": "#/$defs/sigil"}, + "sealed_generation_binding": {"$ref": "#/$defs/sealedGenerationBinding"}, + "writer_revocation_evidence_binding": {"$ref": "#/$defs/writerRevocationEvidenceBinding"}, + "sealed_at": {"$ref": "#/$defs/timestamp"}, + "binding_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sealedStagingBindingId": {"type": "string", "pattern": "^SSB-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "writerRevocationEvidenceId": {"type": "string", "pattern": "^OWR-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "positiveU63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "sealedGenerationBinding": { + "oneOf": [ + {"$ref": "#/$defs/backendGeneration"}, + {"$ref": "#/$defs/opaqueSealedGeneration"} + ] + }, + "backendGeneration": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "backend_id", "backend_profile_sigil", "object_identity_sigil", "generation"], + "properties": { + "kind": {"const": "BACKEND_GENERATION"}, + "backend_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, + "backend_profile_sigil": {"$ref": "#/$defs/sigil"}, + "object_identity_sigil": {"$ref": "#/$defs/sigil"}, + "generation": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"} + } + }, + "opaqueSealedGeneration": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "backend_id", "backend_profile_sigil", "object_identity_sigil", "sealed_generation_sigil"], + "properties": { + "kind": {"const": "OPAQUE_SEALED_GENERATION"}, + "backend_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, + "backend_profile_sigil": {"$ref": "#/$defs/sigil"}, + "object_identity_sigil": {"$ref": "#/$defs/sigil"}, + "sealed_generation_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "writerRevocationEvidenceBinding": { + "type": "object", + "additionalProperties": false, + "required": ["revocation_evidence_id", "revocation_evidence_sigil"], + "properties": { + "revocation_evidence_id": {"$ref": "#/$defs/writerRevocationEvidenceId"}, + "revocation_evidence_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/execution-specification-1.0.json b/schemas/execution-specification-1.0.json new file mode 100644 index 0000000..09e9f87 --- /dev/null +++ b/schemas/execution-specification-1.0.json @@ -0,0 +1,72 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-specification/1.0", + "title": "Execution Specification v1", + "description": "Closed RFC-0012 immutable resolved execution authority. External resolution, narrowing, canonical ordering, durable allocation, and cross-policy equality remain semantic checks.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "specification_id", "created_at", "task_binding", "capability_binding", "snapshot_binding", "authorization", "policies", "output_contracts", "result_requirement", "runtime_constraints", "assurance_requirement", "deadline_policy", "attempt_budget", "job_budget", "retry_policy", "logging_policy", "post_terminal_derivation", "conformance_policy_version", "specification_sigil"], + "properties": { + "schema_version": {"const": "execution-specification/1.0"}, + "specification_id": {"$ref": "#/$defs/specificationId"}, + "created_at": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/timestamp"}, + "task_binding": {"$ref": "#/$defs/taskBinding"}, + "capability_binding": {"$ref": "#/$defs/capabilityBinding"}, + "snapshot_binding": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/snapshotBinding"}, + "authorization": {"$ref": "#/$defs/authorization"}, + "policies": {"$ref": "#/$defs/policies"}, + "output_contracts": {"type": "array", "maxItems": 256, "items": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/outputGrant"}, "uniqueItems": true}, + "result_requirement": {"$ref": "#/$defs/resultRequirement"}, + "runtime_constraints": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/runtimeAuthority"}, + "assurance_requirement": {"$ref": "#/$defs/assuranceRequirement"}, + "deadline_policy": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/deadlineAuthority"}, + "attempt_budget": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/attemptBudget"}, + "job_budget": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/jobBudget"}, + "retry_policy": {"$ref": "#/$defs/retryPolicy"}, + "logging_policy": {"$ref": "#/$defs/loggingPolicy"}, + "post_terminal_derivation": {"$ref": "#/$defs/postTerminalDerivation"}, + "conformance_policy_version": {"const": "sanctum-authority-intersection/1.0"}, + "specification_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + }, + "$defs": { + "specificationId": {"type": "string", "pattern": "^ES-[0-7][0-9A-HJKMNP-TV-Z]{25}$", "minLength": 29, "maxLength": 29}, + "policyId": {"type": "string", "pattern": "^POL-[0-7][0-9A-HJKMNP-TV-Z]{25}$", "minLength": 30, "maxLength": 30}, + "taskBinding": {"type": "object", "additionalProperties": false, "required": ["task_id", "task_capsule_sigil"], "properties": {"task_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/taskId"}, "task_capsule_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "capabilityBinding": {"type": "object", "additionalProperties": false, "required": ["capability_id", "contract_version", "capability_contract_sigil"], "properties": {"capability_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/capabilityId"}, "contract_version": {"const": "2.0"}, "capability_contract_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "authorization": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["ward_decision_id", "ward_decision_sigil", "approval_requirement"], "properties": {"ward_decision_id": {"$ref": "#/$defs/wardDecisionId"}, "ward_decision_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "approval_requirement": {"const": "NOT_REQUIRED"}}}, + {"type": "object", "additionalProperties": false, "required": ["ward_decision_id", "ward_decision_sigil", "approval_requirement", "approval_receipt_id", "approval_receipt_sigil"], "properties": {"ward_decision_id": {"$ref": "#/$defs/wardDecisionId"}, "ward_decision_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "approval_requirement": {"const": "REQUIRED"}, "approval_receipt_id": {"$ref": "#/$defs/receiptId"}, "approval_receipt_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}} + ]}, + "wardDecisionId": {"type": "string", "pattern": "^WD-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "receiptId": {"type": "string", "pattern": "^RC-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "resolvedPolicyBase": {"type": "object", "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"]}, + "filesystemPolicy": {"type": "object", "additionalProperties": false, "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"], "properties": {"policy_kind": {"const": "FILESYSTEM"}, "policy_id": {"$ref": "#/$defs/policyId"}, "policy_version": {"const": "1.0"}, "rules": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/filesystemAuthority"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "executablePolicy": {"type": "object", "additionalProperties": false, "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"], "properties": {"policy_kind": {"const": "EXECUTABLE"}, "policy_id": {"$ref": "#/$defs/policyId"}, "policy_version": {"const": "1.0"}, "rules": {"$ref": "#/$defs/resolvedExecutableAuthority"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "processPolicy": {"type": "object", "additionalProperties": false, "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"], "properties": {"policy_kind": {"const": "PROCESS"}, "policy_id": {"$ref": "#/$defs/policyId"}, "policy_version": {"const": "1.0"}, "rules": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/processAuthority"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "networkPolicy": {"type": "object", "additionalProperties": false, "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"], "properties": {"policy_kind": {"const": "NETWORK"}, "policy_id": {"$ref": "#/$defs/policyId"}, "policy_version": {"const": "1.0"}, "rules": {"$ref": "#/$defs/resolvedNetworkAuthority"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "environmentPolicy": {"type": "object", "additionalProperties": false, "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"], "properties": {"policy_kind": {"const": "ENVIRONMENT"}, "policy_id": {"$ref": "#/$defs/policyId"}, "policy_version": {"const": "1.0"}, "rules": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/environmentAuthority"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "credentialPolicy": {"type": "object", "additionalProperties": false, "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"], "properties": {"policy_kind": {"const": "CREDENTIAL"}, "policy_id": {"$ref": "#/$defs/policyId"}, "policy_version": {"const": "1.0"}, "rules": {"$ref": "#/$defs/resolvedCredentialAuthority"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "resourcePolicy": {"type": "object", "additionalProperties": false, "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"], "properties": {"policy_kind": {"const": "RESOURCE"}, "policy_id": {"$ref": "#/$defs/policyId"}, "policy_version": {"const": "1.0"}, "rules": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/resourceAuthority"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "inputPolicy": {"type": "object", "additionalProperties": false, "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"], "properties": {"policy_kind": {"const": "INPUT"}, "policy_id": {"$ref": "#/$defs/policyId"}, "policy_version": {"const": "1.0"}, "rules": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/inputAuthority"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "outputPolicy": {"type": "object", "additionalProperties": false, "required": ["policy_kind", "policy_id", "policy_version", "rules", "policy_sigil"], "properties": {"policy_kind": {"const": "OUTPUT"}, "policy_id": {"$ref": "#/$defs/policyId"}, "policy_version": {"const": "1.0"}, "rules": {"$ref": "#/$defs/resolvedOutputAuthority"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "policies": {"type": "object", "additionalProperties": false, "required": ["filesystem", "executable", "process", "network", "environment", "credential", "resource", "input", "output"], "properties": {"filesystem": {"$ref": "#/$defs/filesystemPolicy"}, "executable": {"$ref": "#/$defs/executablePolicy"}, "process": {"$ref": "#/$defs/processPolicy"}, "network": {"$ref": "#/$defs/networkPolicy"}, "environment": {"$ref": "#/$defs/environmentPolicy"}, "credential": {"$ref": "#/$defs/credentialPolicy"}, "resource": {"$ref": "#/$defs/resourcePolicy"}, "input": {"$ref": "#/$defs/inputPolicy"}, "output": {"$ref": "#/$defs/outputPolicy"}}}, + "resolvedExecutableAuthority": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["mode", "grants"], "properties": {"mode": {"const": "DENY"}, "grants": {"type": "array", "maxItems": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["mode", "grants"], "properties": {"mode": {"const": "ALLOWLIST"}, "grants": {"type": "array", "minItems": 1, "maxItems": 384, "uniqueItems": true, "items": {"oneOf": [{"$ref": "#/$defs/resolvedToolGrant"}, {"$ref": "#/$defs/resolvedExecutableGrant"}]}}}} + ]}, + "resolvedToolGrant": {"type": "object", "additionalProperties": false, "required": ["kind", "tool_id", "tool_version", "tool_sigil", "executable_id", "executable_version", "executable_sigil", "runtime_id", "runtime_version", "runtime_sigil", "entrypoint", "argument_schema_id", "argument_schema_sigil", "maximum_invocations", "side_effect_id", "side_effect_authorization"], "properties": {"kind": {"const": "TOOL"}, "tool_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/toolId"}, "tool_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, "tool_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "executable_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/executableId"}, "executable_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, "executable_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "runtime_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/runtimeId"}, "runtime_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, "runtime_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "entrypoint": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/relativePath"}, "argument_schema_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/schemaId"}, "argument_schema_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "maximum_invocations": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "side_effect_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectId"}, "side_effect_authorization": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectGrant"}}}, + "resolvedExecutableGrant": {"type": "object", "additionalProperties": false, "required": ["kind", "executable_id", "executable_version", "executable_sigil", "runtime_id", "runtime_version", "runtime_sigil", "entrypoint", "argument_schema_id", "argument_schema_sigil", "maximum_starts", "side_effect_id", "side_effect_authorization"], "properties": {"kind": {"const": "EXECUTABLE"}, "executable_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/executableId"}, "executable_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, "executable_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "runtime_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/runtimeId"}, "runtime_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, "runtime_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "entrypoint": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/relativePath"}, "argument_schema_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/schemaId"}, "argument_schema_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "maximum_starts": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "side_effect_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectId"}, "side_effect_authorization": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectGrant"}}}, + "resolvedNetworkDestination": {"type": "object", "additionalProperties": false, "required": ["destination_id", "protocol", "host", "ports", "address_policy_sigil", "redirect_policy", "side_effect_id", "side_effect_authorization"], "properties": {"destination_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/destinationId"}, "protocol": {"enum": ["TCP", "UDP", "HTTP", "HTTPS"]}, "host": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/hostName"}, "ports": {"type": "array", "minItems": 1, "maxItems": 32, "uniqueItems": true, "items": {"type": "integer", "minimum": 1, "maximum": 65535}}, "address_policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "redirect_policy": {"enum": ["DENY", "SAME_DESTINATION"]}, "side_effect_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectId"}, "side_effect_authorization": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectGrant"}}}, + "resolvedNetworkAuthority": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["mode", "dns_mode", "destinations", "maximum_connections", "maximum_requests", "maximum_egress_bytes"], "properties": {"mode": {"const": "DENY"}, "dns_mode": {"const": "DENY"}, "destinations": {"type": "array", "maxItems": 0}, "maximum_connections": {"const": 0}, "maximum_requests": {"const": 0}, "maximum_egress_bytes": {"const": 0}}}, {"type": "object", "additionalProperties": false, "required": ["mode", "dns_mode", "destinations", "maximum_connections", "maximum_requests", "maximum_egress_bytes"], "properties": {"mode": {"const": "ALLOWLIST"}, "dns_mode": {"const": "PINNED_ANSWER"}, "destinations": {"type": "array", "minItems": 1, "maxItems": 256, "uniqueItems": true, "items": {"$ref": "#/$defs/resolvedNetworkDestination"}}, "maximum_connections": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "maximum_requests": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "maximum_egress_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}}}]}, + "resolvedCredentialHandle": {"type": "object", "additionalProperties": false, "required": ["handle_id", "credential_class", "scope_sigil", "maximum_uses", "side_effect_id", "side_effect_authorization"], "properties": {"handle_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/credentialHandleId"}, "credential_class": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/token"}, "scope_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "maximum_uses": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "side_effect_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectId"}, "side_effect_authorization": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectGrant"}}}, + "resolvedCredentialAuthority": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["mode", "ambient_credentials", "value_exposure", "handles"], "properties": {"mode": {"const": "DENY"}, "ambient_credentials": {"const": false}, "value_exposure": {"const": "NEVER"}, "handles": {"type": "array", "maxItems": 0}}}, {"type": "object", "additionalProperties": false, "required": ["mode", "ambient_credentials", "value_exposure", "handles"], "properties": {"mode": {"const": "OPAQUE_HANDLES"}, "ambient_credentials": {"const": false}, "value_exposure": {"const": "NEVER"}, "handles": {"type": "array", "minItems": 1, "maxItems": 64, "uniqueItems": true, "items": {"$ref": "#/$defs/resolvedCredentialHandle"}}}}]}, + "resolvedOutputGrant": {"type": "object", "additionalProperties": false, "required": ["logical_name", "schema_id", "schema_sigil", "maximum_bytes", "maximum_count", "path_rule", "side_effect_id", "side_effect_authorization"], "properties": {"logical_name": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/logicalName"}, "schema_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/schemaId"}, "schema_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "maximum_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "maximum_count": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "path_rule": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/pathRule"}, "side_effect_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectId"}, "side_effect_authorization": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectGrant"}}}, + "resolvedOutputAuthority": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["mode", "maximum_outputs", "maximum_aggregate_bytes", "grants"], "properties": {"mode": {"const": "DENY"}, "maximum_outputs": {"const": 0}, "maximum_aggregate_bytes": {"const": 0}, "grants": {"type": "array", "maxItems": 0}}}, {"type": "object", "additionalProperties": false, "required": ["mode", "maximum_outputs", "maximum_aggregate_bytes", "grants"], "properties": {"mode": {"const": "ALLOWLIST"}, "maximum_outputs": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "maximum_aggregate_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "grants": {"type": "array", "minItems": 1, "maxItems": 256, "uniqueItems": true, "items": {"$ref": "#/$defs/resolvedOutputGrant"}}}}]}, + "resultRequirement": {"type": "object", "additionalProperties": false, "required": ["worker_result_mode", "successful_worker_outcome"], "properties": {"worker_result_mode": {"enum": ["REQUIRED", "OPTIONAL", "FORBIDDEN"]}, "successful_worker_outcome": {"const": "COMPLETED"}}}, + "assuranceRequirement": {"type": "object", "additionalProperties": false, "required": ["requested_level", "profile_version", "profile_sigil", "conformance_suite_id", "conformance_suite_sigil"], "properties": {"requested_level": {"enum": ["SANCTUM-A0", "SANCTUM-A1", "SANCTUM-A2"]}, "profile_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, "profile_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "conformance_suite_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/conformanceSuiteId"}, "conformance_suite_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}}}, + "retryPolicy": {"type": "object", "additionalProperties": false, "required": ["max_attempts", "retryable_terminal_reasons", "backoff_kind", "backoff_base_seconds", "backoff_cap_seconds", "resume_policy", "external_side_effects_retry_safe"], "properties": {"max_attempts": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "retryable_terminal_reasons": {"type": "array", "maxItems": 25, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/retryableTerminalReason"}}, "backoff_kind": {"enum": ["NONE", "FIXED", "EXPONENTIAL"]}, "backoff_base_seconds": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "backoff_cap_seconds": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "resume_policy": {"enum": ["FRESH_ONLY", "ALLOW_IMMUTABLE_RESUME"]}, "external_side_effects_retry_safe": {"type": "boolean"}}, "allOf": [{"if": {"properties": {"backoff_kind": {"const": "NONE"}}}, "then": {"properties": {"backoff_base_seconds": {"const": 0}, "backoff_cap_seconds": {"const": 0}}}}, {"if": {"properties": {"backoff_kind": {"const": "FIXED"}}}, "then": {"properties": {"backoff_base_seconds": {"minimum": 1}, "backoff_cap_seconds": {"minimum": 1}}}}, {"if": {"properties": {"max_attempts": {"minimum": 2}}}, "then": {"properties": {"retryable_terminal_reasons": {"minItems": 1}}}}]}, + "loggingPolicy": {"type": "object", "additionalProperties": false, "required": ["stdout_maximum_bytes", "stderr_maximum_bytes", "structured_maximum_bytes", "aggregate_maximum_bytes", "chunk_maximum_bytes", "overflow_behavior"], "properties": {"stdout_maximum_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "stderr_maximum_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "structured_maximum_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "aggregate_maximum_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "chunk_maximum_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "overflow_behavior": {"enum": ["TRUNCATE", "TERMINATE"]}}}, + "postTerminalDerivation": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["mode"], "properties": {"mode": {"const": "NONE"}}}, {"type": "object", "additionalProperties": false, "required": ["mode", "crucible_base_identity", "crucible_base_sigil", "retention_policy_id", "retention_policy_version", "retention_policy_sigil", "terminal_source_maximum_files", "terminal_source_maximum_bytes", "retention_duration_seconds", "source_identity_profile"], "properties": {"mode": {"const": "CODE_MODIFICATION"}, "crucible_base_identity": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/token"}, "crucible_base_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "retention_policy_id": {"$ref": "https://benchwork.dev/schemas/artifact-retention-policy/1.0#/$defs/policyId"}, "retention_policy_version": {"const": "1.0"}, "retention_policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "terminal_source_maximum_files": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "terminal_source_maximum_bytes": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "retention_duration_seconds": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, "source_identity_profile": {"const": "BENCHWORK_SOURCE_TREE_V1"}}}]} + } +} + diff --git a/schemas/execution-start-request-1.0.json b/schemas/execution-start-request-1.0.json new file mode 100644 index 0000000..115953b --- /dev/null +++ b/schemas/execution-start-request-1.0.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-start-request/1.0", + "title": "Execution Start Request v1", + "description": "Closed RFC-0015 contract-only Start request. The complete nested Execution Specification is validated at its canonical RFC-0012 contract ID; Job allocation, persistence, and request-Sigil derivation are outside this contract.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "execution_specification", "idempotency_key"], + "properties": { + "schema_version": {"const": "execution-start-request/1.0"}, + "execution_specification": { + "$ref": "https://benchwork.dev/schemas/execution-specification/1.0" + }, + "idempotency_key": {"$ref": "#/$defs/opaque"} + }, + "$defs": { + "opaque": { + "type": "string", + "not": {"pattern": "[\\u0000-\\u001F\\u007F-\\u009F]"}, + "minLength": 1, + "maxLength": 256 + } + } +} + diff --git a/schemas/execution-state-1.0.json b/schemas/execution-state-1.0.json new file mode 100644 index 0000000..7dc093a --- /dev/null +++ b/schemas/execution-state-1.0.json @@ -0,0 +1,183 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-state/1.0", + "title": "Execution State v1", + "description": "Closed replaceable RFC-0012 replay cache. Validation grants no replay, append, worker, lease, result, storage, assurance, or scientific authority.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "limit_profile", "journal_binding", "executor", "recoveries", "workers", "worker_sessions", "jobs", "attempts", "leases", "log_streams", "deadlines", "idempotency_records", "state_sigil"], + "properties": { + "schema_version": {"const": "execution-state/1.0"}, + "limit_profile": {"const": "EXECUTION_JOURNAL_V1_FIXED_LIMITS"}, + "journal_binding": {"$ref": "#/$defs/journal_binding"}, + "executor": {"$ref": "#/$defs/executor_projection"}, + "recoveries": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/recovery_projection"}}, + "workers": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/worker_projection"}}, + "worker_sessions": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/worker_session_projection"}}, + "jobs": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/job_projection"}}, + "attempts": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/attempt_projection"}}, + "leases": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/lease_projection"}}, + "log_streams": {"type": "array", "maxItems": 12288, "items": {"$ref": "#/$defs/log_stream_projection"}}, + "deadlines": {"type": "array", "maxItems": 32768, "items": {"$ref": "#/$defs/deadline_projection"}}, + "idempotency_records": {"type": "array", "maxItems": 65536, "items": {"$ref": "#/$defs/idempotency_record"}}, + "state_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "positive_u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "opaque_id": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9_:+-]{0,127}$", "minLength": 1, "maxLength": 128}, + "event_id": {"type": "string", "pattern": "^JE-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "journal_id": {"type": "string", "pattern": "^EJ-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "recovery_id": {"type": "string", "pattern": "^RY-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "log_stream_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/logStreamId"}, + "nullable_sigil": {"oneOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, + "nullable_u63": {"oneOf": [{"$ref": "#/$defs/u63"}, {"type": "null"}]}, + "nullable_u64": {"oneOf": [{"$ref": "#/$defs/u64"}, {"type": "null"}]}, + "nullable_timestamp": {"oneOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, + "nullable_event_id": {"oneOf": [{"$ref": "#/$defs/event_id"}, {"type": "null"}]}, + "nullable_attempt_id": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, {"type": "null"}]}, + "nullable_lease_id": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, {"type": "null"}]}, + + "public_fence_tuple": { + "type": "object", "additionalProperties": false, + "required": ["journal_id", "executor_epoch", "job_id", "attempt_id", "lease_id", "fencing_generation"], + "properties": { + "journal_id": {"$ref": "#/$defs/journal_id"}, "executor_epoch": {"$ref": "#/$defs/u64"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, + "lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, + "fencing_generation": {"$ref": "#/$defs/u64"} + } + }, + "executor_build_binding": { + "type": "object", "additionalProperties": false, + "required": ["implementation_id", "implementation_version", "source_revision_sigil", "executable_artifact_sigil", "dependency_set_sigil", "build_configuration_sigil", "executor_build_sigil"], + "properties": { + "implementation_id": {"$ref": "#/$defs/opaque_id"}, "implementation_version": {"$ref": "#/$defs/opaque_id"}, + "source_revision_sigil": {"$ref": "#/$defs/sigil"}, "executable_artifact_sigil": {"$ref": "#/$defs/sigil"}, + "dependency_set_sigil": {"$ref": "#/$defs/sigil"}, "build_configuration_sigil": {"$ref": "#/$defs/sigil"}, + "executor_build_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "job_state": {"enum": ["SUBMITTED", "QUEUED", "ACTIVE", "RETRY_WAIT", "STOPPING", "SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATION"]}, + "attempt_state": {"enum": ["CREATED", "PREFLIGHTING", "READY", "LEASED", "STARTING", "RUNNING", "DRAINING", "STOPPING", "CLEANING", "SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATION", "LEASE_EXPIRED", "LOST", "FENCED", "REJECTED"]}, + "worker_state": {"enum": ["REGISTERED", "ENABLED", "DRAINING", "QUARANTINED", "RETIRED"]}, + "worker_session_state": {"enum": ["REGISTERED", "READY", "BUSY", "DRAINING", "OFFLINE", "QUARANTINED", "CLOSED"]}, + "lease_state": {"enum": ["OFFERED", "ACTIVE", "RELEASED", "REVOKED", "EXPIRED", "FENCED"]}, + + "journal_binding": { + "type": "object", "additionalProperties": false, + "required": ["journal_id", "through_sequence", "through_event_id", "through_event_sigil"], + "properties": {"journal_id": {"$ref": "#/$defs/journal_id"}, "through_sequence": {"$ref": "#/$defs/positive_u63"}, "through_event_id": {"$ref": "#/$defs/event_id"}, "through_event_sigil": {"$ref": "#/$defs/sigil"}} + }, + "terminal_event_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "terminal_state", "terminal_event_id", "terminal_event_sigil", "terminal_sequence", "terminal_recorded_at"], "properties": {"kind": {"const": "PRESENT"}, "terminal_state": {"anyOf": [{"$ref": "#/$defs/job_state"}, {"$ref": "#/$defs/attempt_state"}, {"$ref": "#/$defs/lease_state"}]}, "terminal_event_id": {"$ref": "#/$defs/event_id"}, "terminal_event_sigil": {"$ref": "#/$defs/sigil"}, "terminal_sequence": {"$ref": "#/$defs/positive_u63"}, "terminal_recorded_at": {"$ref": "#/$defs/timestamp"}}} + ] + }, + "resource_counter_floors": { + "type": "object", "additionalProperties": false, + "required": ["cpu_time_seconds", "storage_bytes_written", "network_egress_bytes"], + "properties": {"cpu_time_seconds": {"$ref": "#/$defs/nullable_u63"}, "storage_bytes_written": {"$ref": "#/$defs/nullable_u63"}, "network_egress_bytes": {"$ref": "#/$defs/nullable_u63"}} + }, + + "attempt_authorization_requirement": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptAuthorizationRequirement"}, + "attempt_authorization_binding": { + "type": "object", "additionalProperties": false, + "required": ["authorization_subject_id", "authorization_subject_sigil", "authorization_transition_request_id", "authorization_transition_request_sigil", "authorization_event_id", "authorization_event_body_sigil", "authorization_receipt_id", "authorization_receipt_sigil", "authorization_binding_sigil"], + "properties": { + "authorization_subject_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/authorizationSubjectId"}, "authorization_subject_sigil": {"$ref": "#/$defs/sigil"}, + "authorization_transition_request_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-transition-request/1.0#/$defs/transitionRequestId"}, "authorization_transition_request_sigil": {"$ref": "#/$defs/sigil"}, + "authorization_event_id": {"$ref": "#/$defs/opaque_id"}, "authorization_event_body_sigil": {"$ref": "#/$defs/sigil"}, + "authorization_receipt_id": {"type": "string", "pattern": "^RC-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, "authorization_receipt_sigil": {"$ref": "#/$defs/sigil"}, "authorization_binding_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "attempt_authorization_state": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "PENDING"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "authorization_subject", "attempt_authorization_binding"], "properties": {"kind": {"const": "BOUND"}, "authorization_subject": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0"}, "attempt_authorization_binding": {"$ref": "#/$defs/attempt_authorization_binding"}}} + ] + }, + "reason_codes": {"type": "array", "minItems": 1, "maxItems": 128, "uniqueItems": true, "items": {"$ref": "#/$defs/opaque_id"}}, + "attempt_assurance_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "PENDING"}}}, + {"$ref": "#/$defs/attempt_assurance_claimed"}, {"$ref": "#/$defs/attempt_assurance_negative"} + ] + }, + "attempt_assurance_claimed": {"type": "object", "additionalProperties": false, "required": ["kind", "evaluation_event_id", "evaluation_event_sigil", "evaluation_sequence", "assurance_claim_sigil", "evidence_set_sigil"], "properties": {"kind": {"const": "CLAIMED"}, "evaluation_event_id": {"$ref": "#/$defs/event_id"}, "evaluation_event_sigil": {"$ref": "#/$defs/sigil"}, "evaluation_sequence": {"$ref": "#/$defs/positive_u63"}, "assurance_claim_sigil": {"$ref": "#/$defs/sigil"}, "evidence_set_sigil": {"$ref": "#/$defs/sigil"}}}, + "attempt_assurance_negative": {"type": "object", "additionalProperties": false, "required": ["kind", "evaluation_event_id", "evaluation_event_sigil", "evaluation_sequence", "reason_codes", "evidence_set_sigil"], "properties": {"kind": {"enum": ["UNMET", "UNVERIFIABLE"]}, "evaluation_event_id": {"$ref": "#/$defs/event_id"}, "evaluation_event_sigil": {"$ref": "#/$defs/sigil"}, "evaluation_sequence": {"$ref": "#/$defs/positive_u63"}, "reason_codes": {"$ref": "#/$defs/reason_codes"}, "evidence_set_sigil": {"$ref": "#/$defs/sigil"}}}, + "job_assurance_binding": { + "oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "PENDING"}}}, + {"$ref": "#/$defs/job_assurance_claimed"}, {"$ref": "#/$defs/job_assurance_negative"}, + {"type": "object", "additionalProperties": false, "required": ["kind", "evaluation_event_id", "evaluation_event_sigil", "evaluation_sequence", "reason", "evidence_set_sigil"], "properties": {"kind": {"const": "NOT_APPLICABLE"}, "evaluation_event_id": {"$ref": "#/$defs/event_id"}, "evaluation_event_sigil": {"$ref": "#/$defs/sigil"}, "evaluation_sequence": {"$ref": "#/$defs/positive_u63"}, "reason": {"const": "NO_ATTEMPT_ALLOCATED"}, "evidence_set_sigil": {"$ref": "#/$defs/sigil"}}} + ] + }, + "job_assurance_claimed": {"type": "object", "additionalProperties": false, "required": ["kind", "evaluation_event_id", "evaluation_event_sigil", "evaluation_sequence", "attempt_id", "attempt_assurance_event_sigil", "assurance_claim_sigil", "evidence_set_sigil"], "properties": {"kind": {"const": "CLAIMED"}, "evaluation_event_id": {"$ref": "#/$defs/event_id"}, "evaluation_event_sigil": {"$ref": "#/$defs/sigil"}, "evaluation_sequence": {"$ref": "#/$defs/positive_u63"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, "attempt_assurance_event_sigil": {"$ref": "#/$defs/sigil"}, "assurance_claim_sigil": {"$ref": "#/$defs/sigil"}, "evidence_set_sigil": {"$ref": "#/$defs/sigil"}}}, + "job_assurance_negative": {"type": "object", "additionalProperties": false, "required": ["kind", "evaluation_event_id", "evaluation_event_sigil", "evaluation_sequence", "attempt_id", "attempt_assurance_event_sigil", "reason_codes", "evidence_set_sigil"], "properties": {"kind": {"enum": ["UNMET", "UNVERIFIABLE"]}, "evaluation_event_id": {"$ref": "#/$defs/event_id"}, "evaluation_event_sigil": {"$ref": "#/$defs/sigil"}, "evaluation_sequence": {"$ref": "#/$defs/positive_u63"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, "attempt_assurance_event_sigil": {"$ref": "#/$defs/sigil"}, "reason_codes": {"$ref": "#/$defs/reason_codes"}, "evidence_set_sigil": {"$ref": "#/$defs/sigil"}}}, + + "budget_dimension": {"type": "object", "additionalProperties": false, "required": ["limit", "reserved", "consumed", "exhaustion_status"], "properties": {"limit": {"$ref": "#/$defs/u63"}, "reserved": {"$ref": "#/$defs/u63"}, "consumed": {"$ref": "#/$defs/u63"}, "exhaustion_status": {"enum": ["AVAILABLE", "EXHAUSTED", "EXCEEDED"]}}}, + "budget_ledger": {"type": "object", "additionalProperties": false, "required": ["attempts", "cpu_time_seconds", "storage_bytes_written", "output_bytes", "log_bytes", "process_starts", "network_egress_bytes", "network_requests", "budget_ledger_sigil"], "properties": {"attempts": {"$ref": "#/$defs/budget_dimension"}, "cpu_time_seconds": {"$ref": "#/$defs/budget_dimension"}, "storage_bytes_written": {"$ref": "#/$defs/budget_dimension"}, "output_bytes": {"$ref": "#/$defs/budget_dimension"}, "log_bytes": {"$ref": "#/$defs/budget_dimension"}, "process_starts": {"$ref": "#/$defs/budget_dimension"}, "network_egress_bytes": {"$ref": "#/$defs/budget_dimension"}, "network_requests": {"$ref": "#/$defs/budget_dimension"}, "budget_ledger_sigil": {"$ref": "#/$defs/sigil"}}}, + "budget_settlement_binding": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "PENDING"}}}, {"type": "object", "additionalProperties": false, "required": ["kind", "event_id", "event_sigil", "accounting_capture_event_id", "accounting_capture_event_sigil", "usage_status"], "properties": {"kind": {"const": "SETTLED"}, "event_id": {"$ref": "#/$defs/event_id"}, "event_sigil": {"$ref": "#/$defs/sigil"}, "accounting_capture_event_id": {"$ref": "#/$defs/event_id"}, "accounting_capture_event_sigil": {"$ref": "#/$defs/sigil"}, "usage_status": {"enum": ["MEASURED", "PARTIAL", "UNAVAILABLE"]}}}]}, + "accounting_capture_binding": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "PENDING"}}}, {"type": "object", "additionalProperties": false, "required": ["kind", "event_id", "event_sigil", "usage_status", "accounting_evidence_set_sigil"], "properties": {"kind": {"const": "CAPTURED"}, "event_id": {"$ref": "#/$defs/event_id"}, "event_sigil": {"$ref": "#/$defs/sigil"}, "usage_status": {"enum": ["MEASURED", "PARTIAL", "UNAVAILABLE"]}, "accounting_evidence_set_sigil": {"$ref": "#/$defs/sigil"}}}]}, + + "executor_projection": { + "type": "object", "additionalProperties": false, + "required": ["executor_instance_id", "executor_epoch", "executor_build_binding", "revision", "clock_state", "last_trusted_utc", "clock_uncertain_event_id", "active_recovery_id", "authority_gates", "last_event_id", "last_event_sigil"], + "properties": {"executor_instance_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/executorInstanceId"}, "executor_epoch": {"$ref": "#/$defs/u64"}, "executor_build_binding": {"$ref": "#/$defs/executor_build_binding"}, "revision": {"$ref": "#/$defs/u64"}, "clock_state": {"enum": ["TRUSTED", "UNCERTAIN"]}, "last_trusted_utc": {"$ref": "#/$defs/timestamp"}, "clock_uncertain_event_id": {"$ref": "#/$defs/nullable_event_id"}, "active_recovery_id": {"oneOf": [{"$ref": "#/$defs/recovery_id"}, {"type": "null"}]}, "authority_gates": {"type": "array", "maxItems": 3, "uniqueItems": true, "items": {"enum": ["INTEGRITY_FAILURE", "CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"]}}, "last_event_id": {"$ref": "#/$defs/event_id"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}, + "allOf": [{"if": {"properties": {"clock_state": {"const": "TRUSTED"}}}, "then": {"properties": {"clock_uncertain_event_id": {"type": "null"}}}}, {"if": {"properties": {"clock_state": {"const": "UNCERTAIN"}}}, "then": {"properties": {"clock_uncertain_event_id": {"$ref": "#/$defs/event_id"}}}}] + }, + "recovery_projection": {"type": "object", "additionalProperties": false, "required": ["recovery_id", "revision", "state", "prior_recovery_id", "started_event_sigil", "current_action_set_sigil", "last_event_id", "last_event_sigil"], "properties": {"recovery_id": {"$ref": "#/$defs/recovery_id"}, "revision": {"$ref": "#/$defs/u64"}, "state": {"enum": ["STARTED", "FENCING", "RECONCILING", "FINALIZING", "COMPLETED"]}, "prior_recovery_id": {"oneOf": [{"$ref": "#/$defs/recovery_id"}, {"type": "null"}]}, "started_event_sigil": {"$ref": "#/$defs/sigil"}, "current_action_set_sigil": {"$ref": "#/$defs/nullable_sigil"}, "last_event_id": {"$ref": "#/$defs/event_id"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "worker_projection": {"type": "object", "additionalProperties": false, "required": ["worker_id", "revision", "state", "worker_binding_sigil", "definition_revision", "worker_session_ids", "last_event_id", "last_event_sigil"], "properties": {"worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, "revision": {"$ref": "#/$defs/u64"}, "state": {"$ref": "#/$defs/worker_state"}, "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, "definition_revision": {"$ref": "#/$defs/u64"}, "worker_session_ids": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}}, "last_event_id": {"$ref": "#/$defs/event_id"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "worker_session_projection": { + "type": "object", "additionalProperties": false, + "required": ["worker_session_id", "revision", "state", "worker_id", "worker_binding_sigil", "worker_session_binding_sigil", "executor_epoch", "worker_session_heartbeat_policy_id", "worker_session_heartbeat_policy_sigil", "capacity", "capacity_in_use", "last_heartbeat_sequence", "last_heartbeat_message_sigil", "last_resource_sample_sigil", "resource_counter_floors", "next_heartbeat_due_at", "lease_ids", "last_event_id", "last_event_sigil"], + "properties": {"worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, "revision": {"$ref": "#/$defs/u64"}, "state": {"$ref": "#/$defs/worker_session_state"}, "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, "executor_epoch": {"$ref": "#/$defs/u64"}, "worker_session_heartbeat_policy_id": {"oneOf": [{"type": "string", "pattern": "^WSHP-[0-9A-F]{64}$", "minLength": 69, "maxLength": 69}, {"type": "null"}]}, "worker_session_heartbeat_policy_sigil": {"$ref": "#/$defs/nullable_sigil"}, "capacity": {"$ref": "#/$defs/nullable_u63"}, "capacity_in_use": {"$ref": "#/$defs/u63"}, "last_heartbeat_sequence": {"$ref": "#/$defs/nullable_u63"}, "last_heartbeat_message_sigil": {"$ref": "#/$defs/nullable_sigil"}, "last_resource_sample_sigil": {"$ref": "#/$defs/nullable_sigil"}, "resource_counter_floors": {"$ref": "#/$defs/resource_counter_floors"}, "next_heartbeat_due_at": {"$ref": "#/$defs/nullable_timestamp"}, "lease_ids": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}}, "last_event_id": {"$ref": "#/$defs/event_id"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}, + "allOf": [{"if": {"properties": {"capacity": {"type": "null"}}}, "then": {"properties": {"worker_session_heartbeat_policy_id": {"type": "null"}, "worker_session_heartbeat_policy_sigil": {"type": "null"}, "capacity_in_use": {"const": 0}}}}, {"if": {"properties": {"capacity": {"type": "integer"}}}, "then": {"properties": {"worker_session_heartbeat_policy_id": {"type": "string"}, "worker_session_heartbeat_policy_sigil": {"type": "string"}}}}] + }, + + "queue_key": {"type": "object", "additionalProperties": false, "required": ["ready_sequence", "job_id"], "properties": {"ready_sequence": {"$ref": "#/$defs/positive_u63"}, "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}}}, + "output_hold_release_schedule": {"type": "object", "additionalProperties": false, "required": ["attempt_id", "storage_root_manifest_id", "storage_root_manifest_sigil", "reference_set_id", "reference_set_sigil", "hold_id", "hold_set_event", "retention_duration_seconds", "root_inactivation_event_id", "release_due_at", "deadline_status"], "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, "storage_root_manifest_id": {"$ref": "#/$defs/opaque_id"}, "storage_root_manifest_sigil": {"$ref": "#/$defs/sigil"}, "reference_set_id": {"$ref": "#/$defs/opaque_id"}, "reference_set_sigil": {"$ref": "#/$defs/sigil"}, "hold_id": {"$ref": "#/$defs/opaque_id"}, "hold_set_event": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_ref"}, "retention_duration_seconds": {"$ref": "#/$defs/u63"}, "root_inactivation_event_id": {"$ref": "#/$defs/event_id"}, "release_due_at": {"$ref": "#/$defs/timestamp"}, "deadline_status": {"enum": ["EXACT", "OVERFLOW_FAIL_CLOSED"]}}}, + "job_projection": { + "type": "object", "additionalProperties": false, + "required": ["job_id", "revision", "state", "job_binding_sigil", "job_storage_roots", "attempt_ids", "current_attempt_id", "fencing_counter", "fence_floor", "budget_ledger", "deadline_due_at", "retry_eligible_due_at", "queue_key", "attempt_summaries", "selected_attempt_binding", "completion_anchor_binding", "first_stop_or_fence_binding", "final_fence_binding", "storage_observation_binding", "terminal_source_binding", "output_hold_release_schedules", "job_assurance_binding", "terminal_event_binding", "last_event_id", "last_event_sigil"], + "properties": {"job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "revision": {"$ref": "#/$defs/u64"}, "state": {"$ref": "#/$defs/job_state"}, "job_binding_sigil": {"$ref": "#/$defs/sigil"}, "job_storage_roots": {"type": "array", "maxItems": 1, "items": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/storage_root_binding"}}, "attempt_ids": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}}, "current_attempt_id": {"$ref": "#/$defs/nullable_attempt_id"}, "fencing_counter": {"$ref": "#/$defs/u64"}, "fence_floor": {"$ref": "#/$defs/u64"}, "budget_ledger": {"$ref": "#/$defs/budget_ledger"}, "deadline_due_at": {"$ref": "#/$defs/timestamp"}, "retry_eligible_due_at": {"$ref": "#/$defs/nullable_timestamp"}, "queue_key": {"oneOf": [{"$ref": "#/$defs/queue_key"}, {"type": "null"}]}, "attempt_summaries": {"type": "array", "maxItems": 4096, "items": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/attempt_summary"}}, "selected_attempt_binding": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/selected_attempt_binding"}, {"type": "null"}]}, "completion_anchor_binding": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/completion_anchor_binding"}, {"type": "null"}]}, "first_stop_or_fence_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/first_stop_or_fence_binding"}, "final_fence_binding": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/final_fence_binding"}, {"type": "null"}]}, "storage_observation_binding": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/storage_observation_binding"}, {"type": "null"}]}, "terminal_source_binding": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/terminal_source_binding"}, {"type": "null"}]}, "output_hold_release_schedules": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/output_hold_release_schedule"}}, "job_assurance_binding": {"$ref": "#/$defs/job_assurance_binding"}, "terminal_event_binding": {"$ref": "#/$defs/terminal_event_binding"}, "last_event_id": {"$ref": "#/$defs/event_id"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}} + }, + + "result_intake": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, {"$ref": "#/$defs/result_intake_received"}, {"$ref": "#/$defs/result_intake_disposed"}]}, + "result_intake_received": {"type": "object", "additionalProperties": false, "required": ["kind", "result_ingress_receipt_binding", "observation_evidence_subject_sigil", "result_sigil", "received_at", "ingress_event_intent_id", "ingress_event_id", "ingress_event_sigil"], "properties": {"kind": {"const": "RECEIVED"}, "result_ingress_receipt_binding": {"$ref": "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0#/$defs/result_ingress_receipt_binding"}, "observation_evidence_subject_sigil": {"$ref": "#/$defs/sigil"}, "result_sigil": {"$ref": "#/$defs/sigil"}, "received_at": {"$ref": "#/$defs/timestamp"}, "ingress_event_intent_id": {"$ref": "#/$defs/opaque_id"}, "ingress_event_id": {"$ref": "#/$defs/event_id"}, "ingress_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "result_intake_disposed": {"type": "object", "additionalProperties": false, "required": ["kind", "result_ingress_receipt_binding", "observation_evidence_subject_sigil", "result_sigil", "received_at", "ingress_event_intent_id", "ingress_event_id", "ingress_event_sigil", "observation_evidence_id", "observation_evidence_sigil", "outcome", "disposition_event_id", "disposition_event_sigil"], "properties": {"kind": {"const": "DISPOSED"}, "result_ingress_receipt_binding": {"$ref": "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0#/$defs/result_ingress_receipt_binding"}, "observation_evidence_subject_sigil": {"$ref": "#/$defs/sigil"}, "result_sigil": {"$ref": "#/$defs/sigil"}, "received_at": {"$ref": "#/$defs/timestamp"}, "ingress_event_intent_id": {"$ref": "#/$defs/opaque_id"}, "ingress_event_id": {"$ref": "#/$defs/event_id"}, "ingress_event_sigil": {"$ref": "#/$defs/sigil"}, "observation_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_evidence_id"}, "observation_evidence_sigil": {"$ref": "#/$defs/sigil"}, "outcome": {"enum": ["ACCEPTED", "REJECTED"]}, "disposition_event_id": {"$ref": "#/$defs/event_id"}, "disposition_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "output_staging_preallocation": {"type": "object", "additionalProperties": false, "required": ["storage_subject_id", "output_handle_id", "transfer_id", "transfer_attempt_id", "authorized_maximum_bytes", "preallocation_binding_sigil", "preallocation_event_id", "preallocation_event_sigil"], "properties": {"storage_subject_id": {"$ref": "#/$defs/sigil"}, "output_handle_id": {"$ref": "#/$defs/opaque_id"}, "transfer_id": {"$ref": "#/$defs/opaque_id"}, "transfer_attempt_id": {"$ref": "#/$defs/opaque_id"}, "authorized_maximum_bytes": {"$ref": "#/$defs/positive_u63"}, "preallocation_binding_sigil": {"$ref": "#/$defs/sigil"}, "preallocation_event_id": {"$ref": "#/$defs/event_id"}, "preallocation_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "capacity_failure_binding": {"type": "object", "additionalProperties": false, "required": ["kind", "capacity_failure_id", "capacity_failure_sigil"], "properties": {"kind": {"const": "CAPACITY_FAILED"}, "capacity_failure_id": {"type": "string", "pattern": "^ECF-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, "capacity_failure_sigil": {"$ref": "#/$defs/sigil"}}}, + "quarantine_binding_set_binding": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-quarantine-binding-set/1.0#/$defs/quarantineBindingSetBinding"}, {"type": "object", "additionalProperties": false, "required": ["kind", "capacity_failure_id", "capacity_failure_sigil", "storage_cut_binding"], "properties": {"kind": {"const": "CAPACITY_FAILED"}, "capacity_failure_id": {"type": "string", "pattern": "^ECF-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, "capacity_failure_sigil": {"$ref": "#/$defs/sigil"}, "storage_cut_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/storage_cut_binding"}}}]}, + "attempt_projection": { + "type": "object", "additionalProperties": false, + "required": ["attempt_id", "revision", "state", "attempt_binding_sigil", "job_id", "retry_ordinal", "fencing_generation", "lease_executor_epoch", "public_fence_tuple", "worker_session_binding", "lease_id", "result_binding", "result_intake", "output_staging_preallocations", "attempt_authorization_requirement", "attempt_authorization_state", "completion_anchor_binding", "lease_terminal_binding", "first_stop_or_fence_binding", "storage_observation_binding", "terminal_source_binding", "accounting_capture_binding", "budget_settlement_binding", "attempt_assurance_binding", "input_storage_roots", "output_storage_roots", "control_evidence_set_binding", "quarantine_binding_set_binding", "terminalization_storage_manifest_binding", "output_root_protection", "deadline_due_at", "grace_due_at", "terminal_event_binding", "last_event_id", "last_event_sigil"], + "properties": {"attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, "revision": {"$ref": "#/$defs/u64"}, "state": {"$ref": "#/$defs/attempt_state"}, "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "retry_ordinal": {"$ref": "#/$defs/positive_u63"}, "fencing_generation": {"$ref": "#/$defs/u64"}, "lease_executor_epoch": {"$ref": "#/$defs/nullable_u64"}, "public_fence_tuple": {"oneOf": [{"$ref": "#/$defs/public_fence_tuple"}, {"type": "null"}]}, "worker_session_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/worker_session_binding"}, "lease_id": {"$ref": "#/$defs/nullable_lease_id"}, "result_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/result_binding"}, "result_intake": {"$ref": "#/$defs/result_intake"}, "output_staging_preallocations": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/output_staging_preallocation"}}, "attempt_authorization_requirement": {"$ref": "#/$defs/attempt_authorization_requirement"}, "attempt_authorization_state": {"$ref": "#/$defs/attempt_authorization_state"}, "completion_anchor_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/completion_anchor_binding"}, "lease_terminal_binding": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/lease_terminal_binding"}, {"type": "null"}]}, "first_stop_or_fence_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/first_stop_or_fence_binding"}, "storage_observation_binding": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/storage_observation_binding"}, {"type": "null"}]}, "terminal_source_binding": {"oneOf": [{"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/terminal_source_binding"}, {"type": "null"}]}, "accounting_capture_binding": {"$ref": "#/$defs/accounting_capture_binding"}, "budget_settlement_binding": {"$ref": "#/$defs/budget_settlement_binding"}, "attempt_assurance_binding": {"$ref": "#/$defs/attempt_assurance_binding"}, "input_storage_roots": {"type": "array", "maxItems": 1, "items": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/storage_root_binding"}}, "output_storage_roots": {"type": "array", "maxItems": 1, "items": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/storage_root_binding"}}, "control_evidence_set_binding": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence-set/1.0#/$defs/controlEvidenceSetBinding"}, "quarantine_binding_set_binding": {"$ref": "#/$defs/quarantine_binding_set_binding"}, "terminalization_storage_manifest_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/terminalization_storage_manifest_binding"}, "output_root_protection": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/output_root_protection"}, "deadline_due_at": {"$ref": "#/$defs/timestamp"}, "grace_due_at": {"$ref": "#/$defs/nullable_timestamp"}, "terminal_event_binding": {"$ref": "#/$defs/terminal_event_binding"}, "last_event_id": {"$ref": "#/$defs/event_id"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}} + }, + + "lease_projection": { + "type": "object", "additionalProperties": false, + "required": ["lease_id", "revision", "state", "lease_binding_sigil", "job_id", "attempt_id", "worker_id", "worker_session_id", "executor_epoch", "fencing_generation", "claim_due_at", "expiry_due_at", "maximum_expiry_due_at", "last_heartbeat_sequence", "last_heartbeat_message_sigil", "last_resource_sample_sigil", "resource_counter_floors", "next_heartbeat_due_at", "renewal_counter", "terminal_event_binding", "tombstone_generation", "tombstone_event_sigil", "last_event_id", "last_event_sigil"], + "properties": {"lease_id": {"$ref": "https://benchwork.dev/schemas/execution-lease/1.0#/$defs/leaseId"}, "revision": {"$ref": "#/$defs/u64"}, "state": {"$ref": "#/$defs/lease_state"}, "lease_binding_sigil": {"$ref": "#/$defs/sigil"}, "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, "executor_epoch": {"$ref": "#/$defs/u64"}, "fencing_generation": {"$ref": "#/$defs/u64"}, "claim_due_at": {"$ref": "#/$defs/timestamp"}, "expiry_due_at": {"$ref": "#/$defs/timestamp"}, "maximum_expiry_due_at": {"$ref": "#/$defs/timestamp"}, "last_heartbeat_sequence": {"$ref": "#/$defs/nullable_u63"}, "last_heartbeat_message_sigil": {"$ref": "#/$defs/nullable_sigil"}, "last_resource_sample_sigil": {"$ref": "#/$defs/nullable_sigil"}, "resource_counter_floors": {"$ref": "#/$defs/resource_counter_floors"}, "next_heartbeat_due_at": {"$ref": "#/$defs/nullable_timestamp"}, "renewal_counter": {"$ref": "#/$defs/u63"}, "terminal_event_binding": {"$ref": "#/$defs/terminal_event_binding"}, "tombstone_generation": {"$ref": "#/$defs/nullable_u64"}, "tombstone_event_sigil": {"$ref": "#/$defs/nullable_sigil"}, "last_event_id": {"$ref": "#/$defs/event_id"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}} + }, + "log_stream_projection": {"type": "object", "additionalProperties": false, "required": ["log_stream_id", "revision", "state", "attempt_id", "stream", "next_sequence", "captured_bytes", "dropped_bytes", "truncated", "final_sequence", "stream_set_sigil", "last_event_id", "last_event_sigil"], "properties": {"log_stream_id": {"$ref": "#/$defs/log_stream_id"}, "revision": {"$ref": "#/$defs/u64"}, "state": {"enum": ["OPEN", "CLOSED"]}, "attempt_id": {"$ref": "https://benchwork.dev/schemas/attempt-authorization-subject/1.0#/$defs/attemptId"}, "stream": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, "next_sequence": {"$ref": "#/$defs/u63"}, "captured_bytes": {"$ref": "#/$defs/u63"}, "dropped_bytes": {"$ref": "#/$defs/u63"}, "truncated": {"type": "boolean"}, "final_sequence": {"$ref": "#/$defs/nullable_u63"}, "stream_set_sigil": {"$ref": "#/$defs/nullable_sigil"}, "last_event_id": {"$ref": "#/$defs/event_id"}, "last_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "deadline_projection": {"type": "object", "additionalProperties": false, "required": ["deadline_kind", "due_at", "fixed_priority", "entity_id", "source_event_id", "source_event_sigil"], "properties": {"deadline_kind": {"enum": ["JOB_DEADLINE", "ATTEMPT_DEADLINE", "HEARTBEAT_TIMEOUT", "LEASE_EXPIRY", "LEASE_CLAIM_DEADLINE", "CANCELLATION_GRACE", "RETRY_ELIGIBILITY"]}, "due_at": {"$ref": "#/$defs/timestamp"}, "fixed_priority": {"enum": [10, 20, 30, 40, 50, 60, 70]}, "entity_id": {"$ref": "#/$defs/opaque_id"}, "source_event_id": {"$ref": "#/$defs/event_id"}, "source_event_sigil": {"$ref": "#/$defs/sigil"}}}, + + "idempotency_operation_kind": {"enum": ["START_JOB", "CANCEL_JOB", "REGISTER_WORKER_SESSION", "CLAIM_LEASE", "RENEW_LEASE", "RELEASE_LEASE", "PREALLOCATE_OUTPUT_STAGING", "RECEIVE_RESULT_INGRESS", "SUBMIT_RESULT", "APPEND_LOG_CHUNK", "CLOSE_LOG_STREAM"]}, + "ordinary_operation_kind": {"enum": ["START_JOB", "CANCEL_JOB", "REGISTER_WORKER_SESSION", "CLAIM_LEASE", "RENEW_LEASE", "RELEASE_LEASE", "PREALLOCATE_OUTPUT_STAGING", "RECEIVE_RESULT_INGRESS", "SUBMIT_RESULT"]}, + "log_operation_kind": {"enum": ["APPEND_LOG_CHUNK", "CLOSE_LOG_STREAM"]}, + "ordinary_idempotency_record": {"type": "object", "additionalProperties": false, "required": ["operation_kind", "scope_id", "idempotency_key_sigil", "request_sigil", "disposition_event_id", "disposition_event_sigil"], "properties": {"operation_kind": {"$ref": "#/$defs/ordinary_operation_kind"}, "scope_id": {"$ref": "#/$defs/opaque_id"}, "idempotency_key_sigil": {"$ref": "#/$defs/sigil"}, "request_sigil": {"$ref": "#/$defs/sigil"}, "disposition_event_id": {"$ref": "#/$defs/event_id"}, "disposition_event_sigil": {"$ref": "#/$defs/sigil"}}}, + "log_idempotency_core": {"type": "object", "additionalProperties": false, "required": ["operation_kind", "scope_id", "idempotency_key_sigil", "full_request_identity_sigil", "intake_kind", "intake_id", "intake_record_sigil", "intent_id", "intent_sigil", "disposition_kind", "disposition_anchor_event", "ordered_disposition_events", "latest_disposition_event"], "properties": {"operation_kind": {"$ref": "#/$defs/log_operation_kind"}, "scope_id": {"$ref": "#/$defs/log_stream_id"}, "idempotency_key_sigil": {"$ref": "#/$defs/sigil"}, "full_request_identity_sigil": {"$ref": "#/$defs/sigil"}, "intake_kind": {"enum": ["RAW_CHUNK", "REJECTED_CHUNK_METADATA", "WORKER_EOF"]}, "intake_id": {"$ref": "#/$defs/opaque_id"}, "intake_record_sigil": {"$ref": "#/$defs/sigil"}, "intent_id": {"$ref": "#/$defs/opaque_id"}, "intent_sigil": {"$ref": "#/$defs/sigil"}, "disposition_kind": {"enum": ["COMMIT", "TRUNCATE", "REJECT", "DUPLICATE_OBSERVED", "ACCEPTED", "REJECTED"]}, "disposition_anchor_event": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_ref"}, "ordered_disposition_events": {"type": "array", "minItems": 1, "maxItems": 3, "items": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_ref"}}, "latest_disposition_event": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/event_ref"}}}, + "log_response_binding": {"oneOf": [{"type": "object", "additionalProperties": false, "required": ["kind", "acknowledgement_id", "acknowledgement_sigil"], "properties": {"kind": {"const": "CHUNK_ACK"}, "acknowledgement_id": {"$ref": "#/$defs/opaque_id"}, "acknowledgement_sigil": {"$ref": "#/$defs/sigil"}}}, {"type": "object", "additionalProperties": false, "required": ["kind", "eof_id", "latest_revision", "latest_disposition_sigil", "disposition_head_sigil"], "properties": {"kind": {"const": "EOF_DISPOSITION"}, "eof_id": {"$ref": "#/$defs/opaque_id"}, "latest_revision": {"$ref": "#/$defs/u63"}, "latest_disposition_sigil": {"$ref": "#/$defs/sigil"}, "disposition_head_sigil": {"$ref": "#/$defs/sigil"}}}]}, + "log_pending_ack_record": {"type": "object", "additionalProperties": false, "required": ["kind", "core", "core_projection_sigil"], "properties": {"kind": {"const": "PENDING_ACK"}, "core": {"$ref": "#/$defs/log_idempotency_core"}, "core_projection_sigil": {"$ref": "#/$defs/sigil"}}}, + "log_acked_record": {"type": "object", "additionalProperties": false, "required": ["kind", "core", "core_projection_sigil", "acknowledgement_intent_id", "acknowledgement_intent_sigil", "acknowledgement_kind", "acknowledgement_id", "acknowledgement_sigil", "response_binding", "acked_projection_sigil"], "properties": {"kind": {"const": "ACKED"}, "core": {"$ref": "#/$defs/log_idempotency_core"}, "core_projection_sigil": {"$ref": "#/$defs/sigil"}, "acknowledgement_intent_id": {"$ref": "#/$defs/opaque_id"}, "acknowledgement_intent_sigil": {"$ref": "#/$defs/sigil"}, "acknowledgement_kind": {"enum": ["CHUNK", "FREEZE", "EOF_REJECTION"]}, "acknowledgement_id": {"$ref": "#/$defs/opaque_id"}, "acknowledgement_sigil": {"$ref": "#/$defs/sigil"}, "response_binding": {"$ref": "#/$defs/log_response_binding"}, "acked_projection_sigil": {"$ref": "#/$defs/sigil"}}}, + "idempotency_record": {"oneOf": [{"$ref": "#/$defs/ordinary_idempotency_record"}, {"$ref": "#/$defs/log_pending_ack_record"}, {"$ref": "#/$defs/log_acked_record"}]} + } +} diff --git a/schemas/execution-storage-root-manifest-1.0.json b/schemas/execution-storage-root-manifest-1.0.json new file mode 100644 index 0000000..23fb562 --- /dev/null +++ b/schemas/execution-storage-root-manifest-1.0.json @@ -0,0 +1,189 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-storage-root-manifest/1.0", + "title": "Execution Storage Root Manifest v1", + "description": "Closed RFC-0012 ESM1–ESM5 contract-only wire. Shape and locally provable integrity only; owner resolution, Transfer/Provenance/Quarantine truth, atomic no-transfer proof installation, RFC-0013 replay, Reference Set/hold mutation, Journal authority, and runtime conformance remain external and fail closed.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "manifest_id", + "root_kind", + "job_id", + "attempt_id", + "owner_binding", + "entries", + "blob_refs", + "protection_plan", + "created_at", + "manifest_sigil" + ], + "properties": { + "schema_version": {"const": "execution-storage-root-manifest/1.0"}, + "manifest_id": {"$ref": "#/$defs/manifestId"}, + "root_kind": {"$ref": "#/$defs/rootKind"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, {"type": "null"}]}, + "owner_binding": {"$ref": "#/$defs/ownerBinding"}, + "entries": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/storageRootEntry"}}, + "blob_refs": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}}, + "protection_plan": {"$ref": "#/$defs/protectionPlan"}, + "created_at": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/timestamp"}, + "manifest_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + }, + "allOf": [ + { + "if": {"properties": {"root_kind": {"const": "JOB_INPUT"}}, "required": ["root_kind"]}, + "then": { + "properties": { + "attempt_id": {"type": "null"}, + "owner_binding": {"$ref": "#/$defs/jobInputOwner"}, + "entries": {"items": {"$ref": "#/$defs/jobInputEntry"}}, + "protection_plan": {"$ref": "#/$defs/inputProtectionPlan"} + } + } + }, + { + "if": {"properties": {"root_kind": {"const": "ATTEMPT_INPUT"}}, "required": ["root_kind"]}, + "then": { + "properties": { + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "owner_binding": {"$ref": "#/$defs/attemptInputOwner"}, + "entries": {"items": {"$ref": "#/$defs/attemptInputEntry"}}, + "protection_plan": {"$ref": "#/$defs/inputProtectionPlan"} + } + } + }, + { + "if": {"properties": {"root_kind": {"const": "ATTEMPT_OUTPUT"}}, "required": ["root_kind"]}, + "then": { + "properties": { + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "owner_binding": {"$ref": "#/$defs/attemptOutputOwner"}, + "entries": {"items": {"$ref": "#/$defs/attemptOutputEntry"}}, + "protection_plan": {"$ref": "#/$defs/outputProtectionPlan"} + } + } + } + ], + "$defs": { + "manifestId": {"type": "string", "pattern": "^ESM-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "rootKind": {"enum": ["JOB_INPUT", "ATTEMPT_INPUT", "ATTEMPT_OUTPUT"]}, + "ownerBinding": {"oneOf": [{"$ref": "#/$defs/jobInputOwner"}, {"$ref": "#/$defs/attemptInputOwner"}, {"$ref": "#/$defs/attemptOutputOwner"}]}, + "jobInputOwner": { + "type": "object", "additionalProperties": false, + "required": ["kind", "start_request_sigil", "task_id", "task_capsule_sigil", "specification_id", "specification_sigil", "input_set_sigil"], + "properties": { + "kind": {"const": "JOB_INPUT"}, + "start_request_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "task_id": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/taskId"}, + "task_capsule_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "specification_id": {"$ref": "https://benchwork.dev/schemas/execution-specification/1.0#/$defs/specificationId"}, + "specification_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "input_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + }, + "attemptInputOwner": { + "type": "object", "additionalProperties": false, + "required": ["kind", "job_binding_sigil", "attempt_binding_sigil", "preflight_plan_sigil", "materialization_id", "materialization_record_sigil", "input_set_sigil"], + "properties": { + "kind": {"const": "ATTEMPT_INPUT"}, + "job_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "attempt_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "preflight_plan_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "materialization_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/materializationId"}, + "materialization_record_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "input_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + }, + "attemptOutputOwner": { + "type": "object", "additionalProperties": false, + "required": ["kind", "job_binding_sigil", "attempt_binding_sigil", "result_binding", "log_set_sigil", "output_set_sigil", "control_evidence_set_binding", "terminal_source_binding", "quarantine_plan_sigil"], + "properties": { + "kind": {"const": "ATTEMPT_OUTPUT"}, + "job_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "attempt_binding_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "result_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/result_binding"}, + "log_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "output_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "control_evidence_set_binding": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence-set/1.0#/$defs/controlEvidenceSetBinding"}, + "terminal_source_binding": {"$ref": "https://benchwork.dev/schemas/execution-journal-event/1.0#/$defs/terminal_source_binding"}, + "quarantine_plan_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + }, + "storageRootEntry": { + "type": "object", "additionalProperties": false, + "required": ["storage_subject_id", "subject", "claimed_blob", "storage_origin", "entry_sigil"], + "properties": { + "storage_subject_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "subject": {"$ref": "#/$defs/subject"}, + "claimed_blob": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}, {"type": "null"}]}, + "storage_origin": {"$ref": "#/$defs/storageOrigin"}, + "entry_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } + }, + "jobInputEntry": {"allOf": [{"$ref": "#/$defs/storageRootEntry"}, {"properties": {"subject": {"$ref": "#/$defs/jobInputSubject"}}}]}, + "attemptInputEntry": {"allOf": [{"$ref": "#/$defs/storageRootEntry"}, {"properties": {"subject": {"$ref": "#/$defs/attemptInputSubject"}}}]}, + "attemptOutputEntry": {"allOf": [{"$ref": "#/$defs/storageRootEntry"}, {"properties": {"subject": {"oneOf": [{"$ref": "#/$defs/attemptOutputSubject"}, {"$ref": "#/$defs/logStreamSubject"}, {"$ref": "#/$defs/resourceEvidenceSubject"}, {"$ref": "#/$defs/terminalSourceSubject"}]}}}]}, + "subject": {"oneOf": [{"$ref": "#/$defs/jobInputSubject"}, {"$ref": "#/$defs/attemptInputSubject"}, {"$ref": "#/$defs/attemptOutputSubject"}, {"$ref": "#/$defs/logStreamSubject"}, {"$ref": "#/$defs/resourceEvidenceSubject"}, {"$ref": "#/$defs/terminalSourceSubject"}]}, + "jobInputSubject": { + "type": "object", "additionalProperties": false, + "required": ["kind", "input_ordinal", "input_identity", "input_sigil"], + "properties": {"kind": {"const": "JOB_INPUT"}, "input_ordinal": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "input_identity": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/visibleInput"}, "input_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}} + }, + "attemptInputSubject": { + "type": "object", "additionalProperties": false, + "required": ["kind", "input_ordinal", "input_identity", "input_sigil", "materialization_id"], + "properties": {"kind": {"const": "ATTEMPT_INPUT"}, "input_ordinal": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "input_identity": {"$ref": "https://benchwork.dev/schemas/task-capsule/2.0#/$defs/visibleInput"}, "input_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "materialization_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/materializationId"}} + }, + "attemptOutputSubject": { + "type": "object", "additionalProperties": false, + "required": ["kind", "logical_name", "schema_id", "schema_sigil", "staging_reference_sigil", "byte_size", "blob_sigil"], + "properties": {"kind": {"const": "ATTEMPT_OUTPUT"}, "logical_name": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/logicalName"}, "schema_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/schemaId"}, "schema_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "staging_reference_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "byte_size": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "blob_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}} + }, + "logStreamSubject": { + "type": "object", "additionalProperties": false, + "required": ["kind", "stream", "log_stream_id", "stream_set_sigil", "byte_size", "blob_sigil"], + "properties": {"kind": {"const": "LOG_STREAM"}, "stream": {"enum": ["STDOUT", "STDERR", "STRUCTURED"]}, "log_stream_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/logStreamId"}, "stream_set_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "byte_size": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "blob_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}} + }, + "resourceEvidenceSubject": { + "type": "object", "additionalProperties": false, + "required": ["kind", "control_evidence_id", "control_evidence_sigil", "control_dimension", "phase", "phase_evidence_entry_sigil", "byte_size", "blob_sigil"], + "properties": {"kind": {"const": "RESOURCE_EVIDENCE"}, "control_evidence_id": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/controlEvidenceId"}, "control_evidence_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "control_dimension": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/controlDimension"}, "phase": {"$ref": "https://benchwork.dev/schemas/execution-control-evidence/1.0#/$defs/phase"}, "phase_evidence_entry_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "byte_size": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, "blob_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}} + }, + "terminalSourceSubject": { + "type": "object", "additionalProperties": false, + "required": ["kind", "disposition", "terminal_source_identity", "terminal_source_sigil", "storage_blob", "retention_policy_sigil", "file_count", "byte_count"], + "properties": {"kind": {"const": "TERMINAL_SOURCE"}, "disposition": {"enum": ["VERIFIED", "QUARANTINED"]}, "terminal_source_identity": {"$ref": "https://benchwork.dev/schemas/benchwork-source-tree/1.0#/$defs/sourceTreeId"}, "terminal_source_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "storage_blob": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}, "retention_policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "file_count": {"type": "integer", "minimum": 0, "maximum": 100000}, "byte_count": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}} + }, + "storageOrigin": {"oneOf": [{"$ref": "#/$defs/committedBlobOrigin"}, {"$ref": "#/$defs/quarantineOrigin"}, {"$ref": "#/$defs/notStoredOrigin"}]}, + "committedBlobOrigin": { + "type": "object", "additionalProperties": false, + "required": ["kind", "transfer", "provenance_id", "provenance_sigil", "blob_record_sigil", "terminal_event"], + "properties": {"kind": {"const": "COMMITTED_BLOB"}, "transfer": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/transferRef"}, "provenance_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, "provenance_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "blob_record_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "terminal_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}} + }, + "quarantineOrigin": { + "type": "object", "additionalProperties": false, + "required": ["kind", "transfer", "provenance_id", "provenance_sigil", "quarantine_id", "quarantine_origin_event"], + "properties": {"kind": {"const": "QUARANTINE"}, "transfer": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/transferRef"}, "provenance_id": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/opaque"}, "provenance_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "quarantine_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/quarantineId"}, "quarantine_origin_event": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef"}} + }, + "notStoredOrigin": { + "type": "object", "additionalProperties": false, + "required": ["kind", "transfer", "terminal_reason", "evidence_sigil"], + "properties": {"kind": {"const": "NOT_STORED"}, "transfer": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/transferRef"}, {"type": "null"}]}, "terminal_reason": {"$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/reason"}, "evidence_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}} + }, + "protectionPlan": {"oneOf": [{"$ref": "#/$defs/noProtection"}, {"$ref": "#/$defs/plannedProtection"}]}, + "inputProtectionPlan": {"oneOf": [{"$ref": "#/$defs/noProtection"}, {"allOf": [{"$ref": "#/$defs/plannedProtection"}, {"properties": {"hold_lifetime": {"$ref": "#/$defs/ownerTerminalLifetime"}}}]}]}, + "outputProtectionPlan": {"oneOf": [{"$ref": "#/$defs/noProtection"}, {"allOf": [{"$ref": "#/$defs/plannedProtection"}, {"properties": {"hold_lifetime": {"$ref": "#/$defs/outputRetentionLifetime"}}}]}]}, + "noProtection": {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "NONE"}}}, + "plannedProtection": { + "type": "object", "additionalProperties": false, + "required": ["kind", "reference_set_registration_event_id", "hold_id", "hold_set_event_id", "policy_id", "policy_sigil", "hold_lifetime"], + "properties": {"kind": {"const": "PLANNED"}, "reference_set_registration_event_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventId"}, "hold_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-state/1.0#/$defs/holdId"}, "hold_set_event_id": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventId"}, "policy_id": {"const": "SP-EXECUTION-ROOT-HOLD-V1"}, "policy_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, "hold_lifetime": {"$ref": "#/$defs/holdLifetime"}} + }, + "holdLifetime": {"oneOf": [{"$ref": "#/$defs/ownerTerminalLifetime"}, {"$ref": "#/$defs/outputRetentionLifetime"}]}, + "ownerTerminalLifetime": {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "OWNER_TERMINAL"}}}, + "outputRetentionLifetime": {"type": "object", "additionalProperties": false, "required": ["kind", "maximum_duration_seconds"], "properties": {"kind": {"const": "OUTPUT_RETENTION"}, "maximum_duration_seconds": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}}} + } +} + diff --git a/schemas/execution-worker-1.0.json b/schemas/execution-worker-1.0.json new file mode 100644 index 0000000..05a99ed --- /dev/null +++ b/schemas/execution-worker-1.0.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-worker/1.0", + "title": "Execution Worker v1", + "description": "Closed RFC-0012 immutable Worker definition revision.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "worker_id", "definition_revision", "implementation_name", "implementation_version", "supported_runtimes", "resource_ceilings", "declared_backend_capabilities", "verified_capability_tuples", "maximum_concurrency", "definition_created_at", "worker_binding_sigil"], + "properties": { + "schema_version": {"const": "execution-worker/1.0"}, + "worker_id": {"$ref": "#/$defs/workerId"}, + "definition_revision": {"$ref": "#/$defs/u64"}, + "supersedes_worker_binding_sigil": {"$ref": "#/$defs/sigil"}, + "implementation_name": {"$ref": "#/$defs/opaque128"}, + "implementation_version": {"$ref": "#/$defs/version"}, + "supported_runtimes": {"type": "array", "minItems": 1, "maxItems": 64, "uniqueItems": true, "items": {"$ref": "#/$defs/runtimeSupport"}}, + "resource_ceilings": {"$ref": "#/$defs/resourceCeilings"}, + "declared_backend_capabilities": {"type": "array", "maxItems": 64, "uniqueItems": true, "items": {"$ref": "#/$defs/declaredBackendCapability"}}, + "verified_capability_tuples": {"type": "array", "maxItems": 64, "uniqueItems": true, "items": {"$ref": "#/$defs/verifiedCapabilityTuple"}}, + "maximum_concurrency": {"$ref": "#/$defs/positiveU63"}, + "definition_created_at": {"$ref": "#/$defs/timestamp"}, + "worker_binding_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + {"if": {"properties": {"definition_revision": {"const": 0}}, "required": ["definition_revision"]}, "then": {"not": {"required": ["supersedes_worker_binding_sigil"]}}, "else": {"required": ["supersedes_worker_binding_sigil"]}} + ], + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, + "positiveU63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, + "u63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/u63"}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/timestamp"}, + "workerId": {"type": "string", "pattern": "^WK-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "opaque128": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 128}, + "runtimeSupport": {"type": "object", "additionalProperties": false, "required": ["runtime_id", "runtime_version", "runtime_sigil"], "properties": {"runtime_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/runtimeId"}, "runtime_version": {"$ref": "#/$defs/version"}, "runtime_sigil": {"$ref": "#/$defs/sigil"}}}, + "resourceCeilings": {"type": "object", "additionalProperties": false, "required": ["attempt_budget", "maximum_open_files", "maximum_file_count", "maximum_concurrent_threads"], "properties": {"attempt_budget": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/attemptBudget"}, "maximum_open_files": {"$ref": "#/$defs/u63"}, "maximum_file_count": {"$ref": "#/$defs/u63"}, "maximum_concurrent_threads": {"$ref": "#/$defs/u63"}}}, + "declaredBackendCapability": {"type": "object", "additionalProperties": false, "required": ["capability_id", "capability_version", "declaration_sigil"], "properties": {"capability_id": {"$ref": "#/$defs/opaque128"}, "capability_version": {"$ref": "#/$defs/version"}, "declaration_sigil": {"$ref": "#/$defs/sigil"}}}, + "verifiedCapabilityTuple": {"type": "object", "additionalProperties": false, "required": ["backend_id", "backend_version", "backend_implementation_sigil", "assurance_profile_version", "assurance_profile_sigil", "conformance_suite_id", "conformance_suite_sigil", "backend_configuration_sigil", "verified_at", "evidence_sigils", "tuple_sigil"], "properties": {"backend_id": {"$ref": "#/$defs/opaque128"}, "backend_version": {"$ref": "#/$defs/version"}, "backend_implementation_sigil": {"$ref": "#/$defs/sigil"}, "assurance_profile_version": {"$ref": "#/$defs/version"}, "assurance_profile_sigil": {"$ref": "#/$defs/sigil"}, "conformance_suite_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/conformanceSuiteId"}, "conformance_suite_sigil": {"$ref": "#/$defs/sigil"}, "backend_configuration_sigil": {"$ref": "#/$defs/sigil"}, "verified_at": {"$ref": "#/$defs/timestamp"}, "evidence_sigils": {"type": "array", "minItems": 1, "maxItems": 64, "uniqueItems": true, "items": {"$ref": "#/$defs/sigil"}}, "tuple_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/execution-worker-session-1.0.json b/schemas/execution-worker-session-1.0.json new file mode 100644 index 0000000..ed35820 --- /dev/null +++ b/schemas/execution-worker-session-1.0.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-worker-session/1.0", + "title": "Execution Worker Session v1", + "description": "Closed RFC-0012 immutable Worker Session binding. Parent Worker tuple resolution and durable allocation-slot conformance require the semantic resolver.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "worker_session_id", "worker_id", "worker_binding_sigil", "executor_instance_id", "executor_epoch", "host_identity_sigil", "backend_session_identity", "control_channel_identity_sigil", "verified_capability_tuple_sigil", "maximum_concurrency", "opened_at", "worker_session_binding_sigil"], + "properties": { + "schema_version": {"const": "execution-worker-session/1.0"}, + "worker_session_id": {"$ref": "#/$defs/workerSessionId"}, + "worker_id": {"$ref": "https://benchwork.dev/schemas/execution-worker/1.0#/$defs/workerId"}, + "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_instance_id": {"$ref": "#/$defs/executorInstanceId"}, + "executor_epoch": {"$ref": "#/$defs/u64"}, + "host_identity_sigil": {"$ref": "#/$defs/sigil"}, + "backend_session_identity": {"$ref": "#/$defs/backendSessionIdentity"}, + "control_channel_identity_sigil": {"$ref": "#/$defs/sigil"}, + "verified_capability_tuple_sigil": {"$ref": "#/$defs/sigil"}, + "maximum_concurrency": {"$ref": "#/$defs/positiveU63"}, + "opened_at": {"$ref": "#/$defs/timestamp"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, + "positiveU63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "timestamp": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/timestamp"}, + "workerSessionId": {"type": "string", "pattern": "^WS-[0-7][0-9A-HJKMNP-TV-Z]{25}$", "not": {"pattern": "[\\r\\n]"}, "minLength": 29, "maxLength": 29}, + "executorInstanceId": {"type": "string", "pattern": "^XI-[A-Z0-9]+$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "opaque128": {"type": "string", "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "minLength": 1, "maxLength": 127}, + "backendSessionIdentity": { + "type": "object", + "additionalProperties": false, + "required": ["backend_id", "backend_version", "backend_implementation_sigil", "backend_configuration_sigil", "process_identity_sigil", "session_nonce_sigil"], + "properties": { + "backend_id": {"$ref": "#/$defs/opaque128"}, + "backend_version": {"$ref": "#/$defs/version"}, + "backend_implementation_sigil": {"$ref": "#/$defs/sigil"}, + "backend_configuration_sigil": {"$ref": "#/$defs/sigil"}, + "process_identity_sigil": {"$ref": "#/$defs/sigil"}, + "session_nonce_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/execution-worker-session-heartbeat-policy-1.0.json b/schemas/execution-worker-session-heartbeat-policy-1.0.json new file mode 100644 index 0000000..1626e68 --- /dev/null +++ b/schemas/execution-worker-session-heartbeat-policy-1.0.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/execution-worker-session-heartbeat-policy/1.0", + "title": "Execution Worker Session Heartbeat Policy v1", + "description": "Closed RFC-0012 immutable Worker-Session heartbeat timing policy. This contract-only record does not resolve an Executor build binding, install a Session policy slot, append worker_session.ready, compute a durable due key, or establish live authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "worker_session_heartbeat_policy_id", + "worker_session_id", + "worker_session_binding_sigil", + "executor_instance_id", + "executor_epoch", + "heartbeat_interval_seconds", + "heartbeat_timeout_seconds", + "gap_mode", + "source_sigil", + "created_at", + "worker_session_heartbeat_policy_sigil" + ], + "properties": { + "schema_version": {"const": "execution-worker-session-heartbeat-policy/1.0"}, + "worker_session_heartbeat_policy_id": {"$ref": "#/$defs/workerSessionHeartbeatPolicyId"}, + "worker_session_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/workerSessionId"}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "executor_instance_id": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/executorInstanceId"}, + "executor_epoch": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/u64"}, + "heartbeat_interval_seconds": {"$ref": "#/$defs/positiveU63"}, + "heartbeat_timeout_seconds": {"$ref": "#/$defs/positiveU63"}, + "gap_mode": {"const": "CONTIGUOUS_ONLY"}, + "source_sigil": {"$ref": "#/$defs/sigil"}, + "created_at": {"$ref": "https://benchwork.dev/schemas/execution-worker-session/1.0#/$defs/timestamp"}, + "worker_session_heartbeat_policy_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "positiveU63": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/positiveU63"}, + "workerSessionHeartbeatPolicyId": { + "type": "string", + "pattern": "^WSHP-[0-9A-F]{64}$", + "minLength": 69, + "maxLength": 69 + } + } +} + diff --git a/schemas/mcp-tool-registry-2.0.json b/schemas/mcp-tool-registry-2.0.json new file mode 100644 index 0000000..f27daa1 --- /dev/null +++ b/schemas/mcp-tool-registry-2.0.json @@ -0,0 +1,180 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/mcp-tool-registry/2.0", + "title": "Benchwork MCP Tool Registry v2 Contract Candidate", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "api_version", + "stability", + "input_schema_source", + "response_schema", + "tools" + ], + "properties": { + "schema_version": {"const": "mcp-tool-registry/2.0"}, + "api_version": {"const": "0.4"}, + "stability": {"const": "alpha"}, + "input_schema_source": {"const": "tools/list.inputSchema"}, + "response_schema": {"const": "mcp-tool-result/1.0"}, + "tools": { + "type": "array", + "minItems": 47, + "maxItems": 47, + "uniqueItems": true, + "prefixItems": [ + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/v1Tool"}, + {"$ref": "#/$defs/phase3Tool"}, + {"$ref": "#/$defs/phase3Tool"}, + {"$ref": "#/$defs/phase3Tool"}, + {"$ref": "#/$defs/phase3Tool"}, + {"$ref": "#/$defs/phase3Tool"}, + {"$ref": "#/$defs/phase3Tool"}, + {"$ref": "#/$defs/phase3Tool"}, + {"$ref": "#/$defs/phase3Tool"}, + {"$ref": "#/$defs/phase3Tool"} + ], + "items": false + } + }, + "$defs": { + "v1Tool": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "category", + "permission", + "risk", + "approval", + "canonical_effect" + ], + "properties": { + "name": {"type": "string", "pattern": "^benchwork_[a-z0-9_]+$"}, + "category": {"enum": ["read", "task", "canonical", "experiment"]}, + "permission": {"enum": ["read", "propose", "commit", "execute"]}, + "risk": {"enum": ["low", "medium", "high"]}, + "approval": { + "enum": [ + "none", + "ward", + "human_confirmation", + "disclosure_gate", + "conditional_disclosure" + ] + }, + "canonical_effect": { + "enum": ["none", "task_event", "canonical_event", "analysis_artifact"] + } + } + }, + "phase3Tool": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "category", + "permission", + "risk", + "approval", + "canonical_effect", + "request_schema", + "success_data_schema" + ], + "properties": { + "name": { + "enum": [ + "benchwork_start_job", + "benchwork_observe_job", + "benchwork_cancel_job", + "benchwork_get_job_result", + "benchwork_accept_job_result", + "benchwork_prepare_patch_promotion", + "benchwork_inspect_patch_promotion", + "benchwork_authorize_patch_promotion", + "benchwork_record_patch_promotion_outcome" + ] + }, + "category": {"enum": ["execution", "patch"]}, + "permission": {"enum": ["read", "propose", "commit", "execute"]}, + "risk": {"enum": ["low", "medium", "high"]}, + "approval": { + "enum": [ + "none", + "ward", + "human_confirmation", + "execution_policy", + "execution_control", + "patch_authorization" + ] + }, + "canonical_effect": { + "enum": ["none", "task_event", "canonical_event", "operational_event"] + }, + "request_schema": { + "enum": [ + "execution-start-request/1.0", + "execution-observe-request/1.0", + "execution-cancel-request/1.0", + "execution-get-result-request/1.0", + "execution-accept-result-request/1.0", + "patch-promotion-prepare-request/1.0", + "patch-promotion-inspect-request/1.0", + "patch-promotion-authorize-request/1.0", + "patch-promotion-outcome-request/1.0" + ] + }, + "success_data_schema": { + "enum": [ + "execution-observation/1.0", + "execution-job-outcome/1.0", + "agent-result-record/2.0", + "patch-promotion-prepare-response/1.0", + "patch-promotion-inspect-response/1.0", + "patch-promotion-authorize-response/1.0", + "patch-promotion-outcome-response/1.0" + ] + } + } + } + } +} + diff --git a/schemas/patch-base-1.0.json b/schemas/patch-base-1.0.json new file mode 100644 index 0000000..52c4305 --- /dev/null +++ b/schemas/patch-base-1.0.json @@ -0,0 +1,2 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/patch-base/1.0","type":"object","additionalProperties":false,"required":["schema_version","base_id","identity_profile","source_root_id","source_root_sigil","scope","tree","manifest_blob","input_artifacts","execution","vcs","base_sigil"],"properties":{"schema_version":{"const":"patch-base/1.0"},"base_id":{"$ref":"#/$defs/pb"},"identity_profile":{"$ref":"#/$defs/pbipRef"},"source_root_id":{"$ref":"#/$defs/text128"},"source_root_sigil":{"$ref":"#/$defs/sigil"},"scope":{"$ref":"#/$defs/scope"},"tree":{"$ref":"#/$defs/tree"},"manifest_blob":{"$ref":"#/$defs/blob"},"input_artifacts":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/arRef"}},"execution":{"$ref":"#/$defs/execution"},"vcs":{"anyOf":[{"$ref":"#/$defs/vcs"},{"type":"null"}]},"base_sigil":{"$ref":"#/$defs/sigil"}},"$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"u64":{"type":"integer","minimum":0,"maximum":18446744073709551615},"text128":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","not":{"pattern":"[\\r\\n]"}},"pb":{"type":"string","pattern":"^PB-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"pbip":{"type":"string","pattern":"^PBIP-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":6,"maxLength":128},"ar":{"type":"string","pattern":"^AR-[A-Za-z0-9][A-Za-z0-9._:-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"pbipRef":{"type":"object","additionalProperties":false,"required":["id","sigil"],"properties":{"id":{"$ref":"#/$defs/pbip"},"sigil":{"$ref":"#/$defs/sigil"}}},"arRef":{"type":"object","additionalProperties":false,"required":["id","sigil"],"properties":{"id":{"$ref":"#/$defs/ar"},"sigil":{"$ref":"#/$defs/sigil"}}},"scope":{"type":"object","additionalProperties":false,"required":["root_kind","included_paths","excluded_paths"],"properties":{"root_kind":{"enum":["CRUCIBLE","PROMOTION_TARGET"]},"included_paths":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/path"}},"excluded_paths":{"type":"array","maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/path"}}}},"path":{"type":"string","minLength":1,"maxLength":4096,"pattern":"^[^/\\u0000-\\u001F\\u007F-\\u009F]+(?:/[^/\\u0000-\\u001F\\u007F-\\u009F]+)*$","not":{"pattern":"[\\r\\n]"}},"tree":{"type":"object","additionalProperties":false,"required":["manifest_sigil","root_entry_sigil","entry_count","total_bytes"],"properties":{"manifest_sigil":{"$ref":"#/$defs/sigil"},"root_entry_sigil":{"$ref":"#/$defs/sigil"},"entry_count":{"$ref":"#/$defs/u64"},"total_bytes":{"$ref":"#/$defs/u63"}}},"blob":{"type":"object","additionalProperties":false,"required":["sigil","size_bytes","media_type"],"properties":{"sigil":{"$ref":"#/$defs/sigil"},"size_bytes":{"$ref":"#/$defs/u63"},"media_type":{"$ref":"#/$defs/text128"}}},"execution":{"type":"object","additionalProperties":false,"required":["job_id","job_binding_sigil","attempt_id","attempt_binding_sigil","terminal_event_id","terminal_event_sigil"],"properties":{"job_id":{"$ref":"#/$defs/text128"},"job_binding_sigil":{"$ref":"#/$defs/sigil"},"attempt_id":{"$ref":"#/$defs/text128"},"attempt_binding_sigil":{"$ref":"#/$defs/sigil"},"terminal_event_id":{"$ref":"#/$defs/text128"},"terminal_event_sigil":{"$ref":"#/$defs/sigil"}}},"vcs":{"type":"object","additionalProperties":false,"required":["kind","repository_identity_sigil","commit_sigil","tree_sigil","submodule_policy","dirty_state"],"properties":{"kind":{"const":"GIT"},"repository_identity_sigil":{"$ref":"#/$defs/sigil"},"commit_sigil":{"$ref":"#/$defs/sigil"},"tree_sigil":{"$ref":"#/$defs/sigil"},"submodule_policy":{"enum":["REJECT","PINNED"]},"dirty_state":{"enum":["CLEAN","CAPTURED"]}}}}} + diff --git a/schemas/patch-base-identity-profile-1.0.json b/schemas/patch-base-identity-profile-1.0.json new file mode 100644 index 0000000..92e2751 --- /dev/null +++ b/schemas/patch-base-identity-profile-1.0.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-base-identity-profile/1.0", + "title": "Patch Base Identity Profile v1", + "description": "Closed RFC-0014 patch-base-identity-profile/1.0 contract-only record. Validation is local and does not inspect a filesystem, resolve a Profile, or calculate a tree identity.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "profile_id", "path_scope", "path_semantics", "entry_semantics", "limits", "protected_paths", "profile_sigil"], + "properties": { + "schema_version": {"const": "patch-base-identity-profile/1.0"}, + "profile_id": {"$ref": "#/$defs/pbip"}, + "path_scope": {"$ref": "#/$defs/pathScope"}, + "path_semantics": {"$ref": "#/$defs/pathSemantics"}, + "entry_semantics": {"$ref": "#/$defs/entrySemantics"}, + "limits": {"$ref": "#/$defs/limits"}, + "protected_paths": {"type": "array", "minItems": 1, "maxItems": 256, "uniqueItems": true, "items": {"$ref": "#/$defs/path"}}, + "profile_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "maxPaths": {"type": "integer", "minimum": 1, "maximum": 100000}, + "maxDepth": {"type": "integer", "minimum": 1, "maximum": 4096}, + "pbip": {"type": "string", "pattern": "^PBIP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 6, "maxLength": 128}, + "path": {"type": "string", "minLength": 1, "maxLength": 4096, "pattern": "^[^/\\u0000-\\u001F\\u007F-\\u009F]+(?:/[^/\\u0000-\\u001F\\u007F-\\u009F]+)*$", "not": {"pattern": "[\\r\\n]"}}, + "pathScope": {"type": "object", "additionalProperties": false, "required": ["root_kind", "included_paths", "excluded_paths"], "properties": {"root_kind": {"enum": ["CRUCIBLE", "PROMOTION_TARGET"]}, "included_paths": {"type": "array", "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/path"}}, "excluded_paths": {"type": "array", "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/path"}}}}, + "pathSemantics": {"type": "object", "additionalProperties": false, "required": ["separator", "unicode_normalization", "case_mode", "dot_segments", "link_traversal", "reserved_name_policy"], "properties": {"separator": {"const": "SLASH"}, "unicode_normalization": {"const": "NFC"}, "case_mode": {"enum": ["SENSITIVE", "INSENSITIVE_REJECT_COLLISIONS"]}, "dot_segments": {"const": "REJECT"}, "link_traversal": {"const": "NOFOLLOW"}, "reserved_name_policy": {"const": "REJECT"}}}, + "entrySemantics": {"type": "object", "additionalProperties": false, "required": ["supported_types", "content_digest", "executable_bit", "symlink_target", "metadata_policy"], "properties": {"supported_types": {"type": "array", "minItems": 1, "maxItems": 3, "uniqueItems": true, "items": {"enum": ["FILE", "DIRECTORY", "SYMLINK"]}}, "content_digest": {"const": "SHA256"}, "executable_bit": {"enum": ["SIGNIFICANT", "IGNORED"]}, "symlink_target": {"const": "UTF8_NOFOLLOW"}, "metadata_policy": {"const": "TYPE_CONTENT_MODE_ONLY"}}}, + "limits": {"type": "object", "additionalProperties": false, "required": ["max_paths", "max_total_bytes", "max_file_bytes", "max_depth", "max_symlink_bytes"], "properties": {"max_paths": {"$ref": "#/$defs/maxPaths"}, "max_total_bytes": {"$ref": "#/$defs/u63"}, "max_file_bytes": {"$ref": "#/$defs/u63"}, "max_depth": {"$ref": "#/$defs/maxDepth"}, "max_symlink_bytes": {"$ref": "#/$defs/maxDepth"}}} + } +} + diff --git a/schemas/patch-bundle-1.0.json b/schemas/patch-bundle-1.0.json new file mode 100644 index 0000000..5a40415 --- /dev/null +++ b/schemas/patch-bundle-1.0.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-bundle/1.0", + "title": "Patch Bundle v1", + "description": "Closed RFC-0014 patch-bundle/1.0 contract-only record. Validation is local and does not resolve Base, profile, Receipt, source, Blob bytes, or export provenance.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "bundle_id", "base", "postimage", "operations", "payloads", "renderings", "attachments", "source", "agent_result_receipt", "limits", "bundle_sigil"], + "properties": { + "schema_version": {"const": "patch-bundle/1.0"}, + "bundle_id": {"$ref": "#/$defs/pbu"}, + "base": {"$ref": "#/$defs/pbRef"}, + "postimage": {"$ref": "#/$defs/postimage"}, + "operations": {"type": "array", "minItems": 1, "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/operation"}}, + "payloads": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/blob"}}, + "renderings": {"type": "array", "maxItems": 256, "uniqueItems": true, "items": {"$ref": "#/$defs/blob"}}, + "attachments": {"type": "array", "maxItems": 256, "uniqueItems": true, "items": {"$ref": "#/$defs/blob"}}, + "source": {"$ref": "#/$defs/source"}, + "agent_result_receipt": {"$ref": "#/$defs/receipt"}, + "limits": {"$ref": "#/$defs/limits"}, + "bundle_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "maxPaths": {"type": "integer", "minimum": 1, "maximum": 100000}, + "maxBlobs": {"type": "integer", "minimum": 1, "maximum": 4096}, + "text128": {"type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "not": {"pattern": "[\\r\\n]"}}, + "text4096": {"type": "string", "minLength": 1, "maxLength": 4096, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "not": {"pattern": "[\\r\\n]"}}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "pbu": {"type": "string", "pattern": "^PBU-[A-Za-z0-9][A-Za-z0-9._-]*$", "minLength": 5, "maxLength": 128}, + "pb": {"type": "string", "pattern": "^PB-[A-Za-z0-9][A-Za-z0-9._-]*$", "minLength": 4, "maxLength": 128}, + "pbip": {"type": "string", "pattern": "^PBIP-[A-Za-z0-9][A-Za-z0-9._-]*$", "minLength": 6, "maxLength": 128}, + "rc": {"type": "string", "pattern": "^RC-[A-Za-z0-9][A-Za-z0-9._-]*$", "minLength": 4, "maxLength": 128}, + "ce": {"type": "string", "pattern": "^CE-[A-Za-z0-9][A-Za-z0-9._-]*$", "minLength": 4, "maxLength": 128}, + "pbRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pb"}, "sigil": {"$ref": "#/$defs/sigil"}}}, + "pbipRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pbip"}, "sigil": {"$ref": "#/$defs/sigil"}}}, + "blob": {"type": "object", "additionalProperties": false, "required": ["sigil", "size_bytes", "media_type"], "properties": {"sigil": {"$ref": "#/$defs/sigil"}, "size_bytes": {"$ref": "#/$defs/u63"}, "media_type": {"$ref": "#/$defs/text128"}}}, + "tree": {"type": "object", "additionalProperties": false, "required": ["manifest_sigil", "root_entry_sigil", "entry_count", "total_bytes"], "properties": {"manifest_sigil": {"$ref": "#/$defs/sigil"}, "root_entry_sigil": {"$ref": "#/$defs/sigil"}, "entry_count": {"type": "integer", "minimum": 0, "maximum": 100000}, "total_bytes": {"$ref": "#/$defs/u63"}}}, + "postimage": {"type": "object", "additionalProperties": false, "required": ["identity_profile", "tree", "manifest_blob"], "properties": {"identity_profile": {"$ref": "#/$defs/pbipRef"}, "tree": {"$ref": "#/$defs/tree"}, "manifest_blob": {"$ref": "#/$defs/blob"}}}, + "entry": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "ABSENT"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "blob_sigil", "size_bytes", "executable"], "properties": {"kind": {"const": "FILE"}, "blob_sigil": {"$ref": "#/$defs/sigil"}, "size_bytes": {"$ref": "#/$defs/u63"}, "executable": {"type": "boolean"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "entry_sigil"], "properties": {"kind": {"const": "DIRECTORY"}, "entry_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["kind", "target", "target_sigil"], "properties": {"kind": {"const": "SYMLINK"}, "target": {"$ref": "#/$defs/text4096"}, "target_sigil": {"$ref": "#/$defs/sigil"}}} + ]}, + "operation": {"type": "object", "additionalProperties": false, "required": ["path_bytes", "operation", "preimage", "postimage", "payload_sigil"], "properties": {"path_bytes": {"$ref": "#/$defs/text4096"}, "operation": {"enum": ["ADD", "MODIFY", "DELETE", "TYPE_CHANGE"]}, "preimage": {"$ref": "#/$defs/entry"}, "postimage": {"$ref": "#/$defs/entry"}, "payload_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}}}, + "source": {"type": "object", "additionalProperties": false, "required": ["kind", "terminal_source_sigil", "execution_event_sigil", "frozen_at"], "properties": {"kind": {"const": "RETAINED_TERMINAL_SOURCE"}, "terminal_source_sigil": {"$ref": "#/$defs/sigil"}, "execution_event_sigil": {"$ref": "#/$defs/sigil"}, "frozen_at": {"$ref": "#/$defs/timestamp"}}}, + "receipt": {"type": "object", "additionalProperties": false, "required": ["receipt_id", "receipt_sigil", "event_id", "event_body_sigil"], "properties": {"receipt_id": {"$ref": "#/$defs/rc"}, "receipt_sigil": {"$ref": "#/$defs/sigil"}, "event_id": {"$ref": "#/$defs/ce"}, "event_body_sigil": {"$ref": "#/$defs/sigil"}}}, + "limits": {"type": "object", "additionalProperties": false, "required": ["max_paths", "max_blobs", "max_total_bytes", "max_payload_bytes"], "properties": {"max_paths": {"$ref": "#/$defs/maxPaths"}, "max_blobs": {"$ref": "#/$defs/maxBlobs"}, "max_total_bytes": {"$ref": "#/$defs/u63"}, "max_payload_bytes": {"$ref": "#/$defs/u63"}}} + } +} + diff --git a/schemas/patch-operational-evidence-manifest-1.0.json b/schemas/patch-operational-evidence-manifest-1.0.json new file mode 100644 index 0000000..76def88 --- /dev/null +++ b/schemas/patch-operational-evidence-manifest-1.0.json @@ -0,0 +1,240 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-operational-evidence-manifest/1.0", + "title": "Patch Operational Evidence Manifest v1", + "description": "Closed RFC-0014 event-evidence or Journal-suffix source manifest. Contract-only validation does not resolve a Promotion Journal payload, control record, Blob, Reference Set, plan, hold, or external authority and does not append an Event or release Storage.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "evidence_manifest_id", + "activation", + "body", + "control_records", + "blob_refs", + "evidence_sigils", + "manifest_sigil" + ], + "properties": { + "schema_version": {"const": "patch-operational-evidence-manifest/1.0"}, + "evidence_manifest_id": {"$ref": "#/$defs/evidenceManifestId"}, + "activation": {"$ref": "#/$defs/evidenceActivation"}, + "body": {"$ref": "#/$defs/operationalEvidenceBody"}, + "control_records": { + "type": "array", + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/controlRef"} + }, + "blob_refs": { + "type": "array", + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"} + }, + "evidence_sigils": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": {"$ref": "#/$defs/sigil"} + }, + "manifest_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$", + "minLength": 71, + "maxLength": 71 + }, + "u63": { + "type": "integer", + "minimum": 0, + "maximum": 9223372036854775807 + }, + "u64": { + "type": "integer", + "minimum": 0, + "maximum": 18446744073709551615 + }, + "evidenceManifestId": { + "type": "string", + "pattern": "^PEM-[A-F0-9]{64}$", + "minLength": 68, + "maxLength": 68 + }, + "pj": { + "type": "string", + "pattern": "^PJ-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 4, + "maxLength": 128 + }, + "pje": { + "type": "string", + "pattern": "^PJE-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 5, + "maxLength": 128 + }, + "pat": { + "type": "string", + "pattern": "^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 5, + "maxLength": 128 + }, + "pra": { + "type": "string", + "pattern": "^PRA-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 5, + "maxLength": 128 + }, + "ptri": { + "type": "string", + "pattern": "^PTRI-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 6, + "maxLength": 128 + }, + "eventType": { + "enum": [ + "coordinator.replay-started", + "target.guard-validated", + "promotion.verification-started", + "promotion.applied", + "promotion.recovered-postimage-observed", + "promotion.already-applied", + "promotion.stale", + "promotion.conflicted", + "promotion.failed", + "promotion.partial", + "promotion.cancelled", + "recovery.verification-started", + "recovery.base-restored", + "recovery.postimage-accepted", + "recovery.abandoned", + "recovery.stale", + "recovery.failed", + "recovery.partial", + "recovery.cancelled" + ] + }, + "evidenceActivation": { + "type": "object", + "additionalProperties": false, + "required": [ + "operational_journal_id", + "activation_event_id", + "activation_event_type", + "payload_field" + ], + "properties": { + "operational_journal_id": {"$ref": "#/$defs/pj"}, + "activation_event_id": {"$ref": "#/$defs/pje"}, + "activation_event_type": {"$ref": "#/$defs/eventType"}, + "payload_field": { + "enum": [ + "PRIOR_STEP_PROTECTION", + "EVIDENCE_PROTECTION", + "SUFFIX_EVIDENCE_PROTECTION" + ] + } + } + }, + "promotionEvidenceOwner": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "attempt_id"], + "properties": { + "kind": {"const": "PROMOTION"}, + "attempt_id": {"$ref": "#/$defs/pat"} + } + }, + "recoveryEvidenceOwner": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "recovery_attempt_id", "parent_attempt_id"], + "properties": { + "kind": {"const": "RECOVERY"}, + "recovery_attempt_id": {"$ref": "#/$defs/pra"}, + "parent_attempt_id": {"$ref": "#/$defs/pat"} + } + }, + "journalSuffixEvidenceOwner": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "journal_id", "recovery_id"], + "properties": { + "kind": {"const": "JOURNAL_SUFFIX"}, + "journal_id": {"$ref": "#/$defs/pj"}, + "recovery_id": {"$ref": "#/$defs/ptri"} + } + }, + "eventEvidenceBody": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "owner", + "role", + "claims_sigil", + "evidence_binding_sigil" + ], + "properties": { + "kind": {"const": "EVENT_EVIDENCE"}, + "owner": { + "oneOf": [ + {"$ref": "#/$defs/promotionEvidenceOwner"}, + {"$ref": "#/$defs/recoveryEvidenceOwner"} + ] + }, + "role": { + "enum": [ + "GUARD_VALIDATION", + "VERIFICATION", + "TERMINAL", + "ABANDONMENT" + ] + }, + "claims_sigil": {"$ref": "#/$defs/sigil"}, + "evidence_binding_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "journalSuffixEvidenceBody": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "owner", + "old_head", + "observed_eof", + "suffix_kind", + "last_complete_offset", + "target_head", + "original_suffix_blob", + "classification_sigil" + ], + "properties": { + "kind": {"const": "JOURNAL_SUFFIX"}, + "owner": {"$ref": "#/$defs/journalSuffixEvidenceOwner"}, + "old_head": {"$ref": "https://benchwork.dev/schemas/patch-promotion-journal-head/1.0"}, + "observed_eof": {"$ref": "#/$defs/u64"}, + "suffix_kind": {"enum": ["COMPLETE", "TORN_EOF"]}, + "last_complete_offset": {"$ref": "#/$defs/u64"}, + "target_head": {"$ref": "https://benchwork.dev/schemas/patch-promotion-journal-head/1.0"}, + "original_suffix_blob": {"$ref": "https://benchwork.dev/schemas/artifact-provenance/1.0#/$defs/blobRef"}, + "classification_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "operationalEvidenceBody": { + "oneOf": [ + {"$ref": "#/$defs/eventEvidenceBody"}, + {"$ref": "#/$defs/journalSuffixEvidenceBody"} + ] + } + } +} + diff --git a/schemas/patch-operational-root-plan-1.0.json b/schemas/patch-operational-root-plan-1.0.json new file mode 100644 index 0000000..735599c --- /dev/null +++ b/schemas/patch-operational-root-plan-1.0.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-operational-root-plan/1.0", + "title": "Patch Operational Root Plan v1", + "description": "Closed RFC-0014 previsibility plan. Validation is contract-only: it does not resolve Storage records, reserve slots, or validate a future Promotion Journal event.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "plan_id", "operational_journal_id", "activation_event_id", "activation_event_type", "payload_field", "root_kind", "operational_root_id", "control_record", "reference_set", "reference_set_registration_event", "hold_id", "hold_set_event_id", "policy_id", "policy_sigil", "authorization_kind", "plan_sigil"], + "properties": { + "schema_version": {"const": "patch-operational-root-plan/1.0"}, "plan_id": {"$ref": "#/$defs/plan_id"}, "operational_journal_id": {"$ref": "#/$defs/pj"}, "activation_event_id": {"$ref": "#/$defs/pje"}, "activation_event_type": {"$ref": "#/$defs/event_type"}, "payload_field": {"$ref": "#/$defs/payload_field"}, "root_kind": {"$ref": "#/$defs/root_kind"}, "operational_root_id": {"$ref": "#/$defs/root_id"}, "control_record": {"$ref": "#/$defs/control_record"}, "reference_set": {"$ref": "#/$defs/reference_set"}, "reference_set_registration_event": {"$ref": "#/$defs/storage_event"}, "hold_id": {"$ref": "#/$defs/sh"}, "hold_set_event_id": {"$ref": "#/$defs/se"}, "policy_id": {"$ref": "#/$defs/sp"}, "policy_sigil": {"$ref": "#/$defs/sigil"}, "authorization_kind": {"enum": ["PROMOTION_CONTROL", "JOURNAL_RECOVERY"]}, "plan_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + {"oneOf": [ + {"properties": {"activation_event_type": {"const": "coordinator.replay-started"}, "payload_field": {"const": "SUFFIX_EVIDENCE_PROTECTION"}, "root_kind": {"const": "JOURNAL_SUFFIX"}, "authorization_kind": {"const": "JOURNAL_RECOVERY"}}}, + {"properties": {"activation_event_type": {"const": "target.guard-validated"}, "payload_field": {"const": "PRIOR_STEP_PROTECTION"}, "root_kind": {"const": "EVIDENCE"}, "authorization_kind": {"const": "PROMOTION_CONTROL"}}}, + {"properties": {"activation_event_type": {"const": "promotion.checkpoint-committed"}, "payload_field": {"const": "CHECKPOINT_PROTECTION"}, "root_kind": {"const": "CHECKPOINT"}, "authorization_kind": {"const": "PROMOTION_CONTROL"}}}, + {"properties": {"activation_event_type": {"const": "promotion.mutation-intent-committed"}, "payload_field": {"const": "INTENT_PROTECTION"}, "root_kind": {"const": "MUTATION_INTENT"}, "authorization_kind": {"const": "PROMOTION_CONTROL"}}}, + {"properties": {"activation_event_type": {"const": "recovery.checkpoint-verified"}, "payload_field": {"const": "CHECKPOINT_PROTECTION"}, "root_kind": {"const": "CHECKPOINT"}, "authorization_kind": {"const": "PROMOTION_CONTROL"}}}, + {"properties": {"activation_event_type": {"const": "recovery.intent-committed"}, "payload_field": {"const": "INTENT_PROTECTION"}, "root_kind": {"const": "RECOVERY_INTENT"}, "authorization_kind": {"const": "PROMOTION_CONTROL"}}}, + {"properties": {"activation_event_type": {"enum": ["promotion.verification-started", "promotion.applied", "promotion.recovered-postimage-observed", "promotion.already-applied", "promotion.stale", "promotion.conflicted", "promotion.failed", "promotion.partial", "promotion.cancelled", "recovery.verification-started", "recovery.base-restored", "recovery.postimage-accepted", "recovery.abandoned", "recovery.stale", "recovery.failed", "recovery.partial", "recovery.cancelled"]}, "payload_field": {"const": "EVIDENCE_PROTECTION"}, "root_kind": {"const": "EVIDENCE"}, "authorization_kind": {"const": "PROMOTION_CONTROL"}}} + ]}, + {"if": {"properties": {"root_kind": {"const": "CHECKPOINT"}}}, "then": {"properties": {"control_record": {"properties": {"schema_version": {"const": "patch-promotion-checkpoint/1.0"}}}}}}, + {"if": {"properties": {"root_kind": {"const": "MUTATION_INTENT"}}}, "then": {"properties": {"control_record": {"properties": {"schema_version": {"const": "patch-promotion-mutation-intent/1.0"}}}}}}, + {"if": {"properties": {"root_kind": {"const": "RECOVERY_INTENT"}}}, "then": {"properties": {"control_record": {"properties": {"schema_version": {"const": "patch-promotion-recovery-intent/1.0"}}}}}}, + {"if": {"properties": {"root_kind": {"enum": ["EVIDENCE", "JOURNAL_SUFFIX"]}}}, "then": {"properties": {"control_record": {"properties": {"schema_version": {"const": "patch-operational-evidence-manifest/1.0"}}}}}} + ], + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "pj": {"type": "string", "pattern": "^PJ-[A-Za-z0-9][A-Za-z0-9._-]*$", "minLength": 4, "maxLength": 128}, "pje": {"type": "string", "pattern": "^PJE-[A-Za-z0-9][A-Za-z0-9._-]*$", "minLength": 5, "maxLength": 128}, "plan_id": {"type": "string", "pattern": "^PORP-[A-F0-9]{64}$", "minLength": 69, "maxLength": 69}, "root_id": {"type": "string", "pattern": "^PROOT-[0-9a-f]{32}$", "minLength": 38, "maxLength": 38}, + "sh": {"type": "string", "pattern": "^SH-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, "se": {"type": "string", "pattern": "^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, "sp": {"type": "string", "pattern": "^SP-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, "rs": {"type": "string", "pattern": "^RS-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, "sj": {"type": "string", "pattern": "^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$", "minLength": 4, "maxLength": 128}, + "storage_opaque": {"type": "string", "minLength": 1, "maxLength": 256, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, + "event_type": {"enum": ["coordinator.replay-started", "target.guard-validated", "promotion.checkpoint-committed", "promotion.mutation-intent-committed", "promotion.verification-started", "promotion.applied", "promotion.recovered-postimage-observed", "promotion.already-applied", "promotion.stale", "promotion.conflicted", "promotion.failed", "promotion.partial", "promotion.cancelled", "recovery.checkpoint-verified", "recovery.intent-committed", "recovery.verification-started", "recovery.base-restored", "recovery.postimage-accepted", "recovery.abandoned", "recovery.stale", "recovery.failed", "recovery.partial", "recovery.cancelled"]}, + "payload_field": {"enum": ["CHECKPOINT_PROTECTION", "INTENT_PROTECTION", "PRIOR_STEP_PROTECTION", "EVIDENCE_PROTECTION", "SUFFIX_EVIDENCE_PROTECTION"]}, "root_kind": {"enum": ["CHECKPOINT", "MUTATION_INTENT", "RECOVERY_INTENT", "EVIDENCE", "JOURNAL_SUFFIX"]}, + "control_record": {"type": "object", "additionalProperties": false, "required": ["schema_version", "record_id", "record_sigil"], "properties": {"schema_version": {"$ref": "#/$defs/storage_opaque"}, "record_id": {"$ref": "#/$defs/storage_opaque"}, "record_sigil": {"$ref": "#/$defs/sigil"}}}, + "reference_set": {"type": "object", "additionalProperties": false, "required": ["reference_set_id", "reference_set_sigil"], "properties": {"reference_set_id": {"$ref": "#/$defs/rs"}, "reference_set_sigil": {"$ref": "#/$defs/sigil"}}}, + "storage_event": {"type": "object", "additionalProperties": false, "required": ["journal_id", "event_id", "sequence", "event_sigil"], "properties": {"journal_id": {"$ref": "#/$defs/sj"}, "event_id": {"$ref": "#/$defs/se"}, "sequence": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, "event_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/patch-operational-root-release-evidence-1.0.json b/schemas/patch-operational-root-release-evidence-1.0.json new file mode 100644 index 0000000..7f0ff45 --- /dev/null +++ b/schemas/patch-operational-root-release-evidence-1.0.json @@ -0,0 +1,441 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-operational-root-release-evidence/1.0", + "title": "Patch Operational Root Release Evidence v1", + "description": "Closed RFC-0014 release-evidence wire contract. Contract-only validation does not replay Promotion or Storage journals and grants no hold-release authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "release_evidence_id", + "operational_journal_id", + "operational_root_id", + "operational_root_sigil", + "operational_root_plan", + "hold_id", + "reference_set", + "hold_set_event", + "activation_event", + "inactivation_event", + "release_condition", + "terminal_authority", + "canonical_completion", + "guard_completion", + "promotion_prefix", + "storage_prefix", + "policy", + "trusted_clock", + "retention_completion", + "intent_absence", + "record_sigil" + ], + "properties": { + "schema_version": { + "const": "patch-operational-root-release-evidence/1.0" + }, + "release_evidence_id": { + "$ref": "#/$defs/prel" + }, + "operational_journal_id": { + "$ref": "#/$defs/pj" + }, + "operational_root_id": { + "$ref": "#/$defs/proot" + }, + "operational_root_sigil": { + "$ref": "#/$defs/sigil" + }, + "operational_root_plan": { + "$ref": "#/$defs/storageControlRef" + }, + "hold_id": { + "$ref": "#/$defs/sh" + }, + "reference_set": { + "$ref": "#/$defs/referenceSetRef" + }, + "hold_set_event": { + "$ref": "#/$defs/storageEventRef" + }, + "activation_event": { + "$ref": "#/$defs/promotionEventRef" + }, + "inactivation_event": { + "$ref": "#/$defs/promotionEventRef" + }, + "release_condition": { + "$ref": "#/$defs/releaseCondition" + }, + "terminal_authority": { + "$ref": "#/$defs/storageControlRef" + }, + "canonical_completion": { + "$ref": "#/$defs/canonicalCompletion" + }, + "guard_completion": { + "$ref": "#/$defs/guardCompletion" + }, + "promotion_prefix": { + "$ref": "#/$defs/journalPrefix" + }, + "storage_prefix": { + "$ref": "#/$defs/storagePrefixRef" + }, + "policy": { + "$ref": "#/$defs/releasePolicyBinding" + }, + "trusted_clock": { + "$ref": "#/$defs/storageClockRef" + }, + "retention_completion": { + "$ref": "#/$defs/retentionCompletion" + }, + "intent_absence": { + "$ref": "#/$defs/intentAbsence" + }, + "record_sigil": { + "$ref": "#/$defs/sigil" + } + }, + "$defs": { + "sigil": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/sigil" + }, + "timestamp": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/timestamp" + }, + "u63": { + "$ref": "https://benchwork.dev/schemas/artifact-storage-reference-intent/1.0#/$defs/u63" + }, + "pj": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/pj" + }, + "proot": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/proot" + }, + "sh": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/sh" + }, + "prel": { + "type": "string", + "pattern": "^PREL-[0-9a-f]{32}$", + "minLength": 37, + "maxLength": 37 + }, + "storageControlRef": { + "$ref": "https://benchwork.dev/schemas/patch-operational-root-plan/1.0#/$defs/control_record" + }, + "referenceSetRef": { + "$ref": "https://benchwork.dev/schemas/patch-operational-root-plan/1.0#/$defs/reference_set" + }, + "storageEventRef": { + "$ref": "https://benchwork.dev/schemas/patch-operational-root-plan/1.0#/$defs/storage_event" + }, + "promotionEventRef": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/promotionEventRef" + }, + "storagePrefixRef": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/storagePrefixRef" + }, + "storageClockRef": { + "$ref": "https://benchwork.dev/schemas/artifact-materialization/1.0#/$defs/clockRef" + }, + "journalPrefix": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-inspect-request/1.0#/$defs/journal_prefix" + }, + "receipt": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/receipt" + }, + "referenceIntentRef": { + "type": "object", + "additionalProperties": false, + "required": [ + "reference_intent_id", + "record_sigil" + ], + "properties": { + "reference_intent_id": { + "$ref": "https://benchwork.dev/schemas/artifact-storage-reference-intent/1.0#/$defs/intentId" + }, + "record_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "releaseCondition": { + "enum": [ + "NON_PARTIAL_OUTCOME_OBSERVED", + "RESOLVED_RECOVERY_OBSERVED", + "ABANDONED_WITH_DISPOSITION", + "JOURNAL_RECOVERY_COMPLETED" + ] + }, + "abandonedRootDisposition": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-recovery-record/1.0#/$defs/rootDisposition" + }, + "terminalGuardCompletion": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-recovery-record/1.0#/$defs/terminalGuard" + }, + "abandonmentDispositionAuthority": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-recovery-record/1.0#/$defs/disposition" + }, + "noGuardAllocated": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "owner_kind", + "owner_attempt_id", + "attempt_terminal_event", + "allocation_absence_proof_sigil" + ], + "properties": { + "kind": { + "const": "NO_GUARD_ALLOCATED" + }, + "owner_kind": { + "enum": [ + "PROMOTION", + "RECOVERY" + ] + }, + "owner_attempt_id": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "not": { + "pattern": "[\\r\\n]" + } + }, + "attempt_terminal_event": { + "$ref": "#/$defs/promotionEventRef" + }, + "allocation_absence_proof_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "notApplicableJournalSuffixGuard": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "tail_recovery_id", + "completion_event" + ], + "properties": { + "kind": { + "const": "NOT_APPLICABLE_JOURNAL_SUFFIX" + }, + "tail_recovery_id": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/ptri" + }, + "completion_event": { + "$ref": "#/$defs/promotionEventRef" + } + } + }, + "guardCompletion": { + "oneOf": [ + { + "$ref": "#/$defs/terminalGuardCompletion" + }, + { + "$ref": "#/$defs/noGuardAllocated" + }, + { + "$ref": "#/$defs/notApplicableJournalSuffixGuard" + } + ] + }, + "canonicalCommitted": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "receipt", + "reference_intent", + "commit_event" + ], + "properties": { + "kind": { + "const": "COMMITTED_CANONICAL_RECORD" + }, + "receipt": { + "$ref": "#/$defs/receipt" + }, + "reference_intent": { + "$ref": "#/$defs/referenceIntentRef" + }, + "commit_event": { + "$ref": "#/$defs/storageEventRef" + } + } + }, + "canonicalNotApplicable": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind" + ], + "properties": { + "kind": { + "const": "NOT_APPLICABLE_JOURNAL_SUFFIX" + } + } + }, + "canonicalCompletion": { + "oneOf": [ + { + "$ref": "#/$defs/canonicalCommitted" + }, + { + "$ref": "#/$defs/canonicalNotApplicable" + } + ] + }, + "releasePolicyBinding": { + "type": "object", + "additionalProperties": false, + "required": [ + "policy_id", + "policy_sigil", + "deletion_grace_seconds", + "retain_until" + ], + "properties": { + "policy_id": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/sp" + }, + "policy_sigil": { + "$ref": "#/$defs/sigil" + }, + "deletion_grace_seconds": { + "$ref": "#/$defs/u63" + }, + "retain_until": { + "anyOf": [ + { + "$ref": "#/$defs/timestamp" + }, + { + "type": "null" + } + ] + } + } + }, + "retentionCompletion": { + "type": "object", + "additionalProperties": false, + "required": [ + "inactivation_recorded_at", + "grace_due_at", + "release_not_before", + "trusted_lower_bound", + "proof_sigil" + ], + "properties": { + "inactivation_recorded_at": { + "$ref": "#/$defs/timestamp" + }, + "grace_due_at": { + "$ref": "#/$defs/timestamp" + }, + "release_not_before": { + "$ref": "#/$defs/timestamp" + }, + "trusted_lower_bound": { + "$ref": "#/$defs/timestamp" + }, + "proof_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "attemptIntentAbsence": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "owner_kind", + "owner_attempt_id", + "promotion_open_intent_ids", + "storage_open_reference_intent_ids", + "absence_proof_sigil" + ], + "properties": { + "kind": { + "const": "ATTEMPT_OPERATIONAL_INTENTS_ABSENT" + }, + "owner_kind": { + "enum": [ + "PROMOTION", + "RECOVERY" + ] + }, + "owner_attempt_id": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "not": { + "pattern": "[\\r\\n]" + } + }, + "promotion_open_intent_ids": { + "type": "array", + "maxItems": 0 + }, + "storage_open_reference_intent_ids": { + "type": "array", + "maxItems": 0 + }, + "absence_proof_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "tailIntentAbsence": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "tail_recovery_id", + "promotion_open_intent_ids", + "storage_open_reference_intent_ids", + "absence_proof_sigil" + ], + "properties": { + "kind": { + "const": "TAIL_RECOVERY_INTENTS_ABSENT" + }, + "tail_recovery_id": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0#/$defs/ptri" + }, + "promotion_open_intent_ids": { + "type": "array", + "maxItems": 0 + }, + "storage_open_reference_intent_ids": { + "type": "array", + "maxItems": 0 + }, + "absence_proof_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "intentAbsence": { + "oneOf": [ + { + "$ref": "#/$defs/attemptIntentAbsence" + }, + { + "$ref": "#/$defs/tailIntentAbsence" + } + ] + } + } +} + + diff --git a/schemas/patch-promotion-adapter-1.0.json b/schemas/patch-promotion-adapter-1.0.json new file mode 100644 index 0000000..847655b --- /dev/null +++ b/schemas/patch-promotion-adapter-1.0.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-adapter/1.0", + "title": "Patch Promotion Adapter v1", + "description": "Closed RFC-0014 patch-promotion-adapter/1.0 contract-only record. Validation does not assert an adapter's actual Host, filesystem, clock, guard, or recovery capabilities.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "adapter_id", "adapter_version", "mode", "platform_profile", "deadline_policy", "guard_backend", "mutation_semantics", "recovery_semantics", "disabled_behaviors", "limits", "configuration_sigil", "adapter_sigil"], + "properties": { + "schema_version": {"const": "patch-promotion-adapter/1.0"}, + "adapter_id": {"$ref": "#/$defs/ppa"}, "adapter_version": {"$ref": "#/$defs/text64"}, "mode": {"enum": ["FULL_TREE_ATOMIC_CAS", "PER_ENTRY_GENERATIONAL_CAS"]}, + "platform_profile": {"$ref": "#/$defs/platform"}, "deadline_policy": {"$ref": "#/$defs/deadline"}, "guard_backend": {"$ref": "#/$defs/guard"}, "mutation_semantics": {"$ref": "#/$defs/mutation"}, "recovery_semantics": {"$ref": "#/$defs/recovery"}, + "disabled_behaviors": {"type": "array", "minItems": 1, "maxItems": 256, "uniqueItems": true, "items": {"$ref": "#/$defs/text128"}}, "limits": {"$ref": "#/$defs/limits"}, "configuration_sigil": {"$ref": "#/$defs/sigil"}, "adapter_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "text64": {"type": "string", "minLength": 0, "maxLength": 64, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "text128": {"type": "string", "minLength": 0, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, + "ppa": {"type": "string", "pattern": "^PPA-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "platform": {"type": "object", "additionalProperties": false, "required": ["os_family", "filesystem_sigil", "path_profile_sigil", "atomic_replace_scope", "conformance_suite_sigil"], "properties": {"os_family": {"enum": ["POSIX", "WINDOWS"]}, "filesystem_sigil": {"$ref": "#/$defs/sigil"}, "path_profile_sigil": {"$ref": "#/$defs/sigil"}, "atomic_replace_scope": {"enum": ["FULL_TREE", "PER_ENTRY"]}, "conformance_suite_sigil": {"$ref": "#/$defs/sigil"}}}, + "deadline": {"type": "object", "additionalProperties": false, "required": ["preview_lifetime_seconds", "guard_lifetime_seconds", "guard_renewal_interval_seconds", "clock_uncertainty_tolerance_seconds", "trusted_utc_source_profile_sigil", "monotonic_source_profile_sigil", "suspend_policy"], "properties": {"preview_lifetime_seconds": {"type": "integer", "minimum": 1, "maximum": 86400}, "guard_lifetime_seconds": {"type": "integer", "minimum": 1, "maximum": 3600}, "guard_renewal_interval_seconds": {"type": "integer", "minimum": 1, "maximum": 1800}, "clock_uncertainty_tolerance_seconds": {"type": "integer", "minimum": 0, "maximum": 300}, "trusted_utc_source_profile_sigil": {"$ref": "#/$defs/sigil"}, "monotonic_source_profile_sigil": {"$ref": "#/$defs/sigil"}, "suspend_policy": {"enum": ["FENCE_ON_UNPROVABLE", "COUNT_TRUSTED_SUSPEND"]}}}, + "guard": {"type": "object", "additionalProperties": false, "required": ["backend_id", "profile_sigil", "cas_semantics", "readback_semantics", "durable_tombstones", "durable_fence_floor", "generation_successor_profile_sigil", "max_active_guards"], "properties": {"backend_id": {"$ref": "#/$defs/text128"}, "profile_sigil": {"$ref": "#/$defs/sigil"}, "cas_semantics": {"const": "EXACT_GENERATION"}, "readback_semantics": {"const": "LINEARIZABLE"}, "durable_tombstones": {"const": true}, "durable_fence_floor": {"const": true}, "generation_successor_profile_sigil": {"$ref": "#/$defs/sigil"}, "max_active_guards": {"type": "integer", "minimum": 1, "maximum": 4096}}}, + "mutation": {"type": "object", "additionalProperties": false, "required": ["descriptor_relative_nofollow", "preimage_compare_and_swap", "topology_compare_and_swap", "mode", "atomicity", "per_step_receipts"], "properties": {"descriptor_relative_nofollow": {"const": true}, "preimage_compare_and_swap": {"const": true}, "topology_compare_and_swap": {"const": true}, "mode": {"enum": ["FULL_TREE_ATOMIC_CAS", "PER_ENTRY_GENERATIONAL_CAS"]}, "atomicity": {"enum": ["FULL_TREE", "TARGET_WIDE_GENERATION"]}, "per_step_receipts": {"type": "boolean"}}}, + "recovery": {"type": "object", "additionalProperties": false, "required": ["actions", "checkpoint_required", "verifier_readback_required", "partial_fence_required"], "properties": {"actions": {"type": "array", "minItems": 3, "maxItems": 3, "uniqueItems": true, "items": {"enum": ["RESTORE_BASE", "ACCEPT_POSTIMAGE", "ABANDON"]}}, "checkpoint_required": {"const": true}, "verifier_readback_required": {"const": true}, "partial_fence_required": {"const": true}}}, + "limits": {"type": "object", "additionalProperties": false, "required": ["max_paths", "max_total_bytes", "max_operation_bytes", "max_backend_retries", "max_active_guards"], "properties": {"max_paths": {"type": "integer", "minimum": 1, "maximum": 100000}, "max_total_bytes": {"$ref": "#/$defs/u63"}, "max_operation_bytes": {"$ref": "#/$defs/u63"}, "max_backend_retries": {"type": "integer", "minimum": 0, "maximum": 64}, "max_active_guards": {"type": "integer", "minimum": 1, "maximum": 4096}}} + } +} + diff --git a/schemas/patch-promotion-attempt-1.0.json b/schemas/patch-promotion-attempt-1.0.json new file mode 100644 index 0000000..9f42717 --- /dev/null +++ b/schemas/patch-promotion-attempt-1.0.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-attempt/1.0", + "title": "Patch Promotion Attempt v1", + "description": "Closed RFC-0014 patch-promotion-attempt/1.0 contract-only record. Validation is local and does not resolve Authorization, Target, Adapter, Profile, or Promotion Journal history.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "attempt_id", "authorization", "operation_sigil", "target", "target_content_generation", "adapter", "mode", "created_at", "state", "revision", "attempt_sigil"], + "properties": { + "schema_version": {"const": "patch-promotion-attempt/1.0"}, "attempt_id": {"$ref": "#/$defs/pat"}, "authorization": {"$ref": "#/$defs/pauRef"}, "operation_sigil": {"$ref": "#/$defs/sigil"}, "target": {"$ref": "#/$defs/target"}, "target_content_generation": {"$ref": "#/$defs/text256"}, "adapter": {"$ref": "#/$defs/ppaRef"}, "mode": {"enum": ["FULL_TREE_ATOMIC_CAS", "PER_ENTRY_GENERATIONAL_CAS"]}, "created_at": {"$ref": "#/$defs/timestamp"}, "state": {"enum": ["CREATED", "PREFLIGHTING", "READY", "MUTATING", "VERIFYING", "APPLIED", "RECOVERED_POSTIMAGE_OBSERVED", "ALREADY_APPLIED", "STALE", "CONFLICT", "FAILED", "PARTIAL", "CANCELLED"]}, "revision": {"$ref": "#/$defs/u64"}, "attempt_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "text128": {"type": "string", "minLength": 0, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "text256": {"type": "string", "minLength": 0, "maxLength": 256, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "pat": {"type": "string", "pattern": "^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pau": {"type": "string", "pattern": "^PAU-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pt": {"type": "string", "pattern": "^PT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pbip": {"type": "string", "pattern": "^PBIP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 6, "maxLength": 128}, "ppa": {"type": "string", "pattern": "^PPA-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "pauRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pau"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "pbipRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pbip"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "ppaRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/ppa"}, "sigil": {"$ref": "#/$defs/sigil"}}}, + "root": {"type": "object", "additionalProperties": false, "required": ["root_object_sigil", "root_generation", "topology_sigil"], "properties": {"root_object_sigil": {"$ref": "#/$defs/sigil"}, "root_generation": {"$ref": "#/$defs/text256"}, "topology_sigil": {"$ref": "#/$defs/sigil"}}}, + "target": {"type": "object", "additionalProperties": false, "required": ["target_id", "target_class", "identity_profile", "root_identity", "selection_authorization_sigil"], "properties": {"target_id": {"$ref": "#/$defs/pt"}, "target_class": {"enum": ["WORKTREE", "DIRECTORY"]}, "identity_profile": {"$ref": "#/$defs/pbipRef"}, "root_identity": {"$ref": "#/$defs/root"}, "selection_authorization_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/patch-promotion-authorization-1.0.json b/schemas/patch-promotion-authorization-1.0.json new file mode 100644 index 0000000..3a2f025 --- /dev/null +++ b/schemas/patch-promotion-authorization-1.0.json @@ -0,0 +1,7 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", "$id":"https://benchwork.dev/schemas/patch-promotion-authorization/1.0", "title":"Patch Promotion Authorization v1", "description":"Closed RFC-0014 patch-promotion-authorization/1.0 contract-only record. Validation does not resolve the Preview, token, clock, or canonical Receipt.", "type":"object", "additionalProperties":false, + "required":["schema_version","authorization_id","decision","preview","proposal","target_state_evidence","target_content_generation","affected_paths","operation_sigil","residual_risks","target","base","postimage","validation","adapter","mode","recovery","abandoned_lineage","expires_at","confirmation_token_sigil","actor","host","decision_at","clock_policy_sigil","clock_evidence_sigil","request_sigil","idempotency_key_sigil","authorization_sigil"], + "properties":{"schema_version":{"const":"patch-promotion-authorization/1.0"},"authorization_id":{"$ref":"#/$defs/pau"},"decision":{"const":"AUTHORIZE"},"preview":{"$ref":"#/$defs/prvRef"},"proposal":{"$ref":"#/$defs/ppRef"},"target_state_evidence":{"$ref":"https://benchwork.dev/schemas/patch-target-state-evidence/1.0"},"target_content_generation":{"$ref":"#/$defs/text256"},"affected_paths":{"type":"array","minItems":1,"maxItems":100000,"uniqueItems":true,"items":{"$ref":"#/$defs/text4096"}},"operation_sigil":{"$ref":"#/$defs/sigil"},"residual_risks":{"type":"array","minItems":0,"maxItems":256,"items":{"$ref":"#/$defs/text4096"}},"target":{"$ref":"https://benchwork.dev/schemas/patch-promotion-attempt/1.0#/$defs/target"},"base":{"$ref":"#/$defs/pbRef"},"postimage":{"$ref":"https://benchwork.dev/schemas/patch-promotion-mutation-intent/1.0#/$defs/postimage"},"validation":{"$ref":"#/$defs/validation"},"adapter":{"$ref":"#/$defs/ppaRef"},"mode":{"enum":["FULL_TREE_ATOMIC_CAS","PER_ENTRY_GENERATIONAL_CAS"]},"recovery":{"anyOf":[{"$ref":"#/$defs/recovery"},{"type":"null"}]},"abandoned_lineage":{"anyOf":[{"$ref":"#/$defs/abandoned"},{"type":"null"}]},"expires_at":{"$ref":"#/$defs/timestamp"},"confirmation_token_sigil":{"$ref":"#/$defs/sigil"},"actor":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/actor"},"host":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/host"},"decision_at":{"$ref":"#/$defs/timestamp"},"clock_policy_sigil":{"$ref":"#/$defs/sigil"},"clock_evidence_sigil":{"$ref":"#/$defs/sigil"},"request_sigil":{"$ref":"#/$defs/sigil"},"idempotency_key_sigil":{"$ref":"#/$defs/sigil"},"authorization_sigil":{"$ref":"#/$defs/sigil"}}, + "$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u64":{"type":"integer","minimum":0,"maximum":18446744073709551615},"text256":{"type":"string","minLength":0,"maxLength":256,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"text4096":{"type":"string","minLength":0,"maxLength":4096,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"pau":{"type":"string","pattern":"^PAU-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"prv":{"type":"string","pattern":"^PRV-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pp":{"type":"string","pattern":"^PP-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"pb":{"type":"string","pattern":"^PB-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"pvp":{"type":"string","pattern":"^PVP-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pve":{"type":"string","pattern":"^PVE-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"ppa":{"type":"string","pattern":"^PPA-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pat":{"type":"string","pattern":"^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pck":{"type":"string","pattern":"^PCK-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pmi":{"type":"string","pattern":"^PMI-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pra":{"type":"string","pattern":"^PRA-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"prr":{"type":"string","pattern":"^PRR-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"rc":{"type":"string","pattern":"^RC-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"ce":{"type":"string","pattern":"^CE-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"ref":{"type":"object","additionalProperties":false,"required":["id","sigil"],"properties":{"id":{"type":"string"},"sigil":{"$ref":"#/$defs/sigil"}}},"prvRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/prv"}}}]},"ppRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pp"}}}]},"pbRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pb"}}}]},"ppaRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/ppa"}}}]},"validation":{"type":"object","additionalProperties":false,"required":["policy","evidence"],"properties":{"policy":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pvp"}}}]},"evidence":{"type":"array","minItems":1,"maxItems":4096,"uniqueItems":true,"items":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pve"}}}]}}}},"receipt":{"type":"object","additionalProperties":false,"required":["receipt_id","receipt_sigil","event_id","event_body_sigil"],"properties":{"receipt_id":{"$ref":"#/$defs/rc"},"receipt_sigil":{"$ref":"#/$defs/sigil"},"event_id":{"$ref":"#/$defs/ce"},"event_body_sigil":{"$ref":"#/$defs/sigil"}}},"recovery":{"type":"object","additionalProperties":false,"required":["parent_attempt_id","parent_outcome_receipt","checkpoint","mutation_intent","action","lineage"],"properties":{"parent_attempt_id":{"$ref":"#/$defs/pat"},"parent_outcome_receipt":{"$ref":"#/$defs/receipt"},"checkpoint":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pck"}}}]},"mutation_intent":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pmi"}}}]},"action":{"enum":["RESTORE_BASE","ACCEPT_POSTIMAGE","ABANDON"]},"lineage":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/lineage"}}},"abandoned":{"type":"object","additionalProperties":false,"required":["target_id","reentry_proposal","logical_fence_generation","logical_fence_revision","logical_fence_sigil","abandonment_head_sigil","recovery_attempt_id","recovery_record_id","recovery_record_sigil","recovery_record_receipt","abandonment_disposition_sigil","observed_identity_sigil","target_content_generation"],"properties":{"target_id":{"type":"string","pattern":"^PT-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"reentry_proposal":{"$ref":"#/$defs/ppRef"},"logical_fence_generation":{"$ref":"#/$defs/u64"},"logical_fence_revision":{"$ref":"#/$defs/u64"},"logical_fence_sigil":{"$ref":"#/$defs/sigil"},"abandonment_head_sigil":{"$ref":"#/$defs/sigil"},"recovery_attempt_id":{"$ref":"#/$defs/pra"},"recovery_record_id":{"$ref":"#/$defs/prr"},"recovery_record_sigil":{"$ref":"#/$defs/sigil"},"recovery_record_receipt":{"$ref":"#/$defs/receipt"},"abandonment_disposition_sigil":{"$ref":"#/$defs/sigil"},"observed_identity_sigil":{"$ref":"#/$defs/sigil"},"target_content_generation":{"$ref":"#/$defs/text256"}}}} +} + diff --git a/schemas/patch-promotion-authorize-request-1.0.json b/schemas/patch-promotion-authorize-request-1.0.json new file mode 100644 index 0000000..940db03 --- /dev/null +++ b/schemas/patch-promotion-authorize-request-1.0.json @@ -0,0 +1,8 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", "$id":"https://benchwork.dev/schemas/patch-promotion-authorize-request/1.0", "title":"Patch Promotion Authorize Request v1", "description":"Closed RFC-0014 patch-promotion-authorize-request/1.0 request. Its raw confirmation token is redacted from request_sigil input.", "type":"object", "additionalProperties":false, + "required":["schema_version","request_id","decision","preview","confirmation_token","affirmative_confirmation","reason","actor","host","requested_at","idempotency_key","confirmation_token_sigil","request_sigil"], + "properties":{"schema_version":{"const":"patch-promotion-authorize-request/1.0"},"request_id":{"$ref":"#/$defs/par"},"decision":{"enum":["AUTHORIZE","REJECT"]},"preview":{"$ref":"#/$defs/prvRef"},"confirmation_token":{"anyOf":[{"$ref":"#/$defs/token"},{"type":"null"}]},"affirmative_confirmation":{"anyOf":[{"const":true},{"type":"null"}]},"reason":{"$ref":"#/$defs/text4096"},"actor":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/actor"},"host":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/host"},"requested_at":{"$ref":"#/$defs/timestamp"},"idempotency_key":{"$ref":"#/$defs/text256"},"confirmation_token_sigil":{"anyOf":[{"$ref":"#/$defs/sigil"},{"type":"null"}]},"request_sigil":{"$ref":"#/$defs/sigil"}}, + "oneOf":[{"properties":{"decision":{"const":"AUTHORIZE"},"confirmation_token":{"$ref":"#/$defs/token"},"affirmative_confirmation":{"const":true},"confirmation_token_sigil":{"$ref":"#/$defs/sigil"}}},{"properties":{"decision":{"const":"REJECT"},"confirmation_token":{"type":"null"},"affirmative_confirmation":{"type":"null"},"confirmation_token_sigil":{"type":"null"}}}], + "$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"token":{"type":"string","pattern":"^[A-Za-z0-9_-]{43}$","minLength":43,"maxLength":43},"text256":{"type":"string","minLength":0,"maxLength":256,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"text4096":{"type":"string","minLength":0,"maxLength":4096,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"par":{"type":"string","pattern":"^PAR-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"prv":{"type":"string","pattern":"^PRV-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"ref":{"type":"object","additionalProperties":false,"required":["id","sigil"],"properties":{"id":{"type":"string"},"sigil":{"$ref":"#/$defs/sigil"}}},"prvRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/prv"}}}]}} +} + diff --git a/schemas/patch-promotion-authorize-response-1.0.json b/schemas/patch-promotion-authorize-response-1.0.json new file mode 100644 index 0000000..f8b40bd --- /dev/null +++ b/schemas/patch-promotion-authorize-response-1.0.json @@ -0,0 +1,8 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", "$id":"https://benchwork.dev/schemas/patch-promotion-authorize-response/1.0", "title":"Patch Promotion Authorize Response v1", "description":"Closed RFC-0014 patch-promotion-authorize-response/1.0 response. It never contains a raw confirmation token.", "type":"object", "additionalProperties":false, + "required":["schema_version","decision","record","receipt","response_sigil"], + "properties":{"schema_version":{"const":"patch-promotion-authorize-response/1.0"},"decision":{"enum":["AUTHORIZE","REJECT"]},"record":{"oneOf":[{"$ref":"#/$defs/authorization"},{"$ref":"#/$defs/rejection"}]},"receipt":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/receipt"},"response_sigil":{"$ref":"#/$defs/sigil"}}, + "allOf":[{"if":{"properties":{"decision":{"const":"AUTHORIZE"}}},"then":{"properties":{"record":{"$ref":"#/$defs/authorization"}}}},{"if":{"properties":{"decision":{"const":"REJECT"}}},"then":{"properties":{"record":{"$ref":"#/$defs/rejection"}}}}], + "$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"authorization":{"type":"object","additionalProperties":false,"required":["kind","authorization"],"properties":{"kind":{"const":"AUTHORIZE"},"authorization":{"$ref":"https://benchwork.dev/schemas/patch-promotion-authorization/1.0"}}},"rejection":{"type":"object","additionalProperties":false,"required":["kind","rejection"],"properties":{"kind":{"const":"REJECT"},"rejection":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0"}}}} +} + diff --git a/schemas/patch-promotion-checkpoint-1.0.json b/schemas/patch-promotion-checkpoint-1.0.json new file mode 100644 index 0000000..173b3fb --- /dev/null +++ b/schemas/patch-promotion-checkpoint-1.0.json @@ -0,0 +1,43 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-checkpoint/1.0", + "title": "Patch Promotion Checkpoint v1", + "description": "Closed RFC-0014 patch-promotion-checkpoint/1.0 contract-only record. Validation is local and does not resolve a Base, Attempt, Target, Blob bytes, or verifier evidence.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "checkpoint_id", "attempt_id", "target_id", "base", "affected_paths", "entries", "checkpoint_blobs", "created_at", "verified_at", "checkpoint_sigil"], + "properties": { + "schema_version": {"const": "patch-promotion-checkpoint/1.0"}, + "checkpoint_id": {"$ref": "#/$defs/pck"}, + "attempt_id": {"$ref": "#/$defs/pat"}, + "target_id": {"$ref": "#/$defs/pt"}, + "base": {"$ref": "#/$defs/pbRef"}, + "affected_paths": {"type": "array", "minItems": 1, "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/path"}}, + "entries": {"type": "array", "minItems": 1, "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/checkpointEntry"}}, + "checkpoint_blobs": {"type": "array", "minItems": 0, "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/blob"}}, + "created_at": {"$ref": "#/$defs/timestamp"}, + "verified_at": {"$ref": "#/$defs/timestamp"}, + "checkpoint_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "text128": {"type": "string", "minLength": 0, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, + "text4096": {"type": "string", "minLength": 0, "maxLength": 4096, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, + "path": {"allOf": [{"$ref": "#/$defs/text4096"}, {"type": "string", "minLength": 1}]}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "pck": {"type": "string", "pattern": "^PCK-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "pat": {"type": "string", "pattern": "^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "pt": {"type": "string", "pattern": "^PT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "pb": {"type": "string", "pattern": "^PB-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "pbRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pb"}, "sigil": {"$ref": "#/$defs/sigil"}}}, + "blob": {"type": "object", "additionalProperties": false, "required": ["sigil", "size_bytes", "media_type"], "properties": {"sigil": {"$ref": "#/$defs/sigil"}, "size_bytes": {"$ref": "#/$defs/u63"}, "media_type": {"$ref": "#/$defs/text128"}}}, + "absent": {"type": "object", "additionalProperties": false, "required": ["kind"], "properties": {"kind": {"const": "ABSENT"}}}, + "file": {"type": "object", "additionalProperties": false, "required": ["kind", "blob_sigil", "size_bytes", "executable"], "properties": {"kind": {"const": "FILE"}, "blob_sigil": {"$ref": "#/$defs/sigil"}, "size_bytes": {"$ref": "#/$defs/u63"}, "executable": {"type": "boolean"}}}, + "directory": {"type": "object", "additionalProperties": false, "required": ["kind", "entry_sigil"], "properties": {"kind": {"const": "DIRECTORY"}, "entry_sigil": {"$ref": "#/$defs/sigil"}}}, + "symlink": {"type": "object", "additionalProperties": false, "required": ["kind", "target", "target_sigil"], "properties": {"kind": {"const": "SYMLINK"}, "target": {"$ref": "#/$defs/text4096"}, "target_sigil": {"$ref": "#/$defs/sigil"}}}, + "entryIdentity": {"oneOf": [{"$ref": "#/$defs/absent"}, {"$ref": "#/$defs/file"}, {"$ref": "#/$defs/directory"}, {"$ref": "#/$defs/symlink"}]}, + "checkpointEntry": {"type": "object", "additionalProperties": false, "required": ["path_bytes", "preimage", "checkpoint_blob", "verification_sigil"], "properties": {"path_bytes": {"$ref": "#/$defs/path"}, "preimage": {"$ref": "#/$defs/entryIdentity"}, "checkpoint_blob": {"anyOf": [{"$ref": "#/$defs/blob"}, {"type": "null"}]}, "verification_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/patch-promotion-inspect-request-1.0.json b/schemas/patch-promotion-inspect-request-1.0.json new file mode 100644 index 0000000..2a608b5 --- /dev/null +++ b/schemas/patch-promotion-inspect-request-1.0.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-inspect-request/1.0", + "title": "Patch Promotion Inspect Request v1", + "description": "Closed RFC-0014 contract-only read request. Validation checks wire syntax only and does not resolve a Journal prefix or return records.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "selector", "page_size", "cursor", "fixed_prefix", "request_sigil"], + "properties": { + "schema_version": {"const": "patch-promotion-inspect-request/1.0"}, + "selector": {"oneOf": [ + {"$ref": "#/$defs/proposal"}, {"$ref": "#/$defs/preview"}, {"$ref": "#/$defs/decision"}, + {"$ref": "#/$defs/promotion_attempt"}, {"$ref": "#/$defs/recovery_attempt"}, + {"$ref": "#/$defs/promotion_outcome"}, {"$ref": "#/$defs/recovery_record"} + ]}, + "page_size": {"type": "integer", "minimum": 1, "maximum": 256}, + "cursor": {"anyOf": [{"$ref": "#/$defs/text512"}, {"type": "null"}]}, + "fixed_prefix": {"anyOf": [{"$ref": "#/$defs/journal_prefix"}, {"type": "null"}]}, + "request_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [{ + "if": {"properties": {"cursor": {"type": "string"}}}, + "then": {"properties": {"fixed_prefix": {"$ref": "#/$defs/journal_prefix"}}} + }], + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "text512": {"type": "string", "minLength": 0, "maxLength": 512, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, + "pp": {"type": "string", "pattern": "^PP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "prv": {"type": "string", "pattern": "^PRV-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "pat": {"type": "string", "pattern": "^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "pra": {"type": "string", "pattern": "^PRA-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "po": {"type": "string", "pattern": "^PO-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "prr": {"type": "string", "pattern": "^PRR-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "proposal": {"type": "object", "additionalProperties": false, "required": ["kind", "proposal_id"], "properties": {"kind": {"const": "PROPOSAL"}, "proposal_id": {"$ref": "#/$defs/pp"}}}, + "preview": {"type": "object", "additionalProperties": false, "required": ["kind", "preview_id"], "properties": {"kind": {"const": "PREVIEW"}, "preview_id": {"$ref": "#/$defs/prv"}}}, + "decision": {"type": "object", "additionalProperties": false, "required": ["kind", "preview_id"], "properties": {"kind": {"const": "DECISION"}, "preview_id": {"$ref": "#/$defs/prv"}}}, + "promotion_attempt": {"type": "object", "additionalProperties": false, "required": ["kind", "attempt_id"], "properties": {"kind": {"const": "PROMOTION_ATTEMPT"}, "attempt_id": {"$ref": "#/$defs/pat"}}}, + "recovery_attempt": {"type": "object", "additionalProperties": false, "required": ["kind", "recovery_attempt_id"], "properties": {"kind": {"const": "RECOVERY_ATTEMPT"}, "recovery_attempt_id": {"$ref": "#/$defs/pra"}}}, + "promotion_outcome": {"type": "object", "additionalProperties": false, "required": ["kind", "outcome_id"], "properties": {"kind": {"const": "PROMOTION_OUTCOME"}, "outcome_id": {"$ref": "#/$defs/po"}}}, + "recovery_record": {"type": "object", "additionalProperties": false, "required": ["kind", "recovery_record_id"], "properties": {"kind": {"const": "RECOVERY_RECORD"}, "recovery_record_id": {"$ref": "#/$defs/prr"}}}, + "journal_prefix": {"type": "object", "additionalProperties": false, "required": ["head", "state_sigil"], "properties": {"head": {"$ref": "https://benchwork.dev/schemas/patch-promotion-journal-head/1.0"}, "state_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/patch-promotion-journal-event-1.0.json b/schemas/patch-promotion-journal-event-1.0.json new file mode 100644 index 0000000..25d6c6f --- /dev/null +++ b/schemas/patch-promotion-journal-event-1.0.json @@ -0,0 +1,4227 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-journal-event/1.0", + "title": "Patch Promotion Journal Event v1", + "description": "Closed RFC-0014 Promotion Journal Event wire contract. Contract-only validation does not resolve a Journal prefix, replay State, Receipt, HoldBinding, Storage/Chronicle record, or grant Promotion or recovery authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "journal_id", + "event_id", + "sequence", + "coordinator_id", + "coordinator_epoch", + "event_type", + "recorded_at", + "entity_revisions", + "causation_event_id", + "idempotency_key_sigil", + "payload", + "previous_event_sigil", + "event_sigil" + ], + "properties": { + "schema_version": { + "const": "patch-promotion-journal-event/1.0" + }, + "journal_id": { + "$ref": "#/$defs/pj" + }, + "event_id": { + "$ref": "#/$defs/pje" + }, + "sequence": { + "$ref": "#/$defs/positiveU64" + }, + "coordinator_id": { + "$ref": "#/$defs/pc" + }, + "coordinator_epoch": { + "$ref": "#/$defs/u64" + }, + "event_type": { + "$ref": "#/$defs/eventType" + }, + "recorded_at": { + "$ref": "#/$defs/timestamp" + }, + "entity_revisions": { + "type": "array", + "minItems": 1, + "maxItems": 1000000, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/entityRevision" + } + }, + "causation_event_id": { + "anyOf": [ + { + "$ref": "#/$defs/pje" + }, + { + "type": "null" + } + ] + }, + "idempotency_key_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "payload": { + "type": "object" + }, + "previous_event_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "event_sigil": { + "$ref": "#/$defs/sigil" + } + }, + "oneOf": [ + { + "properties": { + "event_type": { + "const": "coordinator.epoch-started" + }, + "payload": { + "$ref": "#/$defs/payload1" + } + } + }, + { + "properties": { + "event_type": { + "const": "coordinator.replay-started" + }, + "payload": { + "$ref": "#/$defs/payload2" + } + } + }, + { + "properties": { + "event_type": { + "const": "coordinator.integrity-failed" + }, + "payload": { + "$ref": "#/$defs/payload3" + } + } + }, + { + "properties": { + "event_type": { + "const": "coordinator.clock-uncertain" + }, + "payload": { + "$ref": "#/$defs/payload4" + } + } + }, + { + "properties": { + "event_type": { + "const": "coordinator.clock-restored" + }, + "payload": { + "$ref": "#/$defs/payload5" + } + } + }, + { + "properties": { + "event_type": { + "const": "canonical.receipt-observed" + }, + "payload": { + "$ref": "#/$defs/payload6" + } + } + }, + { + "properties": { + "event_type": { + "const": "preview.prepared" + }, + "payload": { + "$ref": "#/$defs/payload7" + } + } + }, + { + "properties": { + "event_type": { + "const": "preview.decision-submission-started" + }, + "payload": { + "$ref": "#/$defs/payload8" + } + } + }, + { + "properties": { + "event_type": { + "const": "preview.decision-failed" + }, + "payload": { + "$ref": "#/$defs/payload9" + } + } + }, + { + "properties": { + "event_type": { + "const": "preview.expired" + }, + "payload": { + "$ref": "#/$defs/payload10" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-acquire-intent-committed" + }, + "payload": { + "$ref": "#/$defs/payload11" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-acquired" + }, + "payload": { + "$ref": "#/$defs/payload12" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-renew-intent-committed" + }, + "payload": { + "$ref": "#/$defs/payload13" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-renewed" + }, + "payload": { + "$ref": "#/$defs/payload14" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-validated" + }, + "payload": { + "$ref": "#/$defs/payload15" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-release-intent-committed" + }, + "payload": { + "$ref": "#/$defs/payload16" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-fence-intent-committed" + }, + "payload": { + "$ref": "#/$defs/payload17" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-fenced" + }, + "payload": { + "$ref": "#/$defs/payload18" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-released" + }, + "payload": { + "$ref": "#/$defs/payload19" + } + } + }, + { + "properties": { + "event_type": { + "const": "target.guard-failed" + }, + "payload": { + "$ref": "#/$defs/payload20" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.attempt-created" + }, + "payload": { + "$ref": "#/$defs/payload21" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.preflight-started" + }, + "payload": { + "$ref": "#/$defs/payload22" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.checkpoint-committed" + }, + "payload": { + "$ref": "#/$defs/payload23" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.ready" + }, + "payload": { + "$ref": "#/$defs/payload24" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.mutation-intent-committed" + }, + "payload": { + "$ref": "#/$defs/payload25" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.verification-started" + }, + "payload": { + "$ref": "#/$defs/payload26" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.applied" + }, + "payload": { + "$ref": "#/$defs/payload27" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.recovered-postimage-observed" + }, + "payload": { + "$ref": "#/$defs/payload28" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.already-applied" + }, + "payload": { + "$ref": "#/$defs/payload29" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.stale" + }, + "payload": { + "$ref": "#/$defs/payload30" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.conflicted" + }, + "payload": { + "$ref": "#/$defs/payload31" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.failed" + }, + "payload": { + "$ref": "#/$defs/payload32" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.partial" + }, + "payload": { + "$ref": "#/$defs/payload33" + } + } + }, + { + "properties": { + "event_type": { + "const": "promotion.cancelled" + }, + "payload": { + "$ref": "#/$defs/payload34" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.attempt-created" + }, + "payload": { + "$ref": "#/$defs/payload35" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.preflight-started" + }, + "payload": { + "$ref": "#/$defs/payload36" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.checkpoint-verified" + }, + "payload": { + "$ref": "#/$defs/payload37" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.ready" + }, + "payload": { + "$ref": "#/$defs/payload38" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.intent-committed" + }, + "payload": { + "$ref": "#/$defs/payload39" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.verification-started" + }, + "payload": { + "$ref": "#/$defs/payload40" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.base-restored" + }, + "payload": { + "$ref": "#/$defs/payload41" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.postimage-accepted" + }, + "payload": { + "$ref": "#/$defs/payload42" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.abandoned" + }, + "payload": { + "$ref": "#/$defs/payload43" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.stale" + }, + "payload": { + "$ref": "#/$defs/payload44" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.failed" + }, + "payload": { + "$ref": "#/$defs/payload45" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.partial" + }, + "payload": { + "$ref": "#/$defs/payload46" + } + } + }, + { + "properties": { + "event_type": { + "const": "recovery.cancelled" + }, + "payload": { + "$ref": "#/$defs/payload47" + } + } + } + ], + "$defs": { + "sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$", + "minLength": 71, + "maxLength": 71 + }, + "u64": { + "type": "integer", + "minimum": 0, + "maximum": 18446744073709552000 + }, + "positiveU64": { + "type": "integer", + "minimum": 1, + "maximum": 18446744073709552000 + }, + "positiveU63": { + "type": "integer", + "minimum": 1, + "maximum": 9223372036854776000 + }, + "timestamp": { + "type": "string", + "format": "date-time", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", + "minLength": 20, + "maxLength": 27 + }, + "text64": { + "type": "string", + "minLength": 0, + "maxLength": 64, + "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", + "not": { + "pattern": "[\\r\\n]" + } + }, + "text128": { + "type": "string", + "minLength": 0, + "maxLength": 128, + "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", + "not": { + "pattern": "[\\r\\n]" + } + }, + "text256": { + "type": "string", + "minLength": 0, + "maxLength": 256, + "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", + "not": { + "pattern": "[\\r\\n]" + } + }, + "text512": { + "type": "string", + "minLength": 0, + "maxLength": 512, + "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", + "not": { + "pattern": "[\\r\\n]" + } + }, + "eventType": { + "enum": [ + "coordinator.epoch-started", + "coordinator.replay-started", + "coordinator.integrity-failed", + "coordinator.clock-uncertain", + "coordinator.clock-restored", + "canonical.receipt-observed", + "preview.prepared", + "preview.decision-submission-started", + "preview.decision-failed", + "preview.expired", + "target.guard-acquire-intent-committed", + "target.guard-acquired", + "target.guard-renew-intent-committed", + "target.guard-renewed", + "target.guard-validated", + "target.guard-release-intent-committed", + "target.guard-fence-intent-committed", + "target.guard-fenced", + "target.guard-released", + "target.guard-failed", + "promotion.attempt-created", + "promotion.preflight-started", + "promotion.checkpoint-committed", + "promotion.ready", + "promotion.mutation-intent-committed", + "promotion.verification-started", + "promotion.applied", + "promotion.recovered-postimage-observed", + "promotion.already-applied", + "promotion.stale", + "promotion.conflicted", + "promotion.failed", + "promotion.partial", + "promotion.cancelled", + "recovery.attempt-created", + "recovery.preflight-started", + "recovery.checkpoint-verified", + "recovery.ready", + "recovery.intent-committed", + "recovery.verification-started", + "recovery.base-restored", + "recovery.postimage-accepted", + "recovery.abandoned", + "recovery.stale", + "recovery.failed", + "recovery.partial", + "recovery.cancelled" + ] + }, + "pj": { + "type": "string", + "pattern": "^PJ-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "pje": { + "type": "string", + "pattern": "^PJE-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "pc": { + "type": "string", + "pattern": "^PC-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "ptri": { + "type": "string", + "pattern": "^PTRI-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 6, + "maxLength": 128 + }, + "proot": { + "type": "string", + "pattern": "^PROOT-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 7, + "maxLength": 128 + }, + "pg": { + "type": "string", + "pattern": "^PG-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "prv": { + "type": "string", + "pattern": "^PRV-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "ce": { + "type": "string", + "pattern": "^CE-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "rc": { + "type": "string", + "pattern": "^RC-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "pat": { + "type": "string", + "pattern": "^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "pck": { + "type": "string", + "pattern": "^PCK-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "pmi": { + "type": "string", + "pattern": "^PMI-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "pra": { + "type": "string", + "pattern": "^PRA-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "pri": { + "type": "string", + "pattern": "^PRI-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "pt": { + "type": "string", + "pattern": "^PT-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "po": { + "type": "string", + "pattern": "^PO-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "prr": { + "type": "string", + "pattern": "^PRR-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "pp": { + "type": "string", + "pattern": "^PP-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "per": { + "type": "string", + "pattern": "^PER-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "pdf": { + "type": "string", + "pattern": "^PDF-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 5, + "maxLength": 128 + }, + "porp": { + "type": "string", + "pattern": "^PORP-[A-Za-z0-9][A-Za-z0-9._-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 6, + "maxLength": 128 + }, + "sj": { + "type": "string", + "pattern": "^SJ-[A-Za-z0-9][A-Za-z0-9._:-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "se": { + "type": "string", + "pattern": "^SE-[A-Za-z0-9][A-Za-z0-9._:-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "sh": { + "type": "string", + "pattern": "^SH-[A-Za-z0-9][A-Za-z0-9._:-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "rs": { + "type": "string", + "pattern": "^RS-[A-Za-z0-9][A-Za-z0-9._:-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "sp": { + "type": "string", + "pattern": "^SP-[A-Za-z0-9][A-Za-z0-9._:-]*$", + "not": { + "pattern": "[\\r\\n]" + }, + "minLength": 4, + "maxLength": 128 + }, + "pckRef": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "sigil" + ], + "properties": { + "id": { + "$ref": "#/$defs/pck" + }, + "sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "pmiRef": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "sigil" + ], + "properties": { + "id": { + "$ref": "#/$defs/pmi" + }, + "sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "pgRef": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "sigil" + ], + "properties": { + "id": { + "$ref": "#/$defs/pg" + }, + "sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "priRef": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "sigil" + ], + "properties": { + "id": { + "$ref": "#/$defs/pri" + }, + "sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "receipt": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-authorization/1.0#/$defs/receipt" + }, + "actor": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/actor" + }, + "host": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/host" + }, + "headRef": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-journal-head/1.0" + }, + "storageEventRef": { + "$ref": "https://benchwork.dev/schemas/artifact-storage-journal-event/1.0#/$defs/eventRef" + }, + "storagePrefixRef": { + "type": "object", + "additionalProperties": false, + "required": [ + "journal_id", + "through_sequence", + "terminal_event_sigil", + "projected_state_sigil" + ], + "properties": { + "journal_id": { + "$ref": "#/$defs/sj" + }, + "through_sequence": { + "$ref": "#/$defs/positiveU63" + }, + "terminal_event_sigil": { + "$ref": "#/$defs/sigil" + }, + "projected_state_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "referenceSetRef": { + "type": "object", + "additionalProperties": false, + "required": [ + "reference_set_id", + "reference_set_sigil" + ], + "properties": { + "reference_set_id": { + "$ref": "#/$defs/rs" + }, + "reference_set_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "rootPlanRef": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "sigil" + ], + "properties": { + "id": { + "$ref": "#/$defs/porp" + }, + "sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "holdAuthorization": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "subject_id", + "authorization_sigil" + ], + "properties": { + "kind": { + "enum": [ + "PROMOTION_CONTROL", + "JOURNAL_RECOVERY", + "EXECUTION_ROOT_IMPORT" + ] + }, + "subject_id": { + "$ref": "#/$defs/text128" + }, + "authorization_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "holdBinding": { + "type": "object", + "additionalProperties": false, + "required": [ + "root_plan", + "hold_id", + "hold_set_event", + "frozen_storage_prefix", + "target_reference_set", + "policy_id", + "policy_sigil", + "authorization" + ], + "properties": { + "root_plan": { + "$ref": "#/$defs/rootPlanRef" + }, + "hold_id": { + "$ref": "#/$defs/sh" + }, + "hold_set_event": { + "$ref": "#/$defs/storageEventRef" + }, + "frozen_storage_prefix": { + "$ref": "#/$defs/storagePrefixRef" + }, + "target_reference_set": { + "$ref": "#/$defs/referenceSetRef" + }, + "policy_id": { + "$ref": "#/$defs/sp" + }, + "policy_sigil": { + "$ref": "#/$defs/sigil" + }, + "authorization": { + "$ref": "#/$defs/holdAuthorization" + } + } + }, + "promotionEventRef": { + "type": "object", + "additionalProperties": false, + "required": [ + "protocol_id", + "protocol_version", + "journal_id", + "event_id", + "sequence", + "event_type", + "event_sigil" + ], + "properties": { + "protocol_id": { + "const": "benchwork.patch-promotion" + }, + "protocol_version": { + "const": "1.0" + }, + "journal_id": { + "$ref": "#/$defs/pj" + }, + "event_id": { + "$ref": "#/$defs/pje" + }, + "sequence": { + "$ref": "#/$defs/positiveU64" + }, + "event_type": { + "$ref": "#/$defs/eventType" + }, + "event_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "logicalFencePromotionRecord": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "outcome_id", + "outcome_sigil", + "receipt" + ], + "properties": { + "kind": { + "const": "PROMOTION_OUTCOME" + }, + "outcome_id": { + "$ref": "#/$defs/po" + }, + "outcome_sigil": { + "$ref": "#/$defs/sigil" + }, + "receipt": { + "$ref": "#/$defs/receipt" + } + } + }, + "logicalFenceRecoveryRecord": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "recovery_record_id", + "recovery_record_sigil", + "receipt" + ], + "properties": { + "kind": { + "const": "RECOVERY_RECORD" + }, + "recovery_record_id": { + "$ref": "#/$defs/prr" + }, + "recovery_record_sigil": { + "$ref": "#/$defs/sigil" + }, + "receipt": { + "$ref": "#/$defs/receipt" + } + } + }, + "abandonedLineage": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-authorization/1.0#/$defs/abandoned" + }, + "logicalFenceReceiptTransition": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "target_id", + "logical_fence_generation", + "parent_attempt_id", + "terminal_event", + "canonical_record" + ], + "properties": { + "kind": { + "const": "PROMOTION_PARTIAL_CANONICALIZED" + }, + "target_id": { + "$ref": "#/$defs/pt" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "parent_attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_event": { + "$ref": "#/$defs/promotionEventRef" + }, + "canonical_record": { + "$ref": "#/$defs/logicalFencePromotionRecord" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "target_id", + "logical_fence_generation", + "parent_attempt_id", + "recovery_attempt_id", + "terminal_status", + "terminal_event", + "canonical_record", + "next_state" + ], + "properties": { + "kind": { + "const": "RECOVERY_RECORD_CANONICALIZED" + }, + "target_id": { + "$ref": "#/$defs/pt" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "parent_attempt_id": { + "$ref": "#/$defs/pat" + }, + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "terminal_status": { + "enum": [ + "BASE_RESTORED", + "POSTIMAGE_ACCEPTED", + "ABANDONED", + "STALE", + "FAILED", + "PARTIAL", + "CANCELLED" + ] + }, + "terminal_event": { + "$ref": "#/$defs/promotionEventRef" + }, + "canonical_record": { + "$ref": "#/$defs/logicalFenceRecoveryRecord" + }, + "next_state": { + "enum": [ + "ACTIVE", + "ABANDONED", + "CLEAR" + ] + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "target_id", + "logical_fence_generation", + "attempt_id", + "terminal_status", + "terminal_event", + "abandoned_lineage", + "canonical_record" + ], + "properties": { + "kind": { + "const": "ABANDONED_REENTRY_RESOLVED" + }, + "target_id": { + "$ref": "#/$defs/pt" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_status": { + "enum": [ + "APPLIED", + "RECOVERED_POSTIMAGE_OBSERVED", + "ALREADY_APPLIED" + ] + }, + "terminal_event": { + "$ref": "#/$defs/promotionEventRef" + }, + "abandoned_lineage": { + "$ref": "#/$defs/abandonedLineage" + }, + "canonical_record": { + "$ref": "#/$defs/logicalFencePromotionRecord" + } + } + } + ] + }, + "guardRecoveryStart": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "origin_state", + "guard_sigil", + "last_physical_intent_event_id", + "last_physical_intent_event_sigil", + "backend_request_sigil", + "prior_backend_generation", + "intended_backend_generation", + "prior_fence_floor", + "intended_fence_floor", + "last_readback_evidence_sigil" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "origin_state": { + "enum": [ + "ACQUIRING", + "HELD", + "RENEWING", + "RELEASING", + "FENCING", + "RECOVERING" + ] + }, + "guard_sigil": { + "$ref": "#/$defs/sigil" + }, + "last_physical_intent_event_id": { + "anyOf": [ + { + "$ref": "#/$defs/pje" + }, + { + "type": "null" + } + ] + }, + "last_physical_intent_event_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "backend_request_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "prior_backend_generation": { + "anyOf": [ + { + "$ref": "#/$defs/text256" + }, + { + "type": "null" + } + ] + }, + "intended_backend_generation": { + "anyOf": [ + { + "$ref": "#/$defs/text256" + }, + { + "type": "null" + } + ] + }, + "prior_fence_floor": { + "$ref": "#/$defs/u64" + }, + "intended_fence_floor": { + "$ref": "#/$defs/u64" + }, + "last_readback_evidence_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + } + } + }, + "patchErrorDetails": { + "type": "object", + "additionalProperties": false, + "required": [ + "error_id", + "retryable", + "entity_kind", + "entity_id", + "state", + "expected_sigil", + "observed_sigil", + "due_at", + "idempotency_key_sigil", + "failure_id", + "reason_code", + "evidence_sigils", + "detail_sigil" + ], + "properties": { + "error_id": { + "$ref": "#/$defs/per" + }, + "retryable": { + "type": "boolean" + }, + "entity_kind": { + "anyOf": [ + { + "enum": [ + "PROPOSAL", + "PREVIEW", + "DECISION", + "GUARD", + "PROMOTION_ATTEMPT", + "RECOVERY_ATTEMPT", + "REFERENCE_INTENT", + "JOURNAL" + ] + }, + { + "type": "null" + } + ] + }, + "entity_id": { + "anyOf": [ + { + "$ref": "#/$defs/text128" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "$ref": "#/$defs/text64" + }, + { + "type": "null" + } + ] + }, + "expected_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "observed_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "due_at": { + "anyOf": [ + { + "$ref": "#/$defs/timestamp" + }, + { + "type": "null" + } + ] + }, + "idempotency_key_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "failure_id": { + "anyOf": [ + { + "$ref": "#/$defs/pdf" + }, + { + "type": "null" + } + ] + }, + "reason_code": { + "enum": [ + "SCHEMA_INVALID", + "NOT_FOUND", + "INELIGIBLE", + "STALE", + "CAS_CONFLICT", + "KEY_REUSED", + "PREVIEW_EXPIRED", + "DECISION_PENDING", + "DEFINITIVE_PRECOMMIT_ABORT", + "CHRONICLE_HEAD_CONFLICT", + "POLICY_INELIGIBLE", + "STALE_BINDING", + "DEADLINE_CROSSED", + "TOKEN_INVALID", + "CLOCK_UNCERTAIN", + "ACTIVE_GUARD_LIMIT", + "GUARD_BACKEND_UNAVAILABLE", + "INTEGRITY_FAILURE", + "STORAGE_UNAVAILABLE", + "CHRONICLE_UNAVAILABLE", + "REFERENCE_PIN_FAILED", + "RECOVERY_REQUIRED", + "OUTCOME_INVALID", + "UNSUPPORTED_TARGET" + ] + }, + "evidence_sigils": { + "type": "array", + "minItems": 0, + "maxItems": 16, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/sigil" + } + }, + "detail_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "entityRevision": { + "type": "object", + "additionalProperties": false, + "required": [ + "entity_type", + "entity_id", + "prior_revision", + "next_revision" + ], + "properties": { + "entity_type": { + "$ref": "#/$defs/text64" + }, + "entity_id": { + "$ref": "#/$defs/text128" + }, + "prior_revision": { + "$ref": "#/$defs/u64" + }, + "next_revision": { + "$ref": "#/$defs/u64" + } + } + }, + "payload1": { + "type": "object", + "additionalProperties": false, + "required": [ + "prior_epoch", + "new_epoch", + "replayed_head", + "replayed_state_sigil", + "clock_evidence_sigil", + "completed_tail_recovery_id", + "deactivated_operational_root_ids", + "started_at" + ], + "properties": { + "prior_epoch": { + "$ref": "#/$defs/u64" + }, + "new_epoch": { + "$ref": "#/$defs/u64" + }, + "replayed_head": { + "$ref": "#/$defs/headRef" + }, + "replayed_state_sigil": { + "$ref": "#/$defs/sigil" + }, + "clock_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "completed_tail_recovery_id": { + "anyOf": [ + { + "$ref": "#/$defs/ptri" + }, + { + "type": "null" + } + ] + }, + "deactivated_operational_root_ids": { + "type": "array", + "minItems": 0, + "maxItems": 1000000, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/proot" + } + }, + "started_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload2": { + "type": "object", + "additionalProperties": false, + "required": [ + "prior_epoch", + "recovery_epoch", + "validated_head", + "frames_file_size", + "tail_recovery_id", + "tail_recovery_intent_sigil", + "suffix_evidence_sigil", + "suffix_evidence_protection", + "unresolved_guards", + "started_at" + ], + "properties": { + "prior_epoch": { + "$ref": "#/$defs/u64" + }, + "recovery_epoch": { + "$ref": "#/$defs/u64" + }, + "validated_head": { + "$ref": "#/$defs/headRef" + }, + "frames_file_size": { + "$ref": "#/$defs/u64" + }, + "tail_recovery_id": { + "anyOf": [ + { + "$ref": "#/$defs/ptri" + }, + { + "type": "null" + } + ] + }, + "tail_recovery_intent_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "suffix_evidence_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "suffix_evidence_protection": { + "anyOf": [ + { + "$ref": "#/$defs/holdBinding" + }, + { + "type": "null" + } + ] + }, + "unresolved_guards": { + "type": "array", + "minItems": 0, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/guardRecoveryStart" + } + }, + "started_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload3": { + "type": "object", + "additionalProperties": false, + "required": [ + "reason", + "evidence_sigils", + "first_bad_offset", + "first_bad_event_id", + "detected_at" + ], + "properties": { + "reason": { + "enum": [ + "JOURNAL", + "HEAD", + "FRAME", + "CLOCK", + "GUARD", + "TARGET", + "STORAGE", + "CHRONICLE", + "SCHEMA" + ] + }, + "evidence_sigils": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/sigil" + } + }, + "first_bad_offset": { + "anyOf": [ + { + "$ref": "#/$defs/u64" + }, + { + "type": "null" + } + ] + }, + "first_bad_event_id": { + "anyOf": [ + { + "$ref": "#/$defs/pje" + }, + { + "type": "null" + } + ] + }, + "detected_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload4": { + "type": "object", + "additionalProperties": false, + "required": [ + "last_trusted_utc", + "observed_utc", + "monotonic_status", + "divergence_seconds", + "cause", + "prior_anchor_evidence_sigil", + "guards_to_fence", + "detected_at" + ], + "properties": { + "last_trusted_utc": { + "$ref": "#/$defs/timestamp" + }, + "observed_utc": { + "anyOf": [ + { + "$ref": "#/$defs/timestamp" + }, + { + "type": "null" + } + ] + }, + "monotonic_status": { + "enum": [ + "OK", + "RESET", + "UNAVAILABLE" + ] + }, + "divergence_seconds": { + "anyOf": [ + { + "$ref": "#/$defs/u64" + }, + { + "type": "null" + } + ] + }, + "cause": { + "enum": [ + "ROLLBACK", + "FORWARD_JUMP", + "EXCESSIVE_SLEW", + "MONOTONIC_RESET", + "SUSPEND_UNKNOWN", + "SOURCE_UNTRUSTED", + "ARITHMETIC" + ] + }, + "prior_anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "guards_to_fence": { + "type": "array", + "minItems": 0, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/pg" + } + }, + "detected_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload5": { + "type": "object", + "additionalProperties": false, + "required": [ + "trusted_source_sigil", + "policy_sigil", + "restored_utc", + "new_anchor_evidence_sigil", + "resolved_decision_ids", + "fenced_guard_ids" + ], + "properties": { + "trusted_source_sigil": { + "$ref": "#/$defs/sigil" + }, + "policy_sigil": { + "$ref": "#/$defs/sigil" + }, + "restored_utc": { + "$ref": "#/$defs/timestamp" + }, + "new_anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "resolved_decision_ids": { + "type": "array", + "minItems": 0, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/prv" + } + }, + "fenced_guard_ids": { + "type": "array", + "minItems": 0, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/pg" + } + } + } + }, + "payload6": { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "subject_id", + "submission_event_id", + "canonical_event_id", + "event_body_sigil", + "receipt", + "request_sigil", + "canonical_commit_event", + "resulting_chronicle_head_sigil", + "logical_fence_transition", + "deactivated_operational_root_ids", + "observed_at" + ], + "properties": { + "kind": { + "enum": [ + "AUTHORIZATION", + "REJECTION", + "PROPOSAL", + "VALIDATION", + "PROMOTION_OUTCOME", + "RECOVERY_RECORD" + ] + }, + "subject_id": { + "$ref": "#/$defs/text128" + }, + "submission_event_id": { + "anyOf": [ + { + "$ref": "#/$defs/pje" + }, + { + "type": "null" + } + ] + }, + "canonical_event_id": { + "$ref": "#/$defs/ce" + }, + "event_body_sigil": { + "$ref": "#/$defs/sigil" + }, + "receipt": { + "$ref": "#/$defs/receipt" + }, + "request_sigil": { + "$ref": "#/$defs/sigil" + }, + "canonical_commit_event": { + "$ref": "#/$defs/storageEventRef" + }, + "resulting_chronicle_head_sigil": { + "$ref": "#/$defs/sigil" + }, + "logical_fence_transition": { + "anyOf": [ + { + "$ref": "#/$defs/logicalFenceReceiptTransition" + }, + { + "type": "null" + } + ] + }, + "deactivated_operational_root_ids": { + "type": "array", + "minItems": 0, + "maxItems": 1000000, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/proot" + } + }, + "observed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload7": { + "type": "object", + "additionalProperties": false, + "required": [ + "preview", + "prepare_request_sigil", + "prepare_binding_sigil", + "confirmation_token_ciphertext", + "token_storage_profile_sigil", + "idempotency_key_sigil", + "monotonic_anchor_evidence_sigil", + "original_remaining_ns" + ], + "properties": { + "preview": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-preview/1.0" + }, + "prepare_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "prepare_binding_sigil": { + "$ref": "#/$defs/sigil" + }, + "confirmation_token_ciphertext": { + "$ref": "#/$defs/text512" + }, + "token_storage_profile_sigil": { + "$ref": "#/$defs/sigil" + }, + "idempotency_key_sigil": { + "$ref": "#/$defs/sigil" + }, + "monotonic_anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "original_remaining_ns": { + "$ref": "#/$defs/u64" + } + } + }, + "payload8": { + "type": "object", + "additionalProperties": false, + "required": [ + "preview_id", + "decision", + "decision_at", + "clock_policy_sigil", + "clock_evidence_sigil", + "redacted_request_sigil", + "idempotency_key_sigil", + "actor", + "host", + "expected_chronicle_head_sigil" + ], + "properties": { + "preview_id": { + "$ref": "#/$defs/prv" + }, + "decision": { + "enum": [ + "AUTHORIZE", + "REJECT" + ] + }, + "decision_at": { + "$ref": "#/$defs/timestamp" + }, + "clock_policy_sigil": { + "$ref": "#/$defs/sigil" + }, + "clock_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "redacted_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "idempotency_key_sigil": { + "$ref": "#/$defs/sigil" + }, + "actor": { + "$ref": "#/$defs/actor" + }, + "host": { + "$ref": "#/$defs/host" + }, + "expected_chronicle_head_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "payload9": { + "type": "object", + "additionalProperties": false, + "required": [ + "preview_id", + "decision", + "redacted_request_sigil", + "idempotency_key_sigil", + "reason", + "error_details", + "chronicle_absence_evidence_sigil", + "deadline_evidence_sigil", + "failed_at" + ], + "properties": { + "preview_id": { + "$ref": "#/$defs/prv" + }, + "decision": { + "enum": [ + "AUTHORIZE", + "REJECT" + ] + }, + "redacted_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "idempotency_key_sigil": { + "$ref": "#/$defs/sigil" + }, + "reason": { + "enum": [ + "DEFINITIVE_PRECOMMIT_ABORT", + "CHRONICLE_HEAD_CONFLICT", + "POLICY_INELIGIBLE", + "STALE_BINDING", + "DEADLINE_CROSSED" + ] + }, + "error_details": { + "$ref": "#/$defs/patchErrorDetails" + }, + "chronicle_absence_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "deadline_evidence_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "failed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload10": { + "type": "object", + "additionalProperties": false, + "required": [ + "preview_id", + "expires_at", + "trusted_utc", + "deadline_basis", + "monotonic_elapsed_ns", + "original_remaining_ns", + "anchor_evidence_sigil", + "decision_absence_evidence_sigil", + "idempotency_key_sigil" + ], + "properties": { + "preview_id": { + "$ref": "#/$defs/prv" + }, + "expires_at": { + "$ref": "#/$defs/timestamp" + }, + "trusted_utc": { + "$ref": "#/$defs/timestamp" + }, + "deadline_basis": { + "enum": [ + "UTC", + "MONOTONIC", + "BOTH" + ] + }, + "monotonic_elapsed_ns": { + "$ref": "#/$defs/u64" + }, + "original_remaining_ns": { + "$ref": "#/$defs/u64" + }, + "anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "decision_absence_evidence_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "idempotency_key_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + } + } + }, + "payload11": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard", + "prior_backend_generation", + "intended_backend_generation", + "prior_fence_floor", + "intended_fence_floor", + "target_content_generation", + "deadline_policy_sigil", + "clock_anchor_evidence_sigil", + "original_remaining_ns", + "backend_request_sigil", + "committed_at" + ], + "properties": { + "guard": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-target-guard/1.0" + }, + "prior_backend_generation": { + "anyOf": [ + { + "$ref": "#/$defs/text256" + }, + { + "type": "null" + } + ] + }, + "intended_backend_generation": { + "$ref": "#/$defs/text256" + }, + "prior_fence_floor": { + "$ref": "#/$defs/u64" + }, + "intended_fence_floor": { + "$ref": "#/$defs/u64" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "deadline_policy_sigil": { + "$ref": "#/$defs/sigil" + }, + "clock_anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "original_remaining_ns": { + "$ref": "#/$defs/u64" + }, + "backend_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "committed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload12": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "backend_request_sigil", + "backend_receipt_sigil", + "observed_backend_generation", + "observed_fence_floor", + "fencing_generation", + "expires_at", + "clock_anchor_evidence_sigil", + "original_remaining_ns", + "readback_evidence_sigil" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "backend_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "backend_receipt_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_backend_generation": { + "$ref": "#/$defs/text256" + }, + "observed_fence_floor": { + "$ref": "#/$defs/u64" + }, + "fencing_generation": { + "$ref": "#/$defs/u64" + }, + "expires_at": { + "$ref": "#/$defs/timestamp" + }, + "clock_anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "original_remaining_ns": { + "$ref": "#/$defs/u64" + }, + "readback_evidence_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "payload13": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "prior_backend_generation", + "intended_backend_generation", + "prior_expires_at", + "intended_expires_at", + "fencing_generation", + "fence_floor", + "intended_anchor_evidence_sigil", + "intended_original_remaining_ns", + "backend_request_sigil", + "committed_at" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "prior_backend_generation": { + "$ref": "#/$defs/text256" + }, + "intended_backend_generation": { + "$ref": "#/$defs/text256" + }, + "prior_expires_at": { + "$ref": "#/$defs/timestamp" + }, + "intended_expires_at": { + "$ref": "#/$defs/timestamp" + }, + "fencing_generation": { + "$ref": "#/$defs/u64" + }, + "fence_floor": { + "$ref": "#/$defs/u64" + }, + "intended_anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "intended_original_remaining_ns": { + "$ref": "#/$defs/u64" + }, + "backend_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "committed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload14": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "backend_request_sigil", + "backend_receipt_sigil", + "observed_backend_generation", + "prior_expires_at", + "new_expires_at", + "fencing_generation", + "fence_floor", + "new_anchor_evidence_sigil", + "new_original_remaining_ns", + "readback_evidence_sigil" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "backend_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "backend_receipt_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_backend_generation": { + "$ref": "#/$defs/text256" + }, + "prior_expires_at": { + "$ref": "#/$defs/timestamp" + }, + "new_expires_at": { + "$ref": "#/$defs/timestamp" + }, + "fencing_generation": { + "$ref": "#/$defs/u64" + }, + "fence_floor": { + "$ref": "#/$defs/u64" + }, + "new_anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "new_original_remaining_ns": { + "$ref": "#/$defs/u64" + }, + "readback_evidence_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "payload15": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "attempt_id", + "operation_step", + "backend_generation", + "fencing_generation", + "fence_floor", + "target_content_generation", + "intended_target_content_generation", + "prior_step_receipt_sigil", + "prior_step_protection", + "expires_at", + "trusted_utc", + "monotonic_elapsed_ns", + "original_remaining_ns", + "clock_anchor_evidence_sigil", + "readback_evidence_sigil" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "attempt_id": { + "$ref": "#/$defs/text128" + }, + "operation_step": { + "$ref": "#/$defs/u64" + }, + "backend_generation": { + "$ref": "#/$defs/text256" + }, + "fencing_generation": { + "$ref": "#/$defs/u64" + }, + "fence_floor": { + "$ref": "#/$defs/u64" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "intended_target_content_generation": { + "$ref": "#/$defs/text256" + }, + "prior_step_receipt_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "prior_step_protection": { + "$ref": "#/$defs/holdBinding" + }, + "expires_at": { + "$ref": "#/$defs/timestamp" + }, + "trusted_utc": { + "$ref": "#/$defs/timestamp" + }, + "monotonic_elapsed_ns": { + "$ref": "#/$defs/u64" + }, + "original_remaining_ns": { + "$ref": "#/$defs/u64" + }, + "clock_anchor_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "readback_evidence_sigil": { + "$ref": "#/$defs/sigil" + } + } + }, + "payload16": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "prior_backend_generation", + "intended_absence_generation", + "fencing_generation", + "fence_floor", + "cause", + "backend_request_sigil", + "committed_at" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "prior_backend_generation": { + "$ref": "#/$defs/text256" + }, + "intended_absence_generation": { + "$ref": "#/$defs/text256" + }, + "fencing_generation": { + "$ref": "#/$defs/u64" + }, + "fence_floor": { + "$ref": "#/$defs/u64" + }, + "cause": { + "enum": [ + "TERMINAL", + "CANCELLED", + "RECOVERY_COMPLETE", + "SHUTDOWN" + ] + }, + "backend_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "committed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload17": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "origin_state", + "prior_backend_generation", + "intended_backend_generation", + "prior_fence_floor", + "intended_fence_floor", + "prior_fencing_generation", + "intended_fencing_generation", + "cause", + "cause_evidence_sigil", + "backend_request_sigil", + "committed_at" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "origin_state": { + "enum": [ + "ACQUIRING", + "HELD", + "RENEWING", + "RELEASING", + "RECOVERING" + ] + }, + "prior_backend_generation": { + "anyOf": [ + { + "$ref": "#/$defs/text256" + }, + { + "type": "null" + } + ] + }, + "intended_backend_generation": { + "$ref": "#/$defs/text256" + }, + "prior_fence_floor": { + "$ref": "#/$defs/u64" + }, + "intended_fence_floor": { + "$ref": "#/$defs/u64" + }, + "prior_fencing_generation": { + "$ref": "#/$defs/u64" + }, + "intended_fencing_generation": { + "$ref": "#/$defs/u64" + }, + "cause": { + "enum": [ + "EPOCH_CHANGE", + "CLOCK_UNCERTAIN", + "DEADLINE", + "CRASH_RECOVERY", + "PARTIAL", + "INTEGRITY" + ] + }, + "cause_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "backend_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "committed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload18": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "fence_intent_event_id", + "backend_request_sigil", + "backend_receipt_sigil", + "observed_backend_generation", + "observed_fence_floor", + "observed_fencing_generation", + "readback_evidence_sigil", + "fenced_at" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "fence_intent_event_id": { + "$ref": "#/$defs/pje" + }, + "backend_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "backend_receipt_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_backend_generation": { + "$ref": "#/$defs/text256" + }, + "observed_fence_floor": { + "$ref": "#/$defs/u64" + }, + "observed_fencing_generation": { + "$ref": "#/$defs/u64" + }, + "readback_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "fenced_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload19": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "release_intent_event_id", + "backend_request_sigil", + "backend_receipt_sigil", + "observed_absence_generation", + "observed_fencing_generation", + "observed_fence_floor", + "readback_evidence_sigil", + "released_at" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "release_intent_event_id": { + "$ref": "#/$defs/pje" + }, + "backend_request_sigil": { + "$ref": "#/$defs/sigil" + }, + "backend_receipt_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_absence_generation": { + "$ref": "#/$defs/text256" + }, + "observed_fencing_generation": { + "$ref": "#/$defs/u64" + }, + "observed_fence_floor": { + "$ref": "#/$defs/u64" + }, + "readback_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "released_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload20": { + "type": "object", + "additionalProperties": false, + "required": [ + "guard_id", + "failed_phase", + "backend_request_sigil", + "observed_absence_generation", + "observed_fencing_generation", + "observed_fence_floor", + "failure_evidence_sigil", + "reason", + "failed_at" + ], + "properties": { + "guard_id": { + "$ref": "#/$defs/pg" + }, + "failed_phase": { + "enum": [ + "ACQUIRE", + "RENEW", + "RELEASE", + "RECOVER" + ] + }, + "backend_request_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "observed_absence_generation": { + "$ref": "#/$defs/text256" + }, + "observed_fencing_generation": { + "$ref": "#/$defs/u64" + }, + "observed_fence_floor": { + "$ref": "#/$defs/u64" + }, + "failure_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "reason": { + "enum": [ + "DEFINITIVE_REJECT", + "LOST_BEFORE_USE", + "UNSUPPORTED" + ] + }, + "failed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload21": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt", + "authorization_receipt", + "created_at" + ], + "properties": { + "attempt": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-attempt/1.0" + }, + "authorization_receipt": { + "$ref": "#/$defs/receipt" + }, + "created_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload22": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "authorization_sigil", + "target_state_evidence_sigil", + "target_content_generation", + "adapter_sigil", + "started_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "authorization_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_state_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "adapter_sigil": { + "$ref": "#/$defs/sigil" + }, + "started_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload23": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "checkpoint", + "checkpoint_protection", + "checkpoint_verification_sigil", + "committed_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "checkpoint": { + "$ref": "#/$defs/pckRef" + }, + "checkpoint_protection": { + "$ref": "#/$defs/holdBinding" + }, + "checkpoint_verification_sigil": { + "$ref": "#/$defs/sigil" + }, + "committed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload24": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "guard", + "checkpoint", + "base_identity_sigil", + "target_content_generation", + "control_revalidation_sigil", + "ready_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "guard": { + "$ref": "#/$defs/pgRef" + }, + "checkpoint": { + "$ref": "#/$defs/pckRef" + }, + "base_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "control_revalidation_sigil": { + "$ref": "#/$defs/sigil" + }, + "ready_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload25": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "mutation_intent", + "intent_protection", + "guard", + "target_content_generation", + "committed_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "mutation_intent": { + "$ref": "#/$defs/pmiRef" + }, + "intent_protection": { + "$ref": "#/$defs/holdBinding" + }, + "guard": { + "$ref": "#/$defs/pgRef" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "committed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload26": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "mutation_intent", + "guard", + "fresh_target_identity_sigil", + "fresh_target_content_generation", + "adapter_write_evidence_sigil", + "evidence_protection", + "scan_evidence_sigil", + "started_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "mutation_intent": { + "$ref": "#/$defs/pmiRef" + }, + "guard": { + "$ref": "#/$defs/pgRef" + }, + "fresh_target_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "fresh_target_content_generation": { + "$ref": "#/$defs/text256" + }, + "adapter_write_evidence_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "scan_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "started_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload27": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "terminal_status", + "before_identity_sigil", + "after_identity_sigil", + "before_generation", + "after_generation", + "checkpoint_id", + "mutation_intent_id", + "guard_id", + "adapter_write_evidence_sigil", + "verifier_evidence_sigils", + "path_observations_sigil", + "diagnostics_sigil", + "evidence_protection", + "terminal_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_status": { + "const": "APPLIED" + }, + "before_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "after_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "before_generation": { + "$ref": "#/$defs/text256" + }, + "after_generation": { + "$ref": "#/$defs/text256" + }, + "checkpoint_id": { + "$ref": "#/$defs/pck" + }, + "mutation_intent_id": { + "$ref": "#/$defs/pmi" + }, + "guard_id": { + "$ref": "#/$defs/pg" + }, + "adapter_write_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "verifier_evidence_sigils": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/sigil" + } + }, + "path_observations_sigil": { + "$ref": "#/$defs/sigil" + }, + "diagnostics_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload28": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "terminal_status", + "before_identity_sigil", + "after_identity_sigil", + "before_generation", + "after_generation", + "checkpoint_id", + "mutation_intent_id", + "guard_id", + "adapter_write_evidence_sigil", + "verifier_evidence_sigils", + "path_observations_sigil", + "diagnostics_sigil", + "evidence_protection", + "terminal_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_status": { + "const": "RECOVERED_POSTIMAGE_OBSERVED" + }, + "before_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "after_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "before_generation": { + "$ref": "#/$defs/text256" + }, + "after_generation": { + "$ref": "#/$defs/text256" + }, + "checkpoint_id": { + "$ref": "#/$defs/pck" + }, + "mutation_intent_id": { + "$ref": "#/$defs/pmi" + }, + "guard_id": { + "$ref": "#/$defs/pg" + }, + "adapter_write_evidence_sigil": { + "type": "null" + }, + "verifier_evidence_sigils": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/sigil" + } + }, + "path_observations_sigil": { + "$ref": "#/$defs/sigil" + }, + "diagnostics_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload29": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "terminal_status", + "observed_postimage_sigil", + "target_content_generation", + "scan_evidence_sigil", + "path_observations_sigil", + "diagnostics_sigil", + "evidence_protection", + "checkpoint_id", + "mutation_intent_id", + "terminal_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_status": { + "const": "ALREADY_APPLIED" + }, + "observed_postimage_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "scan_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "path_observations_sigil": { + "$ref": "#/$defs/sigil" + }, + "diagnostics_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "checkpoint_id": { + "anyOf": [ + { + "$ref": "#/$defs/pck" + }, + { + "type": "null" + } + ] + }, + "mutation_intent_id": { + "type": "null" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload30": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "terminal_status", + "stale_kind", + "expected_sigil", + "observed_sigil", + "target_identity_sigil", + "target_content_generation", + "evidence_sigil", + "path_observations_sigil", + "diagnostics_sigil", + "evidence_protection", + "terminal_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_status": { + "const": "STALE" + }, + "stale_kind": { + "enum": [ + "CONTROL", + "VALIDATION", + "TARGET", + "AUTHORIZATION" + ] + }, + "expected_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "path_observations_sigil": { + "$ref": "#/$defs/sigil" + }, + "diagnostics_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload31": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "terminal_status", + "conflict_kind", + "before_identity_sigil", + "after_identity_sigil", + "before_generation", + "after_generation", + "checkpoint_id", + "mutation_intent_id", + "evidence_sigil", + "path_observations_sigil", + "diagnostics_sigil", + "evidence_protection", + "terminal_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_status": { + "const": "CONFLICT" + }, + "conflict_kind": { + "enum": [ + "PATH", + "ADD_OCCUPIED", + "TYPE", + "CASE", + "GENERATION_CAS", + "TOPOLOGY" + ] + }, + "before_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "after_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "before_generation": { + "$ref": "#/$defs/text256" + }, + "after_generation": { + "$ref": "#/$defs/text256" + }, + "checkpoint_id": { + "$ref": "#/$defs/pck" + }, + "mutation_intent_id": { + "$ref": "#/$defs/pmi" + }, + "evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "path_observations_sigil": { + "$ref": "#/$defs/sigil" + }, + "diagnostics_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload32": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "terminal_status", + "failed_phase", + "base_identity_sigil", + "observed_identity_sigil", + "target_content_generation", + "checkpoint_id", + "mutation_intent_id", + "evidence_sigil", + "path_observations_sigil", + "diagnostics_sigil", + "evidence_protection", + "terminal_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_status": { + "const": "FAILED" + }, + "failed_phase": { + "enum": [ + "PREFLIGHT", + "READY", + "MUTATION", + "VERIFICATION", + "RECOVERY_REPLAY" + ] + }, + "base_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "checkpoint_id": { + "anyOf": [ + { + "$ref": "#/$defs/pck" + }, + { + "type": "null" + } + ] + }, + "mutation_intent_id": { + "anyOf": [ + { + "$ref": "#/$defs/pmi" + }, + { + "type": "null" + } + ] + }, + "evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "path_observations_sigil": { + "$ref": "#/$defs/sigil" + }, + "diagnostics_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload33": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "terminal_status", + "base_identity_sigil", + "postimage_identity_sigil", + "observed_identity_sigil", + "target_content_generation", + "checkpoint_id", + "mutation_intent_id", + "logical_fence_generation", + "evidence_sigil", + "path_observations_sigil", + "diagnostics_sigil", + "evidence_protection", + "terminal_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_status": { + "const": "PARTIAL" + }, + "base_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "postimage_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "checkpoint_id": { + "$ref": "#/$defs/pck" + }, + "mutation_intent_id": { + "$ref": "#/$defs/pmi" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "path_observations_sigil": { + "$ref": "#/$defs/sigil" + }, + "diagnostics_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload34": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_id", + "terminal_status", + "cancel_request_sigil", + "no_intent_proof_sigil", + "observed_identity_sigil", + "target_content_generation", + "path_observations_sigil", + "diagnostics_sigil", + "evidence_protection", + "terminal_at" + ], + "properties": { + "attempt_id": { + "$ref": "#/$defs/pat" + }, + "terminal_status": { + "const": "CANCELLED" + }, + "cancel_request_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "no_intent_proof_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "path_observations_sigil": { + "$ref": "#/$defs/sigil" + }, + "diagnostics_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload35": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt", + "authorization_receipt", + "parent_outcome_receipt", + "logical_fence_generation", + "created_at" + ], + "properties": { + "recovery_attempt": { + "$ref": "https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0" + }, + "authorization_receipt": { + "$ref": "#/$defs/receipt" + }, + "parent_outcome_receipt": { + "$ref": "#/$defs/receipt" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "created_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload36": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "action", + "guard", + "target_state_evidence_sigil", + "target_content_generation", + "started_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "action": { + "enum": [ + "RESTORE_BASE", + "ACCEPT_POSTIMAGE", + "ABANDON" + ] + }, + "guard": { + "$ref": "#/$defs/pgRef" + }, + "target_state_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "started_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload37": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "checkpoint", + "checkpoint_protection", + "checkpoint_verification_sigil", + "verified_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "checkpoint": { + "$ref": "#/$defs/pckRef" + }, + "checkpoint_protection": { + "$ref": "#/$defs/holdBinding" + }, + "checkpoint_verification_sigil": { + "$ref": "#/$defs/sigil" + }, + "verified_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload38": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "action", + "guard", + "checkpoint", + "bound_before_identity_sigil", + "target_content_generation", + "ready_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "action": { + "enum": [ + "RESTORE_BASE", + "ACCEPT_POSTIMAGE", + "ABANDON" + ] + }, + "guard": { + "$ref": "#/$defs/pgRef" + }, + "checkpoint": { + "$ref": "#/$defs/pckRef" + }, + "bound_before_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "ready_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload39": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "recovery_intent", + "intent_protection", + "guard", + "target_content_generation", + "committed_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "recovery_intent": { + "$ref": "#/$defs/priRef" + }, + "intent_protection": { + "$ref": "#/$defs/holdBinding" + }, + "guard": { + "$ref": "#/$defs/pgRef" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "committed_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload40": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "recovery_intent", + "action", + "scan_status", + "fresh_target_identity_sigil", + "fresh_target_content_generation", + "evidence_protection", + "scan_evidence_sigil", + "started_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "recovery_intent": { + "$ref": "#/$defs/priRef" + }, + "action": { + "enum": [ + "RESTORE_BASE", + "ACCEPT_POSTIMAGE", + "ABANDON" + ] + }, + "scan_status": { + "enum": [ + "VERIFIED", + "UNVERIFIABLE" + ] + }, + "fresh_target_identity_sigil": { + "anyOf": [ + { + "$ref": "#/$defs/sigil" + }, + { + "type": "null" + } + ] + }, + "fresh_target_content_generation": { + "anyOf": [ + { + "$ref": "#/$defs/text256" + }, + { + "type": "null" + } + ] + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "scan_evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "started_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload41": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "terminal_status", + "action", + "before_identity_sigil", + "after_identity_sigil", + "before_generation", + "after_generation", + "checkpoint_id", + "recovery_intent_id", + "guard_id", + "verifier_evidence_sigils", + "evidence_protection", + "logical_fence_generation", + "terminal_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "terminal_status": { + "const": "BASE_RESTORED" + }, + "action": { + "const": "RESTORE_BASE" + }, + "before_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "after_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "before_generation": { + "$ref": "#/$defs/text256" + }, + "after_generation": { + "$ref": "#/$defs/text256" + }, + "checkpoint_id": { + "$ref": "#/$defs/pck" + }, + "recovery_intent_id": { + "$ref": "#/$defs/pri" + }, + "guard_id": { + "$ref": "#/$defs/pg" + }, + "verifier_evidence_sigils": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/sigil" + } + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload42": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "terminal_status", + "action", + "before_identity_sigil", + "after_identity_sigil", + "before_generation", + "after_generation", + "checkpoint_id", + "recovery_intent_id", + "guard_id", + "verifier_evidence_sigils", + "evidence_protection", + "logical_fence_generation", + "terminal_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "terminal_status": { + "const": "POSTIMAGE_ACCEPTED" + }, + "action": { + "const": "ACCEPT_POSTIMAGE" + }, + "before_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "after_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "before_generation": { + "$ref": "#/$defs/text256" + }, + "after_generation": { + "$ref": "#/$defs/text256" + }, + "checkpoint_id": { + "$ref": "#/$defs/pck" + }, + "recovery_intent_id": { + "$ref": "#/$defs/pri" + }, + "guard_id": { + "$ref": "#/$defs/pg" + }, + "verifier_evidence_sigils": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/sigil" + } + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload43": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "terminal_status", + "action", + "before_identity_sigil", + "after_identity_sigil", + "before_generation", + "after_generation", + "checkpoint_id", + "recovery_intent_id", + "guard_id", + "verifier_evidence_sigils", + "evidence_protection", + "logical_fence_generation", + "terminal_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "terminal_status": { + "const": "ABANDONED" + }, + "action": { + "const": "ABANDON" + }, + "before_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "after_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "before_generation": { + "$ref": "#/$defs/text256" + }, + "after_generation": { + "$ref": "#/$defs/text256" + }, + "checkpoint_id": { + "$ref": "#/$defs/pck" + }, + "recovery_intent_id": { + "$ref": "#/$defs/pri" + }, + "guard_id": { + "$ref": "#/$defs/pg" + }, + "verifier_evidence_sigils": { + "type": "array", + "minItems": 1, + "maxItems": 4096, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/sigil" + } + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload44": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "terminal_status", + "action", + "expected_identity_sigil", + "observed_identity_sigil", + "target_content_generation", + "recovery_intent_id", + "verification_event_id", + "evidence_sigil", + "evidence_protection", + "logical_fence_generation", + "terminal_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "terminal_status": { + "const": "STALE" + }, + "action": { + "enum": [ + "RESTORE_BASE", + "ACCEPT_POSTIMAGE", + "ABANDON" + ] + }, + "expected_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "recovery_intent_id": { + "anyOf": [ + { + "$ref": "#/$defs/pri" + }, + { + "type": "null" + } + ] + }, + "verification_event_id": { + "anyOf": [ + { + "$ref": "#/$defs/pje" + }, + { + "type": "null" + } + ] + }, + "evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload45": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "terminal_status", + "action", + "failed_phase", + "observed_identity_sigil", + "target_content_generation", + "recovery_intent_id", + "verification_event_id", + "evidence_sigil", + "evidence_protection", + "logical_fence_generation", + "terminal_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "terminal_status": { + "const": "FAILED" + }, + "action": { + "enum": [ + "RESTORE_BASE", + "ACCEPT_POSTIMAGE", + "ABANDON" + ] + }, + "failed_phase": { + "enum": [ + "PREFLIGHT", + "READY", + "VERIFICATION", + "CRASH_REPLAY" + ] + }, + "observed_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "recovery_intent_id": { + "anyOf": [ + { + "$ref": "#/$defs/pri" + }, + { + "type": "null" + } + ] + }, + "verification_event_id": { + "anyOf": [ + { + "$ref": "#/$defs/pje" + }, + { + "type": "null" + } + ] + }, + "evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload46": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "terminal_status", + "action", + "base_identity_sigil", + "postimage_identity_sigil", + "observed_identity_sigil", + "target_content_generation", + "checkpoint_id", + "recovery_intent_id", + "verification_event_id", + "logical_fence_generation", + "evidence_sigil", + "evidence_protection", + "terminal_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "terminal_status": { + "const": "PARTIAL" + }, + "action": { + "const": "RESTORE_BASE" + }, + "base_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "postimage_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "checkpoint_id": { + "$ref": "#/$defs/pck" + }, + "recovery_intent_id": { + "$ref": "#/$defs/pri" + }, + "verification_event_id": { + "$ref": "#/$defs/pje" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "evidence_sigil": { + "$ref": "#/$defs/sigil" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "payload47": { + "type": "object", + "additionalProperties": false, + "required": [ + "recovery_attempt_id", + "terminal_status", + "action", + "no_intent_proof_sigil", + "observed_identity_sigil", + "target_content_generation", + "evidence_protection", + "logical_fence_generation", + "terminal_at" + ], + "properties": { + "recovery_attempt_id": { + "$ref": "#/$defs/pra" + }, + "terminal_status": { + "const": "CANCELLED" + }, + "action": { + "enum": [ + "RESTORE_BASE", + "ACCEPT_POSTIMAGE", + "ABANDON" + ] + }, + "no_intent_proof_sigil": { + "$ref": "#/$defs/sigil" + }, + "observed_identity_sigil": { + "$ref": "#/$defs/sigil" + }, + "target_content_generation": { + "$ref": "#/$defs/text256" + }, + "evidence_protection": { + "$ref": "#/$defs/holdBinding" + }, + "logical_fence_generation": { + "$ref": "#/$defs/u64" + }, + "terminal_at": { + "$ref": "#/$defs/timestamp" + } + } + } + } +} + diff --git a/schemas/patch-promotion-journal-head-1.0.json b/schemas/patch-promotion-journal-head-1.0.json new file mode 100644 index 0000000..70e302d --- /dev/null +++ b/schemas/patch-promotion-journal-head-1.0.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-journal-head/1.0", + "title": "Patch Promotion Journal Head v1", + "description": "Closed RFC-0014 patch-promotion-journal-head/1.0 contract-only cache record. Validation does not read frames, replay state, or establish atomic replacement.", + "type": "object", "additionalProperties": false, + "required": ["schema_version", "journal_id", "coordinator_epoch", "event_count", "last_sequence", "last_event_sigil", "committed_offset", "frames_file_sigil_prefix", "projected_state_sigil", "head_generation", "head_sigil"], + "properties": { + "schema_version": {"const": "patch-promotion-journal-head/1.0"}, "journal_id": {"$ref": "#/$defs/pj"}, "coordinator_epoch": {"$ref": "#/$defs/u64"}, "event_count": {"$ref": "#/$defs/u64"}, "last_sequence": {"$ref": "#/$defs/u64"}, "last_event_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "committed_offset": {"$ref": "#/$defs/u64"}, "frames_file_sigil_prefix": {"$ref": "#/$defs/sigil"}, "projected_state_sigil": {"$ref": "#/$defs/sigil"}, "head_generation": {"$ref": "#/$defs/u64"}, "head_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": {"sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, "pj": {"type": "string", "pattern": "^PJ-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}} +} + diff --git a/schemas/patch-promotion-mutation-intent-1.0.json b/schemas/patch-promotion-mutation-intent-1.0.json new file mode 100644 index 0000000..e8787f1 --- /dev/null +++ b/schemas/patch-promotion-mutation-intent-1.0.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-mutation-intent/1.0", + "title": "Patch Promotion Mutation Intent v1", + "description": "Closed RFC-0014 patch-promotion-mutation-intent/1.0 contract-only record. Validation is local and does not resolve its write-ahead dependencies, operation set, or Journal commit.", + "type": "object", "additionalProperties": false, + "required": ["schema_version", "intent_id", "attempt_id", "authorization", "operation_sigil", "guard", "fencing_generation", "fence_floor", "target_content_generation", "checkpoint", "base", "postimage", "operations_sigil", "topology_plan", "root_identity", "ancestor_identities", "adapter", "verification_method", "committed_at", "intent_sigil"], + "properties": { + "schema_version": {"const": "patch-promotion-mutation-intent/1.0"}, "intent_id": {"$ref": "#/$defs/pmi"}, "attempt_id": {"$ref": "#/$defs/pat"}, "authorization": {"$ref": "#/$defs/pauRef"}, "operation_sigil": {"$ref": "#/$defs/sigil"}, "guard": {"$ref": "#/$defs/pgRef"}, "fencing_generation": {"$ref": "#/$defs/u64"}, "fence_floor": {"$ref": "#/$defs/u64"}, "target_content_generation": {"$ref": "#/$defs/text256"}, "checkpoint": {"$ref": "#/$defs/pckRef"}, "base": {"$ref": "#/$defs/pbRef"}, "postimage": {"$ref": "#/$defs/postimage"}, "operations_sigil": {"$ref": "#/$defs/sigil"}, "topology_plan": {"$ref": "#/$defs/topologyPlan"}, "root_identity": {"$ref": "#/$defs/root"}, "ancestor_identities": {"type": "array", "minItems": 1, "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/ancestor"}}, "adapter": {"$ref": "#/$defs/ppaRef"}, "verification_method": {"$ref": "#/$defs/verificationMethod"}, "committed_at": {"$ref": "#/$defs/timestamp"}, "intent_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "text128": {"type": "string", "minLength": 0, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "text256": {"type": "string", "minLength": 0, "maxLength": 256, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "text4096": {"type": "string", "minLength": 0, "maxLength": 4096, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "path": {"allOf": [{"$ref": "#/$defs/text4096"}, {"type": "string", "minLength": 1}]}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "pmi": {"type": "string", "pattern": "^PMI-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pat": {"type": "string", "pattern": "^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pau": {"type": "string", "pattern": "^PAU-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pg": {"type": "string", "pattern": "^PG-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pck": {"type": "string", "pattern": "^PCK-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pb": {"type": "string", "pattern": "^PB-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pbip": {"type": "string", "pattern": "^PBIP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 6, "maxLength": 128}, "ppa": {"type": "string", "pattern": "^PPA-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "ref": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"type": "string"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "pauRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pau"}}}]}, "pgRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pg"}}}]}, "pckRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pck"}}}]}, "pbRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pb"}}}]}, "pbipRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pbip"}}}]}, "ppaRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/ppa"}}}]}, + "blob": {"type": "object", "additionalProperties": false, "required": ["sigil", "size_bytes", "media_type"], "properties": {"sigil": {"$ref": "#/$defs/sigil"}, "size_bytes": {"$ref": "#/$defs/u63"}, "media_type": {"$ref": "#/$defs/text128"}}}, "tree": {"type": "object", "additionalProperties": false, "required": ["manifest_sigil", "root_entry_sigil", "entry_count", "total_bytes"], "properties": {"manifest_sigil": {"$ref": "#/$defs/sigil"}, "root_entry_sigil": {"$ref": "#/$defs/sigil"}, "entry_count": {"type": "integer", "minimum": 0, "maximum": 100000}, "total_bytes": {"$ref": "#/$defs/u63"}}}, "postimage": {"type": "object", "additionalProperties": false, "required": ["identity_profile", "tree", "manifest_blob"], "properties": {"identity_profile": {"$ref": "#/$defs/pbipRef"}, "tree": {"$ref": "#/$defs/tree"}, "manifest_blob": {"$ref": "#/$defs/blob"}}}, + "root": {"type": "object", "additionalProperties": false, "required": ["root_object_sigil", "root_generation", "topology_sigil"], "properties": {"root_object_sigil": {"$ref": "#/$defs/sigil"}, "root_generation": {"$ref": "#/$defs/text256"}, "topology_sigil": {"$ref": "#/$defs/sigil"}}}, "topologyPlan": {"type": "object", "additionalProperties": false, "required": ["mode", "target_wide_generation", "root_identity", "ancestor_set_sigil", "operation_order", "plan_sigil"], "properties": {"mode": {"enum": ["FULL_TREE_ATOMIC_CAS", "PER_ENTRY_GENERATIONAL_CAS"]}, "target_wide_generation": {"$ref": "#/$defs/text256"}, "root_identity": {"$ref": "#/$defs/root"}, "ancestor_set_sigil": {"$ref": "#/$defs/sigil"}, "operation_order": {"type": "array", "minItems": 1, "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/path"}}, "plan_sigil": {"$ref": "#/$defs/sigil"}}}, "ancestor": {"type": "object", "additionalProperties": false, "required": ["path_bytes", "object_identity_sigil", "generation"], "properties": {"path_bytes": {"$ref": "#/$defs/text4096"}, "object_identity_sigil": {"$ref": "#/$defs/sigil"}, "generation": {"$ref": "#/$defs/text256"}}}, "verificationMethod": {"type": "object", "additionalProperties": false, "required": ["kind", "identity_profile", "expected_tree", "verifier_profile_sigil"], "properties": {"kind": {"const": "FULL_TREE_IDENTITY"}, "identity_profile": {"$ref": "#/$defs/pbipRef"}, "expected_tree": {"$ref": "#/$defs/tree"}, "verifier_profile_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/patch-promotion-outcome-1.0.json b/schemas/patch-promotion-outcome-1.0.json new file mode 100644 index 0000000..851e4da --- /dev/null +++ b/schemas/patch-promotion-outcome-1.0.json @@ -0,0 +1,17 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", "$id":"https://benchwork.dev/schemas/patch-promotion-outcome/1.0", "title":"Patch Promotion Outcome v1", "description":"Closed RFC-0014 patch-promotion-outcome/1.0 contract-only record. Validation does not resolve Journal or canonical Receipt state.", "type":"object", "additionalProperties":false, + "required":["schema_version","outcome_id","authorization_receipt","attempt_id","terminal_journal_event_id","terminal_journal_event_sigil","operation_sigil","adapter","before_identity","after_identity","before_generation","after_generation","checkpoint","mutation_intent","guard","timestamps","status","path_observations","adapter_write_evidence","verifier_evidence","diagnostics","outcome_sigil"], + "properties":{"schema_version":{"const":"patch-promotion-outcome/1.0"},"outcome_id":{"$ref":"#/$defs/po"},"authorization_receipt":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/receipt"},"attempt_id":{"$ref":"#/$defs/pat"},"terminal_journal_event_id":{"$ref":"#/$defs/pje"},"terminal_journal_event_sigil":{"$ref":"#/$defs/sigil"},"operation_sigil":{"$ref":"#/$defs/sigil"},"adapter":{"$ref":"#/$defs/ppaRef"},"before_identity":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/tree"},"after_identity":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/tree"},"before_generation":{"$ref":"#/$defs/text256"},"after_generation":{"$ref":"#/$defs/text256"},"checkpoint":{"anyOf":[{"$ref":"#/$defs/pckRef"},{"type":"null"}]},"mutation_intent":{"anyOf":[{"$ref":"#/$defs/pmiRef"},{"type":"null"}]},"guard":{"anyOf":[{"$ref":"#/$defs/pgRef"},{"type":"null"}]},"timestamps":{"$ref":"#/$defs/times"},"status":{"enum":["APPLIED","RECOVERED_POSTIMAGE_OBSERVED","ALREADY_APPLIED","STALE","CONFLICT","FAILED","PARTIAL","CANCELLED"]},"path_observations":{"type":"array","minItems":1,"maxItems":100000,"uniqueItems":true,"items":{"$ref":"#/$defs/pathObservation"}},"adapter_write_evidence":{"anyOf":[{"$ref":"#/$defs/adapterWriteEvidence"},{"type":"null"}]},"verifier_evidence":{"type":"array","minItems":1,"maxItems":4096,"uniqueItems":true,"items":{"$ref":"https://benchwork.dev/schemas/patch-target-state-evidence/1.0#/$defs/blob"}},"diagnostics":{"$ref":"#/$defs/text65536"},"outcome_sigil":{"$ref":"#/$defs/sigil"}}, + "allOf":[ + {"if":{"properties":{"status":{"const":"APPLIED"}}},"then":{"properties":{"checkpoint":{"$ref":"#/$defs/pckRef"},"mutation_intent":{"$ref":"#/$defs/pmiRef"},"guard":{"$ref":"#/$defs/pgRef"},"adapter_write_evidence":{"$ref":"#/$defs/adapterWriteEvidence"}}}}, + {"if":{"properties":{"status":{"enum":["RECOVERED_POSTIMAGE_OBSERVED","CONFLICT","PARTIAL"]}}},"then":{"properties":{"checkpoint":{"$ref":"#/$defs/pckRef"},"mutation_intent":{"$ref":"#/$defs/pmiRef"},"guard":{"$ref":"#/$defs/pgRef"},"adapter_write_evidence":{"type":"null"}}}}, + {"if":{"properties":{"status":{"enum":["ALREADY_APPLIED","STALE","CANCELLED"]}}},"then":{"properties":{"mutation_intent":{"type":"null"},"adapter_write_evidence":{"type":"null"}}}}, + {"if":{"properties":{"status":{"const":"FAILED"}}},"then":{"properties":{"adapter_write_evidence":{"type":"null"}}}}, + {"if":{"properties":{"mutation_intent":{"type":"null"}}},"then":{},"else":{"properties":{"guard":{"$ref":"#/$defs/pgRef"}}}} + ], + "$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"text256":{"type":"string","minLength":0,"maxLength":256,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"text4096":{"type":"string","minLength":0,"maxLength":4096,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"text65536":{"type":"string","minLength":0,"maxLength":65536,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27}, + "po":{"type":"string","pattern":"^PO-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"pat":{"type":"string","pattern":"^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pje":{"type":"string","pattern":"^PJE-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"ppa":{"type":"string","pattern":"^PPA-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pck":{"type":"string","pattern":"^PCK-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pmi":{"type":"string","pattern":"^PMI-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pg":{"type":"string","pattern":"^PG-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128}, + "ref":{"type":"object","additionalProperties":false,"required":["id","sigil"],"properties":{"id":{"type":"string"},"sigil":{"$ref":"#/$defs/sigil"}}},"ppaRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/ppa"}}}]},"pckRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pck"}}}]},"pmiRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pmi"}}}]},"pgRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pg"}}}]}, + "times":{"type":"object","additionalProperties":false,"required":["created_at","mutation_started_at","verification_started_at","terminal_at"],"properties":{"created_at":{"$ref":"#/$defs/timestamp"},"mutation_started_at":{"anyOf":[{"$ref":"#/$defs/timestamp"},{"type":"null"}]},"verification_started_at":{"anyOf":[{"$ref":"#/$defs/timestamp"},{"type":"null"}]},"terminal_at":{"$ref":"#/$defs/timestamp"}}},"pathObservation":{"type":"object","additionalProperties":false,"required":["path_bytes","expected_preimage_sigil","observed_preimage_sigil","expected_postimage_sigil","observed_postimage_sigil","status"],"properties":{"path_bytes":{"$ref":"#/$defs/text4096"},"expected_preimage_sigil":{"$ref":"#/$defs/sigil"},"observed_preimage_sigil":{"$ref":"#/$defs/sigil"},"expected_postimage_sigil":{"$ref":"#/$defs/sigil"},"observed_postimage_sigil":{"$ref":"#/$defs/sigil"},"status":{"enum":["MATCH","MISMATCH"]}}},"adapterWriteEvidence":{"type":"object","additionalProperties":false,"required":["mode","transaction_id_sigil","receipt_sigils","before_generation","after_generation","causal_evidence_sigil"],"properties":{"mode":{"enum":["FULL_TREE_ATOMIC_CAS","PER_ENTRY_GENERATIONAL_CAS"]},"transaction_id_sigil":{"$ref":"#/$defs/sigil"},"receipt_sigils":{"type":"array","minItems":1,"maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}},"before_generation":{"$ref":"#/$defs/text256"},"after_generation":{"$ref":"#/$defs/text256"},"causal_evidence_sigil":{"$ref":"#/$defs/sigil"}}}} +} + diff --git a/schemas/patch-promotion-outcome-request-1.0.json b/schemas/patch-promotion-outcome-request-1.0.json new file mode 100644 index 0000000..be8a6d5 --- /dev/null +++ b/schemas/patch-promotion-outcome-request-1.0.json @@ -0,0 +1,8 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", "$id":"https://benchwork.dev/schemas/patch-promotion-outcome-request/1.0", "title":"Patch Promotion Outcome Request v1", "type":"object", "additionalProperties":false, + "required":["schema_version","request_id","kind","record","evidence_sigils","actor","host","requested_at","idempotency_key","request_sigil"], + "properties":{"schema_version":{"const":"patch-promotion-outcome-request/1.0"},"request_id":{"$ref":"#/$defs/por"},"kind":{"enum":["PROMOTION_OUTCOME","RECOVERY_RECORD"]},"record":{"oneOf":[{"$ref":"#/$defs/outcomeRecord"},{"$ref":"#/$defs/recoveryRecord"}]},"evidence_sigils":{"type":"array","minItems":1,"maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/sigil"}},"actor":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/actor"},"host":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/host"},"requested_at":{"$ref":"#/$defs/timestamp"},"idempotency_key":{"$ref":"#/$defs/text256"},"request_sigil":{"$ref":"#/$defs/sigil"}}, + "allOf":[{"if":{"properties":{"kind":{"const":"PROMOTION_OUTCOME"}}},"then":{"properties":{"record":{"$ref":"#/$defs/outcomeRecord"}}}},{"if":{"properties":{"kind":{"const":"RECOVERY_RECORD"}}},"then":{"properties":{"record":{"$ref":"#/$defs/recoveryRecord"}}}}], + "$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"text256":{"type":"string","minLength":0,"maxLength":256,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"por":{"type":"string","pattern":"^POR-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"outcomeRecord":{"type":"object","additionalProperties":false,"required":["kind","outcome_id","outcome_sigil"],"properties":{"kind":{"const":"PROMOTION_OUTCOME"},"outcome_id":{"type":"string","pattern":"^PO-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"outcome_sigil":{"$ref":"#/$defs/sigil"}}},"recoveryRecord":{"type":"object","additionalProperties":false,"required":["kind","recovery_record_id","recovery_record_sigil"],"properties":{"kind":{"const":"RECOVERY_RECORD"},"recovery_record_id":{"type":"string","pattern":"^PRR-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"recovery_record_sigil":{"$ref":"#/$defs/sigil"}}}} +} + diff --git a/schemas/patch-promotion-outcome-response-1.0.json b/schemas/patch-promotion-outcome-response-1.0.json new file mode 100644 index 0000000..cb111c2 --- /dev/null +++ b/schemas/patch-promotion-outcome-response-1.0.json @@ -0,0 +1,2 @@ +{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://benchwork.dev/schemas/patch-promotion-outcome-response/1.0","type":"object","additionalProperties":false,"required":["schema_version","kind","record_id","record_sigil","receipt","response_sigil"],"properties":{"schema_version":{"const":"patch-promotion-outcome-response/1.0"},"kind":{"enum":["PROMOTION_OUTCOME","RECOVERY_RECORD"]},"record_id":{"type":"string"},"record_sigil":{"$ref":"#/$defs/sigil"},"receipt":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/receipt"},"response_sigil":{"$ref":"#/$defs/sigil"}},"allOf":[{"if":{"properties":{"kind":{"const":"PROMOTION_OUTCOME"}}},"then":{"properties":{"record_id":{"$ref":"#/$defs/po"}}}},{"if":{"properties":{"kind":{"const":"RECOVERY_RECORD"}}},"then":{"properties":{"record_id":{"$ref":"#/$defs/prr"}}}}],"$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"po":{"type":"string","pattern":"^PO-[A-Za-z0-9][A-Za-z0-9._-]*$","minLength":4,"maxLength":128},"prr":{"type":"string","pattern":"^PRR-[A-Za-z0-9][A-Za-z0-9._-]*$","minLength":5,"maxLength":128}}} + diff --git a/schemas/patch-promotion-prepare-request-1.0.json b/schemas/patch-promotion-prepare-request-1.0.json new file mode 100644 index 0000000..5ec996b --- /dev/null +++ b/schemas/patch-promotion-prepare-request-1.0.json @@ -0,0 +1,8 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", "$id":"https://benchwork.dev/schemas/patch-promotion-prepare-request/1.0", "title":"Patch Promotion Prepare Request v1", "description":"Closed RFC-0014 patch-promotion-prepare-request/1.0 contract-only request. Validation does not resolve references, token, clock, or idempotency state.", "type":"object", "additionalProperties":false, + "required":["schema_version","request_id","kind","proposal","validation_policy","validation_evidence","target_state_evidence","adapter","mode","recovery","abandoned_lineage","actor","host","requested_at","idempotency_key","request_sigil"], + "properties":{"schema_version":{"const":"patch-promotion-prepare-request/1.0"},"request_id":{"$ref":"#/$defs/pmr"},"kind":{"enum":["PROMOTE","RECOVER_PARTIAL"]},"proposal":{"$ref":"#/$defs/ppRef"},"validation_policy":{"$ref":"#/$defs/pvpRef"},"validation_evidence":{"type":"array","minItems":1,"maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/pveRef"}},"target_state_evidence":{"$ref":"#/$defs/ptseRef"},"adapter":{"$ref":"#/$defs/ppaRef"},"mode":{"enum":["FULL_TREE_ATOMIC_CAS","PER_ENTRY_GENERATIONAL_CAS"]},"recovery":{"anyOf":[{"$ref":"https://benchwork.dev/schemas/patch-promotion-authorization/1.0#/$defs/recovery"},{"type":"null"}]},"abandoned_lineage":{"anyOf":[{"$ref":"https://benchwork.dev/schemas/patch-promotion-authorization/1.0#/$defs/abandoned"},{"type":"null"}]},"actor":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/actor"},"host":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/host"},"requested_at":{"$ref":"#/$defs/timestamp"},"idempotency_key":{"$ref":"#/$defs/text256"},"request_sigil":{"$ref":"#/$defs/sigil"}}, + "allOf":[{"if":{"properties":{"kind":{"const":"RECOVER_PARTIAL"}}},"then":{"properties":{"recovery":{"$ref":"https://benchwork.dev/schemas/patch-promotion-authorization/1.0#/$defs/recovery"},"abandoned_lineage":{"type":"null"}}}},{"if":{"properties":{"kind":{"const":"PROMOTE"}}},"then":{"properties":{"recovery":{"type":"null"}}}}], + "$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"text256":{"type":"string","minLength":0,"maxLength":256,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"timestamp":{"type":"string","format":"date-time","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$","minLength":20,"maxLength":27},"pmr":{"type":"string","pattern":"^PMR-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pp":{"type":"string","pattern":"^PP-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"pvp":{"type":"string","pattern":"^PVP-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pve":{"type":"string","pattern":"^PVE-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"ptse":{"type":"string","pattern":"^PTSE-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":6,"maxLength":128},"ppa":{"type":"string","pattern":"^PPA-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"ref":{"type":"object","additionalProperties":false,"required":["id","sigil"],"properties":{"id":{"type":"string"},"sigil":{"$ref":"#/$defs/sigil"}}},"ppRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pp"}}}]},"pvpRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pvp"}}}]},"pveRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pve"}}}]},"ptseRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/ptse"}}}]},"ppaRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/ppa"}}}]}} +} + diff --git a/schemas/patch-promotion-prepare-response-1.0.json b/schemas/patch-promotion-prepare-response-1.0.json new file mode 100644 index 0000000..9f46840 --- /dev/null +++ b/schemas/patch-promotion-prepare-response-1.0.json @@ -0,0 +1,7 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", "$id":"https://benchwork.dev/schemas/patch-promotion-prepare-response/1.0", "title":"Patch Promotion Prepare Response v1", "description":"Closed RFC-0014 patch-promotion-prepare-response/1.0 contract-only response. The confirmation token is present only for the response Sigil's redacted projection.", "type":"object", "additionalProperties":false, + "required":["schema_version","preview","confirmation_token","journal_event_id","journal_event_sigil","response_sigil"], + "properties":{"schema_version":{"const":"patch-promotion-prepare-response/1.0"},"preview":{"$ref":"https://benchwork.dev/schemas/patch-promotion-preview/1.0"},"confirmation_token":{"$ref":"#/$defs/token"},"journal_event_id":{"$ref":"#/$defs/pje"},"journal_event_sigil":{"$ref":"#/$defs/sigil"},"response_sigil":{"$ref":"#/$defs/sigil"}}, + "$defs":{"sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"token":{"type":"string","pattern":"^[A-Za-z0-9_-]{43}$","minLength":43,"maxLength":43},"pje":{"type":"string","pattern":"^PJE-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128}} +} + diff --git a/schemas/patch-promotion-preview-1.0.json b/schemas/patch-promotion-preview-1.0.json new file mode 100644 index 0000000..ae7e934 --- /dev/null +++ b/schemas/patch-promotion-preview-1.0.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-preview/1.0", + "title": "Patch Promotion Preview v1", + "description": "Closed RFC-0014 patch-promotion-preview/1.0 contract-only record. Validation does not resolve its references, token, clock, or current fence state.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "preview_id", "kind", "proposal", "bundle", "base", "postimage", "validation_policy", "validation_evidence", "target", "target_state_evidence", "target_content_generation", "adapter", "mode", "deadline_policy_sigil", "affected_paths", "operation_sigil", "recovery", "abandoned_lineage", "residual_risks", "prepared_at", "expires_at", "idempotency_key_sigil", "confirmation_token_sigil", "preview_sigil"], + "properties": { + "schema_version": {"const": "patch-promotion-preview/1.0"}, "preview_id": {"$ref": "#/$defs/prv"}, "kind": {"enum": ["PROMOTE", "RECOVER_PARTIAL"]}, "proposal": {"$ref": "#/$defs/ppRef"}, "bundle": {"$ref": "#/$defs/pbuRef"}, "base": {"$ref": "#/$defs/pbRef"}, "postimage": {"$ref": "https://benchwork.dev/schemas/patch-promotion-mutation-intent/1.0#/$defs/postimage"}, "validation_policy": {"$ref": "#/$defs/pvpRef"}, "validation_evidence": {"type": "array", "minItems": 1, "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/pveRef"}}, "target": {"$ref": "https://benchwork.dev/schemas/patch-promotion-attempt/1.0#/$defs/target"}, "target_state_evidence": {"$ref": "#/$defs/ptseRef"}, "target_content_generation": {"$ref": "#/$defs/text256"}, "adapter": {"$ref": "#/$defs/ppaRef"}, "mode": {"enum": ["FULL_TREE_ATOMIC_CAS", "PER_ENTRY_GENERATIONAL_CAS"]}, "deadline_policy_sigil": {"$ref": "#/$defs/sigil"}, "affected_paths": {"type": "array", "minItems": 1, "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/text4096"}}, "operation_sigil": {"$ref": "#/$defs/sigil"}, "recovery": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/patch-promotion-authorization/1.0#/$defs/recovery"}, {"type": "null"}]}, "abandoned_lineage": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/patch-promotion-authorization/1.0#/$defs/abandoned"}, {"type": "null"}]}, "residual_risks": {"type": "array", "minItems": 0, "maxItems": 256, "items": {"$ref": "#/$defs/text4096"}}, "prepared_at": {"$ref": "#/$defs/timestamp"}, "expires_at": {"$ref": "#/$defs/timestamp"}, "idempotency_key_sigil": {"$ref": "#/$defs/sigil"}, "confirmation_token_sigil": {"$ref": "#/$defs/sigil"}, "preview_sigil": {"$ref": "#/$defs/sigil"} + }, + "allOf": [ + {"if": {"properties": {"kind": {"const": "RECOVER_PARTIAL"}}}, "then": {"properties": {"recovery": {"$ref": "https://benchwork.dev/schemas/patch-promotion-authorization/1.0#/$defs/recovery"}, "abandoned_lineage": {"type": "null"}}}}, + {"if": {"properties": {"kind": {"const": "PROMOTE"}}}, "then": {"properties": {"recovery": {"type": "null"}}}} + ], + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "text256": {"type": "string", "minLength": 0, "maxLength": 256, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "text4096": {"type": "string", "minLength": 0, "maxLength": 4096, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "prv": {"type": "string", "pattern": "^PRV-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pp": {"type": "string", "pattern": "^PP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pbu": {"type": "string", "pattern": "^PBU-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pb": {"type": "string", "pattern": "^PB-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pvp": {"type": "string", "pattern": "^PVP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pve": {"type": "string", "pattern": "^PVE-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "ptse": {"type": "string", "pattern": "^PTSE-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 6, "maxLength": 128}, "ppa": {"type": "string", "pattern": "^PPA-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "ref": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"type": "string"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "ppRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pp"}}}]}, "pbuRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pbu"}}}]}, "pbRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pb"}}}]}, "pvpRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pvp"}}}]}, "pveRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/pve"}}}]}, "ptseRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/ptse"}}}]}, "ppaRef": {"allOf": [{"$ref": "#/$defs/ref"}, {"properties": {"id": {"$ref": "#/$defs/ppa"}}}]} + } +} + diff --git a/schemas/patch-promotion-recovery-attempt-1.0.json b/schemas/patch-promotion-recovery-attempt-1.0.json new file mode 100644 index 0000000..9388636 --- /dev/null +++ b/schemas/patch-promotion-recovery-attempt-1.0.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0", "title": "Patch Promotion Recovery Attempt v1", "description": "Closed RFC-0014 patch-promotion-recovery-attempt/1.0 contract-only record. Validation does not resolve its authorization, parent outcome, logical fence, or Journal history.", "type": "object", "additionalProperties": false, + "required": ["schema_version", "recovery_attempt_id", "parent_attempt_id", "parent_outcome_receipt", "authorization", "action", "target", "bound_before_identity", "bound_before_generation", "checkpoint", "lineage", "created_at", "state", "revision", "recovery_attempt_sigil"], + "properties": {"schema_version": {"const": "patch-promotion-recovery-attempt/1.0"}, "recovery_attempt_id": {"$ref": "#/$defs/pra"}, "parent_attempt_id": {"$ref": "#/$defs/pat"}, "parent_outcome_receipt": {"$ref": "#/$defs/receipt"}, "authorization": {"$ref": "#/$defs/pauRef"}, "action": {"enum": ["RESTORE_BASE", "ACCEPT_POSTIMAGE", "ABANDON"]}, "target": {"$ref": "#/$defs/target"}, "bound_before_identity": {"$ref": "#/$defs/tree"}, "bound_before_generation": {"$ref": "#/$defs/text256"}, "checkpoint": {"$ref": "#/$defs/pckRef"}, "lineage": {"$ref": "#/$defs/lineage"}, "created_at": {"$ref": "#/$defs/timestamp"}, "state": {"enum": ["CREATED", "PREFLIGHTING", "READY", "RECOVERING", "VERIFYING", "BASE_RESTORED", "POSTIMAGE_ACCEPTED", "ABANDONED", "STALE", "FAILED", "PARTIAL", "CANCELLED"]}, "revision": {"$ref": "#/$defs/u64"}, "recovery_attempt_sigil": {"$ref": "#/$defs/sigil"}}, + "$defs": {"sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, "text128": {"type": "string", "minLength": 0, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "text256": {"type": "string", "minLength": 0, "maxLength": 256, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "pra": {"type": "string", "pattern": "^PRA-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pat": {"type": "string", "pattern": "^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pau": {"type": "string", "pattern": "^PAU-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pck": {"type": "string", "pattern": "^PCK-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pt": {"type": "string", "pattern": "^PT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pbip": {"type": "string", "pattern": "^PBIP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 6, "maxLength": 128}, "rc": {"type": "string", "pattern": "^RC-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "ce": {"type": "string", "pattern": "^CE-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "po": {"type": "string", "pattern": "^PO-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "prr": {"type": "string", "pattern": "^PRR-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "receipt": {"type": "object", "additionalProperties": false, "required": ["receipt_id", "receipt_sigil", "event_id", "event_body_sigil"], "properties": {"receipt_id": {"$ref": "#/$defs/rc"}, "receipt_sigil": {"$ref": "#/$defs/sigil"}, "event_id": {"$ref": "#/$defs/ce"}, "event_body_sigil": {"$ref": "#/$defs/sigil"}}}, "pauRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pau"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "pckRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pck"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "pbipRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pbip"}, "sigil": {"$ref": "#/$defs/sigil"}}}, + "root": {"type": "object", "additionalProperties": false, "required": ["root_object_sigil", "root_generation", "topology_sigil"], "properties": {"root_object_sigil": {"$ref": "#/$defs/sigil"}, "root_generation": {"$ref": "#/$defs/text256"}, "topology_sigil": {"$ref": "#/$defs/sigil"}}}, "target": {"type": "object", "additionalProperties": false, "required": ["target_id", "target_class", "identity_profile", "root_identity", "selection_authorization_sigil"], "properties": {"target_id": {"$ref": "#/$defs/pt"}, "target_class": {"enum": ["WORKTREE", "DIRECTORY"]}, "identity_profile": {"$ref": "#/$defs/pbipRef"}, "root_identity": {"$ref": "#/$defs/root"}, "selection_authorization_sigil": {"$ref": "#/$defs/sigil"}}}, "tree": {"type": "object", "additionalProperties": false, "required": ["manifest_sigil", "root_entry_sigil", "entry_count", "total_bytes"], "properties": {"manifest_sigil": {"$ref": "#/$defs/sigil"}, "root_entry_sigil": {"$ref": "#/$defs/sigil"}, "entry_count": {"type": "integer", "minimum": 0, "maximum": 100000}, "total_bytes": {"$ref": "#/$defs/u63"}}}, + "promotionPredecessor": {"type": "object", "additionalProperties": false, "required": ["kind", "parent_attempt_id", "outcome_id", "outcome_sigil", "receipt"], "properties": {"kind": {"const": "PROMOTION_PARTIAL"}, "parent_attempt_id": {"$ref": "#/$defs/pat"}, "outcome_id": {"$ref": "#/$defs/po"}, "outcome_sigil": {"$ref": "#/$defs/sigil"}, "receipt": {"$ref": "#/$defs/receipt"}}}, "recoveryPredecessor": {"type": "object", "additionalProperties": false, "required": ["kind", "parent_attempt_id", "recovery_attempt_id", "terminal_status", "recovery_record_id", "recovery_record_sigil", "receipt"], "properties": {"kind": {"const": "RECOVERY_TERMINAL"}, "parent_attempt_id": {"$ref": "#/$defs/pat"}, "recovery_attempt_id": {"$ref": "#/$defs/pra"}, "terminal_status": {"enum": ["STALE", "FAILED", "PARTIAL", "CANCELLED"]}, "recovery_record_id": {"$ref": "#/$defs/prr"}, "recovery_record_sigil": {"$ref": "#/$defs/sigil"}, "receipt": {"$ref": "#/$defs/receipt"}}}, "lineage": {"type": "object", "additionalProperties": false, "required": ["target_id", "logical_fence_generation", "logical_fence_revision", "logical_fence_sigil", "predecessor_head_sigil", "predecessor"], "properties": {"target_id": {"$ref": "#/$defs/pt"}, "logical_fence_generation": {"$ref": "#/$defs/u64"}, "logical_fence_revision": {"$ref": "#/$defs/u64"}, "logical_fence_sigil": {"$ref": "#/$defs/sigil"}, "predecessor_head_sigil": {"$ref": "#/$defs/sigil"}, "predecessor": {"oneOf": [{"$ref": "#/$defs/promotionPredecessor"}, {"$ref": "#/$defs/recoveryPredecessor"}]}}} + } +} + diff --git a/schemas/patch-promotion-recovery-intent-1.0.json b/schemas/patch-promotion-recovery-intent-1.0.json new file mode 100644 index 0000000..49a6054 --- /dev/null +++ b/schemas/patch-promotion-recovery-intent-1.0.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://benchwork.dev/schemas/patch-promotion-recovery-intent/1.0", "title": "Patch Promotion Recovery Intent v1", "description": "Closed RFC-0014 patch-promotion-recovery-intent/1.0 contract-only record. Validation does not resolve write-ahead dependencies, authorize recovery, or mutate a target.", "type": "object", "additionalProperties": false, + "required": ["schema_version", "recovery_intent_id", "recovery_attempt_id", "parent_attempt_id", "authorization", "action", "guard", "fencing_generation", "fence_floor", "target_content_generation", "checkpoint", "bound_before_identity", "base", "postimage", "topology_plan", "lineage", "committed_at", "recovery_intent_sigil"], + "properties": {"schema_version": {"const": "patch-promotion-recovery-intent/1.0"}, "recovery_intent_id": {"$ref": "#/$defs/pri"}, "recovery_attempt_id": {"$ref": "#/$defs/pra"}, "parent_attempt_id": {"$ref": "#/$defs/pat"}, "authorization": {"$ref": "#/$defs/pauRef"}, "action": {"enum": ["RESTORE_BASE", "ACCEPT_POSTIMAGE", "ABANDON"]}, "guard": {"$ref": "#/$defs/pgRef"}, "fencing_generation": {"$ref": "#/$defs/u64"}, "fence_floor": {"$ref": "#/$defs/u64"}, "target_content_generation": {"$ref": "#/$defs/text256"}, "checkpoint": {"$ref": "#/$defs/pckRef"}, "bound_before_identity": {"$ref": "https://benchwork.dev/schemas/patch-promotion-mutation-intent/1.0#/$defs/tree"}, "base": {"$ref": "#/$defs/pbRef"}, "postimage": {"$ref": "https://benchwork.dev/schemas/patch-promotion-mutation-intent/1.0#/$defs/postimage"}, "topology_plan": {"anyOf": [{"$ref": "https://benchwork.dev/schemas/patch-promotion-mutation-intent/1.0#/$defs/topologyPlan"}, {"type": "null"}]}, "lineage": {"$ref": "https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/lineage"}, "committed_at": {"$ref": "#/$defs/timestamp"}, "recovery_intent_sigil": {"$ref": "#/$defs/sigil"}}, + "$defs": {"sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, "text256": {"type": "string", "minLength": 0, "maxLength": 256, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, "pri": {"type": "string", "pattern": "^PRI-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pra": {"type": "string", "pattern": "^PRA-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pat": {"type": "string", "pattern": "^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pau": {"type": "string", "pattern": "^PAU-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pg": {"type": "string", "pattern": "^PG-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pck": {"type": "string", "pattern": "^PCK-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pb": {"type": "string", "pattern": "^PB-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pauRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pau"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "pgRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pg"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "pckRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pck"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "pbRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pb"}, "sigil": {"$ref": "#/$defs/sigil"}}}} +} + diff --git a/schemas/patch-promotion-recovery-record-1.0.json b/schemas/patch-promotion-recovery-record-1.0.json new file mode 100644 index 0000000..2902c5f --- /dev/null +++ b/schemas/patch-promotion-recovery-record-1.0.json @@ -0,0 +1,23 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", "$id":"https://benchwork.dev/schemas/patch-promotion-recovery-record/1.0", "title":"Patch Promotion Recovery Record v1", "description":"Closed RFC-0014 patch-promotion-recovery-record/1.0 contract-only record. Validation does not resolve Journal, Receipt, guard, or Storage state.", "type":"object", "additionalProperties":false, + "required":["schema_version","recovery_record_id","recovery_attempt_id","authorization_receipt","parent_attempt_id","parent_outcome_receipt","action","guard","checkpoint","recovery_intent","lineage","before_identity","after_identity","before_generation","after_generation","resulting_logical_fence_generation","verifier_evidence","terminal_journal_event_id","terminal_journal_event_sigil","status","abandonment_disposition","recovery_record_sigil"], + "properties":{"schema_version":{"const":"patch-promotion-recovery-record/1.0"},"recovery_record_id":{"$ref":"#/$defs/prr"},"recovery_attempt_id":{"$ref":"#/$defs/pra"},"authorization_receipt":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/receipt"},"parent_attempt_id":{"$ref":"#/$defs/pat"},"parent_outcome_receipt":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/receipt"},"action":{"enum":["RESTORE_BASE","ACCEPT_POSTIMAGE","ABANDON"]},"guard":{"anyOf":[{"$ref":"#/$defs/pgRef"},{"type":"null"}]},"checkpoint":{"$ref":"#/$defs/pckRef"},"recovery_intent":{"anyOf":[{"$ref":"#/$defs/priRef"},{"type":"null"}]},"lineage":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/lineage"},"before_identity":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/tree"},"after_identity":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/tree"},"before_generation":{"$ref":"#/$defs/text256"},"after_generation":{"$ref":"#/$defs/text256"},"resulting_logical_fence_generation":{"$ref":"#/$defs/u64"},"verifier_evidence":{"type":"array","minItems":1,"maxItems":4096,"uniqueItems":true,"items":{"$ref":"https://benchwork.dev/schemas/patch-target-state-evidence/1.0#/$defs/blob"}},"terminal_journal_event_id":{"$ref":"#/$defs/pje"},"terminal_journal_event_sigil":{"$ref":"#/$defs/sigil"},"status":{"enum":["BASE_RESTORED","POSTIMAGE_ACCEPTED","ABANDONED","STALE","FAILED","PARTIAL","CANCELLED"]},"abandonment_disposition":{"anyOf":[{"$ref":"#/$defs/disposition"},{"type":"null"}]},"recovery_record_sigil":{"$ref":"#/$defs/sigil"}}, + "allOf":[ + {"if":{"properties":{"status":{"const":"ABANDONED"}}},"then":{"properties":{"action":{"const":"ABANDON"},"guard":{"$ref":"#/$defs/pgRef"},"recovery_intent":{"$ref":"#/$defs/priRef"},"abandonment_disposition":{"$ref":"#/$defs/disposition"}}}}, + {"if":{"properties":{"action":{"const":"ABANDON"}}},"then":{"properties":{"status":{"const":"ABANDONED"},"abandonment_disposition":{"$ref":"#/$defs/disposition"}}}}, + {"if":{"properties":{"status":{"enum":["BASE_RESTORED","POSTIMAGE_ACCEPTED","PARTIAL"]}}},"then":{"properties":{"guard":{"$ref":"#/$defs/pgRef"},"recovery_intent":{"$ref":"#/$defs/priRef"},"abandonment_disposition":{"type":"null"}}}}, + {"if":{"properties":{"status":{"const":"CANCELLED"}}},"then":{"properties":{"recovery_intent":{"type":"null"},"abandonment_disposition":{"type":"null"}}}}, + {"if":{"properties":{"recovery_intent":{"type":"null"}}},"then":{},"else":{"properties":{"guard":{"$ref":"#/$defs/pgRef"}}}}, + {"if":{"properties":{"status":{"enum":["STALE","FAILED"]}}},"then":{"properties":{"abandonment_disposition":{"type":"null"}}}} + ], + "$defs":{ + "sigil":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","minLength":71,"maxLength":71},"u64":{"type":"integer","minimum":0,"maximum":18446744073709551615},"u63":{"type":"integer","minimum":0,"maximum":9223372036854775807},"text128":{"type":"string","minLength":0,"maxLength":128,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"text256":{"type":"string","minLength":0,"maxLength":256,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]*$","not":{"pattern":"[\\r\\n]"}},"opaque":{"type":"string","minLength":1,"maxLength":256,"pattern":"^[^\\u0000-\\u001F\\u007F-\\u009F]+$","not":{"pattern":"[\\r\\n]"}}, + "prr":{"type":"string","pattern":"^PRR-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pra":{"type":"string","pattern":"^PRA-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pat":{"type":"string","pattern":"^PAT-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pg":{"type":"string","pattern":"^PG-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":4,"maxLength":128},"pck":{"type":"string","pattern":"^PCK-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pri":{"type":"string","pattern":"^PRI-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"pje":{"type":"string","pattern":"^PJE-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":5,"maxLength":128},"proot":{"type":"string","pattern":"^PROOT-[A-Za-z0-9][A-Za-z0-9._-]*$","not":{"pattern":"[\\r\\n]"},"minLength":7,"maxLength":128}, + "ref":{"type":"object","additionalProperties":false,"required":["id","sigil"],"properties":{"id":{"type":"string"},"sigil":{"$ref":"#/$defs/sigil"}}},"pgRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pg"}}}]},"pckRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pck"}}}]},"priRef":{"allOf":[{"$ref":"#/$defs/ref"},{"properties":{"id":{"$ref":"#/$defs/pri"}}}]}, + "eventType":{"enum":["coordinator.epoch-started","coordinator.replay-started","coordinator.integrity-failed","coordinator.clock-uncertain","coordinator.clock-restored","canonical.receipt-observed","preview.prepared","preview.decision-submission-started","preview.decision-failed","preview.expired","target.guard-acquire-intent-committed","target.guard-acquired","target.guard-renew-intent-committed","target.guard-renewed","target.guard-validated","target.guard-release-intent-committed","target.guard-fence-intent-committed","target.guard-fenced","target.guard-released","target.guard-failed","promotion.attempt-created","promotion.preflight-started","promotion.checkpoint-committed","promotion.ready","promotion.mutation-intent-committed","promotion.verification-started","promotion.applied","promotion.recovered-postimage-observed","promotion.already-applied","promotion.stale","promotion.conflicted","promotion.failed","promotion.partial","promotion.cancelled","recovery.attempt-created","recovery.preflight-started","recovery.checkpoint-verified","recovery.ready","recovery.intent-committed","recovery.verification-started","recovery.base-restored","recovery.postimage-accepted","recovery.abandoned","recovery.stale","recovery.failed","recovery.partial","recovery.cancelled"]}, + "event":{"type":"object","additionalProperties":false,"required":["protocol_id","protocol_version","journal_id","event_id","sequence","event_type","event_sigil"],"properties":{"protocol_id":{"const":"benchwork.patch-promotion"},"protocol_version":{"const":"1.0"},"journal_id":{"$ref":"#/$defs/opaque"},"event_id":{"$ref":"#/$defs/pje"},"sequence":{"type":"integer","minimum":1,"maximum":18446744073709551615},"event_type":{"$ref":"#/$defs/eventType"},"event_sigil":{"$ref":"#/$defs/sigil"}}},"storageControl":{"type":"object","additionalProperties":false,"required":["schema_version","record_id","record_sigil"],"properties":{"schema_version":{"$ref":"#/$defs/opaque"},"record_id":{"$ref":"#/$defs/opaque"},"record_sigil":{"$ref":"#/$defs/sigil"}}},"referenceSet":{"type":"object","additionalProperties":false,"required":["reference_set_id","reference_set_sigil"],"properties":{"reference_set_id":{"$ref":"#/$defs/opaque"},"reference_set_sigil":{"$ref":"#/$defs/sigil"}}}, + "terminalGuard":{"type":"object","additionalProperties":false,"required":["kind","guard","terminal_event","terminal_state"],"properties":{"kind":{"const":"TERMINAL_GUARD"},"guard":{"$ref":"#/$defs/pgRef"},"terminal_event":{"$ref":"#/$defs/event"},"terminal_state":{"enum":["RELEASED","FENCED","FAILED"]}}},"rootDisposition":{"type":"object","additionalProperties":false,"required":["operational_root_id","active_operational_root_sigil","operational_root_plan","hold_id","reference_set","policy_id","policy_sigil","disposition"],"properties":{"operational_root_id":{"$ref":"#/$defs/proot"},"active_operational_root_sigil":{"$ref":"#/$defs/sigil"},"operational_root_plan":{"$ref":"#/$defs/storageControl"},"hold_id":{"$ref":"#/$defs/opaque"},"reference_set":{"$ref":"#/$defs/referenceSet"},"policy_id":{"$ref":"#/$defs/opaque"},"policy_sigil":{"$ref":"#/$defs/sigil"},"disposition":{"const":"RELEASE_OPERATIONAL_HOLD_AFTER_CANONICAL_ABANDONMENT"}}}, + "disposition":{"type":"object","additionalProperties":false,"required":["kind","recovery_attempt_id","parent_attempt_id","authorization_receipt","actor","disposition_policy_id","disposition_policy_sigil","terminal_event","observed_partial_identity","observed_generation","logical_fence_generation","guard_completion","root_dispositions","physical_byte_authority","logical_fence_disposition","disposition_sigil"],"properties":{"kind":{"const":"ABANDONED_OPERATIONAL_ROOT_DISPOSITION"},"recovery_attempt_id":{"$ref":"#/$defs/pra"},"parent_attempt_id":{"$ref":"#/$defs/pat"},"authorization_receipt":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/receipt"},"actor":{"$ref":"https://benchwork.dev/schemas/patch-promotion-rejection/1.0#/$defs/actor"},"disposition_policy_id":{"const":"PDP-ABANDONED-ROOT-DISPOSITION-V1"},"disposition_policy_sigil":{"$ref":"#/$defs/sigil"},"terminal_event":{"$ref":"#/$defs/event"},"observed_partial_identity":{"$ref":"https://benchwork.dev/schemas/patch-promotion-recovery-attempt/1.0#/$defs/tree"},"observed_generation":{"$ref":"#/$defs/text256"},"logical_fence_generation":{"$ref":"#/$defs/u64"},"guard_completion":{"$ref":"#/$defs/terminalGuard"},"root_dispositions":{"type":"array","minItems":1,"maxItems":4096,"uniqueItems":true,"items":{"$ref":"#/$defs/rootDisposition"}},"physical_byte_authority":{"const":"NONE"},"logical_fence_disposition":{"const":"PRESERVE"},"disposition_sigil":{"$ref":"#/$defs/sigil"}}} + } +} + diff --git a/schemas/patch-promotion-rejection-1.0.json b/schemas/patch-promotion-rejection-1.0.json new file mode 100644 index 0000000..129cc1c --- /dev/null +++ b/schemas/patch-promotion-rejection-1.0.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-rejection/1.0", + "title": "Patch Promotion Rejection v1", + "description": "Closed RFC-0014 patch-promotion-rejection/1.0 contract-only record. Validation is local and does not resolve a Preview, Proposal, authenticated actor, Host, clock, request, or Receipt.", + "type": "object", "additionalProperties": false, + "required": ["schema_version", "rejection_id", "decision", "preview", "proposal", "actor", "host", "reason", "decision_at", "clock_policy_sigil", "clock_evidence_sigil", "request_sigil", "idempotency_key_sigil", "rejection_sigil"], + "properties": { + "schema_version": {"const": "patch-promotion-rejection/1.0"}, "rejection_id": {"$ref": "#/$defs/prej"}, "decision": {"const": "REJECT"}, "preview": {"$ref": "#/$defs/prvRef"}, "proposal": {"$ref": "#/$defs/ppRef"}, "actor": {"$ref": "#/$defs/actor"}, "host": {"$ref": "#/$defs/host"}, "reason": {"$ref": "#/$defs/text4096"}, "decision_at": {"$ref": "#/$defs/timestamp"}, "clock_policy_sigil": {"$ref": "#/$defs/sigil"}, "clock_evidence_sigil": {"$ref": "#/$defs/sigil"}, "request_sigil": {"$ref": "#/$defs/sigil"}, "idempotency_key_sigil": {"$ref": "#/$defs/sigil"}, "rejection_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "text128": {"type": "string", "minLength": 0, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "text4096": {"type": "string", "minLength": 0, "maxLength": 4096, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "prej": {"type": "string", "pattern": "^PREJ-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 6, "maxLength": 128}, "prv": {"type": "string", "pattern": "^PRV-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, "pp": {"type": "string", "pattern": "^PP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "prvRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/prv"}, "sigil": {"$ref": "#/$defs/sigil"}}}, "ppRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pp"}, "sigil": {"$ref": "#/$defs/sigil"}}}, + "actor": {"type": "object", "additionalProperties": false, "required": ["actor_id", "actor_kind", "authentication_context_sigil"], "properties": {"actor_id": {"$ref": "#/$defs/text128"}, "actor_kind": {"enum": ["HUMAN", "SERVICE"]}, "authentication_context_sigil": {"$ref": "#/$defs/sigil"}}}, "host": {"type": "object", "additionalProperties": false, "required": ["host_id", "host_instance_sigil", "platform_sigil", "interactive_session_sigil"], "properties": {"host_id": {"$ref": "#/$defs/text128"}, "host_instance_sigil": {"$ref": "#/$defs/sigil"}, "platform_sigil": {"$ref": "#/$defs/sigil"}, "interactive_session_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/patch-promotion-target-guard-1.0.json b/schemas/patch-promotion-target-guard-1.0.json new file mode 100644 index 0000000..29e304b --- /dev/null +++ b/schemas/patch-promotion-target-guard-1.0.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-promotion-target-guard/1.0", + "title": "Patch Promotion Target Guard v1", + "description": "Closed RFC-0014 patch-promotion-target-guard/1.0 contract-only record. Validation does not reconstruct a Journal prefix or assert physical guard ownership.", + "type": "object", "additionalProperties": false, + "required": ["schema_version", "guard_id", "target_id", "owner_kind", "owner_attempt_id", "coordinator_id", "coordinator_epoch", "state", "backend_generation", "fencing_generation", "fence_floor", "target_content_generation", "deadline_policy_sigil", "clock_anchor_evidence_sigil", "original_remaining_ns", "acquired_at", "expires_at", "recovery_of_guard_id", "revision", "guard_sigil"], + "properties": { + "schema_version": {"const": "patch-promotion-target-guard/1.0"}, "guard_id": {"$ref": "#/$defs/pg"}, "target_id": {"$ref": "#/$defs/pt"}, "owner_kind": {"enum": ["PROMOTION", "RECOVERY"]}, "owner_attempt_id": {"$ref": "#/$defs/text128"}, "coordinator_id": {"$ref": "#/$defs/pc"}, "coordinator_epoch": {"$ref": "#/$defs/u64"}, "state": {"enum": ["NONE", "ACQUIRING", "HELD", "RENEWING", "RELEASING", "FENCING", "RECOVERING", "RELEASED", "FENCED", "FAILED"]}, + "backend_generation": {"anyOf": [{"$ref": "#/$defs/text256"}, {"type": "null"}]}, "fencing_generation": {"$ref": "#/$defs/u64"}, "fence_floor": {"$ref": "#/$defs/u64"}, "target_content_generation": {"$ref": "#/$defs/text256"}, "deadline_policy_sigil": {"$ref": "#/$defs/sigil"}, "clock_anchor_evidence_sigil": {"anyOf": [{"$ref": "#/$defs/sigil"}, {"type": "null"}]}, "original_remaining_ns": {"anyOf": [{"$ref": "#/$defs/u64"}, {"type": "null"}]}, "acquired_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, "expires_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, "recovery_of_guard_id": {"anyOf": [{"$ref": "#/$defs/pg"}, {"type": "null"}]}, "revision": {"$ref": "#/$defs/u64"}, "guard_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "text128": {"type": "string", "minLength": 0, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "text256": {"type": "string", "minLength": 0, "maxLength": 256, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "pg": {"type": "string", "pattern": "^PG-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pt": {"type": "string", "pattern": "^PT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, "pc": {"type": "string", "pattern": "^PC-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128} + } +} + diff --git a/schemas/patch-target-state-evidence-1.0.json b/schemas/patch-target-state-evidence-1.0.json new file mode 100644 index 0000000..fd96599 --- /dev/null +++ b/schemas/patch-target-state-evidence-1.0.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-target-state-evidence/1.0", + "title": "Patch Target State Evidence v1", + "description": "Closed RFC-0014 patch-target-state-evidence/1.0 contract-only record. Validation is local and does not resolve a Target, Profile, Verifier, Blob, or assurance claim.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "evidence_id", "target_id", "identity_profile", "observed_identity", "target_content_generation", "root_identity", "observed_at", "verifier", "bounds", "evidence_blobs", "evidence_sigil"], + "properties": { + "schema_version": {"const": "patch-target-state-evidence/1.0"}, + "evidence_id": {"$ref": "#/$defs/ptse"}, + "target_id": {"$ref": "#/$defs/pt"}, + "identity_profile": {"$ref": "#/$defs/pbipRef"}, + "observed_identity": {"$ref": "#/$defs/tree"}, + "target_content_generation": {"$ref": "#/$defs/text256"}, + "root_identity": {"$ref": "#/$defs/root"}, + "observed_at": {"$ref": "#/$defs/timestamp"}, + "verifier": {"$ref": "#/$defs/verifier"}, + "bounds": {"$ref": "#/$defs/bounds"}, + "evidence_blobs": {"type": "array", "minItems": 1, "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/blob"}}, + "evidence_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "text64": {"type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "not": {"pattern": "[\\r\\n]"}}, + "text128": {"type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "not": {"pattern": "[\\r\\n]"}}, + "text256": {"type": "string", "minLength": 1, "maxLength": 256, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "not": {"pattern": "[\\r\\n]"}}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", "minLength": 20, "maxLength": 27}, + "ptse": {"type": "string", "pattern": "^PTSE-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 6, "maxLength": 128}, + "pt": {"type": "string", "pattern": "^PT-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "pbip": {"type": "string", "pattern": "^PBIP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 6, "maxLength": 128}, + "pbipRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pbip"}, "sigil": {"$ref": "#/$defs/sigil"}}}, + "tree": {"type": "object", "additionalProperties": false, "required": ["manifest_sigil", "root_entry_sigil", "entry_count", "total_bytes"], "properties": {"manifest_sigil": {"$ref": "#/$defs/sigil"}, "root_entry_sigil": {"$ref": "#/$defs/sigil"}, "entry_count": {"type": "integer", "minimum": 0, "maximum": 100000}, "total_bytes": {"$ref": "#/$defs/u63"}}}, + "root": {"type": "object", "additionalProperties": false, "required": ["root_object_sigil", "root_generation", "topology_sigil"], "properties": {"root_object_sigil": {"$ref": "#/$defs/sigil"}, "root_generation": {"$ref": "#/$defs/text256"}, "topology_sigil": {"$ref": "#/$defs/sigil"}}}, + "verifier": {"type": "object", "additionalProperties": false, "required": ["verifier_id", "verifier_version", "configuration_sigil", "assurance_sigil"], "properties": {"verifier_id": {"$ref": "#/$defs/text128"}, "verifier_version": {"$ref": "#/$defs/text64"}, "configuration_sigil": {"$ref": "#/$defs/sigil"}, "assurance_sigil": {"$ref": "#/$defs/sigil"}}}, + "bounds": {"type": "object", "additionalProperties": false, "required": ["max_paths", "max_total_bytes", "max_depth", "observed_paths", "observed_bytes"], "properties": {"max_paths": {"type": "integer", "minimum": 1, "maximum": 100000}, "max_total_bytes": {"$ref": "#/$defs/u63"}, "max_depth": {"type": "integer", "minimum": 1, "maximum": 4096}, "observed_paths": {"type": "integer", "minimum": 0, "maximum": 100000}, "observed_bytes": {"$ref": "#/$defs/u63"}}}, + "blob": {"type": "object", "additionalProperties": false, "required": ["sigil", "size_bytes", "media_type"], "properties": {"sigil": {"$ref": "#/$defs/sigil"}, "size_bytes": {"$ref": "#/$defs/u63"}, "media_type": {"$ref": "#/$defs/text128"}}} + } +} + diff --git a/schemas/patch-tree-manifest-1.0.json b/schemas/patch-tree-manifest-1.0.json new file mode 100644 index 0000000..e74383f --- /dev/null +++ b/schemas/patch-tree-manifest-1.0.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-tree-manifest/1.0", + "title": "Patch Tree Manifest v1", + "description": "Closed RFC-0014 patch-tree-manifest/1.0 contract-only record. Validation checks local manifest topology and identities but does not resolve its Profile, Blob bytes, or filesystem tree.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "identity_profile", "scope", "path_semantics", "entries", "entry_count", "file_count", "total_bytes", "root_entry_sigil", "manifest_sigil", "record_sigil"], + "properties": { + "schema_version": {"const": "patch-tree-manifest/1.0"}, + "identity_profile": {"$ref": "#/$defs/pbipRef"}, + "scope": {"$ref": "#/$defs/pathScope"}, + "path_semantics": {"$ref": "#/$defs/pathSemantics"}, + "entries": {"type": "array", "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/entry"}}, + "entry_count": {"type": "integer", "minimum": 0, "maximum": 100000}, + "file_count": {"type": "integer", "minimum": 0, "maximum": 100000}, + "total_bytes": {"$ref": "#/$defs/u63"}, + "root_entry_sigil": {"$ref": "#/$defs/sigil"}, + "manifest_sigil": {"$ref": "#/$defs/sigil"}, + "record_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "pbip": {"type": "string", "pattern": "^PBIP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 6, "maxLength": 128}, + "pbipRef": {"type": "object", "additionalProperties": false, "required": ["id", "sigil"], "properties": {"id": {"$ref": "#/$defs/pbip"}, "sigil": {"$ref": "#/$defs/sigil"}}}, + "text4096": {"type": "string", "minLength": 1, "maxLength": 4096, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]+$", "not": {"pattern": "[\\r\\n]"}}, + "path": {"type": "string", "minLength": 1, "maxLength": 4096, "pattern": "^[^/\\u0000-\\u001F\\u007F-\\u009F]+(?:/[^/\\u0000-\\u001F\\u007F-\\u009F]+)*$", "not": {"pattern": "[\\r\\n]"}}, + "pathScope": {"type": "object", "additionalProperties": false, "required": ["root_kind", "included_paths", "excluded_paths"], "properties": {"root_kind": {"enum": ["CRUCIBLE", "PROMOTION_TARGET"]}, "included_paths": {"type": "array", "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/path"}}, "excluded_paths": {"type": "array", "maxItems": 100000, "uniqueItems": true, "items": {"$ref": "#/$defs/path"}}}}, + "pathSemantics": {"type": "object", "additionalProperties": false, "required": ["separator", "unicode_normalization", "case_mode", "dot_segments", "link_traversal", "reserved_name_policy"], "properties": {"separator": {"const": "SLASH"}, "unicode_normalization": {"const": "NFC"}, "case_mode": {"enum": ["SENSITIVE", "INSENSITIVE_REJECT_COLLISIONS"]}, "dot_segments": {"const": "REJECT"}, "link_traversal": {"const": "NOFOLLOW"}, "reserved_name_policy": {"const": "REJECT"}}}, + "blob": {"type": "object", "additionalProperties": false, "required": ["blob_sigil", "size_bytes"], "properties": {"blob_sigil": {"$ref": "#/$defs/sigil"}, "size_bytes": {"$ref": "#/$defs/u63"}}}, + "entry": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["path", "kind", "entry_sigil"], "properties": {"path": {"$ref": "#/$defs/path"}, "kind": {"const": "DIRECTORY"}, "entry_sigil": {"$ref": "#/$defs/sigil"}}}, + {"type": "object", "additionalProperties": false, "required": ["path", "kind", "blob", "executable"], "properties": {"path": {"$ref": "#/$defs/path"}, "kind": {"const": "FILE"}, "blob": {"$ref": "#/$defs/blob"}, "executable": {"type": "boolean"}}}, + {"type": "object", "additionalProperties": false, "required": ["path", "kind", "target", "target_sigil"], "properties": {"path": {"$ref": "#/$defs/path"}, "kind": {"const": "SYMLINK"}, "target": {"$ref": "#/$defs/text4096"}, "target_sigil": {"$ref": "#/$defs/sigil"}}} + ]} + } +} + diff --git a/schemas/patch-validation-policy-1.0.json b/schemas/patch-validation-policy-1.0.json new file mode 100644 index 0000000..94a2926 --- /dev/null +++ b/schemas/patch-validation-policy-1.0.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/patch-validation-policy/1.0", + "title": "Patch Validation Policy v1", + "description": "Closed RFC-0014 patch-validation-policy/1.0 contract-only record. Validation does not resolve assurance, environment, validator, independence, or selected Evidence claims.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "policy_id", "policy_version", "required_checks", "optional_checks", "minimum_assurance", "independence", "environment_rules", "limits", "policy_sigil"], + "properties": { + "schema_version": {"const": "patch-validation-policy/1.0"}, "policy_id": {"$ref": "#/$defs/pvp"}, "policy_version": {"$ref": "#/$defs/text64"}, + "required_checks": {"type": "array", "minItems": 1, "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/requirement"}}, "optional_checks": {"type": "array", "maxItems": 4096, "uniqueItems": true, "items": {"$ref": "#/$defs/requirement"}}, + "minimum_assurance": {"$ref": "#/$defs/assurance"}, "independence": {"$ref": "#/$defs/independence"}, "environment_rules": {"type": "array", "maxItems": 256, "items": {"$ref": "#/$defs/environment"}}, "limits": {"$ref": "#/$defs/limits"}, "policy_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, "u64": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615}, + "text64": {"type": "string", "minLength": 0, "maxLength": 64, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, "text128": {"type": "string", "minLength": 0, "maxLength": 128, "pattern": "^[^\\u0000-\\u001F\\u007F-\\u009F]*$", "not": {"pattern": "[\\r\\n]"}}, + "pvp": {"type": "string", "pattern": "^PVP-[A-Za-z0-9][A-Za-z0-9._-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 5, "maxLength": 128}, + "requirement": {"type": "object", "additionalProperties": false, "required": ["check_id", "check_type", "required_status", "assurance_level", "validator_profile_sigil", "environment_profile_sigil", "timeout_seconds"], "properties": {"check_id": {"$ref": "#/$defs/text128"}, "check_type": {"enum": ["COMMAND", "STATIC_ANALYSIS", "TEST", "LOCAL_REVIEW", "EXTERNAL_REVIEW", "CUSTOM"]}, "required_status": {"const": "PASS"}, "assurance_level": {"$ref": "#/$defs/text64"}, "validator_profile_sigil": {"$ref": "#/$defs/sigil"}, "environment_profile_sigil": {"$ref": "#/$defs/sigil"}, "timeout_seconds": {"type": "integer", "minimum": 1, "maximum": 86400}}}, + "assurance": {"type": "object", "additionalProperties": false, "required": ["minimum_level", "assurance_profile_sigil", "control_evidence_profile_sigil"], "properties": {"minimum_level": {"$ref": "#/$defs/text64"}, "assurance_profile_sigil": {"$ref": "#/$defs/sigil"}, "control_evidence_profile_sigil": {"$ref": "#/$defs/sigil"}}}, + "independence": {"type": "object", "additionalProperties": false, "required": ["mode", "minimum_distinct_validators"], "properties": {"mode": {"enum": ["SAME_VALIDATOR_ALLOWED", "DISTINCT_VALIDATOR", "DISTINCT_CIRCLE", "EXTERNAL"]}, "minimum_distinct_validators": {"type": "integer", "minimum": 1, "maximum": 4096}}}, + "environment": {"type": "object", "additionalProperties": false, "required": ["rule_id", "kind", "value_sigil", "required"], "properties": {"rule_id": {"$ref": "#/$defs/text128"}, "kind": {"enum": ["REQUIRE", "FORBID", "MATCH"]}, "value_sigil": {"$ref": "#/$defs/sigil"}, "required": {"type": "boolean"}}}, + "limits": {"type": "object", "additionalProperties": false, "required": ["max_checks", "max_log_refs", "max_result_artifacts", "max_runtime_seconds"], "properties": {"max_checks": {"type": "integer", "minimum": 1, "maximum": 4096}, "max_log_refs": {"type": "integer", "minimum": 0, "maximum": 256}, "max_result_artifacts": {"type": "integer", "minimum": 0, "maximum": 4096}, "max_runtime_seconds": {"type": "integer", "minimum": 1, "maximum": 86400}}} + } +} + diff --git a/schemas/sanctum-assurance-claim-1.0.json b/schemas/sanctum-assurance-claim-1.0.json new file mode 100644 index 0000000..af81eef --- /dev/null +++ b/schemas/sanctum-assurance-claim-1.0.json @@ -0,0 +1,313 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/sanctum-assurance-claim/1.0", + "title": "Sanctum Assurance Claim v1", + "description": "Closed RFC-0012 AC1-AC10 contract-only Claim wire. Schema validity and local deterministic checks do not resolve Journal, State, Profile, CES, predicate, registry, signature, verification-bundle, atomic-installation, or runtime authority.", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "assurance_claim_id", + "job_id", + "attempt_id", + "attempt_binding_sigil", + "attempt_terminal_event", + "requested_assurance", + "realized_level", + "satisfies_request", + "assurance_profile_binding", + "backend_identity", + "backend_configuration_sigil", + "host_binding", + "policy_set_sigil", + "result_binding", + "control_evidence_set_binding", + "terminal_status", + "evidence_cut", + "verifier_binding", + "issued_at", + "assurance_claim_sigil" + ], + "properties": { + "schema_version": {"const": "sanctum-assurance-claim/1.0"}, + "assurance_claim_id": {"$ref": "#/$defs/assuranceClaimId"}, + "job_id": {"$ref": "https://benchwork.dev/schemas/execution-job/1.0#/$defs/jobId"}, + "attempt_id": {"$ref": "https://benchwork.dev/schemas/execution-attempt/1.0#/$defs/attemptId"}, + "attempt_binding_sigil": {"$ref": "#/$defs/sigil"}, + "attempt_terminal_event": {"$ref": "#/$defs/eventRef"}, + "requested_assurance": {"$ref": "#/$defs/level"}, + "realized_level": {"$ref": "#/$defs/level"}, + "satisfies_request": {"type": "boolean"}, + "assurance_profile_binding": {"$ref": "#/$defs/assuranceProfileBinding"}, + "backend_identity": {"$ref": "#/$defs/token"}, + "backend_configuration_sigil": {"$ref": "#/$defs/sigil"}, + "host_binding": {"$ref": "#/$defs/hostBinding"}, + "policy_set_sigil": {"$ref": "#/$defs/sigil"}, + "result_binding": {"$ref": "#/$defs/resultBinding"}, + "control_evidence_set_binding": {"$ref": "#/$defs/frozenControlEvidenceSetBinding"}, + "terminal_status": {"$ref": "#/$defs/terminalStatus"}, + "evidence_cut": {"$ref": "#/$defs/evidenceCut"}, + "verifier_binding": {"$ref": "#/$defs/verifierBinding"}, + "issued_at": {"$ref": "#/$defs/timestamp"}, + "assurance_claim_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$", + "minLength": 71, + "maxLength": 71 + }, + "token": { + "type": "string", + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 1, + "maxLength": 128 + }, + "upperId": { + "type": "string", + "pattern": "^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$", + "not": {"pattern": "[\\r\\n]"}, + "minLength": 3, + "maxLength": 128 + }, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "timestamp": { + "type": "string", + "format": "date-time", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9](?:[.][0-9]{1,6})?Z$", + "minLength": 20, + "maxLength": 27 + }, + "assuranceClaimId": { + "type": "string", + "pattern": "^AC-[0-7][0-9A-HJKMNP-TV-Z]{25}$", + "minLength": 29, + "maxLength": 29 + }, + "level": {"enum": ["SANCTUM-A0", "SANCTUM-A1", "SANCTUM-A2"]}, + "eventRef": { + "type": "object", + "additionalProperties": false, + "required": ["journal_id", "sequence", "event_id", "event_sigil"], + "properties": { + "journal_id": {"type": "string", "pattern": "^EJ-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "sequence": {"$ref": "#/$defs/u63"}, + "event_id": {"type": "string", "pattern": "^JE-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "event_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "journalPrefix": { + "type": "object", + "additionalProperties": false, + "required": ["journal_id", "ending_sequence", "ending_event_id", "ending_event_sigil"], + "properties": { + "journal_id": {"type": "string", "pattern": "^EJ-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "ending_sequence": {"$ref": "#/$defs/u63"}, + "ending_event_id": {"type": "string", "pattern": "^JE-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "ending_event_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "assuranceProfileBinding": { + "type": "object", + "additionalProperties": false, + "required": ["profile_version", "profile_sigil", "conformance_suite_id", "conformance_suite_sigil"], + "properties": { + "profile_version": {"type": "string", "pattern": "^[0-9]+[.][0-9]+(?:[.][0-9]+)?$", "minLength": 3, "maxLength": 32}, + "profile_sigil": {"$ref": "#/$defs/sigil"}, + "conformance_suite_id": {"type": "string", "pattern": "^CS-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "minLength": 4, "maxLength": 128}, + "conformance_suite_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "hostBinding": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NONE"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "worker_id", "worker_binding_sigil", "worker_session_id", "worker_session_binding_sigil", "host_identity_sigil"], + "properties": { + "kind": {"const": "BOUND"}, + "worker_id": {"type": "string", "pattern": "^WK-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "worker_binding_sigil": {"$ref": "#/$defs/sigil"}, + "worker_session_id": {"type": "string", "pattern": "^WS-[A-Z0-9]+$", "minLength": 4, "maxLength": 128}, + "worker_session_binding_sigil": {"$ref": "#/$defs/sigil"}, + "host_identity_sigil": {"$ref": "#/$defs/sigil"} + } + } + ] + }, + "resultReasonCode": { + "description": "Closed-value ownership belongs to the not-yet-published Execution Journal Event contract; the pure dependency validator must receive and enforce its exact canonical order.", + "type": "string", + "pattern": "^[A-Z][A-Z0-9_]{0,63}$", + "minLength": 1, + "maxLength": 64 + }, + "resultBinding": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["kind"], + "properties": {"kind": {"const": "NONE"}} + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "result_sigil", "disposition_event"], + "properties": { + "kind": {"const": "ACCEPTED"}, + "result_sigil": {"$ref": "#/$defs/sigil"}, + "disposition_event": {"$ref": "#/$defs/eventRef"} + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["kind", "message_sigil", "disposition_event", "reason_codes"], + "properties": { + "kind": {"const": "REJECTED"}, + "message_sigil": {"$ref": "#/$defs/sigil"}, + "disposition_event": {"$ref": "#/$defs/eventRef"}, + "reason_codes": {"type": "array", "minItems": 1, "maxItems": 128, "uniqueItems": true, "items": {"$ref": "#/$defs/resultReasonCode"}} + } + } + ] + }, + "frozenControlEvidenceSetBinding": { + "type": "object", + "additionalProperties": false, + "required": ["kind", "control_evidence_set_id", "control_evidence_set_sigil"], + "properties": { + "kind": {"const": "FROZEN"}, + "control_evidence_set_id": {"type": "string", "pattern": "^CES-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "control_evidence_set_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "terminalStatus": { + "type": "object", + "additionalProperties": false, + "required": ["attempt_state", "process_termination_status", "handle_revocation_status", "cleanup_status", "quarantine_status"], + "properties": { + "attempt_state": {"enum": ["SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATION", "LEASE_EXPIRED", "LOST", "FENCED", "REJECTED"]}, + "process_termination_status": {"enum": ["NOT_STARTED", "EXITED", "TERMINATED", "QUARANTINED", "UNVERIFIABLE"]}, + "handle_revocation_status": {"enum": ["NOT_APPLICABLE", "REVOKED", "FENCED", "QUARANTINED", "UNVERIFIABLE"]}, + "cleanup_status": {"enum": ["NOT_APPLICABLE", "VERIFIED", "PARTIAL", "FAILED", "QUARANTINED"]}, + "quarantine_status": {"enum": ["NOT_REQUIRED", "COMPLETE", "PARTIAL", "FAILED"]} + } + }, + "predicateResultSetBinding": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "predicate_result_set_id", "predicate_result_set_sigil"], + "properties": { + "schema_version": {"const": "sanctum-assurance-predicate-result-set/1.0"}, + "predicate_result_set_id": {"type": "string", "pattern": "^PRS-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "predicate_result_set_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "verificationBundleBinding": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "verification_bundle_id", "verification_bundle_sigil"], + "properties": { + "schema_version": {"const": "sanctum-assurance-verification-bundle/1.0"}, + "verification_bundle_id": {"type": "string", "pattern": "^AVB-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "verification_bundle_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "evidenceCut": { + "type": "object", + "additionalProperties": false, + "required": ["journal_prefix", "state_sigil", "accounting_capture_event", "budget_settlement_event", "control_evidence_allocation_commit_sigil", "control_evidence_inventory_sigil", "control_evidence_set_binding", "predicate_result_set_binding", "verification_bundle_binding", "verification_started_at", "verification_completed_at"], + "properties": { + "journal_prefix": {"$ref": "#/$defs/journalPrefix"}, + "state_sigil": {"$ref": "#/$defs/sigil"}, + "accounting_capture_event": {"$ref": "#/$defs/eventRef"}, + "budget_settlement_event": {"$ref": "#/$defs/eventRef"}, + "control_evidence_allocation_commit_sigil": {"$ref": "#/$defs/sigil"}, + "control_evidence_inventory_sigil": {"$ref": "#/$defs/sigil"}, + "control_evidence_set_binding": {"$ref": "#/$defs/frozenControlEvidenceSetBinding"}, + "predicate_result_set_binding": {"$ref": "#/$defs/predicateResultSetBinding"}, + "verification_bundle_binding": {"$ref": "#/$defs/verificationBundleBinding"}, + "verification_started_at": {"$ref": "#/$defs/timestamp"}, + "verification_completed_at": {"$ref": "#/$defs/timestamp"} + } + }, + "verifierIdentity": { + "type": "object", + "additionalProperties": false, + "required": ["verifier_id", "verifier_build_sigil", "verifier_profile_id", "verifier_profile_sigil"], + "properties": { + "verifier_id": {"$ref": "#/$defs/token"}, + "verifier_build_sigil": {"$ref": "#/$defs/sigil"}, + "verifier_profile_id": {"$ref": "#/$defs/token"}, + "verifier_profile_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "registryAuthorityBinding": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "authority_policy_id", "authority_policy_sigil", "installed_head_id", "installed_head_sigil", "active_transition_id", "active_transition_sigil"], + "properties": { + "schema_version": {"const": "sanctum-verifier-registry-authority-binding/1.0"}, + "authority_policy_id": {"type": "string", "pattern": "^VAP-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "authority_policy_sigil": {"$ref": "#/$defs/sigil"}, + "installed_head_id": {"type": "string", "pattern": "^VRH-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "installed_head_sigil": {"$ref": "#/$defs/sigil"}, + "active_transition_id": {"type": "string", "pattern": "^VAT-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "active_transition_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "registrySnapshotBinding": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "registry_snapshot_id", "registry_snapshot_sigil"], + "properties": { + "schema_version": {"const": "sanctum-trusted-verifier-registry-snapshot/1.0"}, + "registry_snapshot_id": {"type": "string", "pattern": "^VRS-[0-7][0-9A-HJKMNP-TV-Z]{25}$", "minLength": 30, "maxLength": 30}, + "registry_snapshot_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "authorizationBinding": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "authorization_record_id", "authorization_record_sigil"], + "properties": { + "schema_version": {"const": "sanctum-verifier-authorization/1.0"}, + "authorization_record_id": {"type": "string", "pattern": "^VAU-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "authorization_record_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "authenticationBinding": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "authentication_evidence_id", "authentication_evidence_sigil"], + "properties": { + "schema_version": {"const": "sanctum-verifier-authentication-evidence/1.0"}, + "authentication_evidence_id": {"type": "string", "pattern": "^VAE-[0-9A-F]{64}$", "minLength": 68, "maxLength": 68}, + "authentication_evidence_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "verifierBinding": { + "type": "object", + "additionalProperties": false, + "required": ["verifier_identity", "registry_authority_binding", "registry_snapshot_binding", "authorization_binding", "authentication_binding"], + "properties": { + "verifier_identity": {"$ref": "#/$defs/verifierIdentity"}, + "registry_authority_binding": {"$ref": "#/$defs/registryAuthorityBinding"}, + "registry_snapshot_binding": {"$ref": "#/$defs/registrySnapshotBinding"}, + "authorization_binding": {"$ref": "#/$defs/authorizationBinding"}, + "authentication_binding": {"$ref": "#/$defs/authenticationBinding"} + } + } + } +} + diff --git a/schemas/sanctum-assurance-profile-1.0.json b/schemas/sanctum-assurance-profile-1.0.json new file mode 100644 index 0000000..c22d933 --- /dev/null +++ b/schemas/sanctum-assurance-profile-1.0.json @@ -0,0 +1,62 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/sanctum-assurance-profile/1.0", + "title": "Sanctum Assurance Profile v1", + "description": "Structural contract for RFC-0012 sanctum-assurance-profile/1.0. Canonical ordering, level and suite self-Sigils, and matrix minima are semantic requirements.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "profile_version", "levels", "conformance_suites", "profile_sigil"], + "properties": { + "schema_version": {"const": "sanctum-assurance-profile/1.0"}, + "profile_version": {"$ref": "#/$defs/version"}, + "levels": { + "type": "array", "minItems": 3, "maxItems": 3, + "prefixItems": [ + {"$ref": "#/$defs/a0Level"}, {"$ref": "#/$defs/a1Level"}, {"$ref": "#/$defs/a2Level"} + ], + "items": false + }, + "conformance_suites": {"type": "array", "minItems": 1, "maxItems": 4096, "items": {"$ref": "#/$defs/conformanceSuite"}}, + "profile_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "version": {"type": "string", "pattern": "^[0-9]+[.][0-9]+(?:[.][0-9]+)?$", "not": {"pattern": "[\\r\\n]"}, "minLength": 3, "maxLength": 32}, + "suiteId": {"type": "string", "pattern": "^CS-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "level": {"enum": ["SANCTUM-A0", "SANCTUM-A1", "SANCTUM-A2"]}, + "state": {"enum": ["ANY_RECORDED", "OBSERVED", "VERIFIED", "ENFORCED"]}, + "dimension": {"enum": ["IDENTITY_AUTHORIZATION", "FILESYSTEM", "NETWORK", "PROCESS_EXECUTABLE", "RESOURCE", "ENVIRONMENT_CREDENTIAL", "LOG_OUTPUT_CAPTURE", "RUNTIME_INPUT_OUTPUT_IDENTITY", "CANCELLATION_FENCING", "TERMINATION_CLEANUP"]}, + "evidenceKind": {"enum": ["TASK_BINDING", "CAPABILITY_BINDING", "SNAPSHOT_BINDING", "WARD_DECISION", "APPROVAL_RECEIPT", "BACKEND_CONFIGURATION", "HOST_IDENTITY", "POLICY_RESOLUTION", "BASE_IDENTITY", "INPUT_IDENTITY", "MATERIALIZATION_IDENTITY", "ENVIRONMENT_CONSTRUCTION", "FILESYSTEM_POLICY", "NETWORK_POLICY", "EXECUTABLE_SELECTION", "PROCESS_TREE", "WALL_TIME_ENFORCEMENT", "RESOURCE_ACCOUNTING", "CREDENTIAL_NONINHERITANCE", "LOG_CAPTURE", "OUTPUT_VALIDATION", "STORAGE_OBSERVATION", "FENCE_TOMBSTONE", "TERMINATION", "HANDLE_REVOCATION", "CLEANUP", "QUARANTINE", "TERMINAL_SOURCE_VERIFICATION", "CONFORMANCE_FIXTURE"]}, + "controlRequirement": { + "type": "object", "additionalProperties": false, + "required": ["control_dimension", "required_state", "required_evidence_kinds", "requirement_evidence_profile_sigil"], + "properties": { + "control_dimension": {"$ref": "#/$defs/dimension"}, "required_state": {"$ref": "#/$defs/state"}, + "required_evidence_kinds": {"type": "array", "minItems": 1, "maxItems": 29, "uniqueItems": true, "items": {"$ref": "#/$defs/evidenceKind"}}, + "requirement_evidence_profile_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "levelBase": { + "type": "object", "additionalProperties": false, + "required": ["level", "rank", "name", "threat_model_sigil", "control_requirements", "level_sigil"], + "properties": { + "level": {"$ref": "#/$defs/level"}, "rank": {"type": "integer", "minimum": 0, "maximum": 2}, + "name": {"enum": ["DECLARED_ATTEMPT", "SUPERVISED", "ISOLATED"]}, "threat_model_sigil": {"$ref": "#/$defs/sigil"}, + "control_requirements": {"type": "array", "minItems": 10, "maxItems": 10, "items": {"$ref": "#/$defs/controlRequirement"}}, + "level_sigil": {"$ref": "#/$defs/sigil"} + } + }, + "a0Level": {"allOf": [{"$ref": "#/$defs/levelBase"}, {"properties": {"level": {"const": "SANCTUM-A0"}, "rank": {"const": 0}, "name": {"const": "DECLARED_ATTEMPT"}}, "required": ["level", "rank", "name"]}]}, + "a1Level": {"allOf": [{"$ref": "#/$defs/levelBase"}, {"properties": {"level": {"const": "SANCTUM-A1"}, "rank": {"const": 1}, "name": {"const": "SUPERVISED"}}, "required": ["level", "rank", "name"]}]}, + "a2Level": {"allOf": [{"$ref": "#/$defs/levelBase"}, {"properties": {"level": {"const": "SANCTUM-A2"}, "rank": {"const": 2}, "name": {"const": "ISOLATED"}}, "required": ["level", "rank", "name"]}]}, + "conformanceSuite": { + "type": "object", "additionalProperties": false, + "required": ["conformance_suite_id", "suite_version", "level", "backend_constraints_sigil", "host_constraints_sigil", "fixture_set_sigil", "evidence_oracle_sigil", "conformance_suite_sigil"], + "properties": { + "conformance_suite_id": {"$ref": "#/$defs/suiteId"}, "suite_version": {"$ref": "#/$defs/version"}, "level": {"$ref": "#/$defs/level"}, + "backend_constraints_sigil": {"$ref": "#/$defs/sigil"}, "host_constraints_sigil": {"$ref": "#/$defs/sigil"}, "fixture_set_sigil": {"$ref": "#/$defs/sigil"}, "evidence_oracle_sigil": {"$ref": "#/$defs/sigil"}, "conformance_suite_sigil": {"$ref": "#/$defs/sigil"} + } + } + } +} + diff --git a/schemas/task-capsule-2.0.json b/schemas/task-capsule-2.0.json new file mode 100644 index 0000000..52307d1 --- /dev/null +++ b/schemas/task-capsule-2.0.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/task-capsule/2.0", + "title": "Sanctum Task Capsule v2", + "description": "Structural contract for RFC-0011 task-capsule/2.0. Sigils, canonical order, authority narrowing, and external Registry/Snapshot/Ward resolution are semantic requirements.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "task_id", "host", "program_id", "objective", "registry_binding", "capability_binding", "snapshot_binding", "visible_inputs", "expected_outputs", "circle", "requested_assurance", "approval_binding", "created_at", "expires_at", "capsule_sigil"], + "properties": { + "schema_version": {"const": "task-capsule/2.0"}, "task_id": {"$ref": "#/$defs/taskId"}, + "host": {"enum": ["cli", "codex", "claude-code"]}, "program_id": {"$ref": "#/$defs/programId"}, + "objective": {"$ref": "#/$defs/humanText16384"}, "registry_binding": {"$ref": "#/$defs/registryBinding"}, + "capability_binding": {"$ref": "#/$defs/capabilityBinding"}, "snapshot_binding": {"$ref": "#/$defs/snapshotBinding"}, + "visible_inputs": {"type": "array", "maxItems": 4096, "items": {"$ref": "#/$defs/visibleInput"}, "uniqueItems": true}, + "expected_outputs": {"type": "array", "maxItems": 256, "items": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/outputGrant"}, "uniqueItems": true}, + "circle": {"$ref": "#/$defs/circle"}, + "requested_assurance": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/assuranceGrant"}, + "approval_binding": {"$ref": "#/$defs/approvalBinding"}, "created_at": {"$ref": "#/$defs/timestamp"}, + "expires_at": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"type": "null"}]}, "capsule_sigil": {"$ref": "#/$defs/sigil"} + }, + "$defs": { + "sigil": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "minLength": 71, "maxLength": 71}, + "u63": {"type": "integer", "minimum": 0, "maximum": 9223372036854775807}, + "positiveU63": {"type": "integer", "minimum": 1, "maximum": 9223372036854775807}, + "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-5][0-9]:[0-5][0-9]Z$", "minLength": 20, "maxLength": 20}, + "humanText16384": {"type": "string", "pattern": "^[^\\u0000]+$", "minLength": 1, "maxLength": 16384}, + "taskId": {"type": "string", "pattern": "^TK-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "programId": {"type": "string", "pattern": "^RP-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "snapshotId": {"type": "string", "pattern": "^SS-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "circleId": {"type": "string", "pattern": "^CI-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "registryId": {"type": "string", "pattern": "^CR-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "capabilityId": {"type": "string", "pattern": "^bench[.][a-z0-9]+(?:[.][a-z0-9]+)+$", "not": {"pattern": "[\\r\\n]"}, "minLength": 9, "maxLength": 128}, + "logicalName": {"type": "string", "pattern": "^[a-z][a-z0-9_-]*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 1, "maxLength": 64}, + "relativePath": {"type": "string", "pattern": "^(?!/)(?!.*//)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*\\/$)[^\\u0000]+$", "minLength": 1, "maxLength": 1024}, + "mediaType": {"type": "string", "pattern": "^[a-z0-9!#$&^_.+-]+/[a-z0-9!#$&^_.+-]+$", "not": {"pattern": "[\\r\\n]"}, "minLength": 3, "maxLength": 128}, + "registryBinding": {"type": "object", "additionalProperties": false, "required": ["registry_id", "registry_revision", "registry_sigil"], "properties": {"registry_id": {"$ref": "#/$defs/registryId"}, "registry_revision": {"$ref": "#/$defs/u63"}, "registry_sigil": {"$ref": "#/$defs/sigil"}}}, + "capabilityBinding": {"type": "object", "additionalProperties": false, "required": ["capability_id", "contract_version", "contract_sigil"], "properties": {"capability_id": {"$ref": "#/$defs/capabilityId"}, "contract_version": {"const": "2.0"}, "contract_sigil": {"$ref": "#/$defs/sigil"}}}, + "snapshotBinding": {"type": "object", "additionalProperties": false, "required": ["snapshot_id", "snapshot_sigil"], "properties": {"snapshot_id": {"$ref": "#/$defs/snapshotId"}, "snapshot_sigil": {"$ref": "#/$defs/sigil"}}}, + "visibleInput": {"type": "object", "additionalProperties": false, "required": ["logical_name", "object_id", "object_type", "object_sigil", "media_type", "maximum_bytes", "mount_path"], "properties": {"logical_name": {"$ref": "#/$defs/logicalName"}, "object_id": {"$ref": "#/$defs/objectId"}, "object_type": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/snapshotObjectType"}, "object_sigil": {"$ref": "#/$defs/sigil"}, "media_type": {"$ref": "#/$defs/mediaType"}, "maximum_bytes": {"$ref": "#/$defs/positiveU63"}, "mount_path": {"$ref": "#/$defs/relativePath"}}}, + "objectId": {"type": "string", "pattern": "^(?:RP|EV|CL|HY|PT|WK|EX|RUN|RB|AS|DE|AR|IS|DV|RR|RV)-[A-Z0-9]+(?:[._-][A-Z0-9]+)*$", "not": {"pattern": "[\\r\\n]"}, "minLength": 4, "maxLength": 128}, + "approvalBinding": {"oneOf": [ + {"type": "object", "additionalProperties": false, "required": ["requirement", "policy_id", "policy_version", "policy_sigil", "binding_scope", "bound_side_effect_ids"], "properties": {"requirement": {"const": "NOT_REQUIRED"}, "policy_id": {"type": "null"}, "policy_version": {"type": "null"}, "policy_sigil": {"type": "null"}, "binding_scope": {"const": "NONE"}, "bound_side_effect_ids": {"type": "array", "maxItems": 0}}}, + {"type": "object", "additionalProperties": false, "required": ["requirement", "policy_id", "policy_version", "policy_sigil", "binding_scope", "bound_side_effect_ids"], "properties": {"requirement": {"const": "REQUIRED"}, "policy_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/approvalPolicyId"}, "policy_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, "policy_sigil": {"$ref": "#/$defs/sigil"}, "binding_scope": {"const": "EXACT_EXECUTION_POLICY"}, "bound_side_effect_ids": {"type": "array", "maxItems": 128, "items": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectId"}, "uniqueItems": true}}} + ]}, + "circle": {"type": "object", "additionalProperties": false, "required": ["circle_id", "tools", "filesystem", "executable", "process", "network", "environment", "credential", "resource", "input", "output", "runtime", "lifecycle", "side_effects", "circle_sigil"], "properties": {"circle_id": {"$ref": "#/$defs/circleId"}, "tools": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/toolAuthority"}, "filesystem": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/filesystemAuthority"}, "executable": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/executableAuthority"}, "process": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/processAuthority"}, "network": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/networkAuthority"}, "environment": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/environmentAuthority"}, "credential": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/credentialAuthority"}, "resource": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/resourceAuthority"}, "input": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/inputAuthority"}, "output": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/outputAuthority"}, "runtime": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/runtimeAuthority"}, "lifecycle": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/lifecycleAuthority"}, "side_effects": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sideEffectAuthority"}, "circle_sigil": {"$ref": "#/$defs/sigil"}}} + } +} + diff --git a/schemas/tool-execution-definition-1.0.json b/schemas/tool-execution-definition-1.0.json new file mode 100644 index 0000000..4b5dd9d --- /dev/null +++ b/schemas/tool-execution-definition-1.0.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://benchwork.dev/schemas/tool-execution-definition/1.0", + "title": "Tool Execution Definition v1", + "description": "Closed RFC-0011 immutable Tool-to-executable implementation binding. Installed argument-Schema resolution and ToolGrant equality are semantic checks.", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "tool_id", "tool_version", "executable_id", "executable_version", "executable_sigil", "runtime_id", "runtime_version", "runtime_sigil", "entrypoint", "argument_schema_id", "argument_schema_sigil", "tool_sigil"], + "properties": { + "schema_version": {"const": "tool-execution-definition/1.0"}, + "tool_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/toolId"}, + "tool_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, + "executable_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/executableId"}, + "executable_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, + "executable_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "runtime_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/runtimeId"}, + "runtime_version": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/version"}, + "runtime_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "entrypoint": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/relativePath"}, + "argument_schema_id": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/schemaId"}, + "argument_schema_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"}, + "tool_sigil": {"$ref": "https://benchwork.dev/schemas/capability-contract/2.0#/$defs/sigil"} + } +} + diff --git a/scripts/ci/check-phase3-contracts.py b/scripts/ci/check-phase3-contracts.py new file mode 100644 index 0000000..c9d5aee --- /dev/null +++ b/scripts/ci/check-phase3-contracts.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +"""Run the bounded, executable Phase 3 contract gate. + +This gate deliberately verifies only the published contract-only surface and +the non-executing local vertical slice. A pass does not grant Journal replay, +Storage, Result-acceptance, or scientific authority. +""" + +from __future__ import annotations + +import subprocess +import sys +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] +TESTS = ( + "tests/test_execution.py", + "tests/test_execution_state_journal_event_v1_contract.py", + "tests/test_execution_job_submission_replay_v1.py", + "tests/test_agent_result_v2_contract.py", + "tests/test_execution_worker_session_v1_contract.py", + "tests/test_execution_worker_session_replay_v1.py", + "tests/test_execution_job_outcome_v1_contract.py", + "tests/test_artifact_storage_journal_v1_contract.py", + "tests/test_patch_promotion_journal_v1_contract.py", + "tests/test_patch_promotion_bundle_v1_contract.py", + "tests/test_patch_promotion_checkpoint_v1_contract.py", + "tests/test_patch_promotion_mutation_intent_v1_contract.py", + "tests/test_patch_promotion_target_guard_v1_contract.py", + "tests/test_patch_promotion_attempt_v1_contract.py", + "tests/test_patch_promotion_outcome_v1_contract.py", + "tests/test_patch_promotion_recovery_record_v1_contract.py", + "tests/mcp/test_runtime.py", + "tests/mcp/test_tool_registry.py", +) + + +def _run(*command: str) -> None: + completed = subprocess.run(command, cwd=ROOT, check=False) + if completed.returncode: + raise SystemExit(completed.returncode) + + +def main() -> int: + python = sys.executable + _run(python, "scripts/ci/check-schemas.py") + _run(python, "-m", "pytest", "-q", *TESTS) + _run(python, "-m", "ruff", "check", "src/benchwork", "tests") + _run(python, "-m", "mypy", "src") + print("Phase 3 contract gate passed (contract-only/local vertical slice).") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/ci/check-schemas.py b/scripts/ci/check-schemas.py index 3f8bcc4..72d81ff 100644 --- a/scripts/ci/check-schemas.py +++ b/scripts/ci/check-schemas.py @@ -6,6 +6,7 @@ import json import sys from pathlib import Path +from urllib.parse import urldefrag from jsonschema import Draft202012Validator @@ -13,8 +14,42 @@ ROOT = Path(__file__).resolve().parents[2] +def _resolve_pointer(document: object, fragment: str) -> object: + if not fragment: + return document + if not fragment.startswith("/"): + raise ValueError(f"unsupported non-pointer fragment #{fragment}") + current = document + for token in fragment[1:].split("/"): + token = token.replace("~1", "/").replace("~0", "~") + if isinstance(current, dict): + current = current[token] + elif isinstance(current, list): + current = current[int(token)] + else: + raise ValueError(f"unresolvable fragment #{fragment}") + return current + + +def _check_references(value: object, document_id: str, by_id: dict[str, object]) -> None: + if isinstance(value, dict): + reference = value.get("$ref") + if isinstance(reference, str): + base, fragment = urldefrag(reference) + target_id = base or document_id + if target_id not in by_id: + raise ValueError(f"unavailable Schema {target_id}") + _resolve_pointer(by_id[target_id], fragment) + for member in value.values(): + _check_references(member, document_id, by_id) + elif isinstance(value, list): + for member in value: + _check_references(member, document_id, by_id) + + def main() -> int: identifiers: dict[str, Path] = {} + documents: dict[str, object] = {} failures: list[str] = [] for path in sorted((ROOT / "schemas").glob("*.json")): try: @@ -32,9 +67,15 @@ def main() -> int: ) else: identifiers[identifier] = path + documents[identifier] = schema version = path.stem.rsplit("-", 1)[-1] if not isinstance(identifier, str) or not identifier.endswith(f"/{version}"): failures.append(f"{path.name}: $id does not end in /{version}") + for identifier, path in identifiers.items(): + try: + _check_references(documents[identifier], identifier, documents) + except (KeyError, IndexError, ValueError) as error: + failures.append(f"{path.name}: {error}") if failures: print("\n".join(failures)) return 1 diff --git a/src/benchwork/artifact_storage_contracts.py b/src/benchwork/artifact_storage_contracts.py new file mode 100644 index 0000000..c6f53c0 --- /dev/null +++ b/src/benchwork/artifact_storage_contracts.py @@ -0,0 +1,2336 @@ +"""Fail-closed local validators for RFC-0013 Storage Journal wire contracts. + +These helpers check canonical documents and caller-supplied prefix relations. +They never append, replay, repair, or authorize an Artifact Storage Journal. +""" + +from __future__ import annotations + +import json +import math +import unicodedata +from datetime import datetime +from typing import Any, NoReturn + +from .athanor import AthanorError, content_sigil +from .schema_validation import validate_instance + + +def _fail(message: str) -> NoReturn: + raise AthanorError(message) + + +def _reject_duplicate_json_keys(pairs: list[tuple[str, Any]]) -> dict[str, Any]: + value: dict[str, Any] = {} + for key, member in pairs: + if key in value: + _fail(f"duplicate JSON key: {key}") + value[key] = member + return value + + +def _reject_nonfinite(token: str) -> NoReturn: + _fail(f"non-finite JSON number is forbidden: {token}") + + +def _load_strict_object(raw: str | bytes | bytearray, label: str) -> dict[str, Any]: + if isinstance(raw, (bytes, bytearray)): + raw_bytes = bytes(raw) + if raw_bytes.startswith(b"\xef\xbb\xbf"): + _fail(f"invalid {label} JSON: UTF-8 BOM is forbidden") + try: + raw = raw_bytes.decode("utf-8", errors="strict") + except UnicodeDecodeError: + _fail(f"invalid {label} JSON: non-UTF-8 encoding is forbidden") + if raw.startswith("\ufeff"): + _fail(f"invalid {label} JSON: UTF-8 BOM is forbidden") + try: + value = json.loads( + raw, + object_pairs_hook=_reject_duplicate_json_keys, + parse_constant=_reject_nonfinite, + ) + except (json.JSONDecodeError, UnicodeDecodeError) as error: + _fail(f"invalid {label} JSON: {error}") + if not isinstance(value, dict): + _fail(f"{label} JSON root must be an object") + return value + + +def _check_nfc_and_numbers(value: Any) -> None: + if isinstance(value, str): + try: + value.encode("utf-8", errors="strict") + except UnicodeEncodeError: + _fail("JSON string contains a non-Unicode-scalar value") + if unicodedata.normalize("NFC", value) != value: + _fail("JSON string is not NFC-normalized") + elif isinstance(value, dict): + for key, member in value.items(): + _check_nfc_and_numbers(key) + _check_nfc_and_numbers(member) + elif isinstance(value, list): + for member in value: + _check_nfc_and_numbers(member) + elif isinstance(value, float): + if not math.isfinite(value): + _fail("non-finite JSON number is forbidden") + _fail("JSON float is forbidden by canonical Storage wire") + + +def _without(value: dict[str, Any], member: str) -> dict[str, Any]: + return {key: item for key, item in value.items() if key != member} + + +def _parse_time(value: str) -> datetime: + return datetime.fromisoformat(value.replace("Z", "+00:00")) + + +def _upper_digest(prefix: str, preimage: list[Any]) -> str: + return prefix + content_sigil(preimage).removeprefix("sha256:").upper() + + +def derive_artifact_storage_reference_set_id_v1(reference_set: dict[str, Any]) -> str: + """Derive the RFC-0013 deterministic Reference Set identifier.""" + return _upper_digest("RS-", [ + "artifact-storage-reference-set-id/1.0", reference_set["source"], + reference_set["extractor"], reference_set["edges"], reference_set["validation"], + ]) + + +def _derive_reference_set_registration_event_id(reference_set: dict[str, Any]) -> str: + source = reference_set["source"] + if ( + source["kind"] == "OPERATIONAL_CONTROL_RECORD" + and source["schema_version"] == "execution-storage-root-manifest/1.0" + ): + return _upper_digest("SE-", [ + "artifact-storage-execution-root-reference-set-registration-event-id/1.0", + source["identity"], + ]) + return _upper_digest("SE-", [ + "artifact-storage-reference-set-registration-event-id/1.0", + reference_set["reference_set_id"], + ]) + + +def validate_artifact_storage_reference_set_v1(reference_set: dict[str, Any]) -> None: + """Validate a Reference Set locally without resolving its graph.""" + validate_instance("artifact-storage-reference-set-1.0.json", reference_set) + _check_nfc_and_numbers(reference_set) + if reference_set["reference_set_id"] != derive_artifact_storage_reference_set_id_v1(reference_set): + _fail("Artifact Storage Reference Set ID mismatch") + if reference_set["registration_event_id"] != _derive_reference_set_registration_event_id(reference_set): + _fail("Artifact Storage Reference Set registration Event ID mismatch") + if reference_set["reference_set_sigil"] != content_sigil( + _without(reference_set, "reference_set_sigil") + ): + _fail("Artifact Storage Reference Set self-Sigil mismatch") + edges = reference_set["edges"] + edge_keys = [ + (edge["relationship"], edge["target_kind"], edge["target_identity"], edge["target_sigil"]) + for edge in edges + ] + if edge_keys != sorted(edge_keys): + _fail("Artifact Storage Reference Set edges are not sorted") + evidence = reference_set["validation"]["evidence_sigils"] + if evidence != sorted(evidence): + _fail("Artifact Storage Reference Set validation evidence is not sorted") + + +def load_artifact_storage_reference_set_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + reference_set = _load_strict_object(raw, "Artifact Storage Reference Set") + validate_artifact_storage_reference_set_v1(reference_set) + return reference_set + + +def derive_artifact_storage_reference_intent_id_v1(intent: dict[str, Any]) -> str: + """Derive the RFC-0013 deterministic Reference Intent identifier.""" + return _upper_digest("RI-", [ + "artifact-storage-reference-intent-id/1.0", intent["canonical_event_type"], + intent["transition_request_id"], + ]) + + +def validate_artifact_storage_reference_intent_v1(intent: dict[str, Any]) -> None: + """Validate an immutable Reference Intent without resolving its closure.""" + validate_instance("artifact-storage-reference-intent-1.0.json", intent) + _check_nfc_and_numbers(intent) + if intent["reference_intent_id"] != derive_artifact_storage_reference_intent_id_v1(intent): + _fail("Artifact Storage Reference Intent ID mismatch") + if intent["record_sigil"] != content_sigil(_without(intent, "record_sigil")): + _fail("Artifact Storage Reference Intent self-Sigil mismatch") + references = intent["reference_sets"] + reference_ids = [reference["reference_set_id"] for reference in references] + if reference_ids != sorted(reference_ids) or len(set(reference_ids)) != len(reference_ids): + _fail("Artifact Storage Reference Intent Reference Sets are not uniquely sorted") + if intent["blob_sigils"] != sorted(intent["blob_sigils"]): + _fail("Artifact Storage Reference Intent Blob Sigils are not sorted") + + +def load_artifact_storage_reference_intent_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + intent = _load_strict_object(raw, "Artifact Storage Reference Intent") + validate_artifact_storage_reference_intent_v1(intent) + return intent + + +def validate_canonical_reference_commit_supplied_facts_v1( + intent: dict[str, Any], chronicle_event: dict[str, Any], + chronicle_commit: dict[str, Any], +) -> None: + """Compare a candidate canonical pin with supplied Chronicle Event facts. + + This verifies only the local Event/Receipt chain and the immutable intent + head binding. It does not resolve an event-family payload to the request, + authenticate a Chronicle prefix, or grant Chronicle commit authority. + """ + validate_artifact_storage_reference_intent_v1(intent) + validate_instance("chronicle-event-1.1.json", chronicle_event) + _check_nfc_and_numbers(chronicle_event) + receipt = chronicle_event["receipt"] + event_body = { + key: value for key, value in chronicle_event.items() + if key not in {"event_body_sigil", "receipt"} + } + receipt_body = {key: value for key, value in receipt.items() if key != "receipt_sigil"} + if intent["expected_chronicle_head"]["event_count"] == 9223372036854775807: + _fail("Canonical Reference supplied Chronicle commit exceeds the U63 head domain") + expected_head = { + "schema_version": "chronicle-head/1.1", + "event_count": intent["expected_chronicle_head"]["event_count"] + 1, + "terminal_receipt_sigil": receipt["receipt_sigil"], + } + if ( + chronicle_event["event_body_sigil"] != content_sigil(event_body) + or receipt["receipt_sigil"] != content_sigil(receipt_body) + or chronicle_event["type"] != intent["canonical_event_type"] + or chronicle_event["sequence"] != expected_head["event_count"] + or chronicle_event["previous_receipt_sigil"] + != intent["expected_chronicle_head"]["terminal_receipt_sigil"] + or receipt["event_id"] != chronicle_event["event_id"] + or receipt["event_body_sigil"] != chronicle_event["event_body_sigil"] + or receipt["previous_receipt_sigil"] != chronicle_event["previous_receipt_sigil"] + or receipt["accepted_at"] != chronicle_event["occurred_at"] + or chronicle_commit != { + "event_id": chronicle_event["event_id"], + "event_body_sigil": chronicle_event["event_body_sigil"], + "receipt_id": receipt["receipt_id"], + "receipt_sigil": receipt["receipt_sigil"], + "head": expected_head, + } + ): + _fail("Canonical Reference supplied Chronicle commit disagrees with immutable intent") + + +def validate_canonical_reference_release_supplied_facts_v1( + intent: dict[str, Any], abort_authority: dict[str, Any], reason: dict[str, Any], +) -> None: + """Close the local portion of an aborted canonical-reference pin. + + The caller must separately prove by complete authoritative Chronicle replay + that no bound event exists after the expected Head. This helper verifies + the immutable bindings and deterministic absence/authority Sigils only. + """ + validate_artifact_storage_reference_intent_v1(intent) + required = { + "kind", "reference_intent_id", "reference_intent_record_sigil", + "transition_request_id", "transition_request_sigil", "expected_chronicle_head", + "verified_chronicle_head", "absence_evidence_sigil", "authority_sigil", + } + if set(abort_authority) != required: + _fail("Canonical Reference abort authority has an invalid closed shape") + _check_nfc_and_numbers(abort_authority) + verified_head = abort_authority["verified_chronicle_head"] + if ( + set(verified_head) != {"schema_version", "event_count", "terminal_receipt_sigil"} + or verified_head["schema_version"] != "chronicle-head/1.1" + or not isinstance(verified_head["event_count"], int) + or isinstance(verified_head["event_count"], bool) + or not 0 <= verified_head["event_count"] <= 9223372036854775807 + or ( + verified_head["terminal_receipt_sigil"] is not None + and ( + not isinstance(verified_head["terminal_receipt_sigil"], str) + or len(verified_head["terminal_receipt_sigil"]) != 71 + or not verified_head["terminal_receipt_sigil"].startswith("sha256:") + or any( + character not in "0123456789abcdef" + for character in verified_head["terminal_receipt_sigil"][7:] + ) + ) + ) + ): + _fail("Canonical Reference abort authority has an invalid verified Chronicle Head") + if set(reason) != {"code", "evidence_sigils"}: + _fail("Canonical Reference release Reason has an invalid closed shape") + _check_nfc_and_numbers(reason) + absence_preimage = [ + "artifact-storage-canonical-precommit-absence/1.0", + intent["reference_intent_id"], intent["record_sigil"], + intent["transition_request_id"], intent["transition_request_sigil"], + intent["expected_chronicle_head"], abort_authority["verified_chronicle_head"], + ] + expected_evidence = sorted([ + abort_authority["authority_sigil"], abort_authority["absence_evidence_sigil"], + intent["record_sigil"], intent["transition_request_sigil"], + ]) + if ( + abort_authority["kind"] != "HEAD_SUPERSEDED_WITHOUT_BOUND_EVENT" + or abort_authority["reference_intent_id"] != intent["reference_intent_id"] + or abort_authority["reference_intent_record_sigil"] != intent["record_sigil"] + or abort_authority["transition_request_id"] != intent["transition_request_id"] + or abort_authority["transition_request_sigil"] != intent["transition_request_sigil"] + or abort_authority["expected_chronicle_head"] != intent["expected_chronicle_head"] + or abort_authority["verified_chronicle_head"]["schema_version"] != "chronicle-head/1.1" + or abort_authority["verified_chronicle_head"]["event_count"] + <= intent["expected_chronicle_head"]["event_count"] + or abort_authority["absence_evidence_sigil"] != content_sigil(absence_preimage) + or abort_authority["authority_sigil"] != content_sigil({ + key: value for key, value in abort_authority.items() if key != "authority_sigil" + }) + or reason["code"] != "CHRONICLE_REFERENCE_CHANGED" + or reason["evidence_sigils"] != expected_evidence + ): + _fail("Canonical Reference release facts disagree with immutable intent") + + +def validate_artifact_storage_legacy_protection_v1(protection: dict[str, Any]) -> None: + """Validate a Legacy Protection record without resolving its evidence.""" + validate_instance("artifact-storage-legacy-protection-1.0.json", protection) + _check_nfc_and_numbers(protection) + if protection["record_sigil"] != content_sigil(_without(protection, "record_sigil")): + _fail("Artifact Storage Legacy Protection self-Sigil mismatch") + + +def load_artifact_storage_legacy_protection_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + protection = _load_strict_object(raw, "Artifact Storage Legacy Protection") + validate_artifact_storage_legacy_protection_v1(protection) + return protection + + +def validate_artifact_storage_tail_evidence_v1(evidence: dict[str, Any]) -> None: + """Validate immutable recovery evidence without reading its raw bytes.""" + validate_instance("artifact-storage-tail-evidence-1.0.json", evidence) + _check_nfc_and_numbers(evidence) + if evidence["record_sigil"] != content_sigil(_without(evidence, "record_sigil")): + _fail("Artifact Storage Tail Evidence self-Sigil mismatch") + + +def load_artifact_storage_tail_evidence_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + evidence = _load_strict_object(raw, "Artifact Storage Tail Evidence") + validate_artifact_storage_tail_evidence_v1(evidence) + return evidence + + +_RECOVERY_MARKER_PREPARED_PHASES = { + "RECOVERY_EVENT_PREPARED", + "RECOVERY_EVENT_RETRY_EVIDENCE_DURABLE", + "RECOVERY_EVENT_COMMITTED", +} + + +def validate_artifact_storage_recovery_marker_v1(marker: dict[str, Any]) -> None: + """Validate a Recovery Marker locally without inspecting journal frames.""" + validate_instance("artifact-storage-recovery-marker-1.0.json", marker) + _check_nfc_and_numbers(marker) + if marker["record_sigil"] != content_sigil(_without(marker, "record_sigil")): + _fail("Artifact Storage Recovery Marker self-Sigil mismatch") + if marker["last_complete_byte_length"] > marker["old_committed_byte_length"]: + _fail("Artifact Storage Recovery Marker last complete length exceeds old committed length") + if marker["discarded_suffix_size"] != ( + marker["old_committed_byte_length"] - marker["last_complete_byte_length"] + ): + _fail("Artifact Storage Recovery Marker discarded suffix size mismatch") + event_fields = ( + "recovery_event_id", "recovery_event_sigil", "recovery_event_seed_record_sigil", + ) + frame_fields = ( + "recovery_frame_start", "recovery_frame_size", "recovery_frame_sigil", + "prepared_frame_evidence_record_sigil", + ) + phase = marker["phase"] + if phase in {"EVIDENCE_DURABLE", "TAIL_TRUNCATED"}: + if any(marker[field] is not None for field in event_fields + frame_fields): + _fail("Artifact Storage Recovery Marker early phase has recovery Event fields") + elif phase == "RECOVERY_EVENT_ID_DURABLE": + if any(marker[field] is None for field in event_fields) or any( + marker[field] is not None for field in frame_fields + ): + _fail("Artifact Storage Recovery Marker ID-durable phase fields are inconsistent") + elif phase in _RECOVERY_MARKER_PREPARED_PHASES and any( + marker[field] is None for field in event_fields + frame_fields + ): + _fail("Artifact Storage Recovery Marker prepared phase lacks fixed frame fields") + if marker["retry_count"] == 0: + if marker["latest_retry_evidence_record_sigil"] is not None: + _fail("Artifact Storage Recovery Marker zero retry count has retry evidence") + elif marker["latest_retry_evidence_record_sigil"] is None: + _fail("Artifact Storage Recovery Marker retry count lacks retry evidence") + + +def load_artifact_storage_recovery_marker_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + marker = _load_strict_object(raw, "Artifact Storage Recovery Marker") + validate_artifact_storage_recovery_marker_v1(marker) + return marker + + +def validate_artifact_storage_disposition_v1(disposition: dict[str, Any]) -> None: + """Validate a Disposition wire record without resolving its authorization.""" + validate_instance("artifact-storage-disposition-1.0.json", disposition) + _check_nfc_and_numbers(disposition) + if disposition["record_sigil"] != content_sigil(_without(disposition, "record_sigil")): + _fail("Artifact Storage Disposition self-Sigil mismatch") + if _parse_time(disposition["authorized_at"]) >= _parse_time(disposition["expires_at"]): + _fail("Artifact Storage Disposition expiry must follow authorization") + + +def load_artifact_storage_disposition_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + disposition = _load_strict_object(raw, "Artifact Storage Disposition") + validate_artifact_storage_disposition_v1(disposition) + return disposition + + +def validate_artifact_retention_policy_v1(policy: dict[str, Any]) -> None: + """Validate a Retention Policy locally without deciding its applicability.""" + validate_instance("artifact-retention-policy-1.0.json", policy) + _check_nfc_and_numbers(policy) + if policy["record_sigil"] != content_sigil(_without(policy, "record_sigil")): + _fail("Artifact Retention Policy self-Sigil mismatch") + for member in ("required_backends", "required_failure_domains"): + if policy[member] != sorted(policy[member]): + _fail(f"Artifact Retention Policy {member} is not sorted") + + +def load_artifact_retention_policy_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + policy = _load_strict_object(raw, "Artifact Retention Policy") + validate_artifact_retention_policy_v1(policy) + return policy + + +def validate_artifact_gc_plan_v1(plan: dict[str, Any]) -> None: + """Validate a GC Plan's closed local bindings without redoing traversal.""" + validate_instance("artifact-gc-plan-1.0.json", plan) + _check_nfc_and_numbers(plan) + if plan["record_sigil"] != content_sigil(_without(plan, "record_sigil")): + _fail("Artifact GC Plan self-Sigil mismatch") + if _parse_time(plan["created_at"]) >= _parse_time(plan["grace_ends_at"]): + _fail("Artifact GC Plan grace deadline must follow creation") + root_snapshot = plan["root_snapshot"] + proof = plan["closure_proof"] + if ( + proof["root_set_sigil"] != root_snapshot["execution_roots"]["root_set_sigil"] + or proof["extractor_suite_sigil"] != plan["extractor_suite_sigil"] + or proof["bounds"] != plan["bounds"] + ): + _fail("Artifact GC Plan Closure Proof disagrees with plan bindings") + for collection in ( + root_snapshot["reference_set_sigils"], proof["reachable_blob_sigils"], + proof["reachable_replica_ids"], [target["target_id"] for target in plan["targets"]], + ): + if collection != sorted(collection) or len(set(collection)) != len(collection): + _fail("Artifact GC Plan collections must be uniquely sorted") + for target in plan["targets"]: + remaining = target["expected_remaining_replica_ids"] + if remaining != sorted(remaining) or len(set(remaining)) != len(remaining): + _fail("Artifact GC Plan target remaining replicas must be uniquely sorted") + + +def load_artifact_gc_plan_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + plan = _load_strict_object(raw, "Artifact GC Plan") + validate_artifact_gc_plan_v1(plan) + return plan + + +def validate_artifact_provenance_v1(provenance: dict[str, Any]) -> None: + """Validate an immutable Provenance record without resolving its lineage.""" + validate_instance("artifact-provenance-1.0.json", provenance) + _check_nfc_and_numbers(provenance) + if provenance["record_sigil"] != content_sigil(_without(provenance, "record_sigil")): + _fail("Artifact Provenance self-Sigil mismatch") + + +def load_artifact_provenance_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + provenance = _load_strict_object(raw, "Artifact Provenance") + validate_artifact_provenance_v1(provenance) + return provenance + + +def validate_artifact_storage_backend_v1(backend: dict[str, Any]) -> None: + """Validate a Backend Profile record without probing its declared capabilities.""" + validate_instance("artifact-storage-backend-1.0.json", backend) + _check_nfc_and_numbers(backend) + if backend["record_sigil"] != content_sigil(_without(backend, "record_sigil")): + _fail("Artifact Storage Backend self-Sigil mismatch") + if backend["verification_methods"] != sorted(backend["verification_methods"]): + _fail("Artifact Storage Backend verification methods are not sorted") + + +def load_artifact_storage_backend_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + backend = _load_strict_object(raw, "Artifact Storage Backend") + validate_artifact_storage_backend_v1(backend) + return backend + + +def validate_artifact_provenance_policy_v1(policy: dict[str, Any]) -> None: + """Validate a Provenance Policy record without deciding Transfer admission.""" + validate_instance("artifact-provenance-policy-1.0.json", policy) + _check_nfc_and_numbers(policy) + if policy["record_sigil"] != content_sigil(_without(policy, "record_sigil")): + _fail("Artifact Provenance Policy self-Sigil mismatch") + + +def load_artifact_provenance_policy_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + policy = _load_strict_object(raw, "Artifact Provenance Policy") + validate_artifact_provenance_policy_v1(policy) + return policy + + +def validate_artifact_storage_doctor_report_v1(report: dict[str, Any]) -> None: + """Validate a read-only Doctor report without trusting its observations.""" + validate_instance("artifact-storage-doctor-report-1.0.json", report) + _check_nfc_and_numbers(report) + if report["report_sigil"] != content_sigil(_without(report, "report_sigil")): + _fail("Artifact Storage Doctor Report self-Sigil mismatch") + if _parse_time(report["completed_at"]) < _parse_time(report["started_at"]): + _fail("Artifact Storage Doctor Report completes before it starts") + + +def load_artifact_storage_doctor_report_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + report = _load_strict_object(raw, "Artifact Storage Doctor Report") + validate_artifact_storage_doctor_report_v1(report) + return report + + +def validate_artifact_transfer_v1(transfer: dict[str, Any]) -> None: + """Validate immutable Transfer bytes without admitting backend work.""" + validate_instance("artifact-transfer-1.0.json", transfer) + _check_nfc_and_numbers(transfer) + if transfer["record_sigil"] != content_sigil(_without(transfer, "record_sigil")): + _fail("Artifact Transfer self-Sigil mismatch") + if transfer["purpose"] == "ATTEMPT_OUTPUT": + if ( + transfer["direction"] != "INGEST" + or transfer["source"]["kind"] != "ATTEMPT_OUTPUT" + or transfer["source"]["execution"] != transfer["execution"] + or transfer["destination"]["kind"] != "MANAGED_BACKEND" + or transfer["destination"]["backend"] != transfer["backend"] + or transfer["expected_blob_sigil"] is None + ): + _fail("Artifact Transfer ATTEMPT_OUTPUT local bindings are inconsistent") + + +def load_artifact_transfer_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + transfer = _load_strict_object(raw, "Artifact Transfer") + validate_artifact_transfer_v1(transfer) + return transfer + + +def validate_artifact_storage_state_supplied_transfers_v1( + state: dict[str, Any], *, transfers: list[dict[str, Any]], +) -> None: + """Compare State Transfer request projections with supplied immutable records.""" + validate_artifact_storage_state_v1(state) + supplied: dict[str, str] = {} + for transfer in transfers: + validate_artifact_transfer_v1(transfer) + if transfer["transfer_id"] in supplied: + _fail("Artifact Storage supplied Transfers have duplicate IDs") + supplied[transfer["transfer_id"]] = transfer["record_sigil"] + for projection in state["transfer_requests"]: + if supplied.get(projection["transfer_id"]) != projection["request_record_sigil"]: + _fail("Artifact Storage State Transfer projection lacks matching supplied record") + if set(supplied) != {projection["transfer_id"] for projection in state["transfer_requests"]}: + _fail("Artifact Storage supplied Transfers do not exactly match State projections") + + +def validate_artifact_storage_state_supplied_transfer_attempts_v1( + state: dict[str, Any], *, transfers: list[dict[str, Any]], +) -> None: + """Check supplied Transfer ownership for the Attempt records embedded in State. + + This does not replay attempt transitions, reservations, or backend effects. + """ + validate_artifact_storage_state_v1(state) + supplied: dict[str, str] = {} + for transfer in transfers: + validate_artifact_transfer_v1(transfer) + if transfer["transfer_id"] in supplied: + _fail("Artifact Storage supplied Transfers have duplicate IDs") + supplied[transfer["transfer_id"]] = transfer["record_sigil"] + requests = {request["transfer_id"]: request for request in state["transfer_requests"]} + for wrapper in state["transfer_attempts"]: + attempt = wrapper["record"] + request = requests.get(attempt["transfer_id"]) + if request is None or supplied.get(attempt["transfer_id"]) != request["request_record_sigil"]: + _fail("Artifact Storage Transfer Attempt lacks matching supplied Transfer request") + if attempt["transfer_attempt_id"] not in request["attempt_ids"]: + _fail("Artifact Storage Transfer Attempt is absent from its State request projection") + + +def validate_artifact_storage_state_supplied_provenance_policies_v1( + state: dict[str, Any], *, policies: list[dict[str, Any]], +) -> None: + """Compare State Provenance Policy projections with supplied record bytes.""" + validate_artifact_storage_state_v1(state) + supplied: dict[str, str] = {} + for policy in policies: + validate_artifact_provenance_policy_v1(policy) + if policy["provenance_policy_id"] in supplied: + _fail("Artifact Storage supplied Provenance Policies have duplicate IDs") + supplied[policy["provenance_policy_id"]] = policy["record_sigil"] + for projection in state["provenance_policies"]: + if supplied.get(projection["provenance_policy_id"]) != projection["record_sigil"]: + _fail("Artifact Storage State Provenance Policy projection lacks matching supplied record") + if set(supplied) != { + projection["provenance_policy_id"] for projection in state["provenance_policies"] + }: + _fail("Artifact Storage supplied Provenance Policies do not exactly match State projections") + + +def validate_artifact_storage_state_supplied_provenance_v1( + state: dict[str, Any], *, records: list[dict[str, Any]], +) -> None: + """Compare State Provenance projections with complete supplied records.""" + validate_artifact_storage_state_v1(state) + supplied: dict[str, str] = {} + for provenance in records: + validate_artifact_provenance_v1(provenance) + if provenance["provenance_id"] in supplied: + _fail("Artifact Storage supplied Provenance records have duplicate IDs") + supplied[provenance["provenance_id"]] = provenance["record_sigil"] + for projection in state["provenance"]: + if supplied.get(projection["provenance_id"]) != projection["record_sigil"]: + _fail("Artifact Storage State Provenance projection lacks matching supplied record") + if set(supplied) != {projection["provenance_id"] for projection in state["provenance"]}: + _fail("Artifact Storage supplied Provenance records do not exactly match State projections") + + +def validate_artifact_storage_state_supplied_retention_policies_v1( + state: dict[str, Any], *, policies: list[dict[str, Any]], +) -> None: + """Compare State retention-policy projections with supplied record bytes.""" + validate_artifact_storage_state_v1(state) + supplied: dict[str, str] = {} + for policy in policies: + validate_artifact_retention_policy_v1(policy) + if policy["policy_id"] in supplied: + _fail("Artifact Storage supplied Retention Policies have duplicate IDs") + supplied[policy["policy_id"]] = policy["record_sigil"] + for projection in state["retention_policies"]: + if supplied.get(projection["policy_id"]) != projection["record_sigil"]: + _fail("Artifact Storage State Retention Policy projection lacks matching supplied record") + if set(supplied) != {projection["policy_id"] for projection in state["retention_policies"]}: + _fail("Artifact Storage supplied Retention Policies do not exactly match State projections") + + +def validate_artifact_storage_state_supplied_reference_sets_v1( + state: dict[str, Any], *, reference_sets: list[dict[str, Any]], +) -> None: + """Compare State Reference Set projections with exact supplied records.""" + validate_artifact_storage_state_v1(state) + supplied: dict[str, tuple[str, str]] = {} + for reference_set in reference_sets: + validate_artifact_storage_reference_set_v1(reference_set) + reference_set_id = reference_set["reference_set_id"] + if reference_set_id in supplied: + _fail("Artifact Storage supplied Reference Sets have duplicate IDs") + supplied[reference_set_id] = ( + reference_set["reference_set_sigil"], reference_set["source"]["identity"], + ) + for projection in state["reference_sets"]: + if supplied.get(projection["reference_set_id"]) != ( + projection["reference_set_sigil"], projection["source_identity"], + ): + _fail("Artifact Storage State Reference Set projection lacks matching supplied record") + if set(supplied) != {projection["reference_set_id"] for projection in state["reference_sets"]}: + _fail("Artifact Storage supplied Reference Sets do not exactly match State projections") + + +def validate_artifact_storage_state_supplied_control_records_v1( + state: dict[str, Any], *, reference_sets: list[dict[str, Any]], + reference_intents: list[dict[str, Any]], +) -> None: + """Compare State control-record projections with exact supplied documents. + + This verifies supplied immutable bytes only; callers still own durable + resolution, graph closure, Storage replay, and Chronicle authority. + """ + validate_artifact_storage_state_v1(state) + validate_artifact_storage_state_supplied_reference_sets_v1( + state, reference_sets=reference_sets + ) + intent_pairs: dict[str, str] = {} + for intent in reference_intents: + validate_artifact_storage_reference_intent_v1(intent) + if intent["reference_intent_id"] in intent_pairs: + _fail("Artifact Storage supplied Reference Intents have duplicate IDs") + intent_pairs[intent["reference_intent_id"]] = intent["record_sigil"] + for projection in state["canonical_reference_intents"]: + expected_intent_sigil = intent_pairs.get(projection["reference_intent_id"]) + if expected_intent_sigil != projection["record_sigil"]: + _fail("Artifact Storage State Reference Intent projection lacks matching supplied record") + projected_intent_ids = { + projection["reference_intent_id"] for projection in state["canonical_reference_intents"] + } + if set(intent_pairs) != projected_intent_ids: + _fail("Artifact Storage supplied Reference Intents do not exactly match State projections") + + +def validate_artifact_storage_journal_event_v1(event: dict[str, Any]) -> None: + """Validate a closed, self-authenticating Storage Journal Event locally.""" + validate_instance("artifact-storage-journal-event-1.0.json", event) + _check_nfc_and_numbers(event) + if event["event_sigil"] != content_sigil(_without(event, "event_sigil")): + _fail("Artifact Storage Journal Event self-Sigil mismatch") + revisions = event["entity_revisions"] + keys = [(item["entity_type"], item["entity_id"]) for item in revisions] + if len(set(keys)) != len(keys): + _fail("Artifact Storage Journal Event entity revisions must be unique") + + +def load_artifact_storage_journal_event_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + event = _load_strict_object(raw, "Artifact Storage Journal Event") + validate_artifact_storage_journal_event_v1(event) + return event + + +def validate_artifact_storage_journal_prefix_v1(events: list[dict[str, Any]]) -> None: + """Validate a supplied contiguous Storage Event prefix without replaying it.""" + if not events: + _fail("Artifact Storage Journal prefix must contain an initial Event") + previous: dict[str, Any] | None = None + event_ids: set[str] = set() + for expected_sequence, event in enumerate(events, start=1): + validate_artifact_storage_journal_event_v1(event) + if event["event_id"] in event_ids: + _fail("Artifact Storage Journal prefix has duplicate Event identity") + event_ids.add(event["event_id"]) + if expected_sequence == 1 and event["event_type"] != "storage.initialized": + _fail("Artifact Storage Journal prefix does not start with storage.initialized") + if expected_sequence == 1 and event["epoch"] != 1: + _fail("Artifact Storage Journal initial Event must use epoch one") + if event["sequence"] != expected_sequence: + _fail("Artifact Storage Journal prefix sequence is not contiguous") + if previous is not None: + if event["journal_id"] != previous["journal_id"]: + _fail("Artifact Storage Journal prefix changes Journal ID") + if event["previous_event_sigil"] != previous["event_sigil"]: + _fail("Artifact Storage Journal prefix chain Sigil mismatch") + if _parse_time(event["recorded_at"]) < _parse_time(previous["recorded_at"]): + _fail("Artifact Storage Journal prefix recorded time regresses") + if event["epoch"] < previous["epoch"]: + _fail("Artifact Storage Journal prefix epoch regresses") + previous = event + + +def validate_artifact_storage_journal_head_v1(head: dict[str, Any]) -> None: + """Validate the local empty/non-empty Head matrix, never its durable bytes.""" + validate_instance("artifact-storage-journal-head-1.0.json", head) + _check_nfc_and_numbers(head) + empty = head["event_count"] == 0 + if empty: + if ( + head["last_sequence"] != 0 + or head["committed_byte_length"] != 0 + or head["last_event_sigil"] is not None + or head["state_sigil"] is not None + ): + _fail("Artifact Storage empty Journal Head has terminal fields") + elif ( + head["event_count"] != head["last_sequence"] + or head["last_event_sigil"] is None + or head["state_sigil"] is None + ): + _fail("Artifact Storage non-empty Journal Head is inconsistent") + + +def load_artifact_storage_journal_head_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + head = _load_strict_object(raw, "Artifact Storage Journal Head") + validate_artifact_storage_journal_head_v1(head) + return head + + +def validate_artifact_storage_journal_head_supplied_event_v1( + head: dict[str, Any], event: dict[str, Any], state_sigil: str, +) -> None: + """Compare a Head with supplied final Event and State identity only. + + Callers remain responsible for authenticating journal frames and replaying + state; successful comparison grants no append, resolver, or storage power. + """ + validate_artifact_storage_journal_head_v1(head) + validate_artifact_storage_journal_event_v1(event) + if ( + head["event_count"] != event["sequence"] + or head["last_sequence"] != event["sequence"] + or head["journal_id"] != event["journal_id"] + or head["last_event_sigil"] != event["event_sigil"] + or head["state_sigil"] != state_sigil + ): + _fail("Artifact Storage Journal Head contradicts supplied final Event or State") + + +def validate_artifact_storage_journal_head_supplied_prefix_v1( + head: dict[str, Any], events: list[dict[str, Any]], state_sigil: str, +) -> None: + """Compare a Head with a complete caller-supplied contiguous Event prefix.""" + validate_artifact_storage_journal_prefix_v1(events) + validate_artifact_storage_journal_head_supplied_event_v1(head, events[-1], state_sigil) + + +def replay_artifact_storage_initial_prefix_v1( + events: list[dict[str, Any]], *, head: dict[str, Any] | None = None, +) -> dict[str, Any]: + """Rebuild the exact empty Storage State from one initialization Event. + + This is the installed initial reducer only. It checks the fixed twelve + quota snapshots and creates no handles, blobs, or runtime authority. + Later Storage Events remain unavailable until their reducers are installed. + """ + if len(events) != 1: + _fail("Artifact Storage initial replay requires exactly one Event") + event = events[0] + validate_artifact_storage_journal_prefix_v1([event]) + if event["event_type"] != "storage.initialized": + _fail("Artifact Storage initial replay requires storage.initialized") + payload = event["payload"] + snapshots = payload["quota_snapshots"] + expected_pairs = ( + ("JOURNAL", "JOURNAL_BYTE"), ("CONTROL_RECORD", "CONTROL_RECORD_BYTE"), + ("STAGING", "BYTE"), ("STAGING", "OBJECT"), ("QUARANTINE", "BYTE"), + ("QUARANTINE", "OBJECT"), ("COMMITTED", "BYTE"), ("COMMITTED", "OBJECT"), + ("MATERIALIZATION", "BYTE"), ("MATERIALIZATION", "OBJECT"), + ("STREAM", "STREAM"), ("INODE", "INODE"), + ) + if [(item["quota_class"], item["dimension"]) for item in snapshots] != list(expected_pairs): + _fail("Artifact Storage initialization quota snapshots are not the fixed twelve counters") + if any(item["used"] or item["reserved"] or item["pressure_state"] != "CLEAR" for item in snapshots): + _fail("Artifact Storage initialization quota snapshots must be unspent and clear") + effects = event["quota_effects"] + if effects != [{"kind": "INITIALIZE", "snapshot": item} for item in snapshots]: + _fail("Artifact Storage initialization quota effects disagree with snapshots") + if payload["tail_recovery"] is not None: + _fail("Artifact Storage initial replay does not install tail recovery") + backend = payload["backend"] + state: dict[str, Any] = { + "schema_version": "artifact-storage-state/1.0", "journal_id": event["journal_id"], + "storage_format_version": payload["storage_format_version"], "project_id": payload["project_id"], + "backend_profile_id": backend["record_id"], "backend_profile_sigil": backend["record_sigil"], + "conformance_profile_id": payload["conformance_profile_id"], + "conformance_suite_sigil": payload["conformance_suite_sigil"], + "store_status": "INITIALIZING", "active_recovery_id": None, "recovery_origin_status": None, + "clock_status": "TRUSTED", "clock_anchor": payload["clock"], "current_epoch": event["epoch"], + "applied_event_count": 1, "last_event_sigil": event["event_sigil"], + "recoveries": [], "blobs": [], "replicas": [], "transfer_requests": [], "transfer_attempts": [], + "materializations": [], "quarantines": [], "provenance": [], "provenance_policies": [], + "retention_policies": [], "holds": [], "reference_sets": [], "legacy_v1_protections": [], + "gc_plans": [], "canonical_reference_intents": [], "dispositions": [], + "quota_reservations": [], "open_intents": [], "incidents": [], + "availability_counters": {"available_blobs": 0, "degraded_blobs": 0, "unavailable_blobs": 0, "incident_blobs": 0}, + "quota_counters": snapshots, "state_sigil": "", + } + state["state_sigil"] = content_sigil(_without(state, "state_sigil")) + validate_artifact_storage_state_v1(state) + if head is not None: + validate_artifact_storage_journal_head_supplied_event_v1(head, event, state["state_sigil"]) + return state + + +def _reduce_artifact_storage_activation_v1( + state: dict[str, Any], event: dict[str, Any], +) -> dict[str, Any]: + """Apply the empty-protection activation branch after initialization.""" + if state["store_status"] != "INITIALIZING" or event["event_type"] != "storage.activation_completed": + _fail("Artifact Storage activation reducer has an invalid source state or Event") + if ( + event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + ): + _fail("Artifact Storage activation Event disagrees with prior State") + expected_revisions = [{ + "entity_type": "STORE", "entity_id": "STORE", "previous_revision": 1, "next_revision": 2, + }] + if event["entity_revisions"] != expected_revisions: + _fail("Artifact Storage activation Event has invalid Store revision") + payload = event["payload"] + protection_ids = [item["protection_id"] for item in state["legacy_v1_protections"]] + if payload["legacy_protection_ids"] != sorted(protection_ids): + _fail("Artifact Storage activation protections disagree with State") + if any(item["state"] != "PROTECTED" for item in state["legacy_v1_protections"]): + _fail("Artifact Storage activation cannot proceed with failed legacy protection") + if _parse_time(payload["clock"]["utc"]) < _parse_time(state["clock_anchor"]["utc"]): + _fail("Artifact Storage activation clock regresses") + reduced = _without(state, "state_sigil") + reduced.update({ + "store_status": "ACTIVE", "clock_anchor": payload["clock"], + "applied_event_count": event["sequence"], "last_event_sigil": event["event_sigil"], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_clock_gate_v1( + state: dict[str, Any], event: dict[str, Any], *, restoring: bool, +) -> dict[str, Any]: + """Apply the action-free Storage clock gate for an otherwise empty State.""" + required_type = "storage.clock_restored" if restoring else "storage.clock_uncertain" + if event["event_type"] != required_type or state["store_status"] != "ACTIVE": + _fail("Artifact Storage clock reducer has an invalid source state or Event") + if ( + event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["entity_revisions"] != [{ + "entity_type": "STORE", "entity_id": "STORE", + "previous_revision": event["sequence"] - 1, "next_revision": event["sequence"], + }] + ): + _fail("Artifact Storage clock Event disagrees with prior State") + payload = event["payload"] + if state["quota_reservations"] or state["open_intents"]: + _fail("Artifact Storage clock reducer requires no outstanding timed authority") + if restoring: + if state["clock_status"] != "UNCERTAIN" or payload["previous_observation_sigil"] != state["clock_anchor"]["observation_sigil"]: + _fail("Artifact Storage clock restoration disagrees with uncertain State") + clock = payload["new_clock"] + if event["observed_at"] != clock["utc"]: + _fail("Artifact Storage clock restoration observed_at disagrees with new clock") + else: + if state["clock_status"] != "TRUSTED" or payload["previous_clock"] != state["clock_anchor"]: + _fail("Artifact Storage clock uncertainty disagrees with trusted State") + if event["observed_at"] != payload["detected_clock"]["utc"]: + _fail("Artifact Storage clock uncertainty observed_at disagrees with detected clock") + clock = payload["detected_clock"] + if _parse_time(clock["utc"]) < _parse_time(state["clock_anchor"]["utc"]): + _fail("Artifact Storage clock Event regresses trusted time") + reduced = _without(state, "state_sigil") + reduced.update({ + "clock_status": "TRUSTED" if restoring else "UNCERTAIN", "clock_anchor": clock, + "applied_event_count": event["sequence"], "last_event_sigil": event["event_sigil"], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_epoch_started_v1( + state: dict[str, Any], event: dict[str, Any], +) -> dict[str, Any]: + """Apply a coordinator restart, retaining any active Recovery identity.""" + if event["event_type"] != "storage.epoch_started" or state["store_status"] not in { + "INITIALIZING", "ACTIVE", "RECOVERING" + }: + _fail("Artifact Storage epoch reducer has an invalid source state or Event") + payload = event["payload"] + recovering = state["store_status"] == "RECOVERING" + active_recovery_id = state["active_recovery_id"] + if ( + event["journal_id"] != state["journal_id"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["epoch"] != payload["next_epoch"] + or payload["previous_epoch"] != state["current_epoch"] + or payload["next_epoch"] != state["current_epoch"] + 1 + or (recovering and payload["active_recovery_id"] != active_recovery_id) + or (not recovering and payload["active_recovery_id"] is not None) + or (not recovering and payload["tail_recovery"] is not None) + or event["entity_revisions"] != [{ + "entity_type": "STORE", "entity_id": "STORE", + "previous_revision": event["sequence"] - 1, "next_revision": event["sequence"], + }] + ): + _fail("Artifact Storage epoch Event disagrees with prior State") + if event["observed_at"] != payload["clock"]["utc"]: + _fail("Artifact Storage epoch observed_at disagrees with clock") + if _parse_time(payload["clock"]["utc"]) < _parse_time(state["clock_anchor"]["utc"]): + _fail("Artifact Storage epoch clock regresses") + reduced = _without(state, "state_sigil") + reduced.update({ + "current_epoch": payload["next_epoch"], "clock_anchor": payload["clock"], + "applied_event_count": event["sequence"], "last_event_sigil": event["event_sigil"], + "recoveries": [ + {**recovery, "epoch_ids": [*recovery["epoch_ids"], payload["next_epoch"]]} + if recovery["recovery_id"] == active_recovery_id else recovery + for recovery in state["recoveries"] + ] if recovering else state["recoveries"], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_recovery_started_v1( + state: dict[str, Any], event: dict[str, Any] +) -> dict[str, Any]: + """Enter a new Storage Recovery without inferring any open-intent result.""" + payload = event["payload"] + if state["store_status"] not in {"INITIALIZING", "ACTIVE"}: + _fail("Artifact Storage recovery start has an invalid source State") + open_intent_ids = [item["intent_id"] for item in state["open_intents"]] + if ( + event["event_type"] != "storage.recovery_started" + or event["journal_id"] != state["journal_id"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["epoch"] != payload["next_epoch"] + or payload["origin_status"] != state["store_status"] + or payload["previous_epoch"] != state["current_epoch"] + or payload["next_epoch"] != state["current_epoch"] + 1 + or payload["open_intent_ids"] != open_intent_ids + or event["observed_at"] != payload["clock"]["utc"] + or _parse_time(payload["clock"]["utc"]) < _parse_time(state["clock_anchor"]["utc"]) + or event["entity_revisions"] != [{ + "entity_type": "STORE", "entity_id": "STORE", + "previous_revision": event["sequence"] - 1, + "next_revision": event["sequence"], + }] + or event["quota_effects"] + ): + _fail("Artifact Storage recovery start Event disagrees with prior State") + reduced = _without(state, "state_sigil") + reduced.update({ + "store_status": "RECOVERING", + "active_recovery_id": payload["recovery_id"], + "recovery_origin_status": state["store_status"], + "clock_anchor": payload["clock"], + "current_epoch": payload["next_epoch"], + "applied_event_count": event["sequence"], + "last_event_sigil": event["event_sigil"], + "recoveries": [*state["recoveries"], { + "recovery_id": payload["recovery_id"], + "origin_status": state["store_status"], + "state": "ACTIVE", + "started_event_sigil": event["event_sigil"], + "epoch_ids": [payload["next_epoch"]], + "tail_recovery_evidence_record_sigils": [], + "completed_event_sigil": None, + "resume_status": None, + }], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_recovery_completed_v1( + state: dict[str, Any], event: dict[str, Any] +) -> dict[str, Any]: + """Return Storage to its frozen origin after every open intent is resolved.""" + payload = event["payload"] + active_id = state["active_recovery_id"] + if active_id is None: + _fail("Artifact Storage recovery completion requires an active Recovery") + recovery = next(item for item in state["recoveries"] if item["recovery_id"] == active_id) + remaining_intents = [item["intent_id"] for item in state["open_intents"]] + if ( + event["event_type"] != "storage.recovery_completed" + or state["store_status"] != "RECOVERING" + or recovery["state"] != "ACTIVE" + or event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or payload["recovery_id"] != active_id + or payload["epoch"] != state["current_epoch"] + or payload["resume_status"] != state["recovery_origin_status"] + or remaining_intents + or payload["resolved_intent_ids"] != sorted(payload["resolved_intent_ids"]) + or payload["evidence_sigils"] != sorted(payload["evidence_sigils"]) + or event["observed_at"] != payload["clock"]["utc"] + or _parse_time(payload["clock"]["utc"]) < _parse_time(state["clock_anchor"]["utc"]) + or event["entity_revisions"] != [{ + "entity_type": "STORE", "entity_id": "STORE", + "previous_revision": event["sequence"] - 1, + "next_revision": event["sequence"], + }] + or event["quota_effects"] + ): + _fail("Artifact Storage recovery completion Event disagrees with Recovery State") + origin = state["recovery_origin_status"] + assert origin is not None + reduced = _without(state, "state_sigil") + reduced.update({ + "store_status": origin, + "active_recovery_id": None, + "recovery_origin_status": None, + "clock_anchor": payload["clock"], + "applied_event_count": event["sequence"], + "last_event_sigil": event["event_sigil"], + "recoveries": [ + { + **item, + "state": "COMPLETED", + "completed_event_sigil": event["event_sigil"], + "resume_status": origin, + } + if item["recovery_id"] == active_id else item + for item in state["recoveries"] + ], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_message_rejected_v1( + state: dict[str, Any], event: dict[str, Any], +) -> dict[str, Any]: + """Replay a bounded rejected message without changing Storage objects.""" + if event["event_type"] != "storage.message_rejected": + _fail("Artifact Storage message rejection reducer has the wrong Event") + if ( + event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["entity_revisions"] + or event["quota_effects"] + or event["observed_at"] is not None + or event["causation_event_id"] is not None + or event["idempotency_key_sigil"] is not None + ): + _fail("Artifact Storage message rejection Event disagrees with prior State") + reduced = _without(state, "state_sigil") + reduced.update({"applied_event_count": event["sequence"], "last_event_sigil": event["event_sigil"]}) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_legacy_protection_failed_v1( + state: dict[str, Any], event: dict[str, Any], +) -> dict[str, Any]: + """Retain one failed v1 compatibility protection during initialization. + + A failed historical-artifact copy is durable negative evidence. It never + activates the store and cannot be overwritten by a later success record. + """ + payload = event["payload"] + if state["store_status"] != "INITIALIZING" or event["event_type"] != "legacy_v1.protection_failed": + _fail("Artifact Storage legacy protection failure has an invalid source State or Event") + existing = [ + item for item in state["legacy_v1_protections"] + if item["protection_id"] == payload["protection_id"] + or item["artifact_id"] == payload["artifact_id"] + ] + expected_revisions = [{ + "entity_type": "LEGACY_PROTECTION", "entity_id": payload["protection_id"], + "previous_revision": None, "next_revision": 1, + }] + reason = payload["reason"] + if ( + event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["entity_revisions"] != expected_revisions + or event["quota_effects"] + or event["observed_at"] is not None + or event["causation_event_id"] is not None + or event["idempotency_key_sigil"] is not None + or existing + or reason["evidence_sigils"] != sorted(set(reason["evidence_sigils"])) + ): + _fail("Artifact Storage legacy protection failure Event disagrees with prior State") + reduced = _without(state, "state_sigil") + reduced.update({ + "legacy_v1_protections": [ + *state["legacy_v1_protections"], + { + "protection_id": payload["protection_id"], + "artifact_id": payload["artifact_id"], + "state": "FAILED", "record": None, + "receipt_sigil": payload["receipt_sigil"], "reason": reason, + "revision": 1, "last_event_sigil": event["event_sigil"], + }, + ], + "applied_event_count": event["sequence"], "last_event_sigil": event["event_sigil"], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_reference_set_registered_v1( + state: dict[str, Any], event: dict[str, Any], reference_set: dict[str, Any] +) -> dict[str, Any]: + """Project one immutable Reference Set after its exact registration Event. + + The caller supplies the durable record so this reducer can close the + Event-to-record relation without claiming source validation, graph closure, + Journal append, or Storage authority. + """ + validate_artifact_storage_reference_set_v1(reference_set) + payload = event["payload"] + if state["store_status"] != "ACTIVE": + _fail("Artifact Storage Reference Set registration requires an active Store") + if any( + item["reference_set_id"] == reference_set["reference_set_id"] + for item in state["reference_sets"] + ): + _fail("Artifact Storage Reference Set registration duplicates a State projection") + expected_revisions = [{ + "entity_type": "REFERENCE_SET", + "entity_id": reference_set["reference_set_id"], + "previous_revision": None, + "next_revision": 1, + }] + if ( + event["event_type"] != "reference_set.registered" + or event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["entity_revisions"] != expected_revisions + or event["quota_effects"] + or event["observed_at"] is not None + or event["causation_event_id"] is not None + or event["idempotency_key_sigil"] is not None + or event["event_id"] != reference_set["registration_event_id"] + or event["recorded_at"] != reference_set["created_at"] + or payload["reference_set_id"] != reference_set["reference_set_id"] + or payload["reference_set_sigil"] != reference_set["reference_set_sigil"] + or payload["source_identity"] != reference_set["source"]["identity"] + or payload["source_sigil"] != reference_set["source"]["sigil"] + ): + _fail("Artifact Storage Reference Set registration Event disagrees with record") + reduced = _without(state, "state_sigil") + reduced.update({ + "reference_sets": sorted( + [ + *state["reference_sets"], + { + "reference_set_id": reference_set["reference_set_id"], + "reference_set_sigil": reference_set["reference_set_sigil"], + "source_identity": reference_set["source"]["identity"], + "revision": 1, + "last_event_sigil": event["event_sigil"], + }, + ], + key=lambda item: item["reference_set_id"].encode("ascii"), + ), + "applied_event_count": event["sequence"], + "last_event_sigil": event["event_sigil"], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_provenance_policy_registered_v1( + state: dict[str, Any], event: dict[str, Any], policy: dict[str, Any], +) -> dict[str, Any]: + """Project one immutable Provenance Policy after exact registration. + + This closes only the Event-to-record and State-projection relations. In + particular, it does not resolve the policy's authorization or use the + policy to admit a Transfer. + """ + validate_artifact_provenance_policy_v1(policy) + payload = event["payload"] + if state["store_status"] != "ACTIVE": + _fail("Artifact Storage Provenance Policy registration requires an active Store") + if policy["scope"]["project_id"] != state["project_id"]: + _fail("Artifact Storage Provenance Policy scope disagrees with State project") + if any( + item["provenance_policy_id"] == policy["provenance_policy_id"] + for item in state["provenance_policies"] + ): + _fail("Artifact Storage Provenance Policy registration duplicates a State projection") + expected_revisions = [{ + "entity_type": "PROVENANCE_POLICY", + "entity_id": policy["provenance_policy_id"], + "previous_revision": None, + "next_revision": 1, + }] + expected_ref = { + "schema_version": "artifact-provenance-policy/1.0", + "record_id": policy["provenance_policy_id"], + "record_sigil": policy["record_sigil"], + } + if ( + event["event_type"] != "provenance.policy_registered" + or event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["entity_revisions"] != expected_revisions + or event["quota_effects"] + or event["observed_at"] is not None + or event["causation_event_id"] is not None + or event["idempotency_key_sigil"] is not None + or event["recorded_at"] != policy["registered_at"] + or payload["provenance_policy"] != expected_ref + ): + _fail("Artifact Storage Provenance Policy registration Event disagrees with record") + reduced = _without(state, "state_sigil") + reduced.update({ + "provenance_policies": sorted( + [ + *state["provenance_policies"], + { + "provenance_policy_id": policy["provenance_policy_id"], + "record_sigil": policy["record_sigil"], + "revision": 1, + "last_event_sigil": event["event_sigil"], + }, + ], + key=lambda item: item["provenance_policy_id"].encode("ascii"), + ), + "applied_event_count": event["sequence"], + "last_event_sigil": event["event_sigil"], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_retention_policy_registered_v1( + state: dict[str, Any], event: dict[str, Any], policy: dict[str, Any], +) -> dict[str, Any]: + """Project an exact active-Store PROJECT retention-policy registration. + + This is deliberately narrower than policy applicability: it accepts only a + PROJECT scope closed to this State or a REFERENCE_SET scope closed to an + already projected exact State object. BLOB scope still needs a separately + replayed Blob lifecycle and PROGRAM needs an external Program-to-Project + resolver. INITIALIZING requires the two RFC-fixed policies. Those branches + remain unavailable rather than treating a self-Sigiled policy as + authorization. + """ + validate_artifact_retention_policy_v1(policy) + payload = event["payload"] + if state["store_status"] != "ACTIVE": + _fail("Artifact Storage Retention Policy registration requires an active Store") + scope = policy["scope"] + scope_is_closed = ( + scope["kind"] == "PROJECT" and scope["project_id"] == state["project_id"] + ) or ( + scope["kind"] == "REFERENCE_SET" + and any( + projection["reference_set_id"] == scope["reference_set_id"] + and projection["reference_set_sigil"] == scope["reference_set_sigil"] + for projection in state["reference_sets"] + ) + ) + if not scope_is_closed: + _fail("Artifact Storage Retention Policy scope is not locally closed to State project") + if any(item["policy_id"] == policy["policy_id"] for item in state["retention_policies"]): + _fail("Artifact Storage Retention Policy registration duplicates a State projection") + expected_revisions = [{ + "entity_type": "RETENTION_POLICY", + "entity_id": policy["policy_id"], + "previous_revision": None, + "next_revision": 1, + }] + expected_ref = { + "schema_version": "artifact-retention-policy/1.0", + "record_id": policy["policy_id"], + "record_sigil": policy["record_sigil"], + } + if ( + event["event_type"] != "retention.policy_registered" + or event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["entity_revisions"] != expected_revisions + or event["quota_effects"] + or event["observed_at"] is not None + or event["causation_event_id"] is not None + or event["idempotency_key_sigil"] is not None + or event["recorded_at"] != policy["registered_at"] + or payload["policy"] != expected_ref + ): + _fail("Artifact Storage Retention Policy registration Event disagrees with record") + reduced = _without(state, "state_sigil") + reduced.update({ + "retention_policies": sorted( + [ + *state["retention_policies"], + { + "policy_id": policy["policy_id"], + "record_sigil": policy["record_sigil"], + "revision": 1, + "last_event_sigil": event["event_sigil"], + }, + ], + key=lambda item: item["policy_id"].encode("ascii"), + ), + "applied_event_count": event["sequence"], + "last_event_sigil": event["event_sigil"], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _quota_counter_updates_for_claims_v1( + counters: list[dict[str, Any]], claims: list[dict[str, Any]], *, reserve: bool, +) -> list[dict[str, Any]]: + """Apply one checked Reservation claim vector to the twelve counters.""" + by_class = {claim["quota_class"]: claim for claim in claims} + dimensions = { + ("JOURNAL", "JOURNAL_BYTE"): "journal_bytes", + ("CONTROL_RECORD", "CONTROL_RECORD_BYTE"): "control_record_bytes", + ("STAGING", "BYTE"): "byte_count", + ("STAGING", "OBJECT"): "object_count", + ("QUARANTINE", "BYTE"): "byte_count", + ("QUARANTINE", "OBJECT"): "object_count", + ("COMMITTED", "BYTE"): "byte_count", + ("COMMITTED", "OBJECT"): "object_count", + ("MATERIALIZATION", "BYTE"): "byte_count", + ("MATERIALIZATION", "OBJECT"): "object_count", + ("STREAM", "STREAM"): "stream_count", + ("INODE", "INODE"): "inode_count", + } + updated: list[dict[str, Any]] = [] + for counter in counters: + amount = by_class.get(counter["quota_class"], {}).get( + dimensions[(counter["quota_class"], counter["dimension"])], 0 + ) + next_reserved = counter["reserved"] + amount if reserve else counter["reserved"] - amount + if next_reserved < 0 or counter["used"] + next_reserved > counter["limit"]: + _fail("Artifact Storage Reservation exceeds a quota counter") + updated.append({**counter, "reserved": next_reserved}) + return updated + + +def _quota_counter_settlement_v1( + counters: list[dict[str, Any]], original: list[dict[str, Any]], + consumed: list[dict[str, Any]], +) -> list[dict[str, Any]]: + """Settle a reservation: release all reserve, retain consumed usage.""" + dimensions = { + ("JOURNAL", "JOURNAL_BYTE"): "journal_bytes", + ("CONTROL_RECORD", "CONTROL_RECORD_BYTE"): "control_record_bytes", + ("STAGING", "BYTE"): "byte_count", ("STAGING", "OBJECT"): "object_count", + ("QUARANTINE", "BYTE"): "byte_count", ("QUARANTINE", "OBJECT"): "object_count", + ("COMMITTED", "BYTE"): "byte_count", ("COMMITTED", "OBJECT"): "object_count", + ("MATERIALIZATION", "BYTE"): "byte_count", ("MATERIALIZATION", "OBJECT"): "object_count", + ("STREAM", "STREAM"): "stream_count", ("INODE", "INODE"): "inode_count", + } + original_by_class = {claim["quota_class"]: claim for claim in original} + consumed_by_class = {claim["quota_class"]: claim for claim in consumed} + updated: list[dict[str, Any]] = [] + for counter in counters: + quota_class = counter["quota_class"] + field = dimensions[(quota_class, counter["dimension"])] + reserved_amount = original_by_class.get(quota_class, {}).get(field, 0) + consumed_amount = consumed_by_class.get(quota_class, {}).get(field, 0) + next_reserved = counter["reserved"] - reserved_amount + next_used = counter["used"] + consumed_amount + if next_reserved < 0 or next_used + next_reserved > counter["limit"]: + _fail("Artifact Storage Reservation settlement exceeds a quota counter") + updated.append({**counter, "used": next_used, "reserved": next_reserved}) + return updated + + +def _canonical_reference_blob_closure_v1( + roots: list[dict[str, Any]], reference_sets: list[dict[str, Any]], + state: dict[str, Any], +) -> list[str]: + """Recompute the bounded typed Reference Set closure for an intent pin.""" + records = {record["reference_set_id"]: record for record in reference_sets} + if len(records) != len(reference_sets): + _fail("Canonical Reference closure has duplicate supplied Reference Sets") + replica_blobs = { + wrapper["record"]["replica_id"]: wrapper["record"]["blob_sigil"] + for wrapper in state["replicas"] + } + storage_blobs = { + wrapper["record"]["blob_sigil"] for wrapper in state["blobs"] + } + state_sets = { + projection["reference_set_id"]: projection["reference_set_sigil"] + for projection in state["reference_sets"] + } + relationship_matrix = { + "BUNDLE_RETAINS_MEMBER": ("BLOB_MANIFEST", {"BLOB"}), + "CANONICAL_BINDS_BLOB": ("CANONICAL_OBJECT", {"BLOB"}), + "CANONICAL_RETAINS_OBJECT": ( + "CANONICAL_OBJECT", {"CANONICAL_OBJECT", "OPERATIONAL_CONTROL_RECORD", "REFERENCE_SET"} + ), + "CONTROL_RETAINS_BLOB": ("OPERATIONAL_CONTROL_RECORD", {"BLOB"}), + "CONTROL_RETAINS_CONTROL": ("OPERATIONAL_CONTROL_RECORD", {"OPERATIONAL_CONTROL_RECORD"}), + "HOLD_PROTECTS_BLOB": ("OPERATIONAL_CONTROL_RECORD", {"BLOB"}), + "JOB_REQUIRES_BLOB": ("OPERATIONAL_CONTROL_RECORD", {"BLOB"}), + "PATCH_RETAINS_BASE": ("BLOB_MANIFEST", {"BLOB"}), + "PATCH_RETAINS_POSTIMAGE": ("BLOB_MANIFEST", {"BLOB"}), + "REFERENCE_SET_RETAINS_SET": ("OPERATIONAL_CONTROL_RECORD", {"REFERENCE_SET"}), + "TRANSFER_PINS_REPLICA": ("OPERATIONAL_CONTROL_RECORD", {"REPLICA"}), + } + pending = [("REFERENCE_SET", item["reference_set_id"], item["reference_set_sigil"], 0) + for item in roots] + seen: set[tuple[str, str, str]] = set() + edge_keys: set[tuple[str, str, str, str]] = set() + blobs: set[str] = set() + while pending: + kind, identity, sigil, depth = pending.pop() + node = (kind, identity, sigil) + if node in seen: + continue + if len(seen) >= 4096 or depth >= 4096: + _fail("Canonical Reference closure exceeds its traversal bounds") + seen.add(node) + if kind != "REFERENCE_SET": + continue + record = records.get(identity) + if ( + record is None + or record["reference_set_sigil"] != sigil + or state_sets.get(identity) != sigil + ): + _fail("Canonical Reference closure lacks an exact Reference Set") + for edge in record["edges"]: + edge_key = ( + edge["relationship"], edge["target_kind"], edge["target_identity"], + edge["target_sigil"], + ) + if edge_key in edge_keys: + continue + if len(edge_keys) >= 4096: + _fail("Canonical Reference closure exceeds its edge bound") + edge_keys.add(edge_key) + target_kind = edge["target_kind"] + target_id = edge["target_identity"] + target_sigil = edge["target_sigil"] + expected_source, expected_targets = relationship_matrix[edge["relationship"]] + if record["source"]["kind"] != expected_source or target_kind not in expected_targets: + _fail("Canonical Reference closure has an illegal typed edge") + if ( + edge["relationship"] == "REFERENCE_SET_RETAINS_SET" + and record["source"]["schema_version"] + != "artifact-storage-reference-set/1.0" + ): + _fail("Canonical Reference closure Reference Set edge has an invalid source") + if target_kind == "BLOB": + if target_id != target_sigil or target_sigil not in storage_blobs: + _fail("Canonical Reference Blob edge identity disagrees with Sigil") + blobs.add(target_sigil) + elif target_kind == "REPLICA": + blob_sigil = replica_blobs.get(target_id) + if blob_sigil is None or target_sigil != next( + (wrapper["record"]["record_sigil"] for wrapper in state["replicas"] + if wrapper["record"]["replica_id"] == target_id), None + ): + _fail("Canonical Reference closure lacks an exact Replica") + blobs.add(blob_sigil) + elif target_kind == "REFERENCE_SET": + pending.append((target_kind, target_id, target_sigil, depth + 1)) + else: + _fail("Canonical Reference closure has an unresolved typed target") + if len(blobs) > 4096: + _fail("Canonical Reference closure exceeds its Blob bound") + return sorted(blobs) + + +def _validate_canonical_lifecycle_reservation_v1(reservation: dict[str, Any]) -> None: + """Close the capacity arithmetic required before a canonical pin is durable.""" + plan = reservation["capacity_plan"] + if plan["allowed_event_types"] != [ + "canonical_reference.committed", "canonical_reference.released" + ]: + _fail("Canonical Reference lifecycle Reservation has an invalid terminal plan") + required_journal = plan["max_event_frame_count"] * plan["max_event_frame_bytes"] + required_control = ( + plan["max_control_record_count"] * plan["max_control_record_bytes"] + + plan["max_recovery_evidence_count"] * plan["max_recovery_evidence_bytes"] + ) + if required_journal > 9223372036854775807 or required_control > 9223372036854775807: + _fail("Canonical Reference lifecycle Reservation capacity arithmetic overflows") + claims = {claim["quota_class"]: claim for claim in reservation["claims"]} + if ( + claims.get("JOURNAL", {}).get("journal_bytes", 0) < required_journal + or claims.get("CONTROL_RECORD", {}).get("control_record_bytes", 0) < required_control + ): + _fail("Canonical Reference lifecycle Reservation lacks terminal capacity") + + +def _reduce_artifact_storage_canonical_reference_intent_v1( + state: dict[str, Any], event: dict[str, Any], intent: dict[str, Any], + reference_sets: list[dict[str, Any]], +) -> dict[str, Any]: + """Project a canonical-reference pin from exact supplied control records. + + This closes the immutable Storage portion of write-ahead intent admission, + including the bounded Reference Set closure. Chronicle authority remains + external and is deliberately not inferred here. + """ + validate_artifact_storage_reference_intent_v1(intent) + for reference_set in reference_sets: + validate_artifact_storage_reference_set_v1(reference_set) + payload = event["payload"] + reservation = payload["lifecycle_reservation"] + if state["store_status"] != "ACTIVE" or state["clock_status"] != "TRUSTED": + _fail("Canonical Reference intent requires an active trusted Store") + reference_pairs = { + record["reference_set_id"]: record["reference_set_sigil"] + for record in reference_sets + } + if len(reference_pairs) != len(reference_sets): + _fail("Canonical Reference intent supplied Reference Sets have duplicate IDs") + intent_set_pairs = [ + (reference["reference_set_id"], reference["reference_set_sigil"]) + for reference in intent["reference_sets"] + ] + if any(reference_pairs.get(identifier) != sigil for identifier, sigil in intent_set_pairs): + _fail("Canonical Reference intent lacks a supplied immutable Reference Set") + state_set_pairs = { + projection["reference_set_id"]: projection["reference_set_sigil"] + for projection in state["reference_sets"] + } + if any(state_set_pairs.get(identifier) != sigil for identifier, sigil in intent_set_pairs): + _fail("Canonical Reference intent Reference Set is absent from Storage State") + if any( + item["reference_intent_id"] == intent["reference_intent_id"] + for item in state["canonical_reference_intents"] + ) or any( + item["intent_id"] == intent["reference_intent_id"] + for item in state["open_intents"] + ) or any( + item["reservation"]["reservation_id"] == reservation["reservation_id"] + for item in state["quota_reservations"] + ): + _fail("Canonical Reference intent duplicates a Storage projection") + _validate_quota_claim_array(reservation["claims"], "Canonical Reference Reservation claims") + closure_blobs = _canonical_reference_blob_closure_v1( + intent["reference_sets"], reference_sets, state + ) + if ( + reservation["expires_at"] is not None + or reservation["remaining_micros_at_creation"] is not None + or reservation["created_clock"] != state["clock_anchor"] + ): + _fail("Canonical Reference lifecycle Reservation is not the fixed nonexpiring plan") + _validate_canonical_lifecycle_reservation_v1(reservation) + expected_revisions = [ + {"entity_type": "REFERENCE_INTENT", "entity_id": intent["reference_intent_id"], + "previous_revision": None, "next_revision": 1}, + {"entity_type": "QUOTA", "entity_id": reservation["reservation_id"], + "previous_revision": None, "next_revision": 1}, + ] + expected_effect = { + "kind": "RESERVE", "reservation": reservation, + "owner_kind": "CANONICAL_REFERENCE", "owner_id": intent["reference_intent_id"], + "purpose": "CANONICAL_PIN_LIFECYCLE", + } + expected_set_sigils = [sigil for _, sigil in intent_set_pairs] + if ( + event["event_type"] != "canonical_reference.intent_recorded" + or event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["entity_revisions"] != expected_revisions + or event["observed_at"] is not None + or event["causation_event_id"] is not None + or event["idempotency_key_sigil"] != intent["idempotency_key_sigil"] + or event["quota_effects"] != [expected_effect] + or payload["reference_intent"] != { + "schema_version": "artifact-storage-reference-intent/1.0", + "record_id": intent["reference_intent_id"], "record_sigil": intent["record_sigil"], + } + or payload["expected_chronicle_head"] != intent["expected_chronicle_head"] + or intent["blob_sigils"] != closure_blobs + or payload["blob_sigils"] != closure_blobs + or payload["reference_set_sigils"] != expected_set_sigils + ): + _fail("Canonical Reference intent Event disagrees with immutable records") + reduced = _without(state, "state_sigil") + reduced.update({ + "canonical_reference_intents": sorted([ + *state["canonical_reference_intents"], { + "reference_intent_id": intent["reference_intent_id"], "record_sigil": intent["record_sigil"], + "state": "OPEN", "chronicle_commit": None, "release_kind": None, + "release_authority_sigil": None, "release_reason": None, "revision": 1, + "last_event_sigil": event["event_sigil"], + }, + ], key=lambda item: item["reference_intent_id"].encode("ascii")), + "quota_reservations": sorted([ + *state["quota_reservations"], { + "reservation": reservation, "owner_kind": "CANONICAL_REFERENCE", + "owner_id": intent["reference_intent_id"], "purpose": "CANONICAL_PIN_LIFECYCLE", + "state": "ACTIVE", "consumed_claims": [], "released_claims": [], + "remaining_claims": reservation["claims"], "retained_for_event_types": [], + "revision": 1, "last_event_sigil": event["event_sigil"], + }, + ], key=lambda item: item["reservation"]["reservation_id"].encode("ascii")), + "open_intents": sorted([ + *state["open_intents"], { + "intent_kind": "CANONICAL_REFERENCE", "intent_id": intent["reference_intent_id"], + "owner_id": intent["reference_intent_id"], "source_event": { + "journal_id": event["journal_id"], "sequence": event["sequence"], + "event_id": event["event_id"], "event_sigil": event["event_sigil"], + }, "intent_sigil": event["event_sigil"], "revision": 1, + "last_event_sigil": event["event_sigil"], "authorization_expires_at": None, + "expected_chronicle_head": intent["expected_chronicle_head"], + "blob_sigils": intent["blob_sigils"], "reference_set_sigils": expected_set_sigils, + }, + ], key=lambda item: (item["intent_kind"].encode("ascii"), item["intent_id"].encode("ascii"))), + "quota_counters": _quota_counter_updates_for_claims_v1( + state["quota_counters"], reservation["claims"], reserve=True + ), + "applied_event_count": event["sequence"], "last_event_sigil": event["event_sigil"], + }) + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_canonical_reference_committed_v1( + state: dict[str, Any], event: dict[str, Any], intent: dict[str, Any], + chronicle_event: dict[str, Any], +) -> dict[str, Any]: + """Close one OPEN canonical-reference pin from supplied Chronicle facts. + + This reducer closes the durable Storage projection and Reservation only. + The caller is responsible for authoritative Chronicle replay and the + event-family request resolver; this function never appends or authorizes a + Chronicle Event. + """ + projection = next( + (item for item in state["canonical_reference_intents"] + if item["reference_intent_id"] == intent["reference_intent_id"]), + None, + ) + reservation = next( + (item for item in state["quota_reservations"] + if item["owner_kind"] == "CANONICAL_REFERENCE" + and item["owner_id"] == intent["reference_intent_id"]), + None, + ) + open_intent = next( + (item for item in state["open_intents"] + if item["intent_kind"] == "CANONICAL_REFERENCE" + and item["intent_id"] == intent["reference_intent_id"]), + None, + ) + if ( + projection is None or projection["state"] != "OPEN" + or projection["record_sigil"] != intent["record_sigil"] + or reservation is None or reservation["state"] != "ACTIVE" + or open_intent is None + ): + _fail("Canonical Reference commit requires one OPEN intent and active Reservation") + commit = event["payload"]["chronicle_commit"] + validate_canonical_reference_commit_supplied_facts_v1(intent, chronicle_event, commit) + expected_revisions = [ + {"entity_type": "REFERENCE_INTENT", "entity_id": intent["reference_intent_id"], + "previous_revision": 1, "next_revision": 2}, + {"entity_type": "QUOTA", "entity_id": reservation["reservation"]["reservation_id"], + "previous_revision": 1, "next_revision": 2}, + ] + effects = event["quota_effects"] + if len(effects) != 1 or effects[0]["kind"] != "SETTLE": + _fail("Canonical Reference commit requires one Reservation settlement") + settlement = effects[0] + if ( + event["event_type"] != "canonical_reference.committed" + or event["journal_id"] != state["journal_id"] + or event["epoch"] != state["current_epoch"] + or event["sequence"] != state["applied_event_count"] + 1 + or event["previous_event_sigil"] != state["last_event_sigil"] + or event["entity_revisions"] != expected_revisions + or event["observed_at"] is not None + or event["causation_event_id"] != open_intent["source_event"]["event_id"] + or event["idempotency_key_sigil"] != intent["idempotency_key_sigil"] + or event["payload"]["reference_intent_id"] != intent["reference_intent_id"] + or settlement["reservation_id"] != reservation["reservation"]["reservation_id"] + or settlement["state_after"] != "SETTLED" + or settlement["remaining_claims"] + or settlement["retained_for_event_types"] + or settlement["usage_additions"] != settlement["consumed_claims"] + ): + _fail("Canonical Reference commit Event disagrees with OPEN pin") + original = reservation["reservation"]["claims"] + consumed_by_class = {claim["quota_class"]: claim for claim in settlement["consumed_claims"]} + if consumed_by_class.get("JOURNAL", {}).get("journal_bytes", 0) <= 0: + _fail("Canonical Reference commit must account for its Journal frame usage") + reduced = _without(state, "state_sigil") + reduced["canonical_reference_intents"] = [ + { + **item, "state": "COMMITTED", "chronicle_commit": commit, + "release_kind": None, "release_authority_sigil": None, + "release_reason": None, "revision": 2, + "last_event_sigil": event["event_sigil"], + } if item["reference_intent_id"] == intent["reference_intent_id"] else item + for item in state["canonical_reference_intents"] + ] + reduced["quota_reservations"] = [ + { + **item, "state": "SETTLED", "consumed_claims": settlement["consumed_claims"], + "released_claims": settlement["released_claims"], "remaining_claims": [], + "retained_for_event_types": [], "revision": 2, + "last_event_sigil": event["event_sigil"], + } if item["reservation"]["reservation_id"] == reservation["reservation"]["reservation_id"] else item + for item in state["quota_reservations"] + ] + reduced["open_intents"] = [ + item for item in state["open_intents"] + if not (item["intent_kind"] == "CANONICAL_REFERENCE" and item["intent_id"] == intent["reference_intent_id"]) + ] + reduced["quota_counters"] = _quota_counter_settlement_v1( + state["quota_counters"], original, settlement["consumed_claims"] + ) + reduced["applied_event_count"] = event["sequence"] + reduced["last_event_sigil"] = event["event_sigil"] + reduced["state_sigil"] = content_sigil(reduced) + validate_artifact_storage_state_v1(reduced) + return reduced + + +def _reduce_artifact_storage_canonical_reference_released_v1( + state: dict[str, Any], event: dict[str, Any], intent: dict[str, Any], +) -> dict[str, Any]: + """Reject untrusted abort facts pending an authoritative Chronicle resolver. + + A self-consistent supplied head and absence Sigil cannot prove the required + negative fact: that the complete Chronicle suffix contains no Event bound + to this immutable request. Generic Storage replay has no Chronicle + authority, therefore it must retain the OPEN pin rather than project a + RELEASED state. The local fact checker remains available for the future + authoritative resolver boundary. + """ + _fail( + "Canonical Reference release replay requires authoritative Chronicle " + "absence proof and remains fail-closed" + ) + + +def replay_artifact_storage_journal_prefix_v1( + events: list[dict[str, Any]], *, head: dict[str, Any] | None = None, + supplied_reference_sets: list[dict[str, Any]] | None = None, + supplied_reference_intents: list[dict[str, Any]] | None = None, + supplied_chronicle_events: list[dict[str, Any]] | None = None, + supplied_provenance_policies: list[dict[str, Any]] | None = None, + supplied_retention_policies: list[dict[str, Any]] | None = None, +) -> dict[str, Any]: + """Replay installed Storage Journal reducers, failing closed for all others. + + This is deliberately a dispatcher over the installed reducer set rather + than a catalog of fixed-length prefixes. It still rejects every Event type + without a reducer and grants no append or Storage authority. + """ + validate_artifact_storage_journal_prefix_v1(events) + state = replay_artifact_storage_initial_prefix_v1([events[0]]) + for event in events[1:]: + if event["event_type"] == "storage.activation_completed": + state = _reduce_artifact_storage_activation_v1(state, event) + elif event["event_type"] == "storage.epoch_started": + state = _reduce_artifact_storage_epoch_started_v1(state, event) + elif event["event_type"] == "storage.clock_uncertain": + state = _reduce_artifact_storage_clock_gate_v1(state, event, restoring=False) + elif event["event_type"] == "storage.clock_restored": + state = _reduce_artifact_storage_clock_gate_v1(state, event, restoring=True) + elif event["event_type"] == "storage.recovery_started": + state = _reduce_artifact_storage_recovery_started_v1(state, event) + elif event["event_type"] == "storage.recovery_completed": + state = _reduce_artifact_storage_recovery_completed_v1(state, event) + elif event["event_type"] == "storage.message_rejected": + state = _reduce_artifact_storage_message_rejected_v1(state, event) + elif event["event_type"] == "legacy_v1.protection_failed": + state = _reduce_artifact_storage_legacy_protection_failed_v1(state, event) + elif event["event_type"] == "provenance.policy_registered": + if supplied_provenance_policies is None: + _fail("Provenance Policy registration replay requires its supplied record") + matches = [ + record + for record in supplied_provenance_policies + if record.get("provenance_policy_id") + == event["payload"]["provenance_policy"]["record_id"] + ] + if len(matches) != 1: + _fail("Provenance Policy registration replay requires exactly one supplied record") + state = _reduce_artifact_storage_provenance_policy_registered_v1( + state, event, matches[0] + ) + elif event["event_type"] == "retention.policy_registered": + if supplied_retention_policies is None: + _fail("Retention Policy registration replay requires its supplied record") + matches = [ + record + for record in supplied_retention_policies + if record.get("policy_id") == event["payload"]["policy"]["record_id"] + ] + if len(matches) != 1: + _fail("Retention Policy registration replay requires exactly one supplied record") + state = _reduce_artifact_storage_retention_policy_registered_v1( + state, event, matches[0] + ) + elif event["event_type"] == "reference_set.registered": + if supplied_reference_sets is None: + _fail("Reference Set registration replay requires its supplied record") + matches = [ + record + for record in supplied_reference_sets + if record.get("reference_set_id") == event["payload"]["reference_set_id"] + ] + if len(matches) != 1: + _fail("Reference Set registration replay requires exactly one supplied record") + state = _reduce_artifact_storage_reference_set_registered_v1( + state, event, matches[0] + ) + elif event["event_type"] == "canonical_reference.intent_recorded": + if supplied_reference_intents is None or supplied_reference_sets is None: + _fail("Canonical Reference intent replay requires supplied control records") + matches = [ + record for record in supplied_reference_intents + if record.get("reference_intent_id") == event["payload"]["reference_intent"]["record_id"] + ] + if len(matches) != 1: + _fail("Canonical Reference intent replay requires exactly one supplied record") + state = _reduce_artifact_storage_canonical_reference_intent_v1( + state, event, matches[0], supplied_reference_sets + ) + elif event["event_type"] == "canonical_reference.committed": + if supplied_reference_intents is None or supplied_chronicle_events is None: + _fail("Canonical Reference commit replay requires supplied control and Chronicle records") + intent_matches = [record for record in supplied_reference_intents if record.get("reference_intent_id") == event["payload"]["reference_intent_id"]] + commit_matches = [record for record in supplied_chronicle_events if record.get("event_id") == event["payload"]["chronicle_commit"]["event_id"]] + if len(intent_matches) != 1 or len(commit_matches) != 1: + _fail("Canonical Reference commit replay requires exactly one supplied record") + state = _reduce_artifact_storage_canonical_reference_committed_v1( + state, event, intent_matches[0], commit_matches[0] + ) + elif event["event_type"] == "canonical_reference.released": + if supplied_reference_intents is None: + _fail("Canonical Reference release replay requires its supplied control record") + matches = [record for record in supplied_reference_intents if record.get("reference_intent_id") == event["payload"]["reference_intent_id"]] + if len(matches) != 1: + _fail("Canonical Reference release replay requires exactly one supplied record") + state = _reduce_artifact_storage_canonical_reference_released_v1(state, event, matches[0]) + else: + _fail("Artifact Storage Journal replay reducer is unavailable for this Event") + if head is not None: + validate_artifact_storage_journal_head_supplied_event_v1( + head, events[-1], state["state_sigil"] + ) + if supplied_provenance_policies is not None: + validate_artifact_storage_state_supplied_provenance_policies_v1( + state, policies=supplied_provenance_policies + ) + if supplied_retention_policies is not None: + validate_artifact_storage_state_supplied_retention_policies_v1( + state, policies=supplied_retention_policies + ) + if supplied_reference_sets is not None: + validate_artifact_storage_state_supplied_reference_sets_v1( + state, reference_sets=supplied_reference_sets + ) + return state + + +def _state_identity(value: dict[str, Any], collection: str) -> str | tuple[str, str]: + if collection == "open_intents": + return value["intent_kind"], value["intent_id"] + if collection == "quota_reservations": + return value["reservation"]["reservation_id"] + if collection in {"blobs", "replicas", "transfer_attempts", "materializations"}: + record = value["record"] + return record[{"blobs": "blob_sigil", "replicas": "replica_id", "transfer_attempts": "transfer_attempt_id", "materializations": "materialization_id"}[collection]] + identity_member = { + "recoveries": "recovery_id", "transfer_requests": "transfer_id", + "quarantines": "quarantine_id", "provenance": "provenance_id", + "provenance_policies": "provenance_policy_id", "retention_policies": "policy_id", + "holds": "hold_id", "reference_sets": "reference_set_id", + "legacy_v1_protections": "protection_id", "gc_plans": "gc_plan_id", + "canonical_reference_intents": "reference_intent_id", "dispositions": "disposition_id", + "incidents": "incident_id", + }[collection] + return value[identity_member] + + +_STATE_IDENTITY_COLLECTIONS = ( + "recoveries", "blobs", "replicas", "transfer_requests", "transfer_attempts", + "materializations", "quarantines", "provenance", "provenance_policies", + "retention_policies", "holds", "reference_sets", "legacy_v1_protections", + "gc_plans", "canonical_reference_intents", "dispositions", "quota_reservations", + "open_intents", "incidents", +) + +_STATE_WRAPPER_SCHEMAS = { + "blobs": "artifact-blob-1.0.json", + "replicas": "artifact-replica-1.0.json", + "transfer_attempts": "artifact-transfer-attempt-1.0.json", + "materializations": "artifact-materialization-1.0.json", +} + +_QUOTA_CLAIM_FIELDS = ( + "byte_count", "object_count", "inode_count", "stream_count", "journal_bytes", + "control_record_bytes", +) +_QUOTA_CLASS_ALLOWED_FIELDS = { + "JOURNAL": {"journal_bytes"}, + "CONTROL_RECORD": {"control_record_bytes"}, + "STAGING": {"byte_count", "object_count"}, + "QUARANTINE": {"byte_count", "object_count"}, + "COMMITTED": {"byte_count", "object_count"}, + "MATERIALIZATION": {"byte_count", "object_count"}, + "STREAM": {"stream_count"}, + "INODE": {"inode_count"}, +} + + +def _validate_quota_claim_array(claims: list[dict[str, Any]], label: str) -> None: + classes = [claim["quota_class"] for claim in claims] + if len(set(classes)) != len(classes): + _fail(f"Artifact Storage {label} has duplicate quota classes") + if classes != sorted(classes): + _fail(f"Artifact Storage {label} is not quota-class sorted") + for claim in claims: + allowed = _QUOTA_CLASS_ALLOWED_FIELDS[claim["quota_class"]] + if not any(claim[field] for field in allowed): + _fail(f"Artifact Storage {label} has an empty quota claim") + if any(claim[field] for field in set(_QUOTA_CLAIM_FIELDS) - allowed): + _fail(f"Artifact Storage {label} has an illegal quota dimension") + + +def _identity_sort_key(value: str | tuple[str, str]) -> bytes | tuple[bytes, bytes]: + if isinstance(value, tuple): + return value[0].encode("ascii"), value[1].encode("ascii") + return value.encode("ascii") + + +def validate_artifact_storage_state_v1(state: dict[str, Any]) -> None: + """Validate a Storage State's local identity projection, never its replay.""" + validate_instance("artifact-storage-state-1.0.json", state) + _check_nfc_and_numbers(state) + if state["state_sigil"] != content_sigil(_without(state, "state_sigil")): + _fail("Artifact Storage State self-Sigil mismatch") + for collection in _STATE_IDENTITY_COLLECTIONS: + identities = [_state_identity(value, collection) for value in state[collection]] + if len(set(identities)) != len(identities): + _fail(f"Artifact Storage State {collection} identities must be unique") + if identities != sorted(identities, key=_identity_sort_key): + _fail(f"Artifact Storage State {collection} is not identity sorted") + recoveries = {recovery["recovery_id"]: recovery for recovery in state["recoveries"]} + for recovery in recoveries.values(): + if recovery["epoch_ids"] != sorted(recovery["epoch_ids"]): + _fail("Artifact Storage State Recovery epochs are not strictly increasing") + if recovery["state"] == "COMPLETED" and recovery["resume_status"] != recovery["origin_status"]: + _fail("Artifact Storage State completed Recovery resume status disagrees with origin") + active_recoveries = [ + recovery for recovery in recoveries.values() if recovery["state"] == "ACTIVE" + ] + active_recovery = recoveries.get(state["active_recovery_id"]) + if state["store_status"] == "RECOVERING" and ( + active_recovery is None + or active_recovery["state"] != "ACTIVE" + or len(active_recoveries) != 1 + or active_recovery["origin_status"] != state["recovery_origin_status"] + or active_recovery["epoch_ids"][-1] != state["current_epoch"] + ): + _fail("Artifact Storage State active Recovery disagrees with Store projection") + if state["store_status"] != "RECOVERING" and any( + active_recoveries + ): + _fail("Artifact Storage State nonrecovering Store retains an active Recovery") + for collection, schema_name in _STATE_WRAPPER_SCHEMAS.items(): + for wrapper in state[collection]: + record = wrapper["record"] + validate_instance(schema_name, record) + if record["record_sigil"] != content_sigil(_without(record, "record_sigil")): + _fail(f"Artifact Storage State {collection} record self-Sigil mismatch") + if collection == "replicas" and ( + record["object"]["blob_sigil"] != record["blob_sigil"] + or record["object"]["size_bytes"] != record["size_bytes"] + or record["backend"]["backend_id"] != record["object"]["backend_id"] + ): + _fail("Artifact Storage State Replica object disagrees with record") + for quarantine in state["quarantines"]: + if quarantine["record_sigil"] != content_sigil(_without(quarantine, "record_sigil")): + _fail("Artifact Storage State Quarantine record self-Sigil mismatch") + for protection in state["legacy_v1_protections"]: + if protection["state"] != "PROTECTED": + continue + record = protection["record"] + validate_artifact_storage_legacy_protection_v1(record) + if ( + record["protection_id"] != protection["protection_id"] + or record["artifact_id"] != protection["artifact_id"] + or record["artifact_receipt_sigil"] != protection["receipt_sigil"] + ): + _fail("Artifact Storage State Legacy Protection disagrees with its record") + for hold in state["holds"]: + released = hold["state"] == "RELEASED" + if released != (hold["release_authorization_sigil"] is not None): + _fail("Artifact Storage State Hold release authorization disagrees with state") + replicas = { + wrapper["record"]["replica_id"]: wrapper["record"] for wrapper in state["replicas"] + } + replica_ids_by_blob: dict[str, list[str]] = {} + for replica in replicas.values(): + replica_ids_by_blob.setdefault(replica["blob_sigil"], []).append(replica["replica_id"]) + blob_sigils = {wrapper["record"]["blob_sigil"] for wrapper in state["blobs"]} + if any(blob_sigil not in blob_sigils for blob_sigil in replica_ids_by_blob): + _fail("Artifact Storage State Replica has no matching Blob projection") + for wrapper in state["blobs"]: + blob = wrapper["record"] + expected_known = sorted(replica_ids_by_blob.get(blob["blob_sigil"], [])) + if blob["known_replica_ids"] != expected_known: + _fail("Artifact Storage Blob known Replicas disagree with State Replica projections") + if not set(blob["eligible_replica_ids"]).issubset(expected_known): + _fail("Artifact Storage Blob eligible Replicas are not known Replica projections") + for wrapper in state["transfer_attempts"]: + attempt = wrapper["record"] + if attempt["state"] != "COMMITTED": + continue + selected = replicas.get(attempt["selected_replica_id"]) + if selected is None: + _fail("Artifact Storage committed Transfer Attempt lacks its selected Replica") + computed = attempt["commit_intent"]["computed_blob"] + if ( + attempt["computed_blob_sigil"] != computed["blob_sigil"] + or attempt["computed_size_bytes"] != computed["size_bytes"] + or selected["blob_sigil"] != computed["blob_sigil"] + or selected["size_bytes"] != computed["size_bytes"] + or selected["object"] != attempt["commit_intent"]["target_object"] + or selected["state"] != "AVAILABLE" + ): + _fail("Artifact Storage committed Transfer Attempt disagrees with selected Replica") + for wrapper in state["materializations"]: + materialization = wrapper["record"] + source = replicas.get(materialization["source_replica_id"]) + if source is None: + _fail("Artifact Storage Materialization lacks its source Replica") + if source["blob_sigil"] != materialization["source_blob_sigil"]: + _fail("Artifact Storage Materialization source Replica disagrees with Blob") + request_ids = {request["transfer_id"] for request in state["transfer_requests"]} + attempt_ids_by_transfer: dict[str, set[str]] = {} + for wrapper in state["transfer_attempts"]: + attempt = wrapper["record"] + if attempt["transfer_id"] not in request_ids: + _fail("Artifact Storage State Transfer Attempt lacks its request projection") + attempt_ids_by_transfer.setdefault(attempt["transfer_id"], set()).add( + attempt["transfer_attempt_id"] + ) + for request in state["transfer_requests"]: + attempt_ids = set(request["attempt_ids"]) + if attempt_ids != attempt_ids_by_transfer.get(request["transfer_id"], set()): + _fail("Artifact Storage State Transfer Request Attempts disagree with projections") + selected = request["selected_attempt_id"] + if selected is not None and selected not in attempt_ids: + _fail("Artifact Storage State Transfer Request selects an unknown Attempt") + for intent in state["open_intents"]: + source_sigil = intent["source_event"]["event_sigil"] + if ( + intent["source_event"]["journal_id"] != state["journal_id"] + or intent["source_event"]["sequence"] > state["applied_event_count"] + or intent["intent_sigil"] != source_sigil + or intent["last_event_sigil"] != source_sigil + ): + _fail("Artifact Storage State Open Intent disagrees with source Event") + open_intent_ids = [value["intent_id"] for value in state["open_intents"]] + if len(set(open_intent_ids)) != len(open_intent_ids): + _fail("Artifact Storage State open-intent IDs must be globally unique") + quarantine_intents = { + intent["intent_id"]: intent for intent in state["open_intents"] + if intent["intent_kind"] == "QUARANTINE_MOVE" + } + for quarantine in state["quarantines"]: + intent = quarantine_intents.pop(quarantine["quarantine_id"], None) + intent_recorded = quarantine["state"] == "INTENT_RECORDED" + if (intent_recorded != (intent is not None)): + _fail("Artifact Storage State Quarantine move Intent disagrees with projection") + if intent is not None and ( + intent["owner_id"] != quarantine["owner_id"] + or intent["source_object"] != quarantine["source_object"] + or intent["target_object"] != quarantine["destination_object"] + ): + _fail("Artifact Storage State Quarantine move Intent disagrees with projection") + if quarantine_intents: + _fail("Artifact Storage State Quarantine move Intent lacks a projection") + intents_by_owner: dict[tuple[str, str], list[dict[str, Any]]] = {} + for intent in state["open_intents"]: + intents_by_owner.setdefault((intent["intent_kind"], intent["owner_id"]), []).append(intent) + for collection, intent_kind, id_member, staging_member in ( + ("transfer_attempts", "TRANSFER_COMMIT", "transfer_attempt_id", "staging_object"), + ("materializations", "MATERIALIZATION_COMMIT", "materialization_id", "destination_staging_object"), + ): + for wrapper in state[collection]: + record = wrapper["record"] + intents = intents_by_owner.get((intent_kind, record[id_member]), []) + committing = record["state"] == "COMMITTING" + if (committing and len(intents) != 1) or (not committing and intents): + _fail(f"Artifact Storage State {collection} commit Intent disagrees with record state") + if not committing: + continue + intent = intents[0] + commit_intent = record["commit_intent"] + if commit_intent is None: + _fail(f"Artifact Storage State {collection} committing record lacks a commit Intent") + if ( + intent["intent_id"] != commit_intent["intent_id"] + or intent["staging_object"] != record[staging_member] + or intent["staging_object"] != commit_intent["staging_object"] + or intent["target_object"] != commit_intent["target_object"] + ): + _fail(f"Artifact Storage State {collection} commit Intent disagrees with record") + disposition_intents_by_owner: dict[str, list[dict[str, Any]]] = {} + for intent in state["open_intents"]: + if intent["intent_kind"] == "DISPOSITION": + disposition_intents_by_owner.setdefault(intent["owner_id"], []).append(intent) + for disposition in state["dispositions"]: + intents = disposition_intents_by_owner.pop(disposition["disposition_id"], []) + executing = disposition["state"] == "EXECUTING" + if ( + (executing and ( + len(intents) != 1 or intents[0]["intent_id"] != disposition["execution_intent_id"] + )) + or (not executing and intents) + ): + _fail("Artifact Storage State Disposition execution Intent disagrees with projection") + if disposition_intents_by_owner: + _fail("Artifact Storage State Disposition execution Intent lacks a projection") + gc_intents = [intent for intent in state["open_intents"] if intent["intent_kind"] == "GC_DELETE"] + gc_intent_keys: set[tuple[str, str]] = set() + for plan in state["gc_plans"]: + for target in plan["target_states"]: + intents = [ + intent for intent in gc_intents + if intent["intent_id"] == target["deletion_intent_id"] + ] + deleting = target["state"] == "DELETING" + if ( + (deleting and ( + len(intents) != 1 + or intents[0]["owner_id"] != plan["gc_plan_id"] + or intents[0]["target_id"] != target["target_id"] + )) + or (not deleting and intents) + ): + _fail("Artifact Storage State GC deletion Intent disagrees with projection") + if deleting: + gc_intent_keys.add((plan["gc_plan_id"], target["deletion_intent_id"])) + if gc_intent_keys != {(intent["owner_id"], intent["intent_id"]) for intent in gc_intents}: + _fail("Artifact Storage State GC deletion Intent lacks a target projection") + canonical_intents = { + intent["intent_id"]: intent for intent in state["open_intents"] + if intent["intent_kind"] == "CANONICAL_REFERENCE" + } + for projection in state["canonical_reference_intents"]: + intent = canonical_intents.pop(projection["reference_intent_id"], None) + if ( + (projection["state"] == "OPEN") != (intent is not None) + or (intent is not None and intent["owner_id"] != projection["reference_intent_id"]) + ): + _fail("Artifact Storage State canonical-reference Intent disagrees with projection") + if canonical_intents: + _fail("Artifact Storage State canonical-reference Intent lacks a projection") + availability_counts = { + "AVAILABLE": 0, "DEGRADED": 0, "UNAVAILABLE": 0, "INCIDENT": 0, + } + for wrapper in state["blobs"]: + availability_counts[wrapper["record"]["availability"]] += 1 + expected_availability_counters = { + "available_blobs": availability_counts["AVAILABLE"], + "degraded_blobs": availability_counts["DEGRADED"], + "unavailable_blobs": availability_counts["UNAVAILABLE"], + "incident_blobs": availability_counts["INCIDENT"], + } + if state["availability_counters"] != expected_availability_counters: + _fail("Artifact Storage State availability counters disagree with Blob records") + for counter in state["quota_counters"]: + if counter["used"] + counter["reserved"] > counter["limit"]: + _fail("Artifact Storage quota counter exceeds its limit") + for reservation in state["quota_reservations"]: + for field in ("consumed_claims", "released_claims", "remaining_claims"): + _validate_quota_claim_array(reservation[field], f"Quota Reservation {field}") + _validate_quota_claim_array(reservation["reservation"]["claims"], "Reservation claims") + claimed_by_class = { + claim["quota_class"]: claim for claim in reservation["reservation"]["claims"] + } + for field in ("consumed_claims", "released_claims", "remaining_claims"): + for claim in reservation[field]: + original = claimed_by_class.get(claim["quota_class"]) + if original is None or any( + claim[dimension] > original[dimension] + for dimension in _QUOTA_CLAIM_FIELDS + ): + _fail("Artifact Storage Quota Reservation exceeds its original claim") + partition_by_class = { + field: {claim["quota_class"]: claim for claim in reservation[field]} + for field in ("consumed_claims", "released_claims", "remaining_claims") + } + for quota_class, original in claimed_by_class.items(): + if any( + sum( + partition_by_class[field].get(quota_class, {}).get(dimension, 0) + for field in ("consumed_claims", "released_claims", "remaining_claims") + ) != original[dimension] + for dimension in _QUOTA_CLAIM_FIELDS + ): + _fail("Artifact Storage Quota Reservation claims do not partition original claim") + reservation_state = reservation["state"] + if reservation_state == "ACTIVE" and ( + reservation["consumed_claims"] + or reservation["released_claims"] + or reservation["remaining_claims"] != reservation["reservation"]["claims"] + or reservation["retained_for_event_types"] + ): + _fail("Artifact Storage active Quota Reservation is not unspent") + if reservation_state == "RETAINED" and ( + not reservation["remaining_claims"] or not reservation["retained_for_event_types"] + ): + _fail("Artifact Storage retained Quota Reservation lacks remaining claims or events") + if reservation_state == "SETTLED" and ( + reservation["remaining_claims"] or reservation["retained_for_event_types"] + ): + _fail("Artifact Storage settled Quota Reservation retains claims or events") + + +def load_artifact_storage_state_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + state = _load_strict_object(raw, "Artifact Storage State") + validate_artifact_storage_state_v1(state) + return state + + +def validate_artifact_storage_head_supplied_state_v1( + head: dict[str, Any], state: dict[str, Any], +) -> None: + """Compare a Head with a caller-supplied State projection exactly.""" + validate_artifact_storage_journal_head_v1(head) + validate_artifact_storage_state_v1(state) + if ( + head["journal_id"] != state["journal_id"] + or head["storage_format_version"] != state["storage_format_version"] + or head["event_count"] != state["applied_event_count"] + or head["last_sequence"] != state["applied_event_count"] + or head["last_event_sigil"] != state["last_event_sigil"] + or head["current_epoch"] != state["current_epoch"] + or head["state_sigil"] != state["state_sigil"] + ): + _fail("Artifact Storage Journal Head contradicts supplied State") + + +def require_artifact_storage_journal_replay_authority_v1() -> NoReturn: + """Fail closed: this module does not replay or repair a Storage Journal.""" + _fail("Artifact Storage Journal replay authority is unavailable in contract-only scope") + + +def require_artifact_storage_runtime_authority_v1() -> NoReturn: + """Fail closed: local Storage wire validation authorizes no operation.""" + _fail("Artifact Storage runtime authority is unavailable in contract-only scope") diff --git a/src/benchwork/execution.py b/src/benchwork/execution.py index a1607d0..018301e 100644 --- a/src/benchwork/execution.py +++ b/src/benchwork/execution.py @@ -29,7 +29,20 @@ SIGIL = re.compile(r"^sha256:[0-9a-f]{64}$") JOB_ID = re.compile(r"^JB-[A-F0-9]{64}$") SPECIFICATION_ID = re.compile(r"^ES-[A-Z0-9][A-Z0-9._-]*$") +LOCAL_EXECUTION_EVENT_ID = re.compile(r"^JE-[0-9A-F]{16}-[0-9A-F]{16}$") +LOCAL_EXECUTION_TIMESTAMP = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$") MAX_PAGE_SIZE = 256 +LOCAL_EXECUTION_JOURNAL_ID = "EJ-LOCAL-V1" +LOCAL_EXECUTION_EVENT_TYPES = frozenset( + { + "executor.epoch-started", + "job.submitted", + "job.queued", + "job.cancellation_requested", + "job.cancellation_observed", + "job.terminal", + } +) TERMINAL_STATES = frozenset( { "SUCCEEDED", @@ -45,10 +58,60 @@ ) +def _reject_duplicate_json_keys(pairs: list[tuple[str, Any]]) -> dict[str, Any]: + value: dict[str, Any] = {} + for key, member in pairs: + if key in value: + raise AthanorError(f"duplicate JSON key: {key}") + value[key] = member + return value + + +def _reject_nonfinite_json_number(token: str) -> None: + raise AthanorError(f"non-finite JSON number is forbidden: {token}") + + +def _validate_local_json_numbers(value: Any) -> None: + if isinstance(value, float): + raise AthanorError("local JSON float is forbidden") + if isinstance(value, dict): + for member in value.values(): + _validate_local_json_numbers(member) + elif isinstance(value, list): + for member in value: + _validate_local_json_numbers(member) + + +def _load_strict_local_json_object(raw: str, label: str) -> dict[str, Any]: + try: + value = json.loads( + raw, + object_pairs_hook=_reject_duplicate_json_keys, + parse_constant=_reject_nonfinite_json_number, + ) + except json.JSONDecodeError as error: + raise AthanorError(f"{label} contains invalid JSON") from error + if not isinstance(value, dict): + raise AthanorError(f"{label} must be an object") + _validate_local_json_numbers(value) + return value + + def _utc_now() -> str: return datetime.now(UTC).replace(microsecond=0).isoformat().replace("+00:00", "Z") +def _fsync_directory(path: Path) -> None: + try: + descriptor = os.open(path, os.O_RDONLY) + try: + os.fsync(descriptor) + finally: + os.close(descriptor) + except OSError as error: + raise AthanorError("managed storage directory sync failed") from error + + def _atomic_json(path: Path, value: dict[str, Any]) -> None: path.parent.mkdir(parents=True, exist_ok=True) descriptor, temporary_name = tempfile.mkstemp( @@ -64,6 +127,7 @@ def _atomic_json(path: Path, value: dict[str, Any]) -> None: handle.flush() os.fsync(handle.fileno()) os.replace(temporary, path) + _fsync_directory(path.parent) finally: temporary.unlink(missing_ok=True) @@ -82,10 +146,19 @@ def _atomic_bytes(path: Path, value: bytes) -> None: handle.flush() os.fsync(handle.fileno()) os.replace(temporary, path) + _fsync_directory(path.parent) finally: temporary.unlink(missing_ok=True) +def _is_unsafe_managed_directory(path: Path) -> bool: + return path.is_symlink() or (path.exists() and not path.is_dir()) + + +def _is_unsafe_managed_file(path: Path) -> bool: + return path.is_symlink() or (path.exists() and not path.is_file()) + + class LocalBlobStore: """The built-in Phase 3 content-addressed backend. @@ -99,9 +172,22 @@ def __init__(self, root: Path) -> None: self._lock_path = self.path / "locks" / "storage.lock" def initialize(self) -> None: + if _is_unsafe_managed_directory(self.path): + raise AthanorError("managed storage path is not a directory") + locks_path = self.path / "locks" + if _is_unsafe_managed_directory(locks_path): + raise AthanorError("managed storage lock path is not a directory") with _exclusive_lock(self._lock_path): + if _is_unsafe_managed_directory(self.path): + raise AthanorError("managed storage path is not a directory") for name in ("records", "blobs", "staging", "quarantine", "locks", "recovery"): - (self.path / name).mkdir(parents=True, exist_ok=True) + directory = self.path / name + if _is_unsafe_managed_directory(directory): + raise AthanorError(f"managed storage path is not a directory: {name}") + try: + directory.mkdir(parents=True, exist_ok=True) + except OSError as error: + raise AthanorError(f"managed storage directory is unavailable: {name}") from error format_path = self.path / "format.json" expected = { "schema_version": "benchwork-local-artifact-storage-format/0.1", @@ -109,9 +195,13 @@ def initialize(self) -> None: "layout": "BENCHWORK_LOCAL_STORAGE_V1", } if format_path.exists(): + if _is_unsafe_managed_file(format_path): + raise AthanorError("managed storage format is invalid") try: - actual = json.loads(format_path.read_text(encoding="utf-8")) - except json.JSONDecodeError as error: + actual = _load_strict_local_json_object( + format_path.read_text(encoding="utf-8"), "managed storage format", + ) + except (OSError, UnicodeDecodeError) as error: raise AthanorError("managed storage format is invalid") from error if actual != expected: raise AthanorError("managed storage format is incompatible") @@ -127,6 +217,32 @@ def _blob_path(self, sigil: str) -> Path: raise AthanorError("Blob Sigil must be canonical sha256") return self.path / "blobs" / sigil.removeprefix("sha256:") + def _record_path(self, sigil: str) -> Path: + self._blob_path(sigil) + return self.path / "records" / f"blob-{sigil.removeprefix('sha256:')}.json" + + @staticmethod + def _validate_record(record: Any, sigil: str, size_bytes: int) -> None: + if not isinstance(record, dict) or set(record) != { + "schema_version", "blob_sigil", "size_bytes", "media_type", + "backend_id", "availability", "record_sigil", + }: + raise AthanorError("Blob record is invalid") + if ( + record["schema_version"] != "benchwork-local-artifact-blob/0.1" + or record["blob_sigil"] != sigil + or record["size_bytes"] != size_bytes + or not isinstance(record["media_type"], str) + or not record["media_type"] + or len(record["media_type"]) > 128 + or record["backend_id"] != "BE-LOCAL-V1" + or record["availability"] != "AVAILABLE" + or record["record_sigil"] != content_sigil( + {key: value for key, value in record.items() if key != "record_sigil"} + ) + ): + raise AthanorError("Blob record conflict or integrity failure") + def import_bytes(self, value: bytes, *, media_type: str = "application/octet-stream") -> dict[str, Any]: """Commit one immutable Blob, deduplicating only after independent readback.""" if not isinstance(value, bytes): @@ -138,6 +254,8 @@ def import_bytes(self, value: bytes, *, media_type: str = "application/octet-str blob_path = self._blob_path(sigil) with _exclusive_lock(self._lock_path): if blob_path.exists(): + if _is_unsafe_managed_file(blob_path): + raise AthanorError("Blob collision or storage integrity failure") existing = blob_path.read_bytes() if self._sigil_for_bytes(existing) != sigil or len(existing) != len(value): raise AthanorError("Blob collision or storage integrity failure") @@ -156,11 +274,20 @@ def import_bytes(self, value: bytes, *, media_type: str = "application/octet-str "availability": "AVAILABLE", } record["record_sigil"] = content_sigil(record) - record_path = self.path / "records" / f"blob-{sigil.removeprefix('sha256:')}.json" + record_path = self._record_path(sigil) if record_path.exists(): - prior = json.loads(record_path.read_text(encoding="utf-8")) - if prior["blob_sigil"] != sigil or prior["size_bytes"] != len(value): - raise AthanorError("Blob record conflict") + if _is_unsafe_managed_file(record_path): + raise AthanorError("Blob record is invalid") + try: + prior = _load_strict_local_json_object( + record_path.read_text(encoding="utf-8"), "Blob record", + ) + except (OSError, UnicodeDecodeError) as error: + raise AthanorError("Blob record is invalid") from error + self._validate_record(prior, sigil, len(value)) + if prior != record: + raise AthanorError("Blob record conflict or integrity failure") + return prior else: _atomic_json(record_path, record) return record @@ -168,12 +295,24 @@ def import_bytes(self, value: bytes, *, media_type: str = "application/octet-str def read_bytes(self, sigil: str) -> bytes: self.initialize() blob_path = self._blob_path(sigil) + if _is_unsafe_managed_file(blob_path): + raise AthanorError(f"Blob is unavailable: {sigil}") try: value = blob_path.read_bytes() except OSError as error: raise AthanorError(f"Blob is unavailable: {sigil}") from error if self._sigil_for_bytes(value) != sigil: raise AthanorError(f"Blob integrity failure: {sigil}") + record_path = self._record_path(sigil) + if _is_unsafe_managed_file(record_path): + raise AthanorError(f"Blob record is unavailable or invalid: {sigil}") + try: + record = _load_strict_local_json_object( + record_path.read_text(encoding="utf-8"), "Blob record", + ) + except (OSError, UnicodeDecodeError) as error: + raise AthanorError(f"Blob record is unavailable or invalid: {sigil}") from error + self._validate_record(record, sigil, len(value)) return value @@ -194,11 +333,30 @@ def __init__(self, root: Path) -> None: self._lock_path = self.path / "locks" / "execution.lock" def initialize(self) -> None: + if _is_unsafe_managed_directory(self.path): + raise AthanorError("execution storage path is not a directory") + locks_path = self.path / "locks" + if _is_unsafe_managed_directory(locks_path): + raise AthanorError("execution lock path is not a directory") with _exclusive_lock(self._lock_path): - self.path.mkdir(parents=True, exist_ok=True) - (self.path / "locks").mkdir(parents=True, exist_ok=True) + if _is_unsafe_managed_directory(self.path): + raise AthanorError("execution storage path is not a directory") + try: + self.path.mkdir(parents=True, exist_ok=True) + except OSError as error: + raise AthanorError("execution storage directory is unavailable") from error + locks_path = self.path / "locks" + if _is_unsafe_managed_directory(locks_path): + raise AthanorError("execution lock path is not a directory") + try: + locks_path.mkdir(parents=True, exist_ok=True) + except OSError as error: + raise AthanorError("execution lock directory is unavailable") from error if not self._journal_path.exists(): - self._journal_path.touch() + try: + self._journal_path.touch() + except OSError as error: + raise AthanorError("execution journal is unavailable") from error events = self._events_unlocked() if not events: instance_id = f"XI-{uuid4().hex.upper()}" @@ -219,12 +377,26 @@ def initialize(self) -> None: def _events_unlocked(self) -> list[dict[str, Any]]: if not self._journal_path.exists(): return [] + if _is_unsafe_managed_file(self._journal_path): + raise AthanorError("execution journal is unreadable") events: list[dict[str, Any]] = [] previous: str | None = None - for line_number, line in enumerate(self._journal_path.read_text(encoding="utf-8").splitlines(), 1): + previous_recorded_at: datetime | None = None + event_ids: set[str] = set() + try: + journal_bytes = self._journal_path.read_bytes() + journal_text = journal_bytes.decode("utf-8", errors="strict") + except (OSError, UnicodeDecodeError) as error: + raise AthanorError("execution journal is unreadable") from error + if journal_text and not journal_text.endswith("\n"): + raise AthanorError("execution journal has an incomplete tail") + lines = journal_text.splitlines() + for line_number, line in enumerate(lines, 1): try: - event = json.loads(line) - except json.JSONDecodeError as error: + event = _load_strict_local_json_object( + line, f"execution journal Event at line {line_number}", + ) + except UnicodeDecodeError as error: raise AthanorError(f"execution journal contains invalid JSON at line {line_number}") from error if not isinstance(event, dict) or set(event) != { "schema_version", @@ -240,13 +412,51 @@ def _events_unlocked(self) -> list[dict[str, Any]]: raise AthanorError("execution journal Event shape is invalid") if event["schema_version"] != "benchwork-local-execution-journal-event/0.1": raise AthanorError("execution journal Event version is invalid") + if event["journal_id"] != LOCAL_EXECUTION_JOURNAL_ID: + raise AthanorError("execution journal identity is invalid") + if event["event_type"] not in LOCAL_EXECUTION_EVENT_TYPES: + raise AthanorError("execution journal Event type is invalid") + if ( + not isinstance(event["event_id"], str) + or not LOCAL_EXECUTION_EVENT_ID.fullmatch(event["event_id"]) + or not isinstance(event["sequence"], int) + or isinstance(event["sequence"], bool) + or not isinstance(event["recorded_at"], str) + or not isinstance(event["payload"], dict) + or not isinstance(event["event_sigil"], str) + or not SIGIL.fullmatch(event["event_sigil"]) + ): + raise AthanorError("execution journal Event scalar fields are invalid") + try: + recorded_at = datetime.fromisoformat(event["recorded_at"].replace("Z", "+00:00")) + except ValueError as error: + raise AthanorError("execution journal Event recorded_at is invalid") from error + if not LOCAL_EXECUTION_TIMESTAMP.fullmatch(event["recorded_at"]) or recorded_at.tzinfo != UTC: + raise AthanorError("execution journal Event recorded_at is invalid") + if previous_recorded_at is not None and recorded_at < previous_recorded_at: + raise AthanorError("execution journal Event time is decreasing") + if previous is None: + if event["previous_event_sigil"] is not None: + raise AthanorError("execution journal chain is broken") + elif not isinstance(event["previous_event_sigil"], str) or not SIGIL.fullmatch( + event["previous_event_sigil"] + ): + raise AthanorError("execution journal chain is broken") + if event["event_id"] in event_ids: + raise AthanorError("execution journal has a duplicate Event identity") if event["sequence"] != len(events) + 1 or event["previous_event_sigil"] != previous: raise AthanorError("execution journal chain is broken") + if not events and event["event_type"] != "executor.epoch-started": + raise AthanorError("execution journal has no executor epoch") + if events and event["event_type"] == "executor.epoch-started": + raise AthanorError("execution journal has a duplicate executor epoch") expected = content_sigil({key: value for key, value in event.items() if key != "event_sigil"}) if event["event_sigil"] != expected: raise AthanorError("execution journal Event Sigil is invalid") events.append(event) + event_ids.add(event["event_id"]) previous = event["event_sigil"] + previous_recorded_at = recorded_at return events def _write_head_unlocked(self, events: list[dict[str, Any]]) -> None: @@ -254,7 +464,7 @@ def _write_head_unlocked(self, events: list[dict[str, Any]]) -> None: return head = { "schema_version": "benchwork-local-execution-journal-head/0.1", - "journal_id": "EJ-LOCAL-V1", + "journal_id": LOCAL_EXECUTION_JOURNAL_ID, "last_sequence": events[-1]["sequence"], "last_event_id": events[-1]["event_id"], "last_event_sigil": events[-1]["event_sigil"], @@ -265,19 +475,12 @@ def _write_head_unlocked(self, events: list[dict[str, Any]]) -> None: def _append_unlocked(self, event_type: str, payload: dict[str, Any]) -> dict[str, Any]: events = self._events_unlocked() - if event_type not in { - "executor.epoch-started", - "job.submitted", - "job.queued", - "job.cancellation_requested", - "job.cancellation_observed", - "job.terminal", - }: + if event_type not in LOCAL_EXECUTION_EVENT_TYPES: raise AthanorError(f"unsupported execution Event type: {event_type}") sequence = len(events) + 1 event = { "schema_version": "benchwork-local-execution-journal-event/0.1", - "journal_id": "EJ-LOCAL-V1", + "journal_id": LOCAL_EXECUTION_JOURNAL_ID, "event_id": f"JE-{sequence:016X}-{uuid4().hex[:16].upper()}", "sequence": sequence, "event_type": event_type, @@ -286,18 +489,24 @@ def _append_unlocked(self, event_type: str, payload: dict[str, Any]) -> dict[str "payload": payload, } event["event_sigil"] = content_sigil(event) + # Validate the complete candidate prefix before publishing any bytes. + # This remains a local pre-conformance projection, not RFC replay + # authority, but it prevents an internal caller from durably writing a + # transition that the same runtime can never recover. + self._project([*events, event]) with self._journal_path.open("a", encoding="utf-8") as handle: handle.write(canonical_json(event)) handle.write("\n") handle.flush() os.fsync(handle.fileno()) + _fsync_directory(self._journal_path.parent) self._write_head_unlocked([*events, event]) return event @staticmethod def _validate_specification(specification: dict[str, Any]) -> None: required = {"schema_version", "specification_id", "task_binding", "specification_sigil"} - if not isinstance(specification, dict) or not required.issubset(specification): + if not isinstance(specification, dict) or set(specification) != required: raise AthanorError("execution specification is incomplete") if specification["schema_version"] != "benchwork-local-execution-specification/0.1": raise AthanorError("execution specification version is invalid") @@ -338,32 +547,72 @@ def _job_id(specification: dict[str, Any], idempotency_key: str) -> tuple[str, s def _project(events: list[dict[str, Any]]) -> dict[str, Any]: if not events or events[0]["event_type"] != "executor.epoch-started": raise AthanorError("execution journal has no executor epoch") - executor = dict(events[0]["payload"]) + executor = events[0]["payload"] + if ( + set(executor) != { + "executor_instance_id", "executor_epoch", "executor_build_sigil" + } + or not isinstance(executor["executor_instance_id"], str) + or not executor["executor_instance_id"] + or not isinstance(executor["executor_epoch"], int) + or isinstance(executor["executor_epoch"], bool) + or executor["executor_epoch"] < 1 + or not isinstance(executor["executor_build_sigil"], str) + or not SIGIL.fullmatch(executor["executor_build_sigil"]) + ): + raise AthanorError("execution executor epoch payload is invalid") + executor = dict(executor) jobs: dict[str, dict[str, Any]] = {} starts: dict[tuple[str, str], tuple[str, str]] = {} - cancellations: dict[tuple[str, str], str] = {} + cancellations: dict[tuple[str, str], dict[str, Any]] = {} for event in events[1:]: payload = event["payload"] event_type = event["event_type"] if event_type == "job.submitted": - job_id = payload.get("job_id") - task_id = payload.get("task_id") - key_sigil = payload.get("idempotency_key_sigil") + if set(payload) != { + "job_id", "job_binding_sigil", "task_id", "specification", + "start_request_sigil", "idempotency_key_sigil", + }: + raise AthanorError("execution Job submission payload is invalid") + job_id = payload["job_id"] + task_id = payload["task_id"] + key_sigil = payload["idempotency_key_sigil"] if not isinstance(job_id, str) or not JOB_ID.fullmatch(job_id) or job_id in jobs: raise AthanorError("invalid or duplicate execution Job") - if not isinstance(task_id, str) or not isinstance(key_sigil, str): + if ( + not isinstance(task_id, str) + or not task_id + or not isinstance(key_sigil, str) + or not SIGIL.fullmatch(key_sigil) + or not isinstance(payload["start_request_sigil"], str) + or not SIGIL.fullmatch(payload["start_request_sigil"]) + or not isinstance(payload["job_binding_sigil"], str) + or not SIGIL.fullmatch(payload["job_binding_sigil"]) + ): raise AthanorError("execution Job idempotency binding is invalid") + specification = payload["specification"] + ExecutionService._validate_specification(specification) + if task_id != specification["task_binding"]["task_id"]: + raise AthanorError("execution Job submission Task binding is invalid") + expected_job_id = "JB-" + hashlib.sha256(canonical_json([ + "execution-job-id/1.0", task_id, key_sigil, + ]).encode("utf-8")).hexdigest().upper() + expected_binding = content_sigil([ + "execution-job-binding/1.0", job_id, + specification["specification_sigil"], payload["start_request_sigil"], + ]) + if job_id != expected_job_id or payload["job_binding_sigil"] != expected_binding: + raise AthanorError("execution Job submission binding is invalid") scope = (task_id, key_sigil) - request_sigil = payload.get("start_request_sigil") + request_sigil = payload["start_request_sigil"] if scope in starts: raise AthanorError("duplicate execution Job idempotency binding") starts[scope] = (job_id, request_sigil) jobs[job_id] = { - "job_id": job_id, - "job_binding_sigil": payload["job_binding_sigil"], + "job_id": job_id, "job_binding_sigil": payload["job_binding_sigil"], "task_id": task_id, - "specification_id": payload["specification"]["specification_id"], - "specification_sigil": payload["specification"]["specification_sigil"], + "specification_id": specification["specification_id"], + "specification_sigil": specification["specification_sigil"], "state": "SUBMITTED", "revision": 1, "submitted_event_id": event["event_id"], @@ -374,37 +623,95 @@ def _project(events: list[dict[str, Any]]) -> dict[str, Any]: "idempotency_key_sigil": key_sigil, } elif event_type == "job.queued": - job = jobs.get(payload.get("job_id")) + if set(payload) != {"job_id"}: + raise AthanorError("execution Job queue payload is invalid") + if not isinstance(payload["job_id"], str): + raise AthanorError("execution Job queue payload is invalid") + job = jobs.get(payload["job_id"]) if job is None or job["state"] != "SUBMITTED": raise AthanorError("invalid execution Job queue transition") job["state"] = "QUEUED" job["revision"] += 1 elif event_type == "job.cancellation_requested": - job = jobs.get(payload.get("job_id")) - key = payload.get("idempotency_key_sigil") - if job is None or not isinstance(key, str): + if set(payload) != { + "job_id", "job_binding_sigil", "expected_job_revision", + "idempotency_key_sigil", "reason", + }: + raise AthanorError("execution Job cancellation payload is invalid") + if ( + not isinstance(payload["job_id"], str) + or not isinstance(payload["expected_job_revision"], int) + or isinstance(payload["expected_job_revision"], bool) + or payload["expected_job_revision"] < 1 + ): + raise AthanorError("execution Job cancellation payload is invalid") + job = jobs.get(payload["job_id"]) + key = payload["idempotency_key_sigil"] + if ( + job is None + or not isinstance(key, str) + or not SIGIL.fullmatch(key) + or payload["job_binding_sigil"] != job["job_binding_sigil"] + or payload["expected_job_revision"] != job["revision"] + or not isinstance(payload["reason"], str) + or not payload["reason"] + or len(payload["reason"]) > 4096 + ): raise AthanorError("invalid execution Job cancellation") scope = (job["job_id"], key) if scope in cancellations: raise AthanorError("duplicate execution cancellation binding") - cancellations[scope] = event["event_sigil"] + cancellations[scope] = dict(payload) if job["state"] in TERMINAL_STATES: raise AthanorError("terminal Job cannot receive cancellation request") job["state"] = "CANCEL_REQUESTED" job["revision"] += 1 elif event_type == "job.cancellation_observed": - job = jobs.get(payload.get("job_id")) - key = payload.get("idempotency_key_sigil") - if job is None or job["state"] not in TERMINAL_STATES or not isinstance(key, str): + if set(payload) != { + "job_id", "job_binding_sigil", "expected_job_revision", + "idempotency_key_sigil", "reason", + }: + raise AthanorError("execution terminal cancellation payload is invalid") + if ( + not isinstance(payload["job_id"], str) + or not isinstance(payload["expected_job_revision"], int) + or isinstance(payload["expected_job_revision"], bool) + or payload["expected_job_revision"] < 1 + ): + raise AthanorError("execution terminal cancellation payload is invalid") + job = jobs.get(payload["job_id"]) + key = payload["idempotency_key_sigil"] + if ( + job is None + or job["state"] not in TERMINAL_STATES + or not isinstance(key, str) + or not SIGIL.fullmatch(key) + or payload["job_binding_sigil"] != job["job_binding_sigil"] + or payload["expected_job_revision"] != job["revision"] + or not isinstance(payload["reason"], str) + or not payload["reason"] + or len(payload["reason"]) > 4096 + ): raise AthanorError("invalid terminal cancellation observation") scope = (job["job_id"], key) if scope in cancellations: raise AthanorError("duplicate execution cancellation binding") - cancellations[scope] = event["event_sigil"] + cancellations[scope] = dict(payload) elif event_type == "job.terminal": - job = jobs.get(payload.get("job_id")) - state = payload.get("state") - if job is None or job["state"] in TERMINAL_STATES or state not in TERMINAL_STATES: + if set(payload) != {"job_id", "state", "reason"}: + raise AthanorError("execution Job terminal payload is invalid") + if not isinstance(payload["job_id"], str) or not isinstance(payload["state"], str): + raise AthanorError("execution Job terminal payload is invalid") + job = jobs.get(payload["job_id"]) + state = payload["state"] + if ( + job is None + or job["state"] in TERMINAL_STATES + or state not in TERMINAL_STATES + or not isinstance(payload["reason"], str) + or not payload["reason"] + or len(payload["reason"]) > 4096 + ): raise AthanorError("invalid execution Job terminal transition") if job["state"] == "CANCEL_REQUESTED" and state != "CANCELLED": raise AthanorError("cancelled execution Job cannot accept a worker terminal result") @@ -472,7 +779,7 @@ def _observation_unlocked( job = state["jobs"].get(job_id) if job is None: raise AthanorError(f"unknown execution Job: {job_id}") - if not isinstance(limit, int) or not 1 <= limit <= MAX_PAGE_SIZE: + if not isinstance(limit, int) or isinstance(limit, bool) or not 1 <= limit <= MAX_PAGE_SIZE: raise AthanorError(f"observation limit must be in 1..{MAX_PAGE_SIZE}") through_sequence = events[-1]["sequence"] through_sigil = events[-1]["event_sigil"] @@ -494,6 +801,8 @@ def _observation_unlocked( if ( not isinstance(fixed_sequence, int) or not isinstance(last_returned, int) + or isinstance(fixed_sequence, bool) + or isinstance(last_returned, bool) or fixed_sequence < 1 or fixed_sequence > len(events) or last_returned < 0 @@ -543,6 +852,30 @@ def observe( events = self._existing_events() return self._observation_unlocked(events, job_id, limit, cursor) + def queue(self, job_id: str) -> dict[str, Any]: + """Durably make one submitted Job available to the local Worker. + + This is an internal scheduler boundary, not an MCP execution method. + Replaying the operation after a restart is idempotent only for the + already queued projection; terminal or cancellation states never gain + a late queue transition. + """ + if not isinstance(job_id, str) or not JOB_ID.fullmatch(job_id): + raise AthanorError("execution Job ID is invalid") + if not self._journal_path.exists(): + raise AthanorError(f"unknown execution Job: {job_id}") + with _exclusive_lock(self._lock_path): + events = self._events_unlocked() + job = self._project(events)["jobs"].get(job_id) + if job is None: + raise AthanorError(f"unknown execution Job: {job_id}") + if job["state"] == "QUEUED": + return self._observation_unlocked(events, job_id, MAX_PAGE_SIZE, None) + if job["state"] != "SUBMITTED": + raise AthanorError("execution Job is not queueable") + self._append_unlocked("job.queued", {"job_id": job_id}) + return self._observation_unlocked(self._events_unlocked(), job_id, MAX_PAGE_SIZE, None) + def cancel( self, job_id: str, @@ -555,11 +888,20 @@ def cancel( raise AthanorError("execution Job ID is invalid") if not isinstance(job_binding_sigil, str) or not SIGIL.fullmatch(job_binding_sigil): raise AthanorError("execution Job binding is invalid") - if not isinstance(expected_job_revision, int) or expected_job_revision < 1: + if ( + not isinstance(expected_job_revision, int) + or isinstance(expected_job_revision, bool) + or expected_job_revision < 1 + ): raise AthanorError("execution cancellation revision is invalid") if not isinstance(reason, str) or not reason or len(reason) > 4096: raise AthanorError("execution cancellation reason is invalid") - if not isinstance(idempotency_key, str) or not idempotency_key or len(idempotency_key) > 256: + if ( + not isinstance(idempotency_key, str) + or not idempotency_key + or len(idempotency_key) > 256 + or "\x00" in idempotency_key + ): raise AthanorError("execution cancellation idempotency key is invalid") key_sigil = content_sigil(["execution-cancel-idempotency-key/1.0", idempotency_key]) if not self._journal_path.exists(): @@ -570,7 +912,13 @@ def cancel( job = state["jobs"].get(job_id) if job is None or job["job_binding_sigil"] != job_binding_sigil: raise AthanorError("execution Job binding is invalid") - if (job_id, key_sigil) in state["cancellations"]: + prior_cancellation = state["cancellations"].get((job_id, key_sigil)) + if prior_cancellation is not None: + if ( + prior_cancellation["job_binding_sigil"] != job_binding_sigil + or prior_cancellation["reason"] != reason + ): + raise AthanorError("execution cancellation idempotency conflict") return self._observation_unlocked(events, job_id, MAX_PAGE_SIZE, None) if expected_job_revision != job["revision"]: raise AthanorError("execution cancellation revision conflict") @@ -595,7 +943,7 @@ def record_terminal(self, job_id: str, state: str, reason: str) -> dict[str, Any """Trusted local worker adapter hook; it cannot be reached from MCP.""" if state not in TERMINAL_STATES: raise AthanorError("execution terminal state is invalid") - if not isinstance(reason, str) or not reason: + if not isinstance(reason, str) or not reason or len(reason) > 4096: raise AthanorError("execution terminal reason is invalid") if not self._journal_path.exists(): raise AthanorError(f"unknown execution Job: {job_id}") @@ -606,6 +954,8 @@ def record_terminal(self, job_id: str, state: str, reason: str) -> dict[str, Any raise AthanorError("execution Job is not terminalizable") if job["state"] == "CANCEL_REQUESTED" and state != "CANCELLED": raise AthanorError("cancelled execution Job cannot accept a worker terminal result") + if job["state"] not in {"QUEUED", "CANCEL_REQUESTED"}: + raise AthanorError("execution Job must be queued before a worker terminal result") self._append_unlocked("job.terminal", {"job_id": job_id, "state": state, "reason": reason}) return self._observation_unlocked(self._events_unlocked(), job_id, MAX_PAGE_SIZE, None) diff --git a/src/benchwork/execution_contracts.py b/src/benchwork/execution_contracts.py new file mode 100644 index 0000000..a5ab346 --- /dev/null +++ b/src/benchwork/execution_contracts.py @@ -0,0 +1,6411 @@ +"""Pure, fail-closed validators for RFC-0012 State and Journal Event wires. + +These helpers validate closed bytes and deterministic projections only. They +do not append an Event, replay a Journal, acknowledge a request, or grant any +runtime, storage, Result, assurance, or scientific authority. +""" + +from __future__ import annotations + +import hashlib +import json +import math +import unicodedata +from copy import deepcopy +from datetime import datetime +from typing import Any, NoReturn + +from .athanor import AthanorError, canonical_json, content_sigil +from .schema_validation import validate_instance + + +EXECUTION_EVENT_TYPES_V1 = ( + "executor.epoch_started", + "executor.clock_uncertain", + "executor.clock_restored", + "execution.heartbeat_collision_authority_closed", + "recovery.started", + "recovery.action_set_rebased", + "recovery.phase_advanced", + "recovery.completed", + "worker.definition_registered", + "worker.enabled", + "worker.draining", + "worker.quarantined", + "worker.retired", + "worker_session.registered", + "worker_session.ready", + "worker_session.draining", + "worker_session.offline", + "worker_session.quarantined", + "worker_session.closed", + "worker_session.heartbeat_accepted", + "worker_session.message_rejected", + "job.submitted", + "job.queued", + "job.attempt_allocated", + "job.budget_settled", + "job.retry_scheduled", + "job.retry_ready", + "job.stop_latched", + "job.cancellation_observed", + "job.assurance_evaluated", + "job.succeeded", + "job.failed", + "job.cancelled", + "job.timed_out", + "job.policy_violated", + "storage_root.hold_release_observed", + "job.message_rejected", + "attempt.authorization_bound", + "attempt.preflight_started", + "attempt.preflight_progressed", + "attempt.preflight_passed", + "attempt.starting", + "attempt.running", + "attempt.output_staging_preallocated", + "attempt.result_ingress_received", + "attempt.result_accepted", + "attempt.result_rejected", + "attempt.draining", + "attempt.stop_latched", + "attempt.stop_progressed", + "attempt.cleaning", + "attempt.cleanup_progressed", + "attempt.succeeded", + "attempt.failed", + "attempt.cancelled", + "attempt.timed_out", + "attempt.policy_violated", + "attempt.lease_expired", + "attempt.lost", + "attempt.fenced", + "attempt.rejected", + "attempt.assurance_evaluated", + "lease.offered", + "lease.claimed", + "lease.heartbeat_accepted", + "lease.renewed", + "lease.released", + "lease.revoked", + "lease.expired", + "lease.fenced", + "lease.tombstone_republished", + "lease.message_rejected", + "log.chunk_committed", + "log.chunk_duplicate_observed", + "log.chunk_rejected", + "log.truncated", + "log.eof_accepted", + "log.eof_rejected", + "log.closed", + "log.closure_recovery_closed", + "log.intake_recovery_terminalized", +) + +IDEMPOTENCY_OPERATION_KINDS_V1 = ( + "START_JOB", + "CANCEL_JOB", + "REGISTER_WORKER_SESSION", + "CLAIM_LEASE", + "RENEW_LEASE", + "RELEASE_LEASE", + "PREALLOCATE_OUTPUT_STAGING", + "RECEIVE_RESULT_INGRESS", + "SUBMIT_RESULT", + "APPEND_LOG_CHUNK", + "CLOSE_LOG_STREAM", +) +_ENTITY_KIND_ORDER = ( + "EXECUTOR", + "RECOVERY", + "WORKER", + "WORKER_SESSION", + "JOB", + "ATTEMPT", + "LEASE", + "LOG_STREAM", +) +_ENTITY_KIND_RANK = {value: rank for rank, value in enumerate(_ENTITY_KIND_ORDER)} +_RECOVERY_ACTION_KIND_ORDER = ( + "COMMIT_DUE_EVENT", + "RESTORE_CLOCK", + "FENCE_LEASE", + "REPUBLISH_TOMBSTONE", + "OFFLINE_SESSION", + "TERMINATE_PROCESS_TREE", + "REVOKE_HANDLES", + "CLOSE_SESSION", + "CLOSE_LOG", + "VERIFY_OUTPUT_STORAGE", + "VERIFY_TERMINAL_SOURCE", + "BIND_DURABLE_ATTEMPT_AUTHORIZATION", + "RELEASE_INACTIVE_EXECUTION_INPUT_HOLD", + "RELEASE_DUE_EXECUTION_HOLD", + "QUARANTINE_RESOURCE", + "ADVANCE_ATTEMPT", + "CLEAN_RESOURCE", + "COLLECT_ACCOUNTING", + "SETTLE_BUDGET", + "EVALUATE_ATTEMPT_ASSURANCE", + "EVALUATE_JOB_ASSURANCE", + "ADVANCE_JOB", +) +_RECOVERY_ACTION_KIND_RANK = {value: rank for rank, value in enumerate(_RECOVERY_ACTION_KIND_ORDER)} +_RECOVERY_PHASE_KINDS = { + "STARTED": {"COMMIT_DUE_EVENT"}, + "FENCING": { + "FENCE_LEASE", + "REPUBLISH_TOMBSTONE", + "OFFLINE_SESSION", + "BIND_DURABLE_ATTEMPT_AUTHORIZATION", + "ADVANCE_ATTEMPT", + "ADVANCE_JOB", + }, + "RECONCILING": { + "TERMINATE_PROCESS_TREE", + "REVOKE_HANDLES", + "CLOSE_SESSION", + "CLOSE_LOG", + "VERIFY_OUTPUT_STORAGE", + "VERIFY_TERMINAL_SOURCE", + "QUARANTINE_RESOURCE", + "ADVANCE_ATTEMPT", + "CLEAN_RESOURCE", + "COLLECT_ACCOUNTING", + }, + "FINALIZING": { + "RESTORE_CLOCK", + "ADVANCE_ATTEMPT", + "SETTLE_BUDGET", + "EVALUATE_ATTEMPT_ASSURANCE", + "EVALUATE_JOB_ASSURANCE", + "ADVANCE_JOB", + "RELEASE_INACTIVE_EXECUTION_INPUT_HOLD", + "RELEASE_DUE_EXECUTION_HOLD", + }, +} +_RECOVERY_NEXT_PHASE = { + "STARTED": "FENCING", + "FENCING": "RECONCILING", + "RECONCILING": "FINALIZING", +} +_ATTEMPT_TERMINAL_EVENT_TYPES = { + "attempt.succeeded", + "attempt.failed", + "attempt.cancelled", + "attempt.timed_out", + "attempt.policy_violated", + "attempt.lease_expired", + "attempt.lost", + "attempt.fenced", + "attempt.rejected", +} +_CONTROL_DIMENSION_ORDER = ( + "IDENTITY_AUTHORIZATION", + "FILESYSTEM", + "NETWORK", + "PROCESS_EXECUTABLE", + "RESOURCE", + "ENVIRONMENT_CREDENTIAL", + "LOG_OUTPUT_CAPTURE", + "RUNTIME_INPUT_OUTPUT_IDENTITY", + "CANCELLATION_FENCING", + "TERMINATION_CLEANUP", +) +_CONTROL_PHASE_ORDER = ("PREFLIGHT", "RUNTIME", "TERMINATION", "CLEANUP") +_CONTROL_PHASE_RANK = {value: rank for rank, value in enumerate(_CONTROL_PHASE_ORDER)} +_CONTROL_EVIDENCE_KIND_ORDER = ( + "TASK_BINDING", + "CAPABILITY_BINDING", + "SNAPSHOT_BINDING", + "WARD_DECISION", + "APPROVAL_RECEIPT", + "BACKEND_CONFIGURATION", + "HOST_IDENTITY", + "POLICY_RESOLUTION", + "BASE_IDENTITY", + "INPUT_IDENTITY", + "MATERIALIZATION_IDENTITY", + "ENVIRONMENT_CONSTRUCTION", + "FILESYSTEM_POLICY", + "NETWORK_POLICY", + "EXECUTABLE_SELECTION", + "PROCESS_TREE", + "WALL_TIME_ENFORCEMENT", + "RESOURCE_ACCOUNTING", + "CREDENTIAL_NONINHERITANCE", + "LOG_CAPTURE", + "OUTPUT_VALIDATION", + "STORAGE_OBSERVATION", + "FENCE_TOMBSTONE", + "TERMINATION", + "HANDLE_REVOCATION", + "CLEANUP", + "QUARANTINE", + "TERMINAL_SOURCE_VERIFICATION", + "CONFORMANCE_FIXTURE", +) +_CONTROL_EVIDENCE_KIND_RANK = { + value: rank for rank, value in enumerate(_CONTROL_EVIDENCE_KIND_ORDER) +} +_AUTHORITY_GATE_ORDER = ("INTEGRITY_FAILURE", "CLOCK_UNCERTAIN", "RECOVERY_ACTIVE") +_AUTHORITY_GATE_RANK = {value: rank for rank, value in enumerate(_AUTHORITY_GATE_ORDER)} +_DEADLINE_PRIORITY = { + "JOB_DEADLINE": 10, + "ATTEMPT_DEADLINE": 20, + "HEARTBEAT_TIMEOUT": 30, + "LEASE_EXPIRY": 40, + "LEASE_CLAIM_DEADLINE": 50, + "CANCELLATION_GRACE": 60, + "RETRY_ELIGIBILITY": 70, +} +_EXECUTION_REQUEST_SCHEMAS_V1 = { + "start": "execution-start-request-1.0.json", + "observe": "execution-observe-request-1.0.json", + "cancel": "execution-cancel-request-1.0.json", + "get_result": "execution-get-result-request-1.0.json", + "accept_result": "execution-accept-result-request-1.0.json", +} +_IDEMPOTENCY_RANK = {value: rank for rank, value in enumerate(IDEMPOTENCY_OPERATION_KINDS_V1)} +_MISSING = object() + + +def _fail(message: str) -> NoReturn: + raise AthanorError(message) + + +def _reject_duplicate_json_keys(pairs: list[tuple[str, Any]]) -> dict[str, Any]: + result: dict[str, Any] = {} + for key, value in pairs: + if key in result: + _fail(f"duplicate JSON key: {key}") + result[key] = value + return result + + +def _reject_nonfinite(token: str) -> NoReturn: + _fail(f"non-finite JSON number is forbidden: {token}") + + +def _load_strict_object(raw: str | bytes | bytearray, label: str) -> dict[str, Any]: + if isinstance(raw, (bytes, bytearray)): + encoded = bytes(raw) + if encoded.startswith(b"\xef\xbb\xbf"): + _fail(f"invalid {label} JSON: UTF-8 BOM is forbidden") + try: + raw = encoded.decode("utf-8", errors="strict") + except UnicodeDecodeError: + _fail(f"invalid {label} JSON: non-UTF-8 encoding is forbidden") + if isinstance(raw, str) and raw.startswith("\ufeff"): + _fail(f"invalid {label} JSON: UTF-8 BOM is forbidden") + try: + value = json.loads( + raw, + object_pairs_hook=_reject_duplicate_json_keys, + parse_constant=_reject_nonfinite, + ) + except (json.JSONDecodeError, UnicodeDecodeError) as error: + _fail(f"invalid {label} JSON: {error}") + if not isinstance(value, dict): + _fail(f"{label} JSON root must be an object") + return value + + +def _check_nfc(value: Any) -> None: + if isinstance(value, str): + try: + value.encode("utf-8", errors="strict") + except UnicodeEncodeError: + _fail("JSON string contains a non-Unicode-scalar value") + if unicodedata.normalize("NFC", value) != value: + _fail("JSON string is not NFC-normalized") + elif isinstance(value, dict): + for key, member in value.items(): + _check_nfc(key) + _check_nfc(member) + elif isinstance(value, list): + for member in value: + _check_nfc(member) + elif isinstance(value, float): + if not math.isfinite(value): + _fail("non-finite JSON number is forbidden") + _fail("JSON float is forbidden by canonical execution wire") + + +def _without(value: dict[str, Any], member: str) -> dict[str, Any]: + return {key: item for key, item in value.items() if key != member} + + +def _parse_time(value: str) -> datetime: + return datetime.fromisoformat(value.replace("Z", "+00:00")) + + +def derive_execution_observation_cursor_sigil_v1(cursor: dict[str, Any]) -> str: + """Derive the public fixed-prefix cursor Sigil from its other members.""" + if "cursor_sigil" in cursor: + cursor = _without(cursor, "cursor_sigil") + return content_sigil(cursor) + + +def validate_execution_request_v1(kind: str, request: dict[str, Any]) -> None: + """Validate one closed RFC-0015 request without performing its operation.""" + try: + schema_name = _EXECUTION_REQUEST_SCHEMAS_V1[kind] + except KeyError: + _fail(f"unknown Execution API request kind: {kind}") + validate_instance(schema_name, request) + _check_nfc(request) + cursor = request.get("cursor") + if cursor is not None: + if cursor["job_id"] != request["job_id"]: + _fail("Execution observation cursor Job does not match request Job") + if cursor["last_returned_sequence"] > cursor["through_journal_sequence"]: + _fail("Execution observation cursor sequence range is invalid") + if cursor["cursor_sigil"] != derive_execution_observation_cursor_sigil_v1(cursor): + _fail("Execution observation cursor Sigil mismatch") + + +def load_execution_request_v1(kind: str, raw: str | bytes | bytearray) -> dict[str, Any]: + """Strictly decode a closed RFC-0015 request without dispatching it.""" + request = _load_strict_object(raw, f"Execution API {kind} request") + validate_execution_request_v1(kind, request) + return request + + +def _idempotency_projection(record: dict[str, Any]) -> tuple[int, bytes, str]: + owner = record if "operation_kind" in record else record["core"] + operation = owner["operation_kind"] + try: + rank = _IDEMPOTENCY_RANK[operation] + except KeyError: + _fail(f"unknown idempotency operation: {operation}") + return ( + rank, + _unsigned_ascii(owner["scope_id"], "Idempotency scope ID"), + owner["idempotency_key_sigil"], + ) + + +def _unsigned_ascii(value: str, label: str) -> bytes: + try: + return value.encode("ascii", errors="strict") + except UnicodeEncodeError: + _fail(f"{label} must be unsigned ASCII") + + +def validate_execution_budget_ledger_v1(ledger: dict[str, Any]) -> None: + """Validate RFC-0012 budget arithmetic and its local self-Sigil.""" + if ledger["budget_ledger_sigil"] != content_sigil(_without(ledger, "budget_ledger_sigil")): + _fail("Execution budget ledger self-Sigil mismatch") + for name, dimension in ledger.items(): + if name == "budget_ledger_sigil": + continue + total = dimension["consumed"] + dimension["reserved"] + expected_status = ( + "AVAILABLE" + if total < dimension["limit"] + else "EXHAUSTED" + if total == dimension["limit"] + else "EXCEEDED" + ) + if dimension["exhaustion_status"] != expected_status: + _fail(f"Execution budget dimension {name} has incorrect exhaustion status") + + +def validate_execution_state_v1(state: dict[str, Any]) -> None: + """Validate a State cache as bytes/projections, never as replay authority.""" + validate_instance("execution-state-1.0.json", state) + _check_nfc(state) + build = state["executor"]["executor_build_binding"] + if build["executor_build_sigil"] != content_sigil(_without(build, "executor_build_sigil")): + _fail("Execution State executor build self-Sigil mismatch") + executor = state["executor"] + gates = executor["authority_gates"] + if gates != sorted(gates, key=_AUTHORITY_GATE_RANK.__getitem__): + _fail("Execution State authority gates are not in canonical order") + if (executor["clock_state"] == "UNCERTAIN") != ("CLOCK_UNCERTAIN" in gates): + _fail("Execution State clock uncertainty gate disagrees with clock state") + if (executor["active_recovery_id"] is not None) != ("RECOVERY_ACTIVE" in gates): + _fail("Execution State recovery gate disagrees with active recovery") + recovery_ids = [recovery["recovery_id"] for recovery in state["recoveries"]] + if len(recovery_ids) != len(set(recovery_ids)): + _fail("duplicate Recovery projection identity") + if state["recoveries"]: + if state["recoveries"][0]["prior_recovery_id"] is not None: + _fail("first Recovery projection must not name a prior Recovery") + for index, recovery in enumerate(state["recoveries"][1:], 1): + prior_recovery = state["recoveries"][index - 1] + if recovery["prior_recovery_id"] != prior_recovery["recovery_id"]: + _fail("Recovery projection does not name its immediately prior Recovery") + if prior_recovery["state"] != "COMPLETED": + _fail("Recovery projection follows a Recovery that is not completed") + active_recoveries = [ + recovery for recovery in state["recoveries"] if recovery["state"] != "COMPLETED" + ] + if len(active_recoveries) > 1: + _fail("Execution State has more than one active Recovery") + active_recovery_id = executor["active_recovery_id"] + if active_recovery_id is None: + if active_recoveries: + _fail("Execution State active Recovery is missing from executor projection") + elif len(active_recoveries) != 1 or active_recoveries[0]["recovery_id"] != active_recovery_id: + _fail("Execution State executor active Recovery does not match recovery projection") + workers_by_id: dict[str, dict[str, Any]] = {} + for worker in state["workers"]: + worker_id = worker["worker_id"] + if worker_id in workers_by_id: + _fail("duplicate Worker projection identity") + workers_by_id[worker_id] = worker + session_ids = worker["worker_session_ids"] + if session_ids != sorted( + session_ids, key=lambda value: _unsigned_ascii(value, "Worker session ID") + ): + _fail("Worker worker_session_ids are not unsigned-ASCII sorted") + for job in state["jobs"]: + validate_execution_budget_ledger_v1(job["budget_ledger"]) + sessions_by_id: dict[str, dict[str, Any]] = {} + for session in state["worker_sessions"]: + session_id = session["worker_session_id"] + if session_id in sessions_by_id: + _fail("duplicate Worker-Session projection identity") + sessions_by_id[session_id] = session + try: + worker = workers_by_id[session["worker_id"]] + except KeyError: + _fail("Worker-Session projection has no matching Worker") + if session_id not in worker["worker_session_ids"]: + _fail("Worker-Session projection is missing from its Worker") + if session["worker_binding_sigil"] != worker["worker_binding_sigil"]: + _fail("Worker-Session binding Sigil does not match its Worker") + capacity = session["capacity"] + if (capacity is None) != (session["state"] == "REGISTERED"): + _fail("Worker-Session capacity nullability disagrees with Session state") + if capacity is not None and session["capacity_in_use"] > capacity: + _fail("Worker-Session capacity_in_use exceeds capacity") + if (session["last_heartbeat_sequence"] is None) != ( + session["last_heartbeat_message_sigil"] is None + ): + _fail("Worker-Session heartbeat fields must be jointly null or present") + if session["state"] in {"REGISTERED", "OFFLINE", "QUARANTINED", "CLOSED"} and ( + session["next_heartbeat_due_at"] is not None + ): + _fail("Worker-Session terminal or unready state must not have a heartbeat due time") + if session["lease_ids"] != sorted( + session["lease_ids"], key=lambda value: _unsigned_ascii(value, "Lease ID") + ): + _fail("Worker-Session lease_ids are not unsigned-ASCII sorted") + if { + session_id for worker in state["workers"] for session_id in worker["worker_session_ids"] + } != set(sessions_by_id): + _fail("Worker projection session IDs do not exactly match Worker-Session projections") + lease_ids = [lease["lease_id"] for lease in state["leases"]] + if len(lease_ids) != len(set(lease_ids)): + _fail("duplicate Lease projection identity") + terminal_lease_states = {"RELEASED", "REVOKED", "EXPIRED", "FENCED"} + for lease in state["leases"]: + heartbeat_members = ( + lease["last_heartbeat_sequence"], + lease["last_heartbeat_message_sigil"], + lease["last_resource_sample_sigil"], + ) + if any(member is None for member in heartbeat_members) and not all( + member is None for member in heartbeat_members + ): + _fail("Lease heartbeat fields must be jointly null or present") + terminal = lease["state"] in terminal_lease_states + if (lease["next_heartbeat_due_at"] is None) != (lease["state"] != "ACTIVE"): + _fail("Lease heartbeat due time disagrees with lease state") + tombstone_members = (lease["tombstone_generation"], lease["tombstone_event_sigil"]) + if (all(member is not None for member in tombstone_members)) != terminal: + _fail("Lease tombstone fields disagree with terminal lease state") + if _parse_time(lease["expiry_due_at"]) > _parse_time(lease["maximum_expiry_due_at"]): + _fail("Lease expiry due time exceeds its maximum expiry") + try: + session = sessions_by_id[lease["worker_session_id"]] + except KeyError: + _fail("Lease projection has no matching Worker-Session") + if lease["worker_id"] != session["worker_id"]: + _fail("Lease Worker does not match its Worker-Session") + if lease["lease_id"] not in session["lease_ids"]: + _fail("Lease projection is missing from its Worker-Session") + if { + lease_id for session in state["worker_sessions"] for lease_id in session["lease_ids"] + } != set(lease_ids): + _fail("Worker-Session lease IDs do not exactly match Lease projections") + log_stream_ids: set[str] = set() + for log_stream in state["log_streams"]: + log_stream_id = log_stream["log_stream_id"] + if log_stream_id in log_stream_ids: + _fail("duplicate Log-stream projection identity") + log_stream_ids.add(log_stream_id) + final_sequence = log_stream["final_sequence"] + stream_set_sigil = log_stream["stream_set_sigil"] + if log_stream["state"] == "OPEN": + if final_sequence is not None or stream_set_sigil is not None: + _fail("Open Log stream must not have terminal stream fields") + elif stream_set_sigil is None: + _fail("Closed Log stream must have a stream-set Sigil") + elif final_sequence is not None and final_sequence >= log_stream["next_sequence"]: + _fail("Closed Log stream final sequence must precede next sequence") + deadline_keys: list[tuple[datetime, int, bytes]] = [] + for deadline in state["deadlines"]: + if deadline["fixed_priority"] != _DEADLINE_PRIORITY[deadline["deadline_kind"]]: + _fail("Deadline fixed priority disagrees with deadline kind") + deadline_keys.append( + ( + _parse_time(deadline["due_at"]), + deadline["fixed_priority"], + _unsigned_ascii(deadline["entity_id"], "Deadline entity ID"), + ) + ) + if deadline_keys != sorted(deadline_keys): + _fail("Deadlines are not sorted by canonical deadline key") + if len(deadline_keys) != len(set(deadline_keys)): + _fail("duplicate Deadline projection key") + keys = [_idempotency_projection(record) for record in state["idempotency_records"]] + if keys != sorted(keys): + _fail("idempotency_records are not sorted by the canonical 11-rank key") + if len(keys) != len(set(keys)): + _fail("duplicate mixed idempotency comparison tuple") + if state["state_sigil"] != content_sigil(_without(state, "state_sigil")): + _fail("Execution State self-Sigil mismatch") + + +def load_execution_state_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + state = _load_strict_object(raw, "Execution State") + validate_execution_state_v1(state) + return state + + +def build_execution_state_v1(unsigned_state: dict[str, Any]) -> dict[str, Any]: + if "state_sigil" in unsigned_state: + _fail("unsigned Execution State must not contain state_sigil") + state = {**unsigned_state, "state_sigil": content_sigil(unsigned_state)} + validate_execution_state_v1(state) + return state + + +def validate_execution_journal_head_v1(head: dict[str, Any]) -> None: + """Validate the closed Head cache record, never its claimed Journal prefix.""" + validate_instance("execution-journal-head-1.0.json", head) + _check_nfc(head) + if head["head_sigil"] != content_sigil(_without(head, "head_sigil")): + _fail("Execution Journal Head self-Sigil mismatch") + + +def load_execution_journal_head_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + head = _load_strict_object(raw, "Execution Journal Head") + validate_execution_journal_head_v1(head) + return head + + +def validate_execution_initial_state_supplied_facts_v1( + event: dict[str, Any], state: dict[str, Any], head: dict[str, Any] +) -> None: + """Compare an ISR3 initial State with caller-supplied Event and Head bytes. + + This does not authenticate the supplied records or establish a durable + prefix; it only verifies the exact RFC-0012 initial-projection equations. + """ + validate_execution_journal_event_v1(event) + validate_execution_state_v1(state) + validate_execution_journal_head_v1(head) + if event["sequence"] != 1 or event["event_type"] != "executor.epoch_started": + _fail("ISR3 supplied Event is not the sequence-one executor epoch start") + if event["previous_event_sigil"] is not None: + _fail("ISR3 sequence-one Event must have null predecessor") + expected_journal = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + if state["journal_binding"] != expected_journal: + _fail("ISR3 State journal binding disagrees with supplied Event") + expected_head = { + "journal_id": event["journal_id"], + "last_sequence": event["sequence"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + if any(head[member] != value for member, value in expected_head.items()): + _fail("ISR3 Head disagrees with supplied Event") + payload = event["payload"] + executor = state["executor"] + expected_executor = { + "executor_instance_id": event["executor_instance_id"], + "executor_epoch": event["executor_epoch"], + "executor_build_binding": payload["executor_build_binding"], + "revision": 0, + "clock_state": "TRUSTED", + "last_trusted_utc": event["recorded_at"], + "clock_uncertain_event_id": None, + "active_recovery_id": None, + "authority_gates": [], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + if executor != expected_executor: + _fail("ISR3 State executor projection disagrees with supplied Event") + arrays = ( + "recoveries", + "workers", + "worker_sessions", + "jobs", + "attempts", + "leases", + "log_streams", + "deadlines", + "idempotency_records", + ) + if any(state[member] for member in arrays): + _fail("ISR3 State contains a noninitial projection member") + + +def replay_execution_initial_prefix_v1( + events: list[dict[str, Any]], *, head: dict[str, Any] | None = None +) -> dict[str, Any]: + """Reduce exactly the ISR3 sequence-one prefix, otherwise fail closed. + + This is a deterministic cache construction primitive only. It neither + authenticates storage nor grants Journal append, runtime, or resolver + authority. Later Event reducers must be installed explicitly rather than + being inferred from their Schema shape. + """ + if len(events) != 1: + _fail("Execution Journal replay supports only the initial one-Event prefix") + event = events[0] + validate_execution_journal_event_v1(event) + if event["sequence"] != 1 or event["event_type"] != "executor.epoch_started": + _fail("Execution Journal initial replay requires sequence-one executor epoch start") + if event["previous_event_sigil"] is not None: + _fail("Execution Journal initial replay requires a null predecessor") + state = build_execution_state_v1( + { + "schema_version": "execution-state/1.0", + "limit_profile": "EXECUTION_JOURNAL_V1_FIXED_LIMITS", + "journal_binding": { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + }, + "executor": { + "executor_instance_id": event["executor_instance_id"], + "executor_epoch": event["executor_epoch"], + "executor_build_binding": event["payload"]["executor_build_binding"], + "revision": 0, + "clock_state": "TRUSTED", + "last_trusted_utc": event["recorded_at"], + "clock_uncertain_event_id": None, + "active_recovery_id": None, + "authority_gates": [], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + }, + "recoveries": [], + "workers": [], + "worker_sessions": [], + "jobs": [], + "attempts": [], + "leases": [], + "log_streams": [], + "deadlines": [], + "idempotency_records": [], + } + ) + if head is not None: + validate_execution_initial_state_supplied_facts_v1(event, state, head) + return state + + +def validate_execution_job_v1(job: dict[str, Any]) -> None: + """Validate one immutable Job wire without resolving its external bindings.""" + validate_instance("execution-job-1.0.json", job) + _check_nfc(job) + if job["job_binding_sigil"] != content_sigil(_without(job, "job_binding_sigil")): + _fail("Execution Job self-Sigil mismatch") + evidence = job["admission_chronicle_head_evidence"] + if ( + evidence["job_id"] != job["job_id"] + or evidence["start_request_sigil"] != job["start_request_sigil"] + or evidence["observed_chronicle_head"] != job["admission_chronicle_head"] + or evidence["evidence_sigil"] != content_sigil(_without(evidence, "evidence_sigil")) + ): + _fail("Execution Job admission evidence disagrees with Job binding") + + +def _initial_budget_ledger_v1(job_budget: dict[str, Any]) -> dict[str, Any]: + ledger: dict[str, Any] = {} + for dimension, limit in job_budget.items(): + ledger[dimension] = { + "limit": limit, + "reserved": 0, + "consumed": 0, + "exhaustion_status": "EXHAUSTED" if limit == 0 else "AVAILABLE", + } + ledger["budget_ledger_sigil"] = content_sigil(ledger) + return ledger + + +def _reduce_job_submitted_v1( + state: dict[str, Any], event: dict[str, Any], job: dict[str, Any] +) -> dict[str, Any]: + """Reduce the supplied immutable Job's one-way submission projection.""" + validate_execution_job_v1(job) + executor = state["executor"] + if event["event_type"] != "job.submitted": + _fail("internal reducer dispatch does not match Job submission") + if ( + event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or executor["clock_state"] != "TRUSTED" + or executor["authority_gates"] + or any( + state[member] + for member in ( + "recoveries", + "workers", + "worker_sessions", + "jobs", + "attempts", + "leases", + "log_streams", + "deadlines", + "idempotency_records", + ) + ) + ): + _fail("Job submission requires the ungated initial execution projection") + payload = event["payload"] + copied = ( + "job_binding_sigil", + "start_request_sigil", + "submission_idempotency_key_sigil", + "admission_chronicle_head", + "admission_chronicle_head_evidence", + "deadline_due_at", + "job_budget", + "job_storage_roots", + ) + if any(payload[member] != job[member] for member in copied): + _fail("Job submission Event does not exactly copy its supplied Job") + expected_revisions = [ + { + "entity_kind": "JOB", + "entity_id": job["job_id"], + "preceding_revision": None, + "next_revision": 0, + } + ] + if event["entity_revisions"] != expected_revisions: + _fail("Job submission Event has invalid Job creation revision") + if event["idempotency_key_sigil"] != job["submission_idempotency_key_sigil"]: + _fail("Job submission Event idempotency key disagrees with Job") + ledger = _initial_budget_ledger_v1(job["job_budget"]) + if event["recorded_at"] != job["submitted_at"]: + _fail("Job submission recorded_at disagrees with Job submitted_at") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["jobs"] = [ + { + "job_id": job["job_id"], + "revision": 0, + "state": "SUBMITTED", + "job_binding_sigil": job["job_binding_sigil"], + "job_storage_roots": job["job_storage_roots"], + "attempt_ids": [], + "current_attempt_id": None, + "fencing_counter": 0, + "fence_floor": 0, + "budget_ledger": ledger, + "deadline_due_at": job["deadline_due_at"], + "retry_eligible_due_at": None, + "queue_key": None, + "attempt_summaries": [], + "selected_attempt_binding": None, + "completion_anchor_binding": None, + "first_stop_or_fence_binding": {"kind": "NONE"}, + "final_fence_binding": None, + "storage_observation_binding": None, + "terminal_source_binding": None, + "output_hold_release_schedules": [], + "job_assurance_binding": {"kind": "PENDING"}, + "terminal_event_binding": {"kind": "NONE"}, + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ] + reduced["deadlines"] = [ + { + "deadline_kind": "JOB_DEADLINE", + "due_at": job["deadline_due_at"], + "fixed_priority": _DEADLINE_PRIORITY["JOB_DEADLINE"], + "entity_id": job["job_id"], + "source_event_id": event["event_id"], + "source_event_sigil": event["event_sigil"], + } + ] + reduced["idempotency_records"] = [ + { + "operation_kind": "START_JOB", + "scope_id": job["task_id"], + "idempotency_key_sigil": job["submission_idempotency_key_sigil"], + "request_sigil": job["start_request_sigil"], + "disposition_event_id": event["event_id"], + "disposition_event_sigil": event["event_sigil"], + } + ] + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def _reduce_job_queued_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Reduce a submitted Job to its deterministic ready-queue projection.""" + if event["event_type"] != "job.queued" or len(state["jobs"]) != 1: + _fail("Job queue reducer requires exactly one submitted Job") + job = state["jobs"][0] + executor = state["executor"] + if ( + job["state"] != "SUBMITTED" + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["entity_revisions"] + != [ + { + "entity_kind": "JOB", + "entity_id": job["job_id"], + "preceding_revision": job["revision"], + "next_revision": job["revision"] + 1, + } + ] + ): + _fail("Job queue Event disagrees with submitted Job projection") + payload = event["payload"] + if payload["queue_key"] != {"ready_sequence": event["sequence"], "job_id": job["job_id"]}: + _fail("Job queue Event has an invalid queue key") + if not isinstance(payload["admission_evidence_sigil"], str): + _fail("Job queue Event admission evidence is invalid") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["jobs"] = [ + { + **job, + "revision": job["revision"] + 1, + "state": "QUEUED", + "queue_key": payload["queue_key"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ] + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def validate_execution_attempt_v1(attempt: dict[str, Any]) -> None: + """Validate one immutable fresh Attempt without resolving its dependencies.""" + validate_instance("execution-attempt-1.0.json", attempt) + _check_nfc(attempt) + if attempt["attempt_binding_sigil"] != content_sigil( + _without(attempt, "attempt_binding_sigil") + ): + _fail("Execution Attempt self-Sigil mismatch") + + +def _current_attempt_v1(state: dict[str, Any], label: str) -> dict[str, Any]: + """Return the Job's one live Attempt while retaining terminal history.""" + if len(state["jobs"]) != 1: + _fail(f"{label} requires exactly one Job") + attempt_id = state["jobs"][0]["current_attempt_id"] + matches = [item for item in state["attempts"] if item["attempt_id"] == attempt_id] + if attempt_id is None or len(matches) != 1: + _fail(f"{label} requires exactly one current Attempt") + return matches[0] + + +def _replace_attempt_v1( + state: dict[str, Any], attempt_id: str, replacement: dict[str, Any] +) -> list[dict[str, Any]]: + """Replace one retained Attempt projection without losing earlier retries.""" + replaced = False + attempts: list[dict[str, Any]] = [] + for candidate in state["attempts"]: + if candidate["attempt_id"] == attempt_id: + if replaced: + _fail("Execution State has duplicate Attempt identity") + attempts.append(replacement) + replaced = True + else: + attempts.append(candidate) + if not replaced: + _fail("Execution State has no selected Attempt projection") + return attempts + + +def _active_lease_for_attempt_v1( + state: dict[str, Any], attempt: dict[str, Any], label: str +) -> dict[str, Any]: + """Select the exact active Lease attached to the current Attempt.""" + lease_id = attempt["lease_id"] + matches = [ + lease + for lease in state["leases"] + if lease["lease_id"] == lease_id and lease["attempt_id"] == attempt["attempt_id"] + ] + if lease_id is None or len(matches) != 1: + _fail(f"{label} requires one Lease for the current Attempt") + return matches[0] + + +def _lease_named_by_event_v1( + state: dict[str, Any], event: dict[str, Any], label: str +) -> dict[str, Any]: + """Return the one Lease revision target named by an Event.""" + lease_ids = [ + revision["entity_id"] + for revision in event["entity_revisions"] + if revision["entity_kind"] == "LEASE" + ] + if len(lease_ids) != 1: + _fail(f"{label} requires exactly one Lease revision target") + matches = [lease for lease in state["leases"] if lease["lease_id"] == lease_ids[0]] + if len(matches) != 1: + _fail(f"{label} names an unknown Lease") + return matches[0] + + +def _session_for_lease_v1(state: dict[str, Any], lease: dict[str, Any], label: str) -> dict[str, Any]: + """Return the uniquely bound Session for one Lease.""" + matches = [ + session + for session in state["worker_sessions"] + if session["worker_session_id"] == lease["worker_session_id"] + ] + if len(matches) != 1: + _fail(f"{label} requires the Lease Worker Session") + return matches[0] + + +_ASSURANCE_LEVEL_RANK_V1 = { + "SANCTUM-A0": 0, + "SANCTUM-A1": 1, + "SANCTUM-A2": 2, +} + + +def validate_sanctum_assurance_claim_v1(claim: dict[str, Any]) -> None: + """Validate the local closed bytes of an Assurance Claim. + + This does not resolve the verifier registry, evidence records, signatures, + or durable installation. Those facts must be supplied to a separate + authority-bearing verifier. + """ + validate_instance("sanctum-assurance-claim-1.0.json", claim) + _check_nfc(claim) + if claim["assurance_claim_sigil"] != content_sigil( + _without(claim, "assurance_claim_sigil") + ): + _fail("Sanctum Assurance Claim self-Sigil mismatch") + if claim["satisfies_request"] and ( + _ASSURANCE_LEVEL_RANK_V1[claim["realized_level"]] + < _ASSURANCE_LEVEL_RANK_V1[claim["requested_assurance"]] + ): + _fail("Sanctum Assurance Claim satisfying level is below its request") + evidence_cut = claim["evidence_cut"] + if ( + _parse_time(evidence_cut["verification_started_at"]) + > _parse_time(evidence_cut["verification_completed_at"]) + or _parse_time(evidence_cut["verification_completed_at"]) + > _parse_time(claim["issued_at"]) + ): + _fail("Sanctum Assurance Claim verification time order is invalid") + result = claim["result_binding"] + if result["kind"] == "REJECTED" and result["reason_codes"] != sorted( + set(result["reason_codes"]) + ): + _fail("Sanctum Assurance Claim rejected Result reasons are not uniquely sorted") + + +def load_sanctum_assurance_claim_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + """Strictly load a locally valid Claim without granting claim authority.""" + claim = _load_strict_object(raw, "Sanctum Assurance Claim") + validate_sanctum_assurance_claim_v1(claim) + return claim + + +def validate_sanctum_assurance_claim_supplied_attempt_facts_v1( + claim: dict[str, Any], + job: dict[str, Any], + state: dict[str, Any], + attempt_id: str, + accounting_capture_event: dict[str, Any], + budget_settlement_event: dict[str, Any], +) -> None: + """Compare a Claim with caller-supplied terminal Job/Attempt State facts. + + This is a supplied-facts comparator, not a verifier. It closes only the + Claim fields whose values are already frozen in the supplied immutable Job + and Execution State. Registry installation, signer identity, predicate + evaluation, evidence availability and durable currentness remain external + authorities and are deliberately not inferred here. + """ + validate_sanctum_assurance_claim_v1(claim) + validate_execution_job_v1(job) + validate_execution_state_v1(state) + validate_execution_journal_event_v1(accounting_capture_event) + validate_execution_journal_event_v1(budget_settlement_event) + attempts = [item for item in state["attempts"] if item["attempt_id"] == attempt_id] + if len(attempts) != 1 or len(state["jobs"]) != 1: + _fail("Supplied Assurance Claim facts require one Job and named Attempt") + attempt = attempts[0] + state_job = state["jobs"][0] + terminal = attempt["terminal_event_binding"] + capture = attempt["accounting_capture_binding"] + settlement = attempt["budget_settlement_binding"] + result = attempt["result_binding"] + capture_ref = { + "journal_id": state["journal_binding"]["journal_id"], + "sequence": accounting_capture_event["sequence"], + "event_id": capture["event_id"], + "event_sigil": capture["event_sigil"], + } + settlement_ref = { + "journal_id": state["journal_binding"]["journal_id"], + "sequence": budget_settlement_event["sequence"], + "event_id": settlement["event_id"], + "event_sigil": settlement["event_sigil"], + } + capture_attempt_ids = [ + revision["entity_id"] + for revision in accounting_capture_event["entity_revisions"] + if revision["entity_kind"] == "ATTEMPT" + ] + if result["kind"] == "ACCEPTED": + claim_result = { + "kind": "ACCEPTED", + "result_sigil": result["result_sigil"], + "disposition_event": { + "journal_id": state["journal_binding"]["journal_id"], + "sequence": result["disposition_sequence"], + "event_id": result["disposition_event_id"], + "event_sigil": result["disposition_event_sigil"], + }, + } + elif result["kind"] == "REJECTED": + claim_result = { + "kind": "REJECTED", + "message_sigil": result["message_sigil"], + "disposition_event": { + "journal_id": state["journal_binding"]["journal_id"], + "sequence": result["disposition_sequence"], + "event_id": result["disposition_event_id"], + "event_sigil": result["disposition_event_sigil"], + }, + "reason_codes": result["reason_codes"], + } + else: + claim_result = result + if ( + state_job["job_id"] != job["job_id"] + or state_job["job_binding_sigil"] != job["job_binding_sigil"] + or attempt["job_id"] != job["job_id"] + or claim["job_id"] != job["job_id"] + or claim["attempt_id"] != attempt["attempt_id"] + or claim["attempt_binding_sigil"] != attempt["attempt_binding_sigil"] + or terminal["kind"] != "PRESENT" + or capture["kind"] != "CAPTURED" + or settlement["kind"] != "SETTLED" + or claim["attempt_terminal_event"] != { + "journal_id": state["journal_binding"]["journal_id"], + "sequence": terminal["terminal_sequence"], + "event_id": terminal["terminal_event_id"], + "event_sigil": terminal["terminal_event_sigil"], + } + or claim["requested_assurance"] + != job["assurance_requirement"]["requested_level"] + or claim["assurance_profile_binding"] + != { + "profile_version": job["assurance_requirement"]["profile_version"], + "profile_sigil": job["assurance_requirement"]["profile_sigil"], + "conformance_suite_id": job["assurance_requirement"][ + "conformance_suite_id" + ], + "conformance_suite_sigil": job["assurance_requirement"][ + "conformance_suite_sigil" + ], + } + or claim["result_binding"] != claim_result + or claim["control_evidence_set_binding"] + != attempt["control_evidence_set_binding"] + or claim["evidence_cut"]["control_evidence_set_binding"] + != claim["control_evidence_set_binding"] + or claim["evidence_cut"]["control_evidence_set_binding"] + != attempt["control_evidence_set_binding"] + or claim["terminal_status"]["attempt_state"] != attempt["state"] + or claim["evidence_cut"]["journal_prefix"] + != { + "journal_id": state["journal_binding"]["journal_id"], + "ending_sequence": state["journal_binding"]["through_sequence"], + "ending_event_id": state["journal_binding"]["through_event_id"], + "ending_event_sigil": state["journal_binding"]["through_event_sigil"], + } + or claim["evidence_cut"]["state_sigil"] != state["state_sigil"] + or claim["evidence_cut"]["accounting_capture_event"] != capture_ref + or claim["evidence_cut"]["budget_settlement_event"] != settlement_ref + or accounting_capture_event["journal_id"] != capture_ref["journal_id"] + or accounting_capture_event["event_id"] != capture_ref["event_id"] + or accounting_capture_event["event_sigil"] != capture_ref["event_sigil"] + or accounting_capture_event["event_type"] != "attempt.cleanup_progressed" + or accounting_capture_event["payload"]["step"] != "ACCOUNTING_CAPTURED" + or capture_attempt_ids != [attempt_id] + or budget_settlement_event["journal_id"] != settlement_ref["journal_id"] + or budget_settlement_event["event_id"] != settlement_ref["event_id"] + or budget_settlement_event["event_sigil"] != settlement_ref["event_sigil"] + or budget_settlement_event["event_type"] != "job.budget_settled" + or budget_settlement_event["payload"]["attempt_id"] != attempt_id + or budget_settlement_event["payload"]["accounting_capture_event_id"] + != capture["event_id"] + or budget_settlement_event["payload"]["accounting_capture_event_sigil"] + != capture["event_sigil"] + or settlement["accounting_capture_event_id"] != capture["event_id"] + or settlement["accounting_capture_event_sigil"] != capture["event_sigil"] + or not ( + accounting_capture_event["sequence"] < terminal["terminal_sequence"] + < budget_settlement_event["sequence"] + ) + or budget_settlement_event["sequence"] + > state["journal_binding"]["through_sequence"] + ): + _fail("Supplied Sanctum Assurance Claim disagrees with terminal Attempt facts") + + +def _validate_attempt_authorization_subject_v1(subject: dict[str, Any]) -> None: + """Validate the local, immutable portion of one authorization Subject.""" + validate_instance("attempt-authorization-subject-1.0.json", subject) + _check_nfc(subject) + effect_ids = [ + _unsigned_ascii(effect["side_effect_id"], "Attempt authorization side-effect ID") + for effect in subject["effects"] + ] + if effect_ids != sorted(effect_ids) or len(effect_ids) != len(set(effect_ids)): + _fail("Attempt authorization Subject effects are not uniquely sorted") + preimage = [ + "attempt-authorization-subject-id/1.0", + subject["job_id"], + subject["job_binding_sigil"], + subject["attempt_id"], + subject["attempt_binding_sigil"], + subject["retry_ordinal"], + subject["specification_id"], + subject["specification_sigil"], + subject["effects"], + ] + expected_id = "AA-" + hashlib.sha256( + canonical_json(preimage).encode("utf-8") + ).hexdigest().upper() + if ( + subject["authorization_subject_id"] != expected_id + or subject["authorization_subject_sigil"] + != content_sigil(_without(subject, "authorization_subject_sigil")) + ): + _fail("Attempt authorization Subject identity or self-Sigil mismatch") + + +def _reduce_attempt_authorization_bound_v1( + state: dict[str, Any], + event: dict[str, Any], + immutable_job: dict[str, Any], + immutable_attempt: dict[str, Any], +) -> dict[str, Any]: + """Bind a supplied canonical authorization chain to one CREATED Attempt. + + The canonical Event and Receipt are represented by their immutable binding + but are not treated as resolved or accepted here; their authority remains + with the Athanor-facing resolver. + """ + if len(state["jobs"]) != 1: + _fail("Attempt authorization binding requires one Job") + job, attempt, executor = state["jobs"][0], _current_attempt_v1( + state, "Attempt authorization binding" + ), state["executor"] + payload = event["payload"] + subject = payload["authorization_subject"] + binding = payload["attempt_authorization_binding"] + validate_execution_job_v1(immutable_job) + validate_execution_attempt_v1(immutable_attempt) + _validate_attempt_authorization_subject_v1(subject) + if ( + event["event_type"] != "attempt.authorization_bound" + or attempt["state"] != "CREATED" + or attempt["attempt_authorization_requirement"]["kind"] != "REQUIRED" + or attempt["attempt_authorization_state"] != {"kind": "PENDING"} + or attempt["first_stop_or_fence_binding"] != {"kind": "NONE"} + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["entity_revisions"] != [{ + "entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], + "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1, + }] + or subject["job_id"] != job["job_id"] + or subject["job_binding_sigil"] != job["job_binding_sigil"] + or subject["attempt_id"] != attempt["attempt_id"] + or subject["attempt_binding_sigil"] != attempt["attempt_binding_sigil"] + or subject["retry_ordinal"] != attempt["retry_ordinal"] + or immutable_attempt["attempt_id"] != attempt["attempt_id"] + or immutable_attempt["attempt_binding_sigil"] != attempt["attempt_binding_sigil"] + or immutable_job["job_id"] != job["job_id"] + or immutable_job["job_binding_sigil"] != job["job_binding_sigil"] + or subject["specification_id"] != immutable_job["specification_id"] + or subject["specification_sigil"] != immutable_job["specification_sigil"] + or subject["effects"] != attempt["attempt_authorization_requirement"]["effects"] + or {key: binding[key] for key in ("authorization_subject_id", "authorization_subject_sigil")} + != {key: subject[key] for key in ("authorization_subject_id", "authorization_subject_sigil")} + or binding["authorization_binding_sigil"] + != content_sigil(_without(binding, "authorization_binding_sigil")) + ): + _fail("Attempt authorization binding Event disagrees with CREATED Attempt") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], { + **attempt, + "revision": attempt["revision"] + 1, + "attempt_authorization_state": { + "kind": "BOUND", "authorization_subject": subject, + "attempt_authorization_binding": binding, + }, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"], + }) + return build_execution_state_v1(reduced) + + +def validate_execution_worker_v1(worker: dict[str, Any]) -> None: + """Validate one immutable Worker definition revision locally.""" + validate_instance("execution-worker-1.0.json", worker) + _check_nfc(worker) + if worker["worker_binding_sigil"] != content_sigil(_without(worker, "worker_binding_sigil")): + _fail("Execution Worker self-Sigil mismatch") + + +def validate_execution_worker_session_v1(session: dict[str, Any]) -> None: + """Validate one immutable Worker Session binding locally.""" + validate_instance("execution-worker-session-1.0.json", session) + _check_nfc(session) + if session["worker_session_binding_sigil"] != content_sigil( + _without(session, "worker_session_binding_sigil") + ): + _fail("Execution Worker Session self-Sigil mismatch") + + +def validate_execution_worker_session_supplied_worker_v1( + session: dict[str, Any], worker: dict[str, Any] +) -> None: + """Bind a supplied Session to its exact immutable Worker definition.""" + validate_execution_worker_session_v1(session) + validate_execution_worker_v1(worker) + if ( + session["worker_id"] != worker["worker_id"] + or session["worker_binding_sigil"] != worker["worker_binding_sigil"] + or session["maximum_concurrency"] != worker["maximum_concurrency"] + ): + _fail("Execution Worker Session disagrees with supplied Worker") + + +def validate_execution_lease_v1(lease: dict[str, Any]) -> None: + """Validate one immutable Lease offer without granting lease authority.""" + validate_instance("execution-lease-1.0.json", lease) + _check_nfc(lease) + if lease["lease_binding_sigil"] != content_sigil(_without(lease, "lease_binding_sigil")): + _fail("Execution Lease self-Sigil mismatch") + if not ( + _parse_time(lease["offered_at"]) + <= _parse_time(lease["claim_due_at"]) + <= _parse_time(lease["initial_expiry_due_at"]) + <= _parse_time(lease["maximum_expiry_due_at"]) + ): + _fail("Execution Lease deadlines are not non-decreasing") + + +def validate_execution_lease_supplied_bindings_v1( + lease: dict[str, Any], + attempt: dict[str, Any], + worker: dict[str, Any], + session: dict[str, Any], +) -> None: + """Compare a Lease offer to its exact supplied Attempt, Worker, and Session.""" + validate_execution_lease_v1(lease) + validate_execution_attempt_v1(attempt) + validate_execution_worker_session_supplied_worker_v1(session, worker) + if ( + lease["job_id"] != attempt["job_id"] + or lease["attempt_id"] != attempt["attempt_id"] + or lease["fencing_generation"] != attempt["fencing_generation"] + or lease["worker_id"] != worker["worker_id"] + or lease["worker_binding_sigil"] != worker["worker_binding_sigil"] + or lease["worker_session_id"] != session["worker_session_id"] + or lease["worker_session_binding_sigil"] != session["worker_session_binding_sigil"] + or lease["executor_instance_id"] != session["executor_instance_id"] + or lease["executor_epoch"] != session["executor_epoch"] + ): + _fail("Execution Lease disagrees with supplied Attempt, Worker, or Session") + + +def _advance_journal_binding_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["journal_binding"] = { + "journal_id": event["journal_id"], "through_sequence": event["sequence"], + "through_event_id": event["event_id"], "through_event_sigil": event["event_sigil"], + } + return reduced + + +def _reduce_lease_offered_v1(state: dict[str, Any], event: dict[str, Any], lease: dict[str, Any]) -> dict[str, Any]: + """Record one offered Lease without granting Worker execution authority.""" + validate_execution_lease_v1(lease) + attempt = next((item for item in state["attempts"] if item["attempt_id"] == lease["attempt_id"]), None) + session = next((item for item in state["worker_sessions"] if item["worker_session_id"] == lease["worker_session_id"]), None) + worker = next((item for item in state["workers"] if item["worker_id"] == lease["worker_id"]), None) + if attempt is None or session is None or worker is None: + _fail("Lease offer requires a replayed Attempt, Worker, and Session") + executor = state["executor"] + expected_revisions = [ + {"entity_kind": "WORKER_SESSION", "entity_id": session["worker_session_id"], "preceding_revision": session["revision"], "next_revision": session["revision"] + 1}, + {"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}, + {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": None, "next_revision": 0}, + ] + payload = event["payload"] + if ( + event["event_type"] != "lease.offered" or attempt["attempt_id"] != _current_attempt_v1(state, "Lease offer")["attempt_id"] or attempt["state"] != "READY" or attempt["lease_id"] is not None or attempt["worker_session_binding"] != {"kind": "NONE"} or any(item["attempt_id"] == attempt["attempt_id"] and item["state"] in {"OFFERED", "ACTIVE"} for item in state["leases"]) or session["state"] not in {"READY", "BUSY"} + or session["capacity"] is None or session["capacity_in_use"] >= session["capacity"] + or lease["job_id"] != attempt["job_id"] or lease["attempt_id"] != attempt["attempt_id"] + or lease["fencing_generation"] != attempt["fencing_generation"] + or lease["worker_id"] != worker["worker_id"] or lease["worker_binding_sigil"] != worker["worker_binding_sigil"] + or lease["worker_session_id"] != session["worker_session_id"] or lease["worker_session_binding_sigil"] != session["worker_session_binding_sigil"] + or lease["executor_epoch"] != session["executor_epoch"] + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != executor["executor_epoch"] + or event["entity_revisions"] != expected_revisions + or payload["lease_binding_sigil"] != lease["lease_binding_sigil"] or payload["credential_digest"] != lease["lease_credential_digest"] + or any(payload[key] != lease[{"claim_due_at": "claim_due_at", "initial_expiry_due_at": "initial_expiry_due_at", "maximum_expiry_due_at": "maximum_expiry_due_at"}[key]] for key in ("claim_due_at", "initial_expiry_due_at", "maximum_expiry_due_at")) + ): + _fail("Lease offer Event disagrees with replayed state or supplied Lease") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, "worker_session_binding": {"kind": "BOUND", "worker_id": lease["worker_id"], "worker_binding_sigil": lease["worker_binding_sigil"], "worker_session_id": lease["worker_session_id"], "worker_session_binding_sigil": lease["worker_session_binding_sigil"]}, "lease_id": lease["lease_id"], "lease_terminal_binding": None, "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + reduced["worker_sessions"] = [{**session, "revision": session["revision"] + 1, "lease_ids": sorted([*session["lease_ids"], lease["lease_id"]], key=lambda value: _unsigned_ascii(value, "Lease ID")), "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["leases"] = [*state["leases"], {"lease_id": lease["lease_id"], "revision": 0, "state": "OFFERED", "lease_binding_sigil": lease["lease_binding_sigil"], "job_id": lease["job_id"], "attempt_id": lease["attempt_id"], "worker_id": lease["worker_id"], "worker_session_id": lease["worker_session_id"], "executor_epoch": lease["executor_epoch"], "fencing_generation": lease["fencing_generation"], "claim_due_at": lease["claim_due_at"], "expiry_due_at": lease["initial_expiry_due_at"], "maximum_expiry_due_at": lease["maximum_expiry_due_at"], "last_heartbeat_sequence": None, "last_heartbeat_message_sigil": None, "last_resource_sample_sigil": None, "resource_counter_floors": {"cpu_time_seconds": None, "storage_bytes_written": None, "network_egress_bytes": None}, "next_heartbeat_due_at": None, "renewal_counter": 0, "terminal_event_binding": {"kind": "NONE"}, "tombstone_generation": None, "tombstone_event_sigil": None, "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["deadlines"] = sorted([*state["deadlines"], {"deadline_kind": "LEASE_CLAIM_DEADLINE", "due_at": lease["claim_due_at"], "fixed_priority": _DEADLINE_PRIORITY["LEASE_CLAIM_DEADLINE"], "entity_id": lease["lease_id"], "source_event_id": event["event_id"], "source_event_sigil": event["event_sigil"]}], key=lambda item: (_parse_time(item["due_at"]), item["fixed_priority"], _unsigned_ascii(item["entity_id"], "Deadline entity ID"))) + return build_execution_state_v1(reduced) + + +def _reduce_lease_claimed_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Atomically activate an offered Lease and its READY Attempt.""" + lease_id = event["entity_revisions"][-1]["entity_id"] if event["entity_revisions"] else "" + leases = [item for item in state["leases"] if item["lease_id"] == lease_id] + if len(leases) != 1: + _fail("Lease claim reducer requires one offered Lease") + lease = leases[0] + attempts = [item for item in state["attempts"] if item["attempt_id"] == lease["attempt_id"]] + if len(attempts) != 1: + _fail("Lease claim reducer requires the Lease Attempt") + sessions = [ + item + for item in state["worker_sessions"] + if item["worker_session_id"] == lease["worker_session_id"] + ] + if len(sessions) != 1: + _fail("Lease claim reducer requires the Lease Worker Session") + attempt, session = attempts[0], sessions[0] + executor = state["executor"] + payload = event["payload"] + expected_revisions = [ + {"entity_kind": "WORKER_SESSION", "entity_id": session["worker_session_id"], "preceding_revision": session["revision"], "next_revision": session["revision"] + 1}, + {"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}, + {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": lease["revision"], "next_revision": lease["revision"] + 1}, + ] + if ( + event["event_type"] != "lease.claimed" or attempt["attempt_id"] != _current_attempt_v1(state, "Lease claim")["attempt_id"] or lease["state"] != "OFFERED" or attempt["state"] != "READY" + or session["state"] not in {"READY", "BUSY"} or session["capacity"] is None + or session["capacity_in_use"] + 1 > session["capacity"] + or attempt["lease_id"] != lease["lease_id"] or attempt["worker_session_binding"]["kind"] != "BOUND" + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["entity_revisions"] != expected_revisions + or payload["claimed_at"] != event["recorded_at"] or _parse_time(payload["claimed_at"]) > _parse_time(lease["claim_due_at"]) + or payload["session_capacity_after"] != session["capacity_in_use"] + 1 + ): + _fail("Lease claim Event disagrees with offered Lease state") + fence = {"journal_id": event["journal_id"], "executor_epoch": lease["executor_epoch"], "job_id": lease["job_id"], "attempt_id": lease["attempt_id"], "lease_id": lease["lease_id"], "fencing_generation": lease["fencing_generation"]} + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, "state": "LEASED", "lease_executor_epoch": lease["executor_epoch"], "public_fence_tuple": fence, "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + capacity_after = session["capacity_in_use"] + 1 + reduced["worker_sessions"] = [{**session, "revision": session["revision"] + 1, "state": "BUSY", "capacity_in_use": capacity_after, "next_heartbeat_due_at": payload["next_heartbeat_due_at"], "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["leases"] = [{**candidate, "revision": candidate["revision"] + 1, "state": "ACTIVE", "expiry_due_at": candidate["initial_expiry_due_at"] if "initial_expiry_due_at" in candidate else candidate["expiry_due_at"], "next_heartbeat_due_at": payload["next_heartbeat_due_at"], "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} if candidate["lease_id"] == lease["lease_id"] else candidate for candidate in state["leases"]] + reduced["deadlines"] = sorted([item for item in state["deadlines"] if not (item["deadline_kind"] == "LEASE_CLAIM_DEADLINE" and item["entity_id"] == lease["lease_id"])] + [ + {"deadline_kind": "LEASE_EXPIRY", "due_at": lease["expiry_due_at"], "fixed_priority": _DEADLINE_PRIORITY["LEASE_EXPIRY"], "entity_id": lease["lease_id"], "source_event_id": event["event_id"], "source_event_sigil": event["event_sigil"]}, + {"deadline_kind": "HEARTBEAT_TIMEOUT", "due_at": payload["next_heartbeat_due_at"], "fixed_priority": _DEADLINE_PRIORITY["HEARTBEAT_TIMEOUT"], "entity_id": session["worker_session_id"], "source_event_id": event["event_id"], "source_event_sigil": event["event_sigil"]}, + ], key=lambda item: (_parse_time(item["due_at"]), item["fixed_priority"], _unsigned_ascii(item["entity_id"], "Deadline entity ID"))) + return build_execution_state_v1(reduced) + + +def _reduce_attempt_starting_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Advance a leased Attempt only while its exact Lease remains active.""" + attempt = _current_attempt_v1(state, "Attempt start reducer") + lease = _active_lease_for_attempt_v1(state, attempt, "Attempt start reducer") + executor = state["executor"] + if ( + event["event_type"] != "attempt.starting" or attempt["state"] != "LEASED" or lease["state"] != "ACTIVE" + or attempt["lease_id"] != lease["lease_id"] or attempt["lease_executor_epoch"] != lease["executor_epoch"] + or attempt["public_fence_tuple"] != {"journal_id": event["journal_id"], "executor_epoch": lease["executor_epoch"], "job_id": lease["job_id"], "attempt_id": lease["attempt_id"], "lease_id": lease["lease_id"], "fencing_generation": lease["fencing_generation"]} + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + ): + _fail("Attempt start Event disagrees with active Lease authority") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, "state": "STARTING", "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + return build_execution_state_v1(reduced) + + +def _reduce_attempt_running_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Record that an already-started Attempt has entered its running phase.""" + attempt = _current_attempt_v1(state, "Attempt running reducer") + lease = _active_lease_for_attempt_v1(state, attempt, "Attempt running reducer") + executor = state["executor"] + if ( + event["event_type"] != "attempt.running" or attempt["state"] != "STARTING" or lease["state"] != "ACTIVE" + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + ): + _fail("Attempt running Event disagrees with starting Attempt") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, "state": "RUNNING", "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + return build_execution_state_v1(reduced) + + +def _reduce_result_ingress_received_v1( + state: dict[str, Any], event: dict[str, Any], receipt: dict[str, Any], intent: dict[str, Any] +) -> dict[str, Any]: + """Record one immutable Worker-result receipt for a running Attempt. + + The supplied intent is deliberately compared, rather than treated as an + append permission. A caller still has to establish the durable Index and + Journal Head separately. + """ + validate_execution_result_ingress_receipt_v1(receipt) + validate_execution_result_ingress_event_intent_v1(intent) + attempt = _current_attempt_v1(state, "Result ingress reducer") + lease = _active_lease_for_attempt_v1(state, attempt, "Result ingress reducer") + executor, payload = state["executor"], event["payload"] + owner = receipt["owner_binding"] + receipt_binding = { + "ingress_receipt_id": receipt["ingress_receipt_id"], + "ingress_receipt_sigil": receipt["ingress_receipt_sigil"], + } + expected_owner = { + "job_id": attempt["job_id"], "job_binding_sigil": state["jobs"][0]["job_binding_sigil"], + "attempt_id": attempt["attempt_id"], "attempt_binding_sigil": attempt["attempt_binding_sigil"], + "lease_id": lease["lease_id"], "lease_binding_sigil": lease["lease_binding_sigil"], + "worker_id": attempt["worker_session_binding"].get("worker_id"), + "worker_binding_sigil": attempt["worker_session_binding"].get("worker_binding_sigil"), + "worker_session_id": attempt["worker_session_binding"].get("worker_session_id"), + "worker_session_binding_sigil": attempt["worker_session_binding"].get("worker_session_binding_sigil"), + "executor_epoch": lease["executor_epoch"], "fence_tuple": attempt["public_fence_tuple"], + } + expected_payload = { + "ingress_receipt_id": receipt["ingress_receipt_id"], + "ingress_receipt_sigil": receipt["ingress_receipt_sigil"], + "result_sigil": receipt["result_sigil"], + "observation_evidence_subject_sigil": receipt["result_observation_binding"]["observation_evidence_subject_sigil"], + "received_at": receipt["received_at"], + } + if ( + event["event_type"] != "attempt.result_ingress_received" + or attempt["state"] != "RUNNING" or lease["state"] != "ACTIVE" + or attempt["result_intake"] != {"kind": "NONE"} + or owner != expected_owner + or receipt["receiver_identity"]["executor_instance_id"] != executor["executor_instance_id"] + or intent["result_ingress_receipt_binding"] != receipt_binding + or intent["event_candidate"] != event + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != lease["executor_epoch"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + or payload != expected_payload + ): + _fail("Result ingress Event disagrees with running Attempt or supplied Receipt") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, + "result_intake": {"kind": "RECEIVED", "result_ingress_receipt_binding": receipt_binding, + "observation_evidence_subject_sigil": expected_payload["observation_evidence_subject_sigil"], + "result_sigil": receipt["result_sigil"], "received_at": receipt["received_at"], + "ingress_event_intent_id": intent["ingress_event_intent_id"], "ingress_event_id": event["event_id"], + "ingress_event_sigil": event["event_sigil"]}, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + return build_execution_state_v1(reduced) + + +def _reduce_result_accepted_v1( + state: dict[str, Any], event: dict[str, Any], evidence: dict[str, Any], receipt: dict[str, Any] +) -> dict[str, Any]: + """Accept a received Result only from MATCHED supplied Observation Evidence.""" + validate_execution_observation_evidence_supplied_receipt_v1(evidence, receipt) + attempt = _current_attempt_v1(state, "Result acceptance reducer") + lease = _active_lease_for_attempt_v1(state, attempt, "Result acceptance reducer") + executor, payload, intake = state["executor"], event["payload"], attempt["result_intake"] + disposition = {"result_ingress_receipt_binding": intake["result_ingress_receipt_binding"], + "observation_evidence_subject_sigil": intake["observation_evidence_subject_sigil"], + "observation_evidence_id": evidence["observation_evidence_id"], + "observation_evidence_sigil": evidence["observation_evidence_sigil"]} + if ( + event["event_type"] != "attempt.result_accepted" or attempt["state"] != "RUNNING" + or lease["state"] != "ACTIVE" or intake["kind"] != "RECEIVED" + or evidence["assessment"]["kind"] != "MATCHED" + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["causation_event_id"] != intake["ingress_event_id"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + or payload != {"result_sigil": intake["result_sigil"], "lease_revision": lease["revision"], + "fence_tuple": attempt["public_fence_tuple"], "received_at": intake["received_at"], + "validation_evidence_sigil": evidence["observation_evidence_sigil"], + "observation_evidence_disposition_binding": disposition} + ): + _fail("Result acceptance Event disagrees with received Result or Observation Evidence") + reduced = _advance_journal_binding_v1(state, event) + result = {"kind": "ACCEPTED", "result_sigil": intake["result_sigil"], + "disposition_event_id": event["event_id"], "disposition_event_sigil": event["event_sigil"], + "disposition_sequence": event["sequence"]} + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, "result_binding": result, + "result_intake": {**intake, "kind": "DISPOSED", "observation_evidence_id": evidence["observation_evidence_id"], + "observation_evidence_sigil": evidence["observation_evidence_sigil"], "outcome": "ACCEPTED", + "disposition_event_id": event["event_id"], "disposition_event_sigil": event["event_sigil"]}, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + return build_execution_state_v1(reduced) + + +def _reduce_result_rejected_v1( + state: dict[str, Any], event: dict[str, Any], evidence: dict[str, Any], receipt: dict[str, Any] +) -> dict[str, Any]: + """Freeze the first non-matching Result disposition before draining.""" + validate_execution_observation_evidence_supplied_receipt_v1(evidence, receipt) + attempt, payload, executor = _current_attempt_v1( + state, "Result rejection reducer" + ), event["payload"], state["executor"] + intake = attempt["result_intake"] + disposition = {"result_ingress_receipt_binding": intake["result_ingress_receipt_binding"], + "observation_evidence_subject_sigil": intake["observation_evidence_subject_sigil"], + "observation_evidence_id": evidence["observation_evidence_id"], + "observation_evidence_sigil": evidence["observation_evidence_sigil"]} + if ( + event["event_type"] != "attempt.result_rejected" or attempt["state"] != "RUNNING" + or intake["kind"] != "RECEIVED" or attempt["result_binding"] != {"kind": "NONE"} + or evidence["assessment"]["kind"] == "MATCHED" + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != attempt["lease_executor_epoch"] + or event["causation_event_id"] != intake["ingress_event_id"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + or payload.get("disposition_kind") != "FIRST_DISPOSITION_REJECTION" + or payload.get("claimed_result_sigil") != intake["result_sigil"] + or payload.get("received_at") != intake["received_at"] + or payload.get("historical_disposition_event_id") is not None + or payload.get("observation_evidence_disposition_binding") != disposition + or not payload.get("reason_codes") + ): + _fail("Result rejection Event disagrees with received Result or Observation Evidence") + reduced = _advance_journal_binding_v1(state, event) + result = {"kind": "REJECTED", "message_sigil": payload["message_sigil"], + "disposition_event_id": event["event_id"], "disposition_event_sigil": event["event_sigil"], + "disposition_sequence": event["sequence"], "reason_codes": payload["reason_codes"]} + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, "result_binding": result, + "result_intake": {**intake, "kind": "DISPOSED", "observation_evidence_id": evidence["observation_evidence_id"], + "observation_evidence_sigil": evidence["observation_evidence_sigil"], "outcome": "REJECTED", + "disposition_event_id": event["event_id"], "disposition_event_sigil": event["event_sigil"]}, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + return build_execution_state_v1(reduced) + + +def _reduce_late_result_rejected_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Retain a late/conflicting Result rejection without rewriting disposition.""" + attempt, payload, executor = _current_attempt_v1( + state, "Late Result rejection reducer" + ), event["payload"], state["executor"] + result = attempt["result_binding"] + terminal_states = {"SUCCEEDED", "FAILED", "CANCELLED", "TIMED_OUT", "POLICY_VIOLATED", "LEASE_EXPIRED", "LOST", "FENCED", "REJECTED"} + historical = result.get("disposition_event_id") if result["kind"] != "NONE" else None + if ( + event["event_type"] != "attempt.result_rejected" + or attempt["state"] not in {"DRAINING", "STOPPING", "CLEANING", *terminal_states} + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != attempt["lease_executor_epoch"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + or payload.get("disposition_kind") != "LATE_OR_CONFLICTING_REJECTION" + or payload.get("historical_disposition_event_id") != historical + or not payload.get("reason_codes") + ): + _fail("Late Result rejection Event disagrees with historical Attempt disposition") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + return build_execution_state_v1(reduced) + + +def _reduce_log_chunk_committed_v1( + state: dict[str, Any], event: dict[str, Any], chunk: dict[str, Any] +) -> dict[str, Any]: + """Append one supplied immutable Log Chunk to its exact open stream.""" + validate_instance("execution-log-chunk-1.0.json", chunk) + attempt = _current_attempt_v1(state, "Log chunk reducer") + lease = _active_lease_for_attempt_v1(state, attempt, "Log chunk reducer") + payload, executor = event["payload"], state["executor"] + matches = [stream for stream in state["log_streams"] if stream["log_stream_id"] == payload["log_stream_id"]] + if len(matches) != 1: + _fail("Log chunk Event has no unique Log-stream projection") + stream = matches[0] + if ( + event["event_type"] != "log.chunk_committed" or stream["state"] != "OPEN" or lease["state"] != "ACTIVE" + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["entity_revisions"] != [{"entity_kind": "LOG_STREAM", "entity_id": stream["log_stream_id"], "preceding_revision": stream["revision"], "next_revision": stream["revision"] + 1}] + or payload["log_stream_id"] != stream["log_stream_id"] or payload["stream"] != stream["stream"] + or payload["sequence"] != stream["next_sequence"] or payload["captured_bytes_after"] != stream["captured_bytes"] + chunk["byte_length"] + or chunk["chunk_record_sigil"] != payload["chunk_record_sigil"] or chunk["blob_sigil"] != payload["blob_sigil"] + or chunk["log_stream_id"] != stream["log_stream_id"] or chunk["stream"] != stream["stream"] or chunk["sequence"] != stream["next_sequence"] + or chunk["job_id"] != attempt["job_id"] or chunk["attempt_id"] != attempt["attempt_id"] or chunk["attempt_binding_sigil"] != attempt["attempt_binding_sigil"] + or chunk["lease_id"] != lease["lease_id"] or chunk["lease_binding_sigil"] != lease["lease_binding_sigil"] + or chunk["worker_session_id"] != lease["worker_session_id"] or chunk["worker_session_binding_sigil"] != attempt["worker_session_binding"].get("worker_session_binding_sigil") + or chunk["worker_id"] != lease["worker_id"] or chunk["executor_epoch"] != lease["executor_epoch"] or chunk["fence_tuple"] != attempt["public_fence_tuple"] + ): + _fail("Log chunk Event disagrees with supplied Chunk or stream projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["log_streams"] = [ + {**candidate, "revision": candidate["revision"] + 1, "next_sequence": candidate["next_sequence"] + 1, + "captured_bytes": payload["captured_bytes_after"], "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"]} + if candidate["log_stream_id"] == stream["log_stream_id"] else candidate + for candidate in state["log_streams"] + ] + return build_execution_state_v1(reduced) + + +def _reduce_worker_session_heartbeat_accepted_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Advance one ready/busy/draining Session's monotonic heartbeat.""" + matches = [session for session in state["worker_sessions"] if session["worker_session_id"] == event["entity_revisions"][0]["entity_id"]] + if len(matches) != 1: + _fail("Worker-Session heartbeat Event has no unique Session projection") + session, payload, executor = matches[0], event["payload"], state["executor"] + floors = payload["resource_counter_floors_after"] + if ( + event["event_type"] != "worker_session.heartbeat_accepted" or session["state"] not in {"READY", "BUSY", "DRAINING"} + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != session["executor_epoch"] + or event["entity_revisions"] != [{"entity_kind": "WORKER_SESSION", "entity_id": session["worker_session_id"], "preceding_revision": session["revision"], "next_revision": session["revision"] + 1}] + or payload["worker_session_heartbeat_policy_id"] != session["worker_session_heartbeat_policy_id"] + or payload["worker_session_heartbeat_policy_sigil"] != session["worker_session_heartbeat_policy_sigil"] + or payload["prior_accepted_sequence"] != session["last_heartbeat_sequence"] + or payload["sequence"] != (session["last_heartbeat_sequence"] + 1 if session["last_heartbeat_sequence"] is not None else 0) + or _parse_time(payload["received_at"]) > _parse_time(payload["next_heartbeat_due_at"]) + or any(value is not None and value < (session["resource_counter_floors"][key] or 0) for key, value in floors.items()) + ): + _fail("Worker-Session heartbeat Event disagrees with Session projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["worker_sessions"] = [ + {**candidate, "revision": candidate["revision"] + 1, "last_heartbeat_sequence": payload["sequence"], + "last_heartbeat_message_sigil": payload["heartbeat_message_sigil"], "last_resource_sample_sigil": payload["resource_sample_sigil"], + "resource_counter_floors": floors, "next_heartbeat_due_at": payload["next_heartbeat_due_at"], + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["worker_session_id"] == session["worker_session_id"] else candidate + for candidate in state["worker_sessions"] + ] + reduced["deadlines"] = sorted([item for item in state["deadlines"] if not (item["deadline_kind"] == "HEARTBEAT_TIMEOUT" and item["entity_id"] == session["worker_session_id"])] + [{ + "deadline_kind": "HEARTBEAT_TIMEOUT", "due_at": payload["next_heartbeat_due_at"], + "fixed_priority": _DEADLINE_PRIORITY["HEARTBEAT_TIMEOUT"], "entity_id": session["worker_session_id"], + "source_event_id": event["event_id"], "source_event_sigil": event["event_sigil"], + }], key=lambda item: (_parse_time(item["due_at"]), item["fixed_priority"], _unsigned_ascii(item["entity_id"], "Deadline entity ID"))) + return build_execution_state_v1(reduced) + + +def _reduce_worker_session_message_rejected_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Retain a rejected Session control message without altering Session state.""" + matches = [session for session in state["worker_sessions"] if session["worker_session_id"] == event["entity_revisions"][0]["entity_id"]] + if len(matches) != 1: + _fail("Worker-Session rejection Event has no unique Session projection") + session, payload, executor = matches[0], event["payload"], state["executor"] + if ( + event["event_type"] != "worker_session.message_rejected" + or payload["message_kind"] not in {"WORKER_SESSION_REGISTRATION", "WORKER_SESSION_HEARTBEAT"} + or not payload["reason_codes"] or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != session["executor_epoch"] + or event["causation_event_id"] != session["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "WORKER_SESSION", "entity_id": session["worker_session_id"], "preceding_revision": session["revision"], "next_revision": session["revision"] + 1}] + ): + _fail("Worker-Session rejection Event disagrees with Session projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["worker_sessions"] = [ + {**candidate, "revision": candidate["revision"] + 1, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["worker_session_id"] == session["worker_session_id"] else candidate + for candidate in state["worker_sessions"] + ] + return build_execution_state_v1(reduced) + + +def _reduce_job_message_rejected_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Retain a rejected cancellation message without changing Job lifecycle.""" + matches = [job for job in state["jobs"] if job["job_id"] == event["entity_revisions"][0]["entity_id"]] + if len(matches) != 1: + _fail("Job message rejection Event has no unique Job projection") + job, payload, executor = matches[0], event["payload"], state["executor"] + if ( + event["event_type"] != "job.message_rejected" or payload["message_kind"] != "CANCEL_REQUEST" + or not payload["reason_codes"] or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] or event["causation_event_id"] != job["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "JOB", "entity_id": job["job_id"], "preceding_revision": job["revision"], "next_revision": job["revision"] + 1}] + ): + _fail("Job message rejection Event disagrees with Job projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["jobs"] = [ + {**candidate, "revision": candidate["revision"] + 1, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["job_id"] == job["job_id"] else candidate + for candidate in state["jobs"] + ] + return build_execution_state_v1(reduced) + + +def _reduce_worker_draining_or_quarantined_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Transition one Worker while preserving its separately projected Sessions.""" + matches = [worker for worker in state["workers"] if worker["worker_id"] == event["entity_revisions"][0]["entity_id"]] + if len(matches) != 1: + _fail("Worker lifecycle Event has no unique Worker projection") + worker, payload, executor = matches[0], event["payload"], state["executor"] + affected = payload["affected_worker_session_ids"] + target = "DRAINING" if event["event_type"] == "worker.draining" else "QUARANTINED" + valid_source = {"ENABLED"} if target == "DRAINING" else {"REGISTERED", "ENABLED", "DRAINING"} + if ( + event["event_type"] not in {"worker.draining", "worker.quarantined"} + or worker["state"] not in valid_source or affected != worker["worker_session_ids"] + or (target == "DRAINING" and not payload["reason_code"]) + or (target == "QUARANTINED" and not payload["reason_codes"]) + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != executor["executor_epoch"] + or event["causation_event_id"] != worker["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "WORKER", "entity_id": worker["worker_id"], "preceding_revision": worker["revision"], "next_revision": worker["revision"] + 1}] + ): + _fail("Worker lifecycle Event disagrees with Worker projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["workers"] = [ + {**candidate, "revision": candidate["revision"] + 1, "state": target, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["worker_id"] == worker["worker_id"] else candidate + for candidate in state["workers"] + ] + return build_execution_state_v1(reduced) + + +def _reduce_worker_retired_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Retire a Worker only after every associated Session and Lease is terminal.""" + matches = [worker for worker in state["workers"] if worker["worker_id"] == event["entity_revisions"][0]["entity_id"]] + if len(matches) != 1: + _fail("Worker retirement Event has no unique Worker projection") + worker, payload, executor = matches[0], event["payload"], state["executor"] + sessions = [session for session in state["worker_sessions"] if session["worker_id"] == worker["worker_id"]] + session_ids = sorted((session["worker_session_id"] for session in sessions), key=lambda value: _unsigned_ascii(value, "Worker session ID")) + terminal_leases = {"RELEASED", "REVOKED", "EXPIRED", "FENCED"} + if ( + event["event_type"] != "worker.retired" or worker["state"] not in {"REGISTERED", "ENABLED", "DRAINING", "QUARANTINED"} + or payload["closed_worker_session_ids"] != session_ids + or any(session["state"] != "CLOSED" for session in sessions) + or any(lease["state"] not in terminal_leases for lease in state["leases"] if lease["worker_id"] == worker["worker_id"]) + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != executor["executor_epoch"] + or event["causation_event_id"] != worker["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "WORKER", "entity_id": worker["worker_id"], "preceding_revision": worker["revision"], "next_revision": worker["revision"] + 1}] + ): + _fail("Worker retirement Event disagrees with terminal Worker resources") + reduced = _advance_journal_binding_v1(state, event) + reduced["workers"] = [ + {**candidate, "revision": candidate["revision"] + 1, "state": "RETIRED", + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["worker_id"] == worker["worker_id"] else candidate + for candidate in state["workers"] + ] + return build_execution_state_v1(reduced) + + +def _reduce_worker_session_lifecycle_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Transition a Session while requiring an exact Lease inventory.""" + matches = [session for session in state["worker_sessions"] if session["worker_session_id"] == event["entity_revisions"][0]["entity_id"]] + if len(matches) != 1: + _fail("Worker-Session lifecycle Event has no unique Session projection") + session, payload, executor = matches[0], event["payload"], state["executor"] + session_leases = [lease for lease in state["leases"] if lease["worker_session_id"] == session["worker_session_id"]] + active_ids = sorted((lease["lease_id"] for lease in session_leases if lease["state"] == "ACTIVE"), key=lambda value: _unsigned_ascii(value, "Lease ID")) + terminal_states = {"RELEASED", "REVOKED", "EXPIRED", "FENCED"} + event_type = event["event_type"] + target_by_event = { + "worker_session.draining": "DRAINING", "worker_session.offline": "OFFLINE", + "worker_session.quarantined": "QUARANTINED", "worker_session.closed": "CLOSED", + } + target = target_by_event.get(event_type) + if target is None: + _fail("Unknown Worker-Session lifecycle Event") + valid_sources = { + "DRAINING": {"READY", "BUSY"}, "OFFLINE": {"REGISTERED", "READY", "BUSY", "DRAINING"}, + "QUARANTINED": {"REGISTERED", "READY", "BUSY", "DRAINING"}, + "CLOSED": {"REGISTERED", "READY", "DRAINING", "OFFLINE", "QUARANTINED"}, + } + if event_type == "worker_session.closed": + inventory_ok = ( + payload["terminal_lease_ids"] == sorted((lease["lease_id"] for lease in session_leases), key=lambda value: _unsigned_ascii(value, "Lease ID")) + and all(lease["state"] in terminal_states for lease in session_leases) + ) + else: + inventory_ok = payload["active_lease_ids"] == active_ids + if ( + session["state"] not in valid_sources[target] or not inventory_ok + or (event_type == "worker_session.draining" and not payload["reason_code"]) + or (event_type == "worker_session.offline" and payload["last_heartbeat_sequence"] != session["last_heartbeat_sequence"]) + or (event_type == "worker_session.quarantined" and not payload["reason_codes"]) + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != session["executor_epoch"] + or event["causation_event_id"] != session["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "WORKER_SESSION", "entity_id": session["worker_session_id"], "preceding_revision": session["revision"], "next_revision": session["revision"] + 1}] + ): + _fail("Worker-Session lifecycle Event disagrees with Session or Lease projections") + reduced = _advance_journal_binding_v1(state, event) + reduced["worker_sessions"] = [ + {**candidate, "revision": candidate["revision"] + 1, "state": target, + "next_heartbeat_due_at": None if target in {"OFFLINE", "QUARANTINED", "CLOSED"} else candidate["next_heartbeat_due_at"], + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["worker_session_id"] == session["worker_session_id"] else candidate + for candidate in state["worker_sessions"] + ] + if target in {"OFFLINE", "QUARANTINED", "CLOSED"}: + reduced["deadlines"] = [item for item in state["deadlines"] if not (item["deadline_kind"] == "HEARTBEAT_TIMEOUT" and item["entity_id"] == session["worker_session_id"])] + return build_execution_state_v1(reduced) + + +def _reduce_log_chunk_duplicate_observed_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Record a duplicate chunk observation without appending bytes twice.""" + payload, executor = event["payload"], state["executor"] + matches = [stream for stream in state["log_streams"] if stream["log_stream_id"] == payload["log_stream_id"]] + if len(matches) != 1: + _fail("Log duplicate Event has no unique Log-stream projection") + stream = matches[0] + original = payload["original_disposition_event"] + if ( + event["event_type"] != "log.chunk_duplicate_observed" or payload["stream"] != stream["stream"] + or payload["sequence"] >= stream["next_sequence"] + or original.get("event_id") == event["event_id"] or original.get("event_sigil") == event["event_sigil"] + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["entity_revisions"] != [{"entity_kind": "LOG_STREAM", "entity_id": stream["log_stream_id"], "preceding_revision": stream["revision"], "next_revision": stream["revision"] + 1}] + ): + _fail("Log duplicate Event disagrees with Log-stream projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["log_streams"] = [ + {**candidate, "revision": candidate["revision"] + 1, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["log_stream_id"] == stream["log_stream_id"] else candidate + for candidate in state["log_streams"] + ] + return build_execution_state_v1(reduced) + + +def _reduce_log_closed_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Freeze one open log stream using its already-recorded local counters.""" + payload, executor = event["payload"], state["executor"] + matches = [stream for stream in state["log_streams"] if stream["log_stream_id"] == payload["log_stream_id"]] + if len(matches) != 1: + _fail("Log close Event has no unique Log-stream projection") + stream = matches[0] + if ( + event["event_type"] != "log.closed" or stream["state"] != "OPEN" + or payload["stream"] != stream["stream"] or payload["final_sequence"] != (stream["next_sequence"] - 1 if stream["next_sequence"] else None) + or payload["captured_bytes"] != stream["captured_bytes"] or payload["dropped_bytes"] != stream["dropped_bytes"] + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["entity_revisions"] != [{"entity_kind": "LOG_STREAM", "entity_id": stream["log_stream_id"], "preceding_revision": stream["revision"], "next_revision": stream["revision"] + 1}] + ): + _fail("Log close Event disagrees with open Log-stream projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["log_streams"] = [ + {**candidate, "revision": candidate["revision"] + 1, "state": "CLOSED", + "final_sequence": payload["final_sequence"], "stream_set_sigil": payload["stream_set_sigil"], + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["log_stream_id"] == stream["log_stream_id"] else candidate + for candidate in state["log_streams"] + ] + return build_execution_state_v1(reduced) + + +def _reduce_log_chunk_rejected_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Retain a rejected log chunk without changing the stream contents.""" + payload, executor = event["payload"], state["executor"] + matches = [stream for stream in state["log_streams"] if stream["log_stream_id"] == payload["log_stream_id"]] + if len(matches) != 1: + _fail("Log rejection Event has no unique Log-stream projection") + stream = matches[0] + if ( + event["event_type"] != "log.chunk_rejected" or payload["stream"] != stream["stream"] + or not payload["reason_codes"] or event["executor_instance_id"] != executor["executor_instance_id"] + or event["entity_revisions"] != [{"entity_kind": "LOG_STREAM", "entity_id": stream["log_stream_id"], "preceding_revision": stream["revision"], "next_revision": stream["revision"] + 1}] + ): + _fail("Log rejection Event disagrees with Log-stream projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["log_streams"] = [ + {**candidate, "revision": candidate["revision"] + 1, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["log_stream_id"] == stream["log_stream_id"] else candidate + for candidate in state["log_streams"] + ] + return build_execution_state_v1(reduced) + + +def _reduce_log_truncated_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Latch a stream truncation without inventing a policy resolver.""" + payload, executor = event["payload"], state["executor"] + matches = [stream for stream in state["log_streams"] if stream["log_stream_id"] == payload["log_stream_id"]] + if len(matches) != 1: + _fail("Log truncation Event has no unique Log-stream projection") + stream = matches[0] + if ( + event["event_type"] != "log.truncated" or stream["state"] != "OPEN" or stream["truncated"] + or payload["stream"] != stream["stream"] or payload["captured_bytes"] != stream["captured_bytes"] + or payload["dropped_bytes"] < stream["dropped_bytes"] or payload["limit_bytes"] < stream["captured_bytes"] + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["entity_revisions"] != [{"entity_kind": "LOG_STREAM", "entity_id": stream["log_stream_id"], "preceding_revision": stream["revision"], "next_revision": stream["revision"] + 1}] + ): + _fail("Log truncation Event disagrees with open Log-stream projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["log_streams"] = [ + {**candidate, "revision": candidate["revision"] + 1, "truncated": True, + "dropped_bytes": payload["dropped_bytes"], "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"]} + if candidate["log_stream_id"] == stream["log_stream_id"] else candidate + for candidate in state["log_streams"] + ] + return build_execution_state_v1(reduced) + + +def _reduce_attempt_draining_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Close a running Attempt after its immutable result disposition.""" + attempt, payload = _current_attempt_v1(state, "Attempt draining reducer"), event["payload"] + executor = state["executor"] + result = attempt["result_binding"] + if result["kind"] == "ACCEPTED": + anchor = {"kind": "RESULT_ACCEPTED", "event_id": result["disposition_event_id"], + "event_sigil": result["disposition_event_sigil"], "sequence": result["disposition_sequence"], + "result_sigil": result["result_sigil"]} + elif result["kind"] == "NONE": + anchor = {"kind": "NO_RESULT", "event_id": event["event_id"], "event_sigil": event["event_sigil"], + "sequence": event["sequence"], "process_exit_observation_sigil": payload["process_exit_observation_sigil"]} + elif result["kind"] == "REJECTED": + anchor = {"kind": "NOT_ESTABLISHED"} + else: + _fail("Attempt draining Event has an unknown Result disposition") + if ( + event["event_type"] != "attempt.draining" or attempt["state"] != "RUNNING" + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != attempt["lease_executor_epoch"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + or payload["result_binding"] != result + ): + _fail("Attempt draining Event disagrees with Result disposition") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, "state": "DRAINING", + "completion_anchor_binding": anchor, "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + return build_execution_state_v1(reduced) + + +def _reduce_attempt_cleaning_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Freeze the terminal-source disposition before cleanup progresses.""" + attempt, payload, executor = _current_attempt_v1( + state, "Attempt cleaning reducer" + ), event["payload"], state["executor"] + if ( + event["event_type"] != "attempt.cleaning" or attempt["state"] not in {"DRAINING", "STOPPING"} + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != attempt["lease_executor_epoch"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + or attempt["terminal_source_binding"] is not None + ): + _fail("Attempt cleaning Event disagrees with draining Attempt") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, "state": "CLEANING", + "terminal_source_binding": payload["terminal_source_binding"], "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"]}) + return build_execution_state_v1(reduced) + + +_STOP_PROGRESS_STEPS_V1 = { + "COOPERATIVE_STOP_REQUESTED", "FORCE_TERMINATION_DUE", "PROCESS_TREE_TERMINATED", "HANDLES_REVOKED", +} + + +def _reduce_attempt_stop_progressed_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Record one bounded termination action while the Attempt is stopping.""" + attempt, payload, executor = _current_attempt_v1( + state, "Stop progress reducer" + ), event["payload"], state["executor"] + if ( + event["event_type"] != "attempt.stop_progressed" or attempt["state"] != "STOPPING" + or payload["step"] not in _STOP_PROGRESS_STEPS_V1 + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != attempt["lease_executor_epoch"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + ): + _fail("Stop progress Event disagrees with stopping Attempt") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + return build_execution_state_v1(reduced) + + +_NONFINAL_CLEANUP_STEPS_V1 = { + "LOGS_CLOSED", "OUTPUTS_CLOSED", "TERMINATION_VERIFIED", "RESOURCES_CLEANED", "QUARANTINE_VERIFIED", +} + + +_ACCOUNTING_CAPTURE_FINALIZATION_KEYS_V1 = { + "kind", "control_evidence_set_binding", "quarantine_binding_set_binding", + "terminalization_storage_manifest_binding", "output_root_protection", +} + + +def _reduce_cleanup_progressed_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Replay cleanup, including the single immutable accounting capture.""" + attempt, payload, executor = _current_attempt_v1( + state, "Cleanup progress reducer" + ), event["payload"], state["executor"] + is_capture = payload["step"] == "ACCOUNTING_CAPTURED" + finalization = payload["finalization_bindings"] + capture_valid = ( + attempt["state"] == "CLEANING" + and attempt["accounting_capture_binding"] == {"kind": "PENDING"} + and set(finalization) == _ACCOUNTING_CAPTURE_FINALIZATION_KEYS_V1 + and finalization["kind"] == "FROZEN" + and finalization["control_evidence_set_binding"].get("kind") == "FROZEN" + and finalization["quarantine_binding_set_binding"].get("kind") == "FROZEN" + and finalization["terminalization_storage_manifest_binding"].get("kind") == "FROZEN" + and finalization["output_root_protection"].get("kind") in {"NO_HOLD", "HELD"} + and finalization["output_root_protection"]["terminalization_storage_manifest_binding"] + == finalization["terminalization_storage_manifest_binding"] + ) + if ( + event["event_type"] != "attempt.cleanup_progressed" + or attempt["state"] not in {"DRAINING", "STOPPING", "CLEANING"} + or (not is_capture and ( + payload["step"] not in _NONFINAL_CLEANUP_STEPS_V1 or finalization != {"kind": "NONE"} + )) + or (is_capture and not capture_valid) + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != attempt["lease_executor_epoch"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}] + ): + _fail("Cleanup progress Event disagrees with Attempt state") + reduced = _advance_journal_binding_v1(state, event) + updated = {**attempt, "revision": attempt["revision"] + 1, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if is_capture: + updated.update({ + "accounting_capture_binding": { + "kind": "CAPTURED", "event_id": event["event_id"], + "event_sigil": event["event_sigil"], "usage_status": "UNAVAILABLE", + "accounting_evidence_set_sigil": payload["cleanup_evidence_sigil"], + }, + "control_evidence_set_binding": finalization["control_evidence_set_binding"], + "quarantine_binding_set_binding": finalization["quarantine_binding_set_binding"], + "terminalization_storage_manifest_binding": finalization["terminalization_storage_manifest_binding"], + "output_root_protection": finalization["output_root_protection"], + }) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], updated) + return build_execution_state_v1(reduced) + + +def _reduce_attempt_terminal_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Project one sealed Attempt terminal Event without deriving its evidence. + + Terminalization evidence is already part of the closed Event payload. The + reducer only checks that it is compatible with the immediately preceding + Attempt projection and copies those immutable bindings into State. It + intentionally does not settle the Job budget, evaluate assurance, or + accept an Outcome. + """ + if len(state["jobs"]) != 1: + _fail("Attempt terminal reducer requires one Job") + terminal_state = _ATTEMPT_TERMINAL_EVENT_STATES_V1.get(event["event_type"]) + if terminal_state is None: + _fail("Attempt terminal reducer received a nonterminal Event") + attempt, job, payload, executor = ( + _current_attempt_v1(state, "Attempt terminal reducer"), state["jobs"][0], event["payload"], state["executor"] + ) + evidence = payload["attempt_terminal_evidence"] + expected_revision = [{ + "entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], + "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1, + }] + copied = ( + "result_binding", "attempt_authorization_state", "completion_anchor_binding", + "worker_session_binding", "lease_terminal_binding", "first_stop_or_fence_binding", + "storage_observation_binding", "terminal_source_binding", + "control_evidence_set_binding", "quarantine_binding_set_binding", + "terminalization_storage_manifest_binding", "output_root_protection", + ) + prior_lease_terminal = attempt["lease_terminal_binding"] + evidence_lease_terminal = evidence["lease_terminal_binding"] + if ( + attempt["state"] not in {"DRAINING", "STOPPING", "CLEANING"} + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != attempt["lease_executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] != expected_revision + or payload["fencing_generation"] != attempt["fencing_generation"] + or payload["final_fence_floor"] < job["fence_floor"] + or payload["final_fence_floor"] < payload["fencing_generation"] + or (prior_lease_terminal is not None and evidence_lease_terminal != prior_lease_terminal) + or (prior_lease_terminal is None and evidence_lease_terminal != {"kind": "NONE"}) + or attempt["accounting_capture_binding"].get("kind") != "CAPTURED" + or evidence["accounting_capture_event_id"] != attempt["accounting_capture_binding"]["event_id"] + or evidence["accounting_capture_event_sigil"] != attempt["accounting_capture_binding"]["event_sigil"] + or any(evidence[member] != attempt[member] for member in ( + "control_evidence_set_binding", "quarantine_binding_set_binding", + "terminalization_storage_manifest_binding", "output_root_protection", + )) + or any(evidence[member] != attempt[member] for member in copied if member in { + "result_binding", "attempt_authorization_state", "completion_anchor_binding", + "worker_session_binding", "first_stop_or_fence_binding", + "terminal_source_binding", + }) + ): + _fail("Attempt terminal Event disagrees with preceding Attempt projection") + if terminal_state == "SUCCEEDED" and evidence["completion_anchor_binding"]["kind"] == "NOT_ESTABLISHED": + _fail("Succeeded Attempt terminal Event requires an established completion anchor") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], { + **attempt, + "revision": attempt["revision"] + 1, + "state": terminal_state, + "storage_observation_binding": evidence["storage_observation_binding"], + "terminal_source_binding": evidence["terminal_source_binding"], + "control_evidence_set_binding": evidence["control_evidence_set_binding"], + "quarantine_binding_set_binding": evidence["quarantine_binding_set_binding"], + "terminalization_storage_manifest_binding": evidence["terminalization_storage_manifest_binding"], + "output_root_protection": evidence["output_root_protection"], + "output_storage_roots": payload["output_storage_roots"], + "terminal_event_binding": { + "kind": "PRESENT", "terminal_state": terminal_state, + "terminal_event_id": event["event_id"], "terminal_event_sigil": event["event_sigil"], + "terminal_sequence": event["sequence"], "terminal_recorded_at": event["recorded_at"], + }, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"], + }) + reduced["deadlines"] = [ + deadline for deadline in state["deadlines"] + if not ( + deadline["entity_id"] == attempt["attempt_id"] + and deadline["deadline_kind"] in {"ATTEMPT_DEADLINE", "CANCELLATION_GRACE"} + ) + ] + return build_execution_state_v1(reduced) + + +def _reduce_job_budget_settled_v1( + state: dict[str, Any], event: dict[str, Any], immutable_attempt: dict[str, Any] +) -> dict[str, Any]: + """Settle one terminal Attempt from its sealed reservation and accounting payload.""" + if len(state["jobs"]) != 1: + _fail("Budget settlement reducer requires one Job") + job, attempt, payload, executor = ( + state["jobs"][0], _current_attempt_v1(state, "Budget settlement reducer"), event["payload"], state["executor"] + ) + validate_execution_attempt_v1(immutable_attempt) + reservation = immutable_attempt["budget_reservation"] + dimensions = tuple(reservation) + if set(payload["reservation"]) != set(dimensions) or set(payload["measured"]) != set(dimensions) or set(payload["charged"]) != set(dimensions): + _fail("Budget settlement Event has incomplete dimension accounting") + if any( + not isinstance(payload[name][dimension], int) + or isinstance(payload[name][dimension], bool) + or payload[name][dimension] < 0 + for name in ("reservation", "measured", "charged") for dimension in dimensions + ): + _fail("Budget settlement Event has invalid dimension accounting") + if payload["usage_status"] == "UNAVAILABLE" and payload["charged"] != reservation: + _fail("Unavailable budget settlement must charge the full reservation") + if payload["usage_status"] == "MEASURED" and payload["charged"] != payload["measured"]: + _fail("Measured budget settlement must charge measured usage") + if payload["usage_status"] == "PARTIAL" and payload["charged"] != reservation: + _fail("Partial budget settlement must charge the full reservation") + if payload["charged"]["attempts"] != 1: + _fail("Budget settlement must charge exactly one Attempt") + if ( + any(payload["charged"][dimension] > reservation[dimension] for dimension in dimensions) + and attempt["state"] != "POLICY_VIOLATION" + ): + _fail("Budget overage requires a policy-violation Attempt terminal state") + expected_revisions = [ + {"entity_kind": "JOB", "entity_id": job["job_id"], "preceding_revision": job["revision"], "next_revision": job["revision"] + 1}, + {"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}, + ] + if ( + event["event_type"] != "job.budget_settled" + or job["state"] not in {"ACTIVE", "STOPPING"} + or attempt["state"] not in _ATTEMPT_TERMINAL_EVENT_STATES_V1.values() + or immutable_attempt["attempt_id"] != attempt["attempt_id"] + or immutable_attempt["attempt_binding_sigil"] != attempt["attempt_binding_sigil"] + or immutable_attempt["job_id"] != job["job_id"] + or attempt["job_id"] != job["job_id"] + or job["current_attempt_id"] != attempt["attempt_id"] + or payload["attempt_id"] != attempt["attempt_id"] + or payload["reservation"] != reservation + or attempt["budget_settlement_binding"] != {"kind": "PENDING"} + or attempt["accounting_capture_binding"]["event_id"] != payload["accounting_capture_event_id"] + or attempt["accounting_capture_binding"]["event_sigil"] != payload["accounting_capture_event_sigil"] + or attempt["accounting_capture_binding"]["usage_status"] != payload["usage_status"] + or attempt["accounting_capture_binding"]["accounting_evidence_set_sigil"] != payload["accounting_evidence_set_sigil"] + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] != executor["executor_build_binding"]["executor_build_sigil"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] != expected_revisions + or _parse_time(payload["accounting_started_at"]) > _parse_time(payload["accounting_ended_at"]) + ): + _fail("Budget settlement Event disagrees with terminal Attempt") + ledger: dict[str, Any] = { + name: dict(value) + for name, value in job["budget_ledger"].items() + if name != "budget_ledger_sigil" + } + for dimension in dimensions: + entry = ledger[dimension] + if entry["reserved"] < reservation[dimension]: + _fail("Budget settlement reservation exceeds the Job ledger") + entry["reserved"] -= reservation[dimension] + entry["consumed"] += payload["charged"][dimension] + total = entry["reserved"] + entry["consumed"] + entry["exhaustion_status"] = "AVAILABLE" if total < entry["limit"] else "EXHAUSTED" if total == entry["limit"] else "EXCEEDED" + ledger["budget_ledger_sigil"] = content_sigil(ledger) + if payload["resulting_budget_ledger_sigil"] != ledger["budget_ledger_sigil"]: + _fail("Budget settlement Event ledger Sigil mismatch") + reduced = _advance_journal_binding_v1(state, event) + reduced["jobs"] = [{**job, "revision": job["revision"] + 1, "budget_ledger": ledger, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], { + **attempt, "revision": attempt["revision"] + 1, + "accounting_capture_binding": attempt["accounting_capture_binding"], + "budget_settlement_binding": {"kind": "SETTLED", "event_id": event["event_id"], + "event_sigil": event["event_sigil"], + "accounting_capture_event_id": payload["accounting_capture_event_id"], + "accounting_capture_event_sigil": payload["accounting_capture_event_sigil"], + "usage_status": payload["usage_status"]}, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"], + }) + return build_execution_state_v1(reduced) + + +def _reduce_attempt_assurance_evaluated_v1( + state: dict[str, Any], event: dict[str, Any] +) -> dict[str, Any]: + """Freeze one terminal Attempt assurance result and its final Job summary.""" + if len(state["jobs"]) != 1: + _fail("Attempt assurance reducer requires one Job") + job, payload, executor = state["jobs"][0], event["payload"], state["executor"] + attempt_id = event["entity_revisions"][-1]["entity_id"] if event["entity_revisions"] else "" + matches = [item for item in state["attempts"] if item["attempt_id"] == attempt_id] + if len(matches) != 1: + _fail("Attempt assurance Event names an unknown Attempt") + attempt = matches[0] + evaluation = payload["evaluation"] + reasons = payload["reason_codes"] + claimed = evaluation == "CLAIMED" + expected_revisions = [ + {"entity_kind": "JOB", "entity_id": job["job_id"], + "preceding_revision": job["revision"], "next_revision": job["revision"] + 1}, + {"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], + "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}, + ] + if ( + evaluation not in {"CLAIMED", "UNMET", "UNVERIFIABLE"} + or (claimed and (payload["assurance_claim_sigil"] is None or reasons)) + or (not claimed and (payload["assurance_claim_sigil"] is not None or not reasons)) + or reasons != sorted(set(reasons)) + or job["state"] not in {"ACTIVE", "STOPPING"} + or job["current_attempt_id"] != attempt["attempt_id"] + or attempt["state"] not in _ATTEMPT_TERMINAL_EVENT_STATES_V1.values() + or attempt["budget_settlement_binding"].get("kind") != "SETTLED" + or attempt["attempt_assurance_binding"] != {"kind": "PENDING"} + or any(summary["attempt_id"] == attempt["attempt_id"] for summary in job["attempt_summaries"]) + or event["event_type"] != "attempt.assurance_evaluated" + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] != executor["executor_build_binding"]["executor_build_sigil"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] != expected_revisions + ): + _fail("Attempt assurance Event disagrees with settled terminal Attempt") + base = {"kind": evaluation, "evaluation_event_id": event["event_id"], + "evaluation_event_sigil": event["event_sigil"], "evaluation_sequence": event["sequence"], + "evidence_set_sigil": payload["evidence_set_sigil"]} + assurance = ( + {**base, "assurance_claim_sigil": payload["assurance_claim_sigil"]} + if claimed else {**base, "reason_codes": reasons} + ) + summary = { + "attempt_id": attempt["attempt_id"], "attempt_binding_sigil": attempt["attempt_binding_sigil"], + "retry_ordinal": attempt["retry_ordinal"], "terminal_state": attempt["state"], + "terminal_event_id": attempt["terminal_event_binding"]["terminal_event_id"], + "terminal_event_sigil": attempt["terminal_event_binding"]["terminal_event_sigil"], + "worker_session_binding": attempt["worker_session_binding"], + "attempt_authorization_requirement": attempt["attempt_authorization_requirement"], + "attempt_authorization_state": attempt["attempt_authorization_state"], + "budget_settlement_event_sigil": attempt["budget_settlement_binding"]["event_sigil"], + "assurance_evaluation_event_sigil": event["event_sigil"], + } + reduced = _advance_journal_binding_v1(state, event) + reduced["jobs"] = [{ + **job, "revision": job["revision"] + 1, "current_attempt_id": None, + "attempt_summaries": [*job["attempt_summaries"], summary], + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"], + }] + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], { + **attempt, + "revision": attempt["revision"] + 1, + "attempt_assurance_binding": assurance, + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + }) + return build_execution_state_v1(reduced) + + +def _reduce_job_assurance_evaluated_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Freeze the Job assurance roll-up from an already finalized Attempt.""" + if len(state["jobs"]) != 1: + _fail("Job assurance reducer requires one Job") + job, payload, executor = state["jobs"][0], event["payload"], state["executor"] + evaluation, attempt_id, reasons = payload["evaluation"], payload["attempt_id"], payload["reason_codes"] + expected = [{"entity_kind": "JOB", "entity_id": job["job_id"], + "preceding_revision": job["revision"], "next_revision": job["revision"] + 1}] + if ( + evaluation not in {"CLAIMED", "UNMET", "UNVERIFIABLE", "NOT_APPLICABLE"} + or job["state"] not in {"ACTIVE", "STOPPING"} + or job["current_attempt_id"] is not None or job["job_assurance_binding"] != {"kind": "PENDING"} + or event["event_type"] != "job.assurance_evaluated" + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] != executor["executor_build_binding"]["executor_build_sigil"] + or event["causation_event_id"] != job["last_event_id"] + or event["entity_revisions"] != expected or reasons != sorted(set(reasons)) + ): + _fail("Job assurance Event disagrees with finalized Job prefix") + if evaluation == "NOT_APPLICABLE": + if job["attempt_summaries"] or attempt_id is not None or payload["attempt_assurance_event_sigil"] is not None or payload["assurance_claim_sigil"] is not None or reasons != ["NO_ATTEMPT_ALLOCATED"]: + _fail("No-attempt Job assurance Event disagrees with Job") + binding = {"kind": evaluation, "evaluation_event_id": event["event_id"], + "evaluation_event_sigil": event["event_sigil"], "evaluation_sequence": event["sequence"], + "reason": "NO_ATTEMPT_ALLOCATED", "evidence_set_sigil": payload["evidence_set_sigil"]} + else: + matches = [item for item in state["attempts"] if item["attempt_id"] == attempt_id] + if len(matches) != 1: + _fail("Job assurance Event names an unknown Attempt") + attempt = matches[0] + attempt_assurance = attempt["attempt_assurance_binding"] + if ( + not job["attempt_summaries"] + or attempt_id != max(job["attempt_summaries"], key=lambda item: item["retry_ordinal"])["attempt_id"] + or attempt_assurance.get("kind") != evaluation + or payload["attempt_assurance_event_sigil"] != attempt_assurance["evaluation_event_sigil"] + or payload["evidence_set_sigil"] != attempt_assurance["evidence_set_sigil"] + or (evaluation == "CLAIMED" and (payload["assurance_claim_sigil"] != attempt_assurance["assurance_claim_sigil"] or reasons)) + or (evaluation != "CLAIMED" and (payload["assurance_claim_sigil"] is not None or reasons != attempt_assurance["reason_codes"])) + ): + _fail("Job assurance Event disagrees with Attempt assurance") + base = {"kind": evaluation, "evaluation_event_id": event["event_id"], + "evaluation_event_sigil": event["event_sigil"], "evaluation_sequence": event["sequence"], + "attempt_id": attempt_id, "attempt_assurance_event_sigil": payload["attempt_assurance_event_sigil"], + "evidence_set_sigil": payload["evidence_set_sigil"]} + binding = {**base, "assurance_claim_sigil": payload["assurance_claim_sigil"]} if evaluation == "CLAIMED" else {**base, "reason_codes": reasons} + reduced = _advance_journal_binding_v1(state, event) + reduced["jobs"] = [{**job, "revision": job["revision"] + 1, "job_assurance_binding": binding, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + return build_execution_state_v1(reduced) + + +_JOB_TERMINAL_EVENT_STATES_V1 = { + "job.succeeded": "SUCCEEDED", "job.failed": "FAILED", "job.cancelled": "CANCELLED", + "job.timed_out": "TIMED_OUT", "job.policy_violated": "POLICY_VIOLATION", +} + + +def _reduce_job_terminal_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Close a Job only from its finalized summaries and assurance roll-up.""" + if len(state["jobs"]) != 1: + _fail("Job terminal reducer requires one Job") + job, payload, executor = state["jobs"][0], event["payload"], state["executor"] + terminal_state = _JOB_TERMINAL_EVENT_STATES_V1.get(event["event_type"]) + if terminal_state is None: + _fail("Job terminal reducer received a nonterminal Event") + expected_revision = [{"entity_kind": "JOB", "entity_id": job["job_id"], + "preceding_revision": job["revision"], "next_revision": job["revision"] + 1}] + cause = payload["transition_cause"] + required_cause = { + "job.failed": {"ADMISSION_INVALID", "FATAL_INFRASTRUCTURE", "INTEGRITY_FAILURE", "CLOCK_UNCERTAIN", "ATTEMPT_NONRETRYABLE", "ATTEMPT_REJECTED", "RETRY_EXHAUSTED", "RESULT_REQUIREMENT_FAILED", "OUTPUT_VALIDATION_FAILED", "TERMINAL_SOURCE_RETENTION_FAILED", "TERMINATION_FAILED", "CLEANUP_FAILED", "ASSURANCE_UNMET", "ASSURANCE_UNVERIFIABLE", "BUDGET_EXHAUSTED"}, + "job.cancelled": {"CANCEL_REQUESTED"}, + "job.timed_out": {"JOB_DEADLINE"}, + "job.policy_violated": {"POLICY_VIOLATION"}, + } + if ( + (terminal_state == "SUCCEEDED" and job["state"] != "ACTIVE") + or (terminal_state != "SUCCEEDED" and job["state"] != "STOPPING") + or job["current_attempt_id"] is not None + or job["job_assurance_binding"].get("kind") == "PENDING" + or ( + job["job_assurance_binding"].get("kind") == "NOT_APPLICABLE" + and terminal_state == "SUCCEEDED" + ) + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] != executor["executor_build_binding"]["executor_build_sigil"] + or event["causation_event_id"] != job["last_event_id"] + or event["entity_revisions"] != expected_revision + or payload["attempt_summaries"] != job["attempt_summaries"] + or payload["job_assurance_event_sigil"] != job["job_assurance_binding"]["evaluation_event_sigil"] + or payload["budget_ledger_sigil"] != job["budget_ledger"]["budget_ledger_sigil"] + or ( + terminal_state == "SUCCEEDED" and ( + cause["code"] != "COMPLETION_ESTABLISHED" + or cause["trigger_kind"] != "PRIOR_EVENT" + or cause["trigger_event_id"] != job["last_event_id"] + or cause["effective_sequence"] != job["job_assurance_binding"]["evaluation_sequence"] + ) + ) + or (terminal_state != "SUCCEEDED" and cause["code"] not in required_cause[event["event_type"]]) + or ( + terminal_state != "SUCCEEDED" and ( + job["first_stop_or_fence_binding"].get("kind") != "PRESENT" + or cause["trigger_kind"] != "PRIOR_EVENT" + or cause["trigger_event_id"] != job["first_stop_or_fence_binding"]["event_id"] + or cause["effective_sequence"] != job["first_stop_or_fence_binding"]["effective_sequence"] + ) + ) + ): + _fail("Job terminal Event disagrees with finalized Job prefix") + selected = payload["selected_attempt_binding"] + summaries = job["attempt_summaries"] + by_id = {item["attempt_id"]: item for item in state["attempts"]} + if ( + [summary["retry_ordinal"] for summary in summaries] + != sorted(summary["retry_ordinal"] for summary in summaries) + or len({summary["attempt_id"] for summary in summaries}) != len(summaries) + or set(job["attempt_ids"]) != set(by_id) + or set(job["attempt_ids"]) != {summary["attempt_id"] for summary in summaries} + or any( + summary["terminal_state"] != by_id[summary["attempt_id"]]["state"] + or summary["attempt_binding_sigil"] != by_id[summary["attempt_id"]]["attempt_binding_sigil"] + or summary["terminal_event_sigil"] != by_id[summary["attempt_id"]]["terminal_event_binding"].get("terminal_event_sigil") + or summary["budget_settlement_event_sigil"] != by_id[summary["attempt_id"]]["budget_settlement_binding"].get("event_sigil") + or summary["assurance_evaluation_event_sigil"] != by_id[summary["attempt_id"]]["attempt_assurance_binding"].get("evaluation_event_sigil") + for summary in summaries + ) + ): + _fail("Job terminal Event has incomplete or non-final Attempt summaries") + if not job["attempt_summaries"]: + if ( + selected != {"kind": "NONE"} or terminal_state == "SUCCEEDED" + or job["attempt_ids"] or state["attempts"] + or payload["completion_anchor_binding"] != {"kind": "NOT_ESTABLISHED"} + or payload["terminal_source_binding"] != {"kind": "NOT_APPLICABLE"} + or payload["first_stop_or_fence_binding"] != job["first_stop_or_fence_binding"] + or payload["output_hold_release_schedules"] + ): + _fail("No-attempt Job terminal Event has invalid selected Attempt") + expected_final_fence = {"kind": "NO_ATTEMPT", "final_fence_floor": 0} + if payload["storage_observation_binding"] != {"kind": "NOT_APPLICABLE"}: + _fail("No-attempt Job terminal Event requires inapplicable storage observation") + else: + attempt_id = max(job["attempt_summaries"], key=lambda item: item["retry_ordinal"])["attempt_id"] + matches = [item for item in state["attempts"] if item["attempt_id"] == attempt_id] + if len(matches) != 1: + _fail("Job terminal Event selected Attempt is unavailable") + attempt = matches[0] + expected_selected = { + "kind": "SELECTED", "attempt_id": attempt["attempt_id"], + "attempt_binding_sigil": attempt["attempt_binding_sigil"], + "attempt_terminal_event_id": attempt["terminal_event_binding"]["terminal_event_id"], + "attempt_terminal_event_sigil": attempt["terminal_event_binding"]["terminal_event_sigil"], + "attempt_authorization_state": attempt["attempt_authorization_state"], + "worker_session_binding": attempt["worker_session_binding"], + "result_binding": attempt["result_binding"], + "completion_anchor_binding": attempt["completion_anchor_binding"], + "first_stop_or_fence_binding": attempt["first_stop_or_fence_binding"], + "storage_observation_binding": attempt["storage_observation_binding"], + } + if ( + selected != expected_selected + or payload["completion_anchor_binding"] != attempt["completion_anchor_binding"] + or payload["first_stop_or_fence_binding"] != attempt["first_stop_or_fence_binding"] + or payload["storage_observation_binding"] != attempt["storage_observation_binding"] + or payload["terminal_source_binding"] != attempt["terminal_source_binding"] + ): + _fail("Job terminal Event does not exactly copy its selected Attempt") + if attempt["lease_terminal_binding"] is None: + expected_final_fence = {"kind": "ASSIGNED_NO_LEASE", "final_fence_floor": job["fence_floor"], + "attempt_id": attempt["attempt_id"], + "attempt_terminal_event_sigil": attempt["terminal_event_binding"]["terminal_event_sigil"]} + else: + lease = attempt["lease_terminal_binding"] + expected_final_fence = {"kind": "TOMBSTONE", "final_fence_floor": lease["final_fence_floor"], + "lease_id": lease["lease_id"], "lease_terminal_event_sigil": lease["terminal_event_sigil"], + "tombstone_event_sigil": lease["tombstone_event_sigil"]} + if terminal_state == "SUCCEEDED" and ( + attempt["state"] != "SUCCEEDED" or job["job_assurance_binding"]["kind"] != "CLAIMED" + or attempt["completion_anchor_binding"]["kind"] == "NOT_ESTABLISHED" + or attempt["storage_observation_binding"].get("kind") != "FROZEN" + or attempt["terminal_source_binding"].get("kind") == "QUARANTINED" + ): + _fail("Succeeded Job terminal Event requires a claimed successful Attempt") + if payload["final_fence_binding"] != expected_final_fence: + _fail("Job terminal Event final fence disagrees with selected Attempt") + reduced = _advance_journal_binding_v1(state, event) + reduced["jobs"] = [{ + **job, "revision": job["revision"] + 1, "state": terminal_state, + "selected_attempt_binding": selected, "completion_anchor_binding": payload["completion_anchor_binding"], + "first_stop_or_fence_binding": payload["first_stop_or_fence_binding"], + "final_fence_binding": payload["final_fence_binding"], + "storage_observation_binding": payload["storage_observation_binding"], + "terminal_source_binding": payload["terminal_source_binding"], + "output_hold_release_schedules": payload["output_hold_release_schedules"], + "terminal_event_binding": {"kind": "PRESENT", "terminal_state": terminal_state, + "terminal_event_id": event["event_id"], "terminal_event_sigil": event["event_sigil"], + "terminal_sequence": event["sequence"], "terminal_recorded_at": event["recorded_at"]}, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"], + }] + reduced["deadlines"] = [deadline for deadline in state["deadlines"] if deadline["entity_id"] != job["job_id"]] + return build_execution_state_v1(reduced) + + +def _reduce_lease_released_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Close active Worker authority and publish its higher fence tombstone.""" + if len(state["jobs"]) != 1: + _fail("Lease release reducer requires one Job") + job, lease = state["jobs"][0], _lease_named_by_event_v1(state, event, "Lease release") + attempts = [item for item in state["attempts"] if item["attempt_id"] == lease["attempt_id"]] + if len(attempts) != 1: + _fail("Lease release requires the Lease Attempt") + attempt, session = attempts[0], _session_for_lease_v1(state, lease, "Lease release") + executor, payload = state["executor"], event["payload"] + expected_revisions = [ + {"entity_kind": "WORKER_SESSION", "entity_id": session["worker_session_id"], "preceding_revision": session["revision"], "next_revision": session["revision"] + 1}, + {"entity_kind": "JOB", "entity_id": job["job_id"], "preceding_revision": job["revision"], "next_revision": job["revision"] + 1}, + {"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}, + {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": lease["revision"], "next_revision": lease["revision"] + 1}, + ] + final_floor = attempt["fencing_generation"] + 1 + if ( + event["event_type"] != "lease.released" or attempt["attempt_id"] != _current_attempt_v1(state, "Lease release")["attempt_id"] or lease["state"] != "ACTIVE" + or attempt["lease_id"] != lease["lease_id"] or session["capacity_in_use"] < 1 + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["causation_event_id"] != attempt["last_event_id"] or event["entity_revisions"] != expected_revisions + or final_floor <= job["fence_floor"] + or payload["prior_fence_floor"] != job["fence_floor"] or payload["tombstone_generation"] != final_floor + or payload["session_capacity_after"] != session["capacity_in_use"] - 1 + ): + _fail("Lease release Event disagrees with active Lease authority") + reduced = _advance_journal_binding_v1(state, event) + capacity_after = session["capacity_in_use"] - 1 + reduced["worker_sessions"] = [{**candidate, "revision": candidate["revision"] + 1, + "state": "READY" if capacity_after == 0 else "BUSY", "capacity_in_use": capacity_after, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["worker_session_id"] == session["worker_session_id"] else candidate + for candidate in state["worker_sessions"]] + reduced["jobs"] = [{**job, "revision": job["revision"] + 1, "fence_floor": final_floor, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, + "lease_terminal_binding": {"kind": "TERMINAL", "lease_id": lease["lease_id"], "lease_state": "RELEASED", + "terminal_event_id": event["event_id"], "terminal_event_sigil": event["event_sigil"], + "final_fence_floor": final_floor, "tombstone_event_sigil": payload["tombstone_publication_sigil"]}, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + reduced["leases"] = [{**candidate, "revision": candidate["revision"] + 1, "state": "RELEASED", + "next_heartbeat_due_at": None, "tombstone_generation": final_floor, + "tombstone_event_sigil": payload["tombstone_publication_sigil"], "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], "terminal_event_binding": { + "kind": "PRESENT", "terminal_state": "RELEASED", "terminal_event_id": event["event_id"], + "terminal_event_sigil": event["event_sigil"], "terminal_sequence": event["sequence"], + "terminal_recorded_at": event["recorded_at"], + }} if candidate["lease_id"] == lease["lease_id"] else candidate for candidate in state["leases"]] + reduced["deadlines"] = [item for item in state["deadlines"] if not ( + item["entity_id"] in {lease["lease_id"], session["worker_session_id"]} + and item["deadline_kind"] in {"LEASE_EXPIRY", "HEARTBEAT_TIMEOUT"} + )] + return build_execution_state_v1(reduced) + + +def _reduce_lease_expired_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Expire offered or active authority without implicitly stopping the Attempt.""" + if len(state["jobs"]) != 1: + _fail("Lease expiry reducer requires one Job") + job, lease = state["jobs"][0], _lease_named_by_event_v1(state, event, "Lease expiry") + attempts = [item for item in state["attempts"] if item["attempt_id"] == lease["attempt_id"]] + if len(attempts) != 1: + _fail("Lease expiry requires the Lease Attempt") + attempt, session = attempts[0], _session_for_lease_v1(state, lease, "Lease expiry") + executor, payload = state["executor"], event["payload"] + active = lease["state"] == "ACTIVE" + expected_revisions = [ + {"entity_kind": "WORKER_SESSION", "entity_id": session["worker_session_id"], "preceding_revision": session["revision"], "next_revision": session["revision"] + 1}, + {"entity_kind": "JOB", "entity_id": job["job_id"], "preceding_revision": job["revision"], "next_revision": job["revision"] + 1}, + {"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}, + {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": lease["revision"], "next_revision": lease["revision"] + 1}, + ] + deadline_kind = "LEASE_EXPIRY" if active else "LEASE_CLAIM_DEADLINE" + due_at = lease["expiry_due_at"] if active else lease["claim_due_at"] + capacity_after = session["capacity_in_use"] - 1 if active else session["capacity_in_use"] + final_floor = attempt["fencing_generation"] + 1 + if ( + event["event_type"] != "lease.expired" or attempt["attempt_id"] != _current_attempt_v1(state, "Lease expiry")["attempt_id"] or lease["state"] not in {"OFFERED", "ACTIVE"} + or attempt["lease_id"] != lease["lease_id"] or (active and session["capacity_in_use"] < 1) + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["causation_event_id"] != attempt["last_event_id"] or event["entity_revisions"] != expected_revisions + or payload["deadline_kind"] != deadline_kind or payload["due_at"] != due_at + or _parse_time(event["recorded_at"]) < _parse_time(due_at) + or final_floor <= job["fence_floor"] + or payload["prior_fence_floor"] != job["fence_floor"] or payload["tombstone_generation"] != final_floor + or payload["session_capacity_after"] != capacity_after + ): + _fail("Lease expiry Event disagrees with Lease authority or deadline") + reduced = _advance_journal_binding_v1(state, event) + reduced["worker_sessions"] = [{**candidate, "revision": candidate["revision"] + 1, + "state": "READY" if capacity_after == 0 else "BUSY", "capacity_in_use": capacity_after, + "next_heartbeat_due_at": None if active else session["next_heartbeat_due_at"], + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["worker_session_id"] == session["worker_session_id"] else candidate + for candidate in state["worker_sessions"]] + reduced["jobs"] = [{**job, "revision": job["revision"] + 1, "fence_floor": final_floor, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, + "lease_terminal_binding": {"kind": "TERMINAL", "lease_id": lease["lease_id"], "lease_state": "EXPIRED", + "terminal_event_id": event["event_id"], "terminal_event_sigil": event["event_sigil"], + "final_fence_floor": final_floor, "tombstone_event_sigil": payload["tombstone_publication_sigil"]}, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + reduced["leases"] = [{**candidate, "revision": candidate["revision"] + 1, "state": "EXPIRED", + "next_heartbeat_due_at": None, "tombstone_generation": final_floor, + "tombstone_event_sigil": payload["tombstone_publication_sigil"], "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], "terminal_event_binding": { + "kind": "PRESENT", "terminal_state": "EXPIRED", "terminal_event_id": event["event_id"], + "terminal_event_sigil": event["event_sigil"], "terminal_sequence": event["sequence"], + "terminal_recorded_at": event["recorded_at"], + }} if candidate["lease_id"] == lease["lease_id"] else candidate for candidate in state["leases"]] + reduced["deadlines"] = [item for item in state["deadlines"] if not ( + (item["entity_id"] == lease["lease_id"] and item["deadline_kind"] in {"LEASE_CLAIM_DEADLINE", "LEASE_EXPIRY"}) + or (active and item["entity_id"] == session["worker_session_id"] and item["deadline_kind"] == "HEARTBEAT_TIMEOUT") + )] + return build_execution_state_v1(reduced) + + +def _reduce_lease_revoked_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Close offered or active authority after a previously recorded stop.""" + if len(state["jobs"]) != 1: + _fail("Lease revocation reducer requires one Job") + job, lease = state["jobs"][0], _lease_named_by_event_v1(state, event, "Lease revocation") + attempts = [item for item in state["attempts"] if item["attempt_id"] == lease["attempt_id"]] + if len(attempts) != 1: + _fail("Lease revocation requires the Lease Attempt") + attempt, session = attempts[0], _session_for_lease_v1(state, lease, "Lease revocation") + executor, payload, cause = state["executor"], event["payload"], event["payload"]["transition_cause"] + active = lease["state"] == "ACTIVE" + first_stop = attempt["first_stop_or_fence_binding"] + expected_revisions = [ + {"entity_kind": "WORKER_SESSION", "entity_id": session["worker_session_id"], "preceding_revision": session["revision"], "next_revision": session["revision"] + 1}, + {"entity_kind": "JOB", "entity_id": job["job_id"], "preceding_revision": job["revision"], "next_revision": job["revision"] + 1}, + {"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}, + {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": lease["revision"], "next_revision": lease["revision"] + 1}, + ] + capacity_after = session["capacity_in_use"] - 1 if active else session["capacity_in_use"] + final_floor = attempt["fencing_generation"] + 1 + if ( + event["event_type"] != "lease.revoked" or attempt["attempt_id"] != _current_attempt_v1(state, "Lease revocation")["attempt_id"] or lease["state"] not in {"OFFERED", "ACTIVE"} + or attempt["state"] != "STOPPING" or first_stop.get("kind") != "PRESENT" + or attempt["lease_id"] != lease["lease_id"] or (active and session["capacity_in_use"] < 1) + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["causation_event_id"] != attempt["last_event_id"] or event["entity_revisions"] != expected_revisions + or cause["trigger_kind"] != "PRIOR_EVENT" or cause["trigger_event_id"] != first_stop["event_id"] + or cause["effective_sequence"] != first_stop["effective_sequence"] + or final_floor <= job["fence_floor"] + or payload["prior_fence_floor"] != job["fence_floor"] or payload["tombstone_generation"] != final_floor + or payload["session_capacity_after"] != capacity_after + ): + _fail("Lease revocation Event disagrees with latched stop or Lease authority") + reduced = _advance_journal_binding_v1(state, event) + reduced["worker_sessions"] = [{**candidate, "revision": candidate["revision"] + 1, + "state": "READY" if capacity_after == 0 else "BUSY", "capacity_in_use": capacity_after, + "next_heartbeat_due_at": None if active else session["next_heartbeat_due_at"], + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["worker_session_id"] == session["worker_session_id"] else candidate + for candidate in state["worker_sessions"]] + reduced["jobs"] = [{**job, "revision": job["revision"] + 1, "fence_floor": final_floor, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], {**attempt, "revision": attempt["revision"] + 1, + "lease_terminal_binding": {"kind": "TERMINAL", "lease_id": lease["lease_id"], "lease_state": "REVOKED", + "terminal_event_id": event["event_id"], "terminal_event_sigil": event["event_sigil"], + "final_fence_floor": final_floor, "tombstone_event_sigil": payload["tombstone_publication_sigil"]}, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}) + reduced["leases"] = [{**candidate, "revision": candidate["revision"] + 1, "state": "REVOKED", + "next_heartbeat_due_at": None, "tombstone_generation": final_floor, + "tombstone_event_sigil": payload["tombstone_publication_sigil"], "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], "terminal_event_binding": { + "kind": "PRESENT", "terminal_state": "REVOKED", "terminal_event_id": event["event_id"], + "terminal_event_sigil": event["event_sigil"], "terminal_sequence": event["sequence"], + "terminal_recorded_at": event["recorded_at"], + }} if candidate["lease_id"] == lease["lease_id"] else candidate for candidate in state["leases"]] + reduced["deadlines"] = [item for item in state["deadlines"] if not ( + (item["entity_id"] == lease["lease_id"] and item["deadline_kind"] in {"LEASE_CLAIM_DEADLINE", "LEASE_EXPIRY"}) + or (active and item["entity_id"] == session["worker_session_id"] and item["deadline_kind"] == "HEARTBEAT_TIMEOUT") + )] + return build_execution_state_v1(reduced) + + +def _reduce_lease_fenced_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Tombstone an offered or active Lease after authority is lost. + + This is the Recovery/epoch-loss branch. It only projects the already + journaled fence decision and does not infer process termination or any + later Attempt terminal state. + """ + if len(state["jobs"]) != 1: + _fail("Lease fencing reducer requires one Job") + job = state["jobs"][0] + lease = _lease_named_by_event_v1(state, event, "Lease fencing") + attempts = [item for item in state["attempts"] if item["attempt_id"] == lease["attempt_id"]] + if len(attempts) != 1: + _fail("Lease fencing requires the Lease Attempt") + attempt = attempts[0] + session = _session_for_lease_v1(state, lease, "Lease fencing") + executor, payload, cause = state["executor"], event["payload"], event["payload"]["transition_cause"] + active = lease["state"] == "ACTIVE" + capacity_after = session["capacity_in_use"] - 1 if active else session["capacity_in_use"] + final_floor = attempt["fencing_generation"] + 1 + expected_revisions = [ + {"entity_kind": "WORKER_SESSION", "entity_id": session["worker_session_id"], "preceding_revision": session["revision"], "next_revision": session["revision"] + 1}, + {"entity_kind": "JOB", "entity_id": job["job_id"], "preceding_revision": job["revision"], "next_revision": job["revision"] + 1}, + {"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}, + {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": lease["revision"], "next_revision": lease["revision"] + 1}, + ] + if ( + event["event_type"] != "lease.fenced" + or attempt["attempt_id"] != _current_attempt_v1(state, "Lease fencing")["attempt_id"] + or lease["state"] not in {"OFFERED", "ACTIVE"} + or attempt["lease_id"] != lease["lease_id"] + or (active and session["capacity_in_use"] < 1) + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["entity_revisions"] != expected_revisions + or cause["code"] not in {"RECOVERY_FENCE", "EXECUTOR_EPOCH_CHANGED", "LOST_OWNERSHIP"} + or cause["trigger_kind"] not in {"PRIOR_EVENT", "RECOVERY_DERIVATION"} + or final_floor <= job["fence_floor"] + or payload["prior_fence_floor"] != job["fence_floor"] + or payload["tombstone_generation"] != final_floor + or payload["session_capacity_after"] != capacity_after + ): + _fail("Lease fencing Event disagrees with Lease authority") + reduced = _advance_journal_binding_v1(state, event) + reduced["worker_sessions"] = [{ + **candidate, + "revision": candidate["revision"] + 1, + "state": "READY" if capacity_after == 0 else "BUSY", + "capacity_in_use": capacity_after, + "next_heartbeat_due_at": None if active else session["next_heartbeat_due_at"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } if candidate["worker_session_id"] == session["worker_session_id"] else candidate + for candidate in state["worker_sessions"]] + reduced["jobs"] = [{ + **job, + "revision": job["revision"] + 1, + "fence_floor": final_floor, + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + }] + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], { + **attempt, + "revision": attempt["revision"] + 1, + "lease_terminal_binding": { + "kind": "TERMINAL", "lease_id": lease["lease_id"], "lease_state": "FENCED", + "terminal_event_id": event["event_id"], "terminal_event_sigil": event["event_sigil"], + "final_fence_floor": final_floor, "tombstone_event_sigil": payload["tombstone_publication_sigil"], + }, + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + }) + reduced["leases"] = [{ + **candidate, + "revision": lease["revision"] + 1, + "state": "FENCED", + "next_heartbeat_due_at": None, + "tombstone_generation": final_floor, + "tombstone_event_sigil": payload["tombstone_publication_sigil"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + "terminal_event_binding": { + "kind": "PRESENT", "terminal_state": "FENCED", + "terminal_event_id": event["event_id"], "terminal_event_sigil": event["event_sigil"], + "terminal_sequence": event["sequence"], "terminal_recorded_at": event["recorded_at"], + }, + } if candidate["lease_id"] == lease["lease_id"] else candidate for candidate in state["leases"]] + reduced["deadlines"] = [item for item in state["deadlines"] if not ( + (item["entity_id"] == lease["lease_id"] and item["deadline_kind"] in {"LEASE_CLAIM_DEADLINE", "LEASE_EXPIRY"}) + or (active and item["entity_id"] == session["worker_session_id"] and item["deadline_kind"] == "HEARTBEAT_TIMEOUT") + )] + return build_execution_state_v1(reduced) + + +def _reduce_lease_tombstone_republished_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Record an additional publication of an already terminal Lease tombstone.""" + lease, payload, executor = ( + _lease_named_by_event_v1(state, event, "Lease tombstone republish"), + event["payload"], state["executor"], + ) + terminal = lease["terminal_event_binding"] + if ( + event["event_type"] != "lease.tombstone_republished" + or lease["state"] not in {"RELEASED", "REVOKED", "EXPIRED", "FENCED"} + or terminal.get("kind") != "PRESENT" + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["entity_revisions"] != [{"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": lease["revision"], "next_revision": lease["revision"] + 1}] + or payload["tombstone_generation"] != lease["tombstone_generation"] + or payload["original_terminal_event_sigil"] != terminal["terminal_event_sigil"] + ): + _fail("Lease tombstone republish Event disagrees with terminal Lease") + reduced = _advance_journal_binding_v1(state, event) + reduced["leases"] = [{**candidate, "revision": candidate["revision"] + 1, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["lease_id"] == lease["lease_id"] else candidate for candidate in state["leases"]] + return build_execution_state_v1(reduced) + + +_LEASE_REJECTED_MESSAGE_KINDS_V1 = { + "LEASE_CLAIM", "LEASE_HEARTBEAT", "LEASE_RENEWAL", "LEASE_RELEASE", +} + + +def _reduce_lease_message_rejected_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Append a non-mutating rejection of a Lease control message.""" + lease, payload, executor = ( + _lease_named_by_event_v1(state, event, "Lease message rejection"), + event["payload"], state["executor"], + ) + if ( + event["event_type"] != "lease.message_rejected" + or payload["message_kind"] not in _LEASE_REJECTED_MESSAGE_KINDS_V1 + or not payload["reason_codes"] + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != lease["executor_epoch"] + or event["causation_event_id"] != lease["last_event_id"] + or event["entity_revisions"] != [{"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": lease["revision"], "next_revision": lease["revision"] + 1}] + ): + _fail("Lease message rejection Event disagrees with Lease projection") + reduced = _advance_journal_binding_v1(state, event) + reduced["leases"] = [{**candidate, "revision": candidate["revision"] + 1, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]} + if candidate["lease_id"] == lease["lease_id"] else candidate for candidate in state["leases"]] + return build_execution_state_v1(reduced) + + +def _reduce_attempt_stop_after_lease_expiry_v1( + state: dict[str, Any], event: dict[str, Any] +) -> dict[str, Any]: + """Latch the mandatory stop after an expired Lease tombstone. + + The expiry is the authoritative trigger; this reducer deliberately does + not infer cancellation, policy, or deadline causes from a local State. + """ + if len(state["jobs"]) != 1 or len(state["attempts"]) != 1 or len(state["leases"]) != 1: + _fail("Lease-expiry stop reducer requires one Job, Attempt, and Lease") + job, attempt, lease = state["jobs"][0], state["attempts"][0], state["leases"][0] + executor, payload, cause = state["executor"], event["payload"], event["payload"]["transition_cause"] + terminal = lease["terminal_event_binding"] + # ``lease.expired`` already advances the Job in this effective-sequence + # due chain, so RFC-0012 requires EQUAL(JOB), not a second advance. + active_expiry = attempt["state"] in {"LEASED", "STARTING", "RUNNING", "DRAINING"} + cause_code = "LEASE_ACTIVE_EXPIRED" if active_expiry else "LEASE_CLAIM_EXPIRED" + expected_revisions = [ + {"entity_kind": "JOB", "entity_id": job["job_id"], "preceding_revision": job["revision"], "next_revision": job["revision"]}, + {"entity_kind": "ATTEMPT", "entity_id": attempt["attempt_id"], "preceding_revision": attempt["revision"], "next_revision": attempt["revision"] + 1}, + ] + first_stop = {"kind": "PRESENT", "event_id": terminal.get("terminal_event_id"), + "event_type": "lease.expired", "event_sigil": terminal.get("terminal_event_sigil"), + "effective_sequence": terminal.get("terminal_sequence")} + if ( + event["event_type"] != "attempt.stop_latched" or lease["state"] != "EXPIRED" + or attempt["state"] not in {"READY", "LEASED", "STARTING", "RUNNING", "DRAINING"} + or job["state"] != "ACTIVE" or attempt["lease_id"] != lease["lease_id"] + or attempt["lease_terminal_binding"] is None or terminal.get("kind") != "PRESENT" + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["causation_event_id"] != terminal["terminal_event_id"] or event["entity_revisions"] != expected_revisions + or cause != {"code": cause_code, "trigger_kind": "PRIOR_EVENT", + "trigger_event_id": terminal["terminal_event_id"], "effective_sequence": terminal["terminal_sequence"], + "evidence_sigil": lease["tombstone_event_sigil"]} + or _parse_time(payload["grace_due_at"]) < _parse_time(event["recorded_at"]) + or attempt["first_stop_or_fence_binding"] != {"kind": "NONE"} + ): + _fail("Attempt stop Event disagrees with expired Lease tombstone") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = [{**attempt, "revision": attempt["revision"] + 1, "state": "STOPPING", + "grace_due_at": payload["grace_due_at"], "first_stop_or_fence_binding": first_stop, + "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["deadlines"] = sorted([*state["deadlines"], { + "deadline_kind": "CANCELLATION_GRACE", "due_at": payload["grace_due_at"], + "fixed_priority": _DEADLINE_PRIORITY["CANCELLATION_GRACE"], "entity_id": attempt["attempt_id"], + "source_event_id": event["event_id"], "source_event_sigil": event["event_sigil"], + }], key=lambda item: (_parse_time(item["due_at"]), item["fixed_priority"], _unsigned_ascii(item["entity_id"], "Deadline entity ID"))) + return build_execution_state_v1(reduced) + + +def _reduce_lease_heartbeat_accepted_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Advance one active Lease's monotonic supervisor-observed heartbeat.""" + if len(state["leases"]) != 1: + _fail("Lease heartbeat reducer requires one active Lease") + lease, payload, executor = state["leases"][0], event["payload"], state["executor"] + prior = lease["last_heartbeat_sequence"] + floors = payload["resource_counter_floors_after"] + if ( + event["event_type"] != "lease.heartbeat_accepted" or lease["state"] != "ACTIVE" + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["entity_revisions"] != [{"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": lease["revision"], "next_revision": lease["revision"] + 1}] + or payload["prior_accepted_sequence"] != prior or payload["sequence"] <= (prior or 0) + or _parse_time(payload["received_at"]) > _parse_time(payload["next_heartbeat_due_at"]) + or _parse_time(payload["received_at"]) > _parse_time(lease["expiry_due_at"]) + or any(value is not None and value < (lease["resource_counter_floors"][key] or 0) for key, value in floors.items()) + ): + _fail("Lease heartbeat Event disagrees with active Lease state") + reduced = _advance_journal_binding_v1(state, event) + reduced["leases"] = [{**lease, "revision": lease["revision"] + 1, + "last_heartbeat_sequence": payload["sequence"], "last_heartbeat_message_sigil": payload["heartbeat_message_sigil"], + "last_resource_sample_sigil": payload["resource_sample_sigil"], "resource_counter_floors": floors, + "next_heartbeat_due_at": payload["next_heartbeat_due_at"], "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["deadlines"] = sorted([item for item in state["deadlines"] if not (item["deadline_kind"] == "HEARTBEAT_TIMEOUT" and item["entity_id"] == lease["worker_session_id"])] + [{"deadline_kind": "HEARTBEAT_TIMEOUT", "due_at": payload["next_heartbeat_due_at"], "fixed_priority": _DEADLINE_PRIORITY["HEARTBEAT_TIMEOUT"], "entity_id": lease["worker_session_id"], "source_event_id": event["event_id"], "source_event_sigil": event["event_sigil"]}], key=lambda item: (_parse_time(item["due_at"]), item["fixed_priority"], _unsigned_ascii(item["entity_id"], "Deadline entity ID"))) + return build_execution_state_v1(reduced) + + +def _reduce_lease_renewed_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + """Extend an active Lease only within its immutable maximum expiry.""" + if len(state["leases"]) != 1: + _fail("Lease renewal reducer requires one active Lease") + lease, payload, executor = state["leases"][0], event["payload"], state["executor"] + if ( + event["event_type"] != "lease.renewed" or lease["state"] != "ACTIVE" + or event["executor_instance_id"] != executor["executor_instance_id"] or event["executor_epoch"] != lease["executor_epoch"] + or event["entity_revisions"] != [{"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": lease["revision"], "next_revision": lease["revision"] + 1}] + or payload["prior_expiry_due_at"] != lease["expiry_due_at"] + or not (_parse_time(lease["expiry_due_at"]) < _parse_time(payload["new_expiry_due_at"]) <= _parse_time(lease["maximum_expiry_due_at"])) + or payload["renewal_counter"] != lease["renewal_counter"] + 1 + ): + _fail("Lease renewal Event disagrees with active Lease state") + reduced = _advance_journal_binding_v1(state, event) + reduced["leases"] = [{**lease, "revision": lease["revision"] + 1, "expiry_due_at": payload["new_expiry_due_at"], "renewal_counter": payload["renewal_counter"], "last_event_id": event["event_id"], "last_event_sigil": event["event_sigil"]}] + reduced["deadlines"] = sorted([item for item in state["deadlines"] if not (item["deadline_kind"] == "LEASE_EXPIRY" and item["entity_id"] == lease["lease_id"])] + [{"deadline_kind": "LEASE_EXPIRY", "due_at": payload["new_expiry_due_at"], "fixed_priority": _DEADLINE_PRIORITY["LEASE_EXPIRY"], "entity_id": lease["lease_id"], "source_event_id": event["event_id"], "source_event_sigil": event["event_sigil"]}], key=lambda item: (_parse_time(item["due_at"]), item["fixed_priority"], _unsigned_ascii(item["entity_id"], "Deadline entity ID"))) + return build_execution_state_v1(reduced) + + +def _reduce_executor_clock_restored_v1( + state: dict[str, Any], event: dict[str, Any], action_set: dict[str, Any] +) -> dict[str, Any]: + """Restore a trusted clock without reopening Recovery-gated authority. + + The frozen FINALIZING action is caller supplied and is used only to bind + this Event to its reserved recovery action. This reducer never derives an + action set, validates a time source, or treats completion of Recovery as + established. + """ + validate_execution_recovery_action_supplied_event_v1(action_set, event) + executor = state["executor"] + recovery_id = executor["active_recovery_id"] + if recovery_id is None or len(state["recoveries"]) != 1: + _fail("Clock restoration requires exactly one active Recovery") + recovery = state["recoveries"][0] + binding = event["recovery_action_binding"] + assert binding is not None + action = action_set["actions"][binding["action_ordinal"]] + payload = event["payload"] + expected_revision = [{ + "entity_kind": "EXECUTOR", + "entity_id": executor["executor_instance_id"], + "preceding_revision": executor["revision"], + "next_revision": executor["revision"] + 1, + }] + if ( + event["event_type"] != "executor.clock_restored" + or executor["clock_state"] != "UNCERTAIN" + or executor["authority_gates"] != ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"] + or recovery["recovery_id"] != recovery_id + or recovery["state"] != "FINALIZING" + or action_set["recovery_id"] != recovery_id + or action_set["phase"] != "FINALIZING" + or action_set["action_set_sigil"] != recovery["current_action_set_sigil"] + or action["action_kind"] != "RESTORE_CLOCK" + or action["entity_kind"] != "EXECUTOR" + or action["entity_id"] != executor["executor_instance_id"] + or action["expected_revision"] != executor["revision"] + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["entity_revisions"] != expected_revision + or action["parameters"]["clock_uncertain_event_id"] + != executor["clock_uncertain_event_id"] + or action["parameters"]["trusted_time_source_sigil"] + != payload["trusted_time_source_sigil"] + or payload["fenced_lease_ids"] + or any(lease["state"] in {"OFFERED", "ACTIVE"} for lease in state["leases"]) + or _parse_time(payload["restored_utc"]) < _parse_time(executor["last_trusted_utc"]) + ): + _fail("Clock restoration Event disagrees with FINALIZING Recovery state") + reduced = _advance_journal_binding_v1(state, event) + reduced["executor"] = { + **executor, + "revision": executor["revision"] + 1, + "clock_state": "TRUSTED", + "last_trusted_utc": payload["restored_utc"], + "clock_uncertain_event_id": None, + "authority_gates": ["RECOVERY_ACTIVE"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def _reduce_recovery_action_set_rebased_v1( + state: dict[str, Any], + event: dict[str, Any], + prior_action_set: dict[str, Any], + replacement_action_set: dict[str, Any], +) -> dict[str, Any]: + """Project a supplied Recovery rebase without deriving replacement work.""" + validate_execution_recovery_rebase_supplied_action_sets_v1( + state, event, prior_action_set, replacement_action_set + ) + recovery_id = state["executor"]["active_recovery_id"] + assert recovery_id is not None + recovery = next(item for item in state["recoveries"] if item["recovery_id"] == recovery_id) + reduced = _advance_journal_binding_v1(state, event) + reduced["recoveries"] = [{ + **recovery, + "revision": recovery["revision"] + 1, + "current_action_set_sigil": replacement_action_set["action_set_sigil"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + }] + return build_execution_state_v1(reduced) + + +def _reduce_recovery_phase_advanced_v1( + state: dict[str, Any], + event: dict[str, Any], + completed_action_set: dict[str, Any], + next_action_set: dict[str, Any], +) -> dict[str, Any]: + """Project a supplied Recovery phase boundary without inferring actions.""" + validate_execution_recovery_phase_advance_supplied_action_sets_v1( + state, event, completed_action_set, next_action_set + ) + recovery_id = state["executor"]["active_recovery_id"] + assert recovery_id is not None + recovery = next(item for item in state["recoveries"] if item["recovery_id"] == recovery_id) + reduced = _advance_journal_binding_v1(state, event) + reduced["recoveries"] = [{ + **recovery, + "revision": recovery["revision"] + 1, + "state": event["payload"]["to_phase"], + "current_action_set_sigil": next_action_set["action_set_sigil"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + }] + return build_execution_state_v1(reduced) + + +def replay_execution_supplied_state_suffix_v1( + state: dict[str, Any], + events: list[dict[str, Any]], + *, + supplied_leases: list[dict[str, Any]] | None = None, + supplied_jobs: list[dict[str, Any]] | None = None, + supplied_attempts: list[dict[str, Any]] | None = None, + supplied_result_ingress_receipts: list[dict[str, Any]] | None = None, + supplied_result_ingress_intents: list[dict[str, Any]] | None = None, + supplied_observation_evidence: list[dict[str, Any]] | None = None, + supplied_log_chunks: list[dict[str, Any]] | None = None, + supplied_assurance_claims: list[dict[str, Any]] | None = None, + supplied_accounting_capture_events: list[dict[str, Any]] | None = None, + supplied_budget_settlement_events: list[dict[str, Any]] | None = None, + supplied_recovery_action_sets: list[dict[str, Any]] | None = None, +) -> dict[str, Any]: + """Reduce installed suffix Events from one caller-supplied verified State. + + This is a deterministic supplied-facts comparator. It does not prove that + ``state`` is current, that its prefix is complete, or that an Event may be + appended to a durable Journal. + """ + validate_execution_state_v1(state) + if not events: + _fail("Execution supplied-state suffix requires at least one Event") + current = state + for event in events: + validate_execution_journal_event_v1(event) + prior = current["journal_binding"] + if ( + event["journal_id"] != prior["journal_id"] + or event["sequence"] != prior["through_sequence"] + 1 + or event["previous_event_sigil"] != prior["through_event_sigil"] + ): + _fail("Execution supplied-state suffix Event does not continue State") + if event["event_type"] == "job.attempt_allocated": + if len(event["entity_revisions"]) < 2: + _fail("Attempt allocation Event lacks its Attempt revision") + attempt = _find_supplied_v1( + supplied_attempts, + event["entity_revisions"][1]["entity_id"], + "attempt_id", + "Attempt allocation", + ) + current = _reduce_job_attempt_allocated_v1( + current, event, attempt, supplied_attempts + ) + elif event["event_type"] == "lease.offered": + lease_id = event["entity_revisions"][-1]["entity_id"] + lease = _find_supplied_v1(supplied_leases, lease_id, "lease_id", "Lease offer") + current = _reduce_lease_offered_v1(current, event, lease) + elif event["event_type"] == "worker_session.heartbeat_accepted": + current = _reduce_worker_session_heartbeat_accepted_v1(current, event) + elif event["event_type"] == "worker_session.message_rejected": + current = _reduce_worker_session_message_rejected_v1(current, event) + elif event["event_type"] == "job.message_rejected": + current = _reduce_job_message_rejected_v1(current, event) + elif event["event_type"] == "attempt.authorization_bound": + immutable_attempt = _find_supplied_v1( + supplied_attempts, + event["entity_revisions"][0]["entity_id"], + "attempt_id", + "Attempt authorization binding", + ) + immutable_job = _find_supplied_v1( + supplied_jobs, current["jobs"][0]["job_id"], "job_id", + "Attempt authorization binding", + ) + current = _reduce_attempt_authorization_bound_v1( + current, event, immutable_job, immutable_attempt + ) + elif event["event_type"] == "attempt.preflight_progressed": + current = _reduce_attempt_preflight_progressed_v1(current, event) + elif event["event_type"] in {"worker.draining", "worker.quarantined"}: + current = _reduce_worker_draining_or_quarantined_v1(current, event) + elif event["event_type"] == "worker.retired": + current = _reduce_worker_retired_v1(current, event) + elif event["event_type"] in {"worker_session.draining", "worker_session.offline", "worker_session.quarantined", "worker_session.closed"}: + current = _reduce_worker_session_lifecycle_v1(current, event) + elif event["event_type"] == "lease.claimed": + current = _reduce_lease_claimed_v1(current, event) + elif event["event_type"] == "attempt.starting": + current = _reduce_attempt_starting_v1(current, event) + elif event["event_type"] == "attempt.running": + current = _reduce_attempt_running_v1(current, event) + elif event["event_type"] == "attempt.result_ingress_received": + receipt = _find_supplied_v1(supplied_result_ingress_receipts, event["payload"]["ingress_receipt_id"], "ingress_receipt_id", "Result ingress") + intent = _find_supplied_v1(supplied_result_ingress_intents, event["event_id"], "event_candidate.event_id", "Result ingress intent") + current = _reduce_result_ingress_received_v1(current, event, receipt, intent) + elif event["event_type"] == "attempt.result_accepted": + evidence = _find_supplied_v1(supplied_observation_evidence, event["payload"]["observation_evidence_disposition_binding"]["observation_evidence_id"], "observation_evidence_id", "Result acceptance") + intake = _current_attempt_v1(current, "Result acceptance dispatch")["result_intake"] + receipt = _find_supplied_v1(supplied_result_ingress_receipts, intake.get("result_ingress_receipt_binding", {}).get("ingress_receipt_id", ""), "ingress_receipt_id", "Result acceptance") + current = _reduce_result_accepted_v1(current, event, evidence, receipt) + elif event["event_type"] == "attempt.result_rejected": + if event["payload"].get("disposition_kind") == "FIRST_DISPOSITION_REJECTION": + evidence = _find_supplied_v1(supplied_observation_evidence, event["payload"].get("observation_evidence_disposition_binding", {}).get("observation_evidence_id", ""), "observation_evidence_id", "Result rejection") + intake = _current_attempt_v1(current, "Result rejection dispatch")["result_intake"] + receipt = _find_supplied_v1(supplied_result_ingress_receipts, intake.get("result_ingress_receipt_binding", {}).get("ingress_receipt_id", ""), "ingress_receipt_id", "Result rejection") + current = _reduce_result_rejected_v1(current, event, evidence, receipt) + else: + current = _reduce_late_result_rejected_v1(current, event) + elif event["event_type"] == "log.closed": + current = _reduce_log_closed_v1(current, event) + elif event["event_type"] == "log.chunk_committed": + chunk = _find_supplied_v1(supplied_log_chunks, event["payload"]["chunk_record_sigil"], "chunk_record_sigil", "Log chunk") + current = _reduce_log_chunk_committed_v1(current, event, chunk) + elif event["event_type"] == "log.chunk_duplicate_observed": + current = _reduce_log_chunk_duplicate_observed_v1(current, event) + elif event["event_type"] == "log.chunk_rejected": + current = _reduce_log_chunk_rejected_v1(current, event) + elif event["event_type"] == "log.truncated": + current = _reduce_log_truncated_v1(current, event) + elif event["event_type"] == "attempt.draining": + current = _reduce_attempt_draining_v1(current, event) + elif event["event_type"] == "attempt.cleaning": + current = _reduce_attempt_cleaning_v1(current, event) + elif event["event_type"] == "attempt.cleanup_progressed": + current = _reduce_cleanup_progressed_v1(current, event) + elif event["event_type"] in _ATTEMPT_TERMINAL_EVENT_STATES_V1: + current = _reduce_attempt_terminal_v1(current, event) + elif event["event_type"] == "job.budget_settled": + immutable_attempt = _find_supplied_v1( + supplied_attempts, + event["payload"]["attempt_id"], + "attempt_id", + "Budget settlement", + ) + current = _reduce_job_budget_settled_v1(current, event, immutable_attempt) + elif event["event_type"] == "attempt.assurance_evaluated": + if event["payload"]["evaluation"] == "CLAIMED": + attempt_id = event["entity_revisions"][-1]["entity_id"] + attempt = _current_attempt_v1(current, "Attempt assurance dispatch") + if attempt["attempt_id"] != attempt_id: + _fail("Attempt assurance Event does not name the current Attempt") + claim = _find_supplied_v1( + supplied_assurance_claims, + event["payload"]["assurance_claim_sigil"], + "assurance_claim_sigil", + "Claimed Attempt assurance", + ) + capture_event = _find_supplied_v1( + supplied_accounting_capture_events, + attempt["accounting_capture_binding"].get("event_id", ""), + "event_id", + "Claimed Attempt assurance accounting capture", + ) + settlement_event = _find_supplied_v1( + supplied_budget_settlement_events, + attempt["budget_settlement_binding"].get("event_id", ""), + "event_id", + "Claimed Attempt assurance settlement", + ) + validate_sanctum_assurance_claim_supplied_attempt_facts_v1( + claim, + _find_supplied_v1( + supplied_jobs, current["jobs"][0]["job_id"], "job_id", + "Claimed Attempt assurance Job", + ), + current, + attempt_id, + capture_event, + settlement_event, + ) + if not claim["satisfies_request"]: + _fail("Claimed Attempt assurance requires a Claim that satisfies its request") + current = _reduce_attempt_assurance_evaluated_v1(current, event) + elif event["event_type"] == "job.assurance_evaluated": + current = _reduce_job_assurance_evaluated_v1(current, event) + elif event["event_type"] in _JOB_TERMINAL_EVENT_STATES_V1: + current = _reduce_job_terminal_v1(current, event) + elif event["event_type"] == "lease.released": + current = _reduce_lease_released_v1(current, event) + elif event["event_type"] == "lease.expired": + current = _reduce_lease_expired_v1(current, event) + elif event["event_type"] == "lease.revoked": + current = _reduce_lease_revoked_v1(current, event) + elif event["event_type"] == "lease.fenced": + current = _reduce_lease_fenced_v1(current, event) + elif event["event_type"] == "lease.tombstone_republished": + current = _reduce_lease_tombstone_republished_v1(current, event) + elif event["event_type"] == "lease.message_rejected": + current = _reduce_lease_message_rejected_v1(current, event) + elif event["event_type"] == "attempt.stop_latched": + current = _reduce_attempt_stop_after_lease_expiry_v1(current, event) + elif event["event_type"] == "attempt.stop_progressed": + current = _reduce_attempt_stop_progressed_v1(current, event) + elif event["event_type"] == "lease.heartbeat_accepted": + current = _reduce_lease_heartbeat_accepted_v1(current, event) + elif event["event_type"] == "lease.renewed": + current = _reduce_lease_renewed_v1(current, event) + elif event["event_type"] == "executor.clock_restored": + action_set_sigil = event["recovery_action_binding"]["action_set_sigil"] if event["recovery_action_binding"] else "" + action_set = _find_supplied_v1( + supplied_recovery_action_sets, + action_set_sigil, + "action_set_sigil", + "Clock restoration", + ) + current = _reduce_executor_clock_restored_v1(current, event, action_set) + elif event["event_type"] == "recovery.action_set_rebased": + prior_action_set = _find_supplied_v1( + supplied_recovery_action_sets, + event["payload"]["prior_action_set_sigil"], + "action_set_sigil", + "Recovery rebase prior action set", + ) + replacement_action_set = _find_supplied_v1( + supplied_recovery_action_sets, + event["payload"]["replacement_action_set_sigil"], + "action_set_sigil", + "Recovery rebase replacement action set", + ) + current = _reduce_recovery_action_set_rebased_v1( + current, event, prior_action_set, replacement_action_set + ) + elif event["event_type"] == "recovery.phase_advanced": + completed_action_set = _find_supplied_v1( + supplied_recovery_action_sets, + event["payload"]["completed_action_set_sigil"], + "action_set_sigil", + "Recovery phase completed action set", + ) + next_action_set = _find_supplied_v1( + supplied_recovery_action_sets, + event["payload"]["next_action_set_sigil"], + "action_set_sigil", + "Recovery phase next action set", + ) + current = _reduce_recovery_phase_advanced_v1( + current, event, completed_action_set, next_action_set + ) + elif event["event_type"] == "recovery.completed": + action_set = _find_supplied_v1( + supplied_recovery_action_sets, + event["payload"]["completed_action_set_sigil"], + "action_set_sigil", + "Recovery completion action set", + ) + current = _reduce_recovery_completed_v1(current, event, action_set) + else: + _fail("Execution supplied-state suffix reducer is unavailable for this Event") + return current + + +def _find_supplied_v1( + records: list[dict[str, Any]] | None, identifier: str, member: str, label: str +) -> dict[str, Any]: + if records is None: + _fail(f"{label} replay requires supplied immutable records") + def member_value(record: dict[str, Any]) -> Any: + value: Any = record + for part in member.split("."): + if not isinstance(value, dict): + return _MISSING + value = value.get(part, _MISSING) + return value + + matches = [record for record in records if member_value(record) == identifier] + if len(matches) != 1: + _fail(f"{label} replay requires exactly one supplied immutable record") + return matches[0] + + +def _reduce_worker_registered_v1( + state: dict[str, Any], event: dict[str, Any], worker: dict[str, Any] +) -> dict[str, Any]: + validate_execution_worker_v1(worker) + executor = state["executor"] + if ( + event["event_type"] != "worker.definition_registered" + or any(item["worker_id"] == worker["worker_id"] for item in state["workers"]) + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or worker["definition_revision"] != 0 + or event["payload"]["worker_binding_sigil"] != worker["worker_binding_sigil"] + or event["payload"]["definition_revision"] != 0 + or not isinstance(event["payload"]["supersedes_worker_binding_sigil"], str) + or event["entity_revisions"] + != [ + { + "entity_kind": "WORKER", + "entity_id": worker["worker_id"], + "preceding_revision": None, + "next_revision": 0, + } + ] + ): + _fail("Worker registration Event disagrees with supplied Worker") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["workers"] = [ + *state["workers"], + { + "worker_id": worker["worker_id"], + "revision": 0, + "state": "REGISTERED", + "worker_binding_sigil": worker["worker_binding_sigil"], + "definition_revision": 0, + "worker_session_ids": [], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + }, + ] + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def _reduce_worker_enabled_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + if event["event_type"] != "worker.enabled" or len(state["workers"]) != 1: + _fail("Worker enable reducer requires one registered Worker") + worker = state["workers"][0] + executor = state["executor"] + if ( + worker["state"] != "REGISTERED" + or event["payload"]["worker_binding_sigil"] != worker["worker_binding_sigil"] + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["entity_revisions"] + != [ + { + "entity_kind": "WORKER", + "entity_id": worker["worker_id"], + "preceding_revision": worker["revision"], + "next_revision": worker["revision"] + 1, + } + ] + ): + _fail("Worker enable Event disagrees with registered Worker") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["workers"] = [ + { + **worker, + "revision": worker["revision"] + 1, + "state": "ENABLED", + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ] + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def _reduce_worker_session_registered_v1( + state: dict[str, Any], event: dict[str, Any], session: dict[str, Any] +) -> dict[str, Any]: + worker = next( + (item for item in state["workers"] if item["worker_id"] == session["worker_id"]), None + ) + executor = state["executor"] + if ( + event["event_type"] != "worker_session.registered" + or worker is None + or worker["state"] != "ENABLED" + or any( + item["worker_session_id"] == session["worker_session_id"] + for item in state["worker_sessions"] + ) + or session["worker_binding_sigil"] != worker["worker_binding_sigil"] + or session["executor_instance_id"] != executor["executor_instance_id"] + or session["executor_epoch"] != executor["executor_epoch"] + or event["payload"]["worker_session_binding_sigil"] + != session["worker_session_binding_sigil"] + or event["payload"]["worker_binding_sigil"] != session["worker_binding_sigil"] + or event["payload"]["backend_session_identity"] != session["backend_session_identity"] + or event["payload"]["control_channel_identity_sigil"] + != session["control_channel_identity_sigil"] + or event["entity_revisions"] + != [ + { + "entity_kind": "WORKER_SESSION", + "entity_id": session["worker_session_id"], + "preceding_revision": None, + "next_revision": 0, + } + ] + ): + _fail("Worker Session registration Event disagrees with supplied Session") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["workers"] = [ + { + **worker, + "worker_session_ids": sorted( + [*worker["worker_session_ids"], session["worker_session_id"]], + key=lambda value: _unsigned_ascii(value, "Worker session ID"), + ), + } + ] + reduced["worker_sessions"] = [ + { + "worker_session_id": session["worker_session_id"], + "revision": 0, + "state": "REGISTERED", + "worker_id": session["worker_id"], + "worker_binding_sigil": session["worker_binding_sigil"], + "worker_session_binding_sigil": session["worker_session_binding_sigil"], + "executor_epoch": session["executor_epoch"], + "worker_session_heartbeat_policy_id": None, + "worker_session_heartbeat_policy_sigil": None, + "capacity": None, + "capacity_in_use": 0, + "last_heartbeat_sequence": None, + "last_heartbeat_message_sigil": None, + "last_resource_sample_sigil": None, + "resource_counter_floors": { + "cpu_time_seconds": None, + "storage_bytes_written": None, + "network_egress_bytes": None, + }, + "next_heartbeat_due_at": None, + "lease_ids": [], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ] + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def _reduce_worker_session_ready_v1(state: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]: + if event["event_type"] != "worker_session.ready" or len(state["worker_sessions"]) != 1: + _fail("Worker Session ready reducer requires one registered Session") + session = state["worker_sessions"][0] + executor = state["executor"] + payload = event["payload"] + if ( + session["state"] != "REGISTERED" + or payload["capacity"] < 1 + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["entity_revisions"] + != [ + { + "entity_kind": "WORKER_SESSION", + "entity_id": session["worker_session_id"], + "preceding_revision": session["revision"], + "next_revision": session["revision"] + 1, + } + ] + ): + _fail("Worker Session ready Event disagrees with registered Session") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["worker_sessions"] = [ + { + **session, + "revision": session["revision"] + 1, + "state": "READY", + "capacity": payload["capacity"], + "worker_session_heartbeat_policy_id": payload["worker_session_heartbeat_policy_id"], + "worker_session_heartbeat_policy_sigil": payload[ + "worker_session_heartbeat_policy_sigil" + ], + "next_heartbeat_due_at": payload["initial_heartbeat_due_at"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ] + reduced["deadlines"] = [ + { + "deadline_kind": "HEARTBEAT_TIMEOUT", + "due_at": payload["initial_heartbeat_due_at"], + "fixed_priority": _DEADLINE_PRIORITY["HEARTBEAT_TIMEOUT"], + "entity_id": session["worker_session_id"], + "source_event_id": event["event_id"], + "source_event_sigil": event["event_sigil"], + } + ] + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def _reserved_budget_ledger_v1( + ledger: dict[str, Any], reservation: dict[str, Any] +) -> dict[str, Any]: + reduced: dict[str, Any] = { + name: dict(value) for name, value in ledger.items() if name != "budget_ledger_sigil" + } + for dimension, value in reservation.items(): + updated = reduced[dimension] + updated["reserved"] += value + total = updated["reserved"] + updated["consumed"] + updated["exhaustion_status"] = ( + "AVAILABLE" + if total < updated["limit"] + else "EXHAUSTED" + if total == updated["limit"] + else "EXCEEDED" + ) + if total > updated["limit"]: + _fail("Attempt allocation exceeds the Job budget") + reduced["budget_ledger_sigil"] = content_sigil(reduced) + return reduced + + +def _reduce_job_attempt_allocated_v1( + state: dict[str, Any], + event: dict[str, Any], + attempt: dict[str, Any], + immutable_attempts: list[dict[str, Any]] | None = None, +) -> dict[str, Any]: + """Atomically allocate one fresh Attempt, budget reservation, and log streams.""" + validate_execution_attempt_v1(attempt) + if event["event_type"] != "job.attempt_allocated" or len(state["jobs"]) != 1: + _fail("Attempt allocation reducer requires exactly one queued Job") + job = state["jobs"][0] + executor = state["executor"] + prior_attempts = state["attempts"] + prior_attempt_ids = {item["attempt_id"] for item in prior_attempts} + prior_log_ids = {item["log_stream_id"] for item in state["log_streams"]} + if immutable_attempts is not None: + for immutable_attempt in immutable_attempts: + validate_execution_attempt_v1(immutable_attempt) + immutable_by_id = {item["attempt_id"]: item for item in immutable_attempts} + if ( + len(immutable_by_id) != len(immutable_attempts) + or immutable_by_id.get(attempt["attempt_id"]) != attempt + or set(immutable_by_id) != prior_attempt_ids | {attempt["attempt_id"]} + or any( + immutable_by_id[prior["attempt_id"]]["attempt_binding_sigil"] + != prior["attempt_binding_sigil"] + or immutable_by_id[prior["attempt_id"]]["job_id"] != job["job_id"] + or immutable_by_id[prior["attempt_id"]]["job_binding_sigil"] + != job["job_binding_sigil"] + for prior in prior_attempts + ) + ): + _fail("Attempt allocation immutable history disagrees with retained State") + prior_crucibles = { + immutable_by_id[prior["attempt_id"]]["crucible_id"] for prior in prior_attempts + } + prior_namespaces = { + immutable_by_id[prior["attempt_id"]]["output_namespace_id"] + for prior in prior_attempts + } + else: + prior_crucibles = set() + prior_namespaces = set() + expected_retry_ordinal = len(prior_attempts) + 1 + if ( + job["state"] != "QUEUED" + or job["current_attempt_id"] is not None + or set(job["attempt_ids"]) != prior_attempt_ids + or len(job["attempt_summaries"]) != len(prior_attempts) + or any(item["state"] not in _ATTEMPT_TERMINAL_EVENT_STATES_V1.values() for item in prior_attempts) + or attempt["job_id"] != job["job_id"] + or attempt["job_binding_sigil"] != job["job_binding_sigil"] + or attempt["attempt_id"] in prior_attempt_ids + or attempt["retry_ordinal"] != expected_retry_ordinal + or attempt["fencing_generation"] != job["fencing_counter"] + 1 + or attempt["crucible_id"] in prior_crucibles + or attempt["output_namespace_id"] in prior_namespaces + or any(log_id in prior_log_ids for log_id in attempt["log_stream_ids"].values()) + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["causation_event_id"] != job["last_event_id"] + ): + _fail("Attempt allocation disagrees with the queued Job projection") + payload = event["payload"] + if ( + payload["attempt_binding_sigil"] != attempt["attempt_binding_sigil"] + or payload["retry_ordinal"] != attempt["retry_ordinal"] + or payload["fencing_generation"] != attempt["fencing_generation"] + or payload["budget_reservation"] != attempt["budget_reservation"] + or payload["prior_fencing_counter"] != job["fencing_counter"] + or payload["resulting_fence_floor"] != attempt["fencing_generation"] + or event["recorded_at"] != attempt["created_at"] + ): + _fail("Attempt allocation Event does not exactly copy Attempt allocation facts") + ledger = _reserved_budget_ledger_v1(job["budget_ledger"], attempt["budget_reservation"]) + if payload["resulting_budget_ledger_sigil"] != ledger["budget_ledger_sigil"]: + _fail("Attempt allocation Event budget ledger Sigil mismatch") + log_ids = attempt["log_stream_ids"] + log_revisions = sorted( + ( + { + "entity_kind": "LOG_STREAM", + "entity_id": log_ids[stream], + "preceding_revision": None, + "next_revision": 0, + } + for stream in ("STDOUT", "STDERR", "STRUCTURED") + ), + key=lambda item: _unsigned_ascii(item["entity_id"], "Log stream ID"), + ) + expected_revisions = [ + { + "entity_kind": "JOB", + "entity_id": job["job_id"], + "preceding_revision": job["revision"], + "next_revision": job["revision"] + 1, + }, + { + "entity_kind": "ATTEMPT", + "entity_id": attempt["attempt_id"], + "preceding_revision": None, + "next_revision": 0, + }, + *log_revisions, + ] + if event["entity_revisions"] != expected_revisions: + _fail("Attempt allocation Event has invalid atomic revision effects") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["jobs"] = [ + { + **job, + "revision": job["revision"] + 1, + "state": "ACTIVE", + "attempt_ids": [*job["attempt_ids"], attempt["attempt_id"]], + "current_attempt_id": attempt["attempt_id"], + "fencing_counter": attempt["fencing_generation"], + "fence_floor": attempt["fencing_generation"], + "budget_ledger": ledger, + "queue_key": None, + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ] + reduced["attempts"] = [ + *prior_attempts, + { + "attempt_id": attempt["attempt_id"], + "revision": 0, + "state": "CREATED", + "attempt_binding_sigil": attempt["attempt_binding_sigil"], + "job_id": job["job_id"], + "retry_ordinal": attempt["retry_ordinal"], + "fencing_generation": attempt["fencing_generation"], + "lease_executor_epoch": None, + "public_fence_tuple": None, + "worker_session_binding": {"kind": "NONE"}, + "lease_id": None, + "result_binding": {"kind": "NONE"}, + "result_intake": {"kind": "NONE"}, + "output_staging_preallocations": [], + "attempt_authorization_requirement": attempt["attempt_authorization_requirement"], + "attempt_authorization_state": {"kind": "NONE"} + if attempt["attempt_authorization_requirement"]["kind"] == "NONE" + else {"kind": "PENDING"}, + "completion_anchor_binding": {"kind": "NOT_ESTABLISHED"}, + "lease_terminal_binding": None, + "first_stop_or_fence_binding": {"kind": "NONE"}, + "storage_observation_binding": None, + "terminal_source_binding": None, + "accounting_capture_binding": {"kind": "PENDING"}, + "budget_settlement_binding": {"kind": "PENDING"}, + "attempt_assurance_binding": {"kind": "PENDING"}, + "input_storage_roots": [], + "output_storage_roots": [], + "control_evidence_set_binding": {"kind": "PENDING"}, + "quarantine_binding_set_binding": {"kind": "PENDING"}, + "terminalization_storage_manifest_binding": {"kind": "PENDING"}, + "output_root_protection": {"kind": "PENDING"}, + "deadline_due_at": attempt["deadline_due_at"], + "grace_due_at": None, + "terminal_event_binding": {"kind": "NONE"}, + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ] + reduced["log_streams"] = [ + *state["log_streams"], + *[ + { + "log_stream_id": log_ids[stream], + "revision": 0, + "state": "OPEN", + "attempt_id": attempt["attempt_id"], + "stream": stream, + "next_sequence": 0, + "captured_bytes": 0, + "dropped_bytes": 0, + "truncated": False, + "final_sequence": None, + "stream_set_sigil": None, + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + for stream in ("STDOUT", "STDERR", "STRUCTURED") + ], + ] + reduced["deadlines"] = [ + *state["deadlines"], + { + "deadline_kind": "ATTEMPT_DEADLINE", + "due_at": attempt["deadline_due_at"], + "fixed_priority": _DEADLINE_PRIORITY["ATTEMPT_DEADLINE"], + "entity_id": attempt["attempt_id"], + "source_event_id": event["event_id"], + "source_event_sigil": event["event_sigil"], + }, + ] + reduced["deadlines"].sort( + key=lambda item: ( + _parse_time(item["due_at"]), + item["fixed_priority"], + _unsigned_ascii(item["entity_id"], "Deadline entity ID"), + ) + ) + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def _reduce_attempt_preflight_started_v1( + state: dict[str, Any], event: dict[str, Any] +) -> dict[str, Any]: + """Reduce a CREATED Attempt after its immutable bindings have been rechecked.""" + if event["event_type"] != "attempt.preflight_started": + _fail("Attempt preflight reducer received the wrong Event") + attempt = _current_attempt_v1(state, "Attempt preflight reducer") + executor = state["executor"] + if ( + attempt["state"] != "CREATED" + or ( + attempt["attempt_authorization_requirement"]["kind"] == "REQUIRED" + and attempt["attempt_authorization_state"]["kind"] != "BOUND" + ) + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["entity_revisions"] + != [ + { + "entity_kind": "ATTEMPT", + "entity_id": attempt["attempt_id"], + "preceding_revision": attempt["revision"], + "next_revision": attempt["revision"] + 1, + } + ] + ): + _fail("Attempt preflight Event disagrees with created Attempt projection") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], + { + **attempt, + "revision": attempt["revision"] + 1, + "state": "PREFLIGHTING", + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ) + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +_PREFLIGHT_PROGRESS_STEPS_V1 = { + "TASK_BINDINGS_VERIFIED", + "POLICIES_VERIFIED", + "BASE_INPUTS_VERIFIED", + "BACKEND_VERIFIED", + "MATERIALIZATION_CREATED", + "OUTPUT_NAMESPACE_CREATED", +} + + +def _reduce_attempt_preflight_progressed_v1( + state: dict[str, Any], event: dict[str, Any] +) -> dict[str, Any]: + """Record one bounded preflight progress observation. + + The immutable evidence Sigil is retained by the Event itself. State has no + mutable progress field, so this reducer validates ordering and the allowed + step without promoting the evidence to authority. + """ + attempt, payload, executor = _current_attempt_v1( + state, "Preflight progress reducer" + ), event["payload"], state["executor"] + if ( + event["event_type"] != "attempt.preflight_progressed" + or attempt["state"] != "PREFLIGHTING" + or payload["step"] not in _PREFLIGHT_PROGRESS_STEPS_V1 + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["causation_event_id"] != attempt["last_event_id"] + or event["entity_revisions"] + != [{ + "entity_kind": "ATTEMPT", + "entity_id": attempt["attempt_id"], + "preceding_revision": attempt["revision"], + "next_revision": attempt["revision"] + 1, + }] + ): + _fail("Preflight progress Event disagrees with preflighting Attempt") + reduced = _advance_journal_binding_v1(state, event) + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], { + **attempt, + "revision": attempt["revision"] + 1, + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + }) + return build_execution_state_v1(reduced) + + +def _reduce_attempt_preflight_passed_v1( + state: dict[str, Any], event: dict[str, Any] +) -> dict[str, Any]: + """Reduce a completed preflight while retaining only its immutable root bindings.""" + if event["event_type"] != "attempt.preflight_passed": + _fail("Attempt preflight-pass reducer received the wrong Event") + attempt = _current_attempt_v1(state, "Attempt preflight-pass reducer") + executor = state["executor"] + roots = event["payload"]["input_storage_roots"] + if ( + attempt["state"] != "PREFLIGHTING" + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["entity_revisions"] + != [ + { + "entity_kind": "ATTEMPT", + "entity_id": attempt["attempt_id"], + "preceding_revision": attempt["revision"], + "next_revision": attempt["revision"] + 1, + } + ] + or any( + root["root_kind"] != "ATTEMPT_INPUT" + or root["job_id"] != attempt["job_id"] + or root["attempt_id"] != attempt["attempt_id"] + for root in roots + ) + ): + _fail("Attempt preflight-pass Event disagrees with preflighting Attempt projection") + if len(roots) > 1: + _fail("Attempt preflight-pass Event has too many input storage roots") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["attempts"] = _replace_attempt_v1(state, attempt["attempt_id"], + { + **attempt, + "revision": attempt["revision"] + 1, + "state": "READY", + "input_storage_roots": roots, + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ) + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def _reduce_executor_clock_uncertain_after_initial_v1( + state: dict[str, Any], event: dict[str, Any] +) -> dict[str, Any]: + """Reduce the no-live-authority clock gate immediately after ISR3.""" + executor = state["executor"] + if event["event_type"] != "executor.clock_uncertain": + _fail("internal reducer dispatch does not match executor clock uncertainty") + if ( + event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + ): + _fail("Clock uncertainty Event disagrees with replayed Executor identity") + if executor["clock_state"] != "TRUSTED" or executor["authority_gates"]: + _fail("Clock uncertainty Event requires an ungated trusted Executor") + revision = event["entity_revisions"] + expected_revision = [ + { + "entity_kind": "EXECUTOR", + "entity_id": executor["executor_instance_id"], + "preceding_revision": executor["revision"], + "next_revision": executor["revision"] + 1, + } + ] + if revision != expected_revision: + _fail("Clock uncertainty Event has invalid Executor revision effect") + payload = event["payload"] + if payload["last_trusted_utc"] != executor["last_trusted_utc"]: + _fail("Clock uncertainty Event disagrees with replayed trusted-time anchor") + if payload["affected_lease_ids"]: + _fail("Clock uncertainty reducer requires no live Lease authority") + if any( + state[member] + for member in ( + "workers", + "worker_sessions", + "jobs", + "attempts", + "leases", + "log_streams", + "deadlines", + "idempotency_records", + "recoveries", + ) + ): + _fail("Clock uncertainty reducer requires the initial empty projections") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced_executor = { + **executor, + "revision": executor["revision"] + 1, + "clock_state": "UNCERTAIN", + "clock_uncertain_event_id": event["event_id"], + "authority_gates": ["CLOCK_UNCERTAIN"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + reduced["executor"] = reduced_executor + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def _reduce_recovery_started_after_clock_uncertain_v1( + state: dict[str, Any], event: dict[str, Any] +) -> dict[str, Any]: + """Reduce the empty-projection Recovery start after the clock gate.""" + executor = state["executor"] + if event["event_type"] != "recovery.started": + _fail("internal reducer dispatch does not match Recovery start") + if ( + event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + ): + _fail("Recovery start Event disagrees with replayed Executor identity") + if ( + executor["clock_state"] != "UNCERTAIN" + or executor["active_recovery_id"] is not None + or executor["authority_gates"] != ["CLOCK_UNCERTAIN"] + or state["recoveries"] + ): + _fail("Recovery start requires the clock-gated initial projection") + if event["recovery_action_binding"] is not None: + _fail("Recovery start must not carry a Recovery action binding") + payload = event["payload"] + if ( + payload["replay_through_sequence"] != state["journal_binding"]["through_sequence"] + or payload["replay_through_event_sigil"] != state["journal_binding"]["through_event_sigil"] + or payload["old_epoch"] != executor["executor_epoch"] + or payload["new_epoch"] != executor["executor_epoch"] + or payload["prior_recovery_id"] is not None + ): + _fail("Recovery start payload disagrees with clock-gated prefix") + if any( + payload[member] + for member in ( + "nonterminal_job_ids", + "nonterminal_attempt_ids", + "nonterminal_lease_ids", + "nonterminal_worker_session_ids", + ) + ): + _fail("Recovery start reducer requires empty nonterminal projections") + if any( + state[member] + for member in ( + "workers", + "worker_sessions", + "jobs", + "attempts", + "leases", + "log_streams", + "deadlines", + "idempotency_records", + ) + ): + _fail("Recovery start reducer requires the initial empty projections") + expected_revisions = [ + { + "entity_kind": "EXECUTOR", + "entity_id": executor["executor_instance_id"], + "preceding_revision": executor["revision"], + "next_revision": executor["revision"] + 1, + }, + { + "entity_kind": "RECOVERY", + "entity_id": payload["recovery_id"], + "preceding_revision": None, + "next_revision": 0, + }, + ] + if event["entity_revisions"] != expected_revisions: + _fail("Recovery start Event has invalid revision effects") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["executor"] = { + **executor, + "revision": executor["revision"] + 1, + "active_recovery_id": payload["recovery_id"], + "authority_gates": ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + reduced["recoveries"] = [ + { + "recovery_id": payload["recovery_id"], + "revision": 0, + "state": "STARTED", + "prior_recovery_id": None, + "started_event_sigil": event["event_sigil"], + "current_action_set_sigil": payload["initial_action_set_sigil"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ] + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def validate_execution_journal_prefix_wire_v1( + events: list[dict[str, Any]], + *, + head: dict[str, Any] | None = None, +) -> None: + """Validate a caller-supplied Journal chain without reducing its State. + + This checks only closed Event bytes, ordering, and an optionally supplied + Head endpoint. It does not establish completeness, durability, currentness, + replay equivalence, append authority, or any runtime authority. + """ + if not events: + _fail("Execution Journal prefix requires a nonempty sequence") + if not all(isinstance(event, dict) for event in events): + _fail("Execution Journal prefix contains a nonobject Event") + if events[0].get("event_type") != "executor.epoch_started": + _fail("Execution Journal prefix must begin with executor epoch start") + journal_id = events[0].get("journal_id") + previous_sigil: str | None = None + previous_recorded_at: datetime | None = None + event_ids: set[str] = set() + epoch_build_sigils: dict[tuple[str, int], str] = {} + for expected_sequence, event in enumerate(events, 1): + validate_execution_journal_event_v1(event) + if event["journal_id"] != journal_id: + _fail("Execution Journal prefix contains multiple journal identities") + if event["event_id"] in event_ids: + _fail("Execution Journal prefix contains a duplicate Event identity") + if event["sequence"] != expected_sequence: + _fail("Execution Journal prefix has a sequence gap") + if event["previous_event_sigil"] != previous_sigil: + _fail("Execution Journal prefix has a broken Event chain") + recorded_at = _parse_time(event["recorded_at"]) + if previous_recorded_at is not None and recorded_at < previous_recorded_at: + _fail("Execution Journal prefix has decreasing recorded_at time") + epoch_key = (event["executor_instance_id"], event["executor_epoch"]) + prior_build_sigil = epoch_build_sigils.setdefault(epoch_key, event["executor_build_sigil"]) + if event["executor_build_sigil"] != prior_build_sigil: + _fail("Execution Journal prefix has conflicting Executor build Sigils") + previous_sigil = event["event_sigil"] + previous_recorded_at = recorded_at + event_ids.add(event["event_id"]) + if head is not None: + validate_execution_journal_head_v1(head) + last = events[-1] + if ( + head["journal_id"] != journal_id + or head["last_sequence"] != last["sequence"] + or head["last_event_id"] != last["event_id"] + or head["last_event_sigil"] != last["event_sigil"] + ): + _fail("Execution Journal Head disagrees with supplied prefix") + + +def replay_execution_journal_prefix_v1( + events: list[dict[str, Any]], + *, + head: dict[str, Any] | None = None, + recovery_action_sets: list[dict[str, Any]] | None = None, + supplied_jobs: list[dict[str, Any]] | None = None, + supplied_attempts: list[dict[str, Any]] | None = None, + supplied_workers: list[dict[str, Any]] | None = None, + supplied_worker_sessions: list[dict[str, Any]] | None = None, + supplied_leases: list[dict[str, Any]] | None = None, + supplied_result_ingress_receipts: list[dict[str, Any]] | None = None, + supplied_result_ingress_intents: list[dict[str, Any]] | None = None, + supplied_observation_evidence: list[dict[str, Any]] | None = None, + supplied_log_chunks: list[dict[str, Any]] | None = None, + supplied_assurance_claims: list[dict[str, Any]] | None = None, + supplied_accounting_capture_events: list[dict[str, Any]] | None = None, + supplied_budget_settlement_events: list[dict[str, Any]] | None = None, +) -> dict[str, Any]: + """Verify a v1 Journal prefix with the installed supplied-facts reducers. + + Prefix integrity is checked before reducer dispatch. A syntactically valid + Event outside the explicitly installed reducer set + fails closed rather than being interpreted as a no-op or guessed transition. + ``recovery_action_sets`` is required only for the action-free + Recovery control path; it is not an authority to derive or execute actions. + """ + if not events: + _fail("Execution Journal replay requires a nonempty prefix") + if recovery_action_sets is not None: + if supplied_jobs is not None: + _fail("Execution Journal replay cannot combine Recovery action sets and supplied Jobs") + if supplied_attempts is not None: + _fail( + "Execution Journal replay cannot combine Recovery action sets and supplied Attempts" + ) + if supplied_workers is not None or supplied_worker_sessions is not None: + _fail( + "Execution Journal replay cannot combine Recovery action sets and supplied Worker records" + ) + if any( + value is not None + for value in ( + supplied_leases, + supplied_result_ingress_receipts, + supplied_result_ingress_intents, + supplied_observation_evidence, + supplied_log_chunks, + supplied_assurance_claims, + supplied_accounting_capture_events, + supplied_budget_settlement_events, + ) + ): + _fail( + "Execution Journal replay cannot combine empty Recovery action sets " + "and unrelated supplied records" + ) + empty_recovery_types = [ + "executor.epoch_started", + "executor.clock_uncertain", + "recovery.started", + "recovery.phase_advanced", + "recovery.phase_advanced", + "recovery.phase_advanced", + ] + event_types = [ + event.get("event_type") if isinstance(event, dict) else None for event in events + ] + if event_types not in (empty_recovery_types, [*empty_recovery_types, "recovery.completed"]): + _fail( + "Execution Journal recovery action sets are only supported for the empty Recovery path" + ) + return replay_execution_empty_recovery_phase_prefix_v1( + events, + recovery_action_sets, + head=head, + ) + return replay_execution_journal_supplied_facts_v1( + events, + head=head, + supplied_jobs=supplied_jobs, + supplied_attempts=supplied_attempts, + supplied_workers=supplied_workers, + supplied_worker_sessions=supplied_worker_sessions, + supplied_leases=supplied_leases, + supplied_result_ingress_receipts=supplied_result_ingress_receipts, + supplied_result_ingress_intents=supplied_result_ingress_intents, + supplied_observation_evidence=supplied_observation_evidence, + supplied_log_chunks=supplied_log_chunks, + supplied_assurance_claims=supplied_assurance_claims, + supplied_accounting_capture_events=supplied_accounting_capture_events, + supplied_budget_settlement_events=supplied_budget_settlement_events, + ) + + +def replay_execution_journal_supplied_facts_v1( + events: list[dict[str, Any]], + *, + head: dict[str, Any] | None = None, + supplied_jobs: list[dict[str, Any]] | None = None, + supplied_attempts: list[dict[str, Any]] | None = None, + supplied_workers: list[dict[str, Any]] | None = None, + supplied_worker_sessions: list[dict[str, Any]] | None = None, + supplied_leases: list[dict[str, Any]] | None = None, + supplied_result_ingress_receipts: list[dict[str, Any]] | None = None, + supplied_result_ingress_intents: list[dict[str, Any]] | None = None, + supplied_observation_evidence: list[dict[str, Any]] | None = None, + supplied_log_chunks: list[dict[str, Any]] | None = None, + supplied_assurance_claims: list[dict[str, Any]] | None = None, + supplied_accounting_capture_events: list[dict[str, Any]] | None = None, + supplied_budget_settlement_events: list[dict[str, Any]] | None = None, + supplied_recovery_action_sets: list[dict[str, Any]] | None = None, +) -> dict[str, Any]: + """Replay the installed v1 reducer set from caller-supplied immutable facts. + + This is deliberately a *supplied-facts* comparator: all dependent records + are supplied by the caller, and the helper proves neither journal + completeness nor durability/currentness of those records. It exists so a + contiguous Journal can use the installed reducers without splitting at + their bootstrap boundaries. Unknown or not-yet-installed Event types + still fail closed. + """ + validate_execution_journal_prefix_wire_v1(events, head=head) + state = replay_execution_initial_prefix_v1([events[0]]) + for event in events[1:]: + if event["event_type"] == "executor.clock_uncertain": + state = _reduce_executor_clock_uncertain_after_initial_v1(state, event) + elif event["event_type"] == "recovery.started": + state = _reduce_recovery_started_after_clock_uncertain_v1(state, event) + elif event["event_type"] == "worker.definition_registered": + worker = _find_supplied_v1( + supplied_workers, + event["payload"]["worker_binding_sigil"], + "worker_binding_sigil", + "Worker registration", + ) + state = _reduce_worker_registered_v1(state, event, worker) + elif event["event_type"] == "worker.enabled": + state = _reduce_worker_enabled_v1(state, event) + elif event["event_type"] == "worker_session.registered": + session = _find_supplied_v1( + supplied_worker_sessions, + event["payload"]["worker_session_binding_sigil"], + "worker_session_binding_sigil", + "Worker Session registration", + ) + worker = _find_supplied_v1( + supplied_workers, session["worker_id"], "worker_id", "Worker Session registration" + ) + validate_execution_worker_session_supplied_worker_v1(session, worker) + state = _reduce_worker_session_registered_v1(state, event, session) + elif event["event_type"] == "worker_session.ready": + state = _reduce_worker_session_ready_v1(state, event) + elif event["event_type"] == "job.submitted": + if supplied_jobs is None or len(supplied_jobs) != 1: + _fail("Job submission replay requires exactly one supplied immutable record") + job = supplied_jobs[0] + state = _reduce_job_submitted_v1(state, event, job) + elif event["event_type"] == "job.queued": + state = _reduce_job_queued_v1(state, event) + elif event["event_type"] == "job.attempt_allocated": + if supplied_attempts is None: + _fail("Attempt allocation replay requires exactly one supplied immutable record") + if len(event["entity_revisions"]) < 2: + _fail("Attempt allocation Event lacks its Attempt revision") + attempt_id = event["entity_revisions"][1]["entity_id"] + attempt = _find_supplied_v1( + supplied_attempts, attempt_id, "attempt_id", "Attempt allocation" + ) + visible_attempt_ids = { + item["attempt_id"] for item in state["attempts"] + } | {attempt_id} + allocation_attempts = [ + item + for item in supplied_attempts + if item["attempt_id"] in visible_attempt_ids + ] + state = _reduce_job_attempt_allocated_v1( + state, event, attempt, allocation_attempts + ) + elif event["event_type"] == "attempt.authorization_bound": + immutable_attempt = _find_supplied_v1( + supplied_attempts, + event["entity_revisions"][0]["entity_id"], + "attempt_id", + "Attempt authorization binding", + ) + immutable_job = _find_supplied_v1( + supplied_jobs, state["jobs"][0]["job_id"], "job_id", + "Attempt authorization binding", + ) + state = _reduce_attempt_authorization_bound_v1( + state, event, immutable_job, immutable_attempt + ) + elif event["event_type"] == "attempt.preflight_started": + state = _reduce_attempt_preflight_started_v1(state, event) + elif event["event_type"] == "attempt.preflight_progressed": + state = _reduce_attempt_preflight_progressed_v1(state, event) + elif event["event_type"] == "attempt.preflight_passed": + state = _reduce_attempt_preflight_passed_v1(state, event) + else: + state = replay_execution_supplied_state_suffix_v1( + state, + [event], + supplied_leases=supplied_leases, + supplied_jobs=supplied_jobs, + supplied_attempts=supplied_attempts, + supplied_result_ingress_receipts=supplied_result_ingress_receipts, + supplied_result_ingress_intents=supplied_result_ingress_intents, + supplied_observation_evidence=supplied_observation_evidence, + supplied_log_chunks=supplied_log_chunks, + supplied_assurance_claims=supplied_assurance_claims, + supplied_accounting_capture_events=supplied_accounting_capture_events, + supplied_budget_settlement_events=supplied_budget_settlement_events, + supplied_recovery_action_sets=supplied_recovery_action_sets, + ) + return state + + +def _reduce_empty_recovery_phase_advance_v1( + state: dict[str, Any], + event: dict[str, Any], + completed_action_set: dict[str, Any], + next_action_set: dict[str, Any], +) -> dict[str, Any]: + """Reduce one action-free Recovery phase transition. + + Callers establish sealed action-set availability separately. This reducer + deliberately accepts only empty action sets and empty completion effects, + so it cannot mistake an omitted operational consequence for a completed + Recovery action. + """ + validate_execution_recovery_phase_advance_supplied_action_sets_v1( + state, + event, + completed_action_set, + next_action_set, + ) + executor = state["executor"] + recovery_id = executor["active_recovery_id"] + if recovery_id is None: + _fail("empty Recovery phase reducer requires an active Recovery") + recovery = next(item for item in state["recoveries"] if item["recovery_id"] == recovery_id) + if ( + event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or completed_action_set["actions"] + or next_action_set["actions"] + or event["payload"]["completed_entity_ids"] + or event["payload"]["quarantined_entity_ids"] + ): + _fail("empty Recovery phase reducer received operational action effects") + reduced = {key: value for key, value in state.items() if key != "state_sigil"} + reduced["recoveries"] = [ + { + **recovery, + "revision": recovery["revision"] + 1, + "state": event["payload"]["to_phase"], + "current_action_set_sigil": next_action_set["action_set_sigil"], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + ] + reduced["journal_binding"] = { + "journal_id": event["journal_id"], + "through_sequence": event["sequence"], + "through_event_id": event["event_id"], + "through_event_sigil": event["event_sigil"], + } + return build_execution_state_v1(reduced) + + +def replay_execution_empty_recovery_phase_prefix_v1( + events: list[dict[str, Any]], + recovery_action_sets: list[dict[str, Any]], + *, + head: dict[str, Any] | None = None, +) -> dict[str, Any]: + """Reduce the action-free ``STARTED -> FINALIZING`` Recovery control path. + + This narrow deterministic projection is intentionally not a general + Journal replay: it requires the initial empty State, an uncertain clock, + four sealed empty action sets, and exactly the three phase transitions. + A final ``recovery.completed`` Event is optional; when supplied, its + ``finalizing_state_sigil`` is verified against the State produced by the + three transitions before the installed completion reducer is invoked. + It does not establish durable action-set availability. + """ + if len(events) not in (6, 7) or len(recovery_action_sets) != 4: + _fail("empty Recovery phase replay requires six or seven Events and four action sets") + validate_execution_journal_prefix_wire_v1(events, head=head) + expected_types = [ + "executor.epoch_started", + "executor.clock_uncertain", + "recovery.started", + "recovery.phase_advanced", + "recovery.phase_advanced", + "recovery.phase_advanced", + ] + if len(events) == 7: + expected_types.append("recovery.completed") + if [event["event_type"] for event in events] != expected_types: + _fail("empty Recovery phase replay has an unsupported Event sequence") + for action_set in recovery_action_sets: + validate_execution_recovery_action_set_v1(action_set) + if action_set["actions"] or action_set["supersedes_action_set_sigil"] is not None: + _fail("empty Recovery phase replay requires initial empty action sets") + state = replay_execution_journal_prefix_v1(events[:3]) + started_set = recovery_action_sets[0] + validate_execution_recovery_start_supplied_action_set_v1( + events[2], + started_set, + events[:2], + ) + if state["recoveries"][0]["current_action_set_sigil"] != started_set["action_set_sigil"]: + _fail("empty Recovery phase replay start State disagrees with action set") + for index, event in enumerate(events[3:6], 1): + completed_set = recovery_action_sets[index - 1] + next_set = recovery_action_sets[index] + validate_execution_recovery_action_set_supplied_prefix_v1( + completed_set, + events[: index + 1], + ) + validate_execution_recovery_action_set_supplied_prefix_v1( + next_set, + events[: index + 2], + ) + state = _reduce_empty_recovery_phase_advance_v1( + state, + event, + completed_set, + next_set, + ) + if len(events) == 7: + state = _reduce_recovery_completed_v1( + state, + events[6], + recovery_action_sets[-1], + ) + return state + + +def validate_execution_recovery_action_set_v1(action_set: dict[str, Any]) -> None: + """Validate a frozen Recovery action set without deriving or executing it.""" + validate_instance("execution-recovery-action-set-1.0.json", action_set) + _check_nfc(action_set) + if action_set["action_set_sigil"] != content_sigil(_without(action_set, "action_set_sigil")): + _fail("Execution Recovery action-set self-Sigil mismatch") + actions = action_set["actions"] + if action_set["derived_through_sequence"] < 1: + _fail("Execution Recovery action set requires a positive derived-through sequence") + if [action["ordinal"] for action in actions] != list(range(len(actions))): + _fail("Execution Recovery action ordinals must be contiguous from zero") + if len({action["target_event_id"] for action in actions}) != len(actions): + _fail("Execution Recovery action target Event IDs must be unique") + logical_actions: set[bytes] = set() + ordering_keys: list[tuple[Any, ...]] = [] + for action in actions: + _validate_execution_recovery_action_phase_v1(action_set["phase"], action) + if ( + action["target_sequence"] + != action_set["derived_through_sequence"] + 2 + action["ordinal"] + ): + _fail("Execution Recovery action target sequence disagrees with ordinal") + prerequisites = action["prerequisite_event_ids"] + if prerequisites != sorted( + prerequisites, + key=lambda value: _unsigned_ascii(value, "Recovery prerequisite Event ID"), + ): + _fail("Execution Recovery prerequisite Event IDs are not unsigned-ASCII sorted") + logical_action = _canonical_execution_recovery_logical_action_v1(action) + if logical_action in logical_actions: + _fail("Execution Recovery action set contains duplicate logical actions") + logical_actions.add(logical_action) + ordering_keys.append(_execution_recovery_action_ordering_key_v1(action, logical_action)) + if ordering_keys != sorted(ordering_keys): + _fail("Execution Recovery actions are not in canonical order") + + +def _validate_execution_recovery_action_phase_v1(phase: str, action: dict[str, Any]) -> None: + kind = action["action_kind"] + if kind not in _RECOVERY_PHASE_KINDS[phase]: + _fail("Execution Recovery action kind is not allowed in its phase") + event_type = action["target_event_type"] + if kind == "ADVANCE_ATTEMPT": + if phase == "FENCING" and event_type != "attempt.stop_latched": + _fail("FENCING Attempt advancement must target STOPPING") + if phase == "RECONCILING" and event_type != "attempt.cleaning": + _fail("RECONCILING Attempt advancement must target CLEANING") + if phase == "FINALIZING" and event_type not in _ATTEMPT_TERMINAL_EVENT_TYPES: + _fail("FINALIZING Attempt advancement must target an Attempt terminal state") + if kind == "ADVANCE_JOB" and phase == "FENCING" and event_type != "job.stop_latched": + _fail("FENCING Job advancement must target STOPPING") + + +def _execution_recovery_action_ordering_key_v1( + action: dict[str, Any], logical_action: bytes +) -> tuple[Any, ...]: + kind = action["action_kind"] + action_kind_rank = _RECOVERY_ACTION_KIND_RANK[kind] + if kind == "COMMIT_DUE_EVENT": + parameters = action["parameters"] + return ( + action_kind_rank, + _parse_time(parameters["due_at"]), + _DEADLINE_PRIORITY[parameters["deadline_kind"]], + _unsigned_ascii(parameters["deadline_entity_id"], "Recovery deadline entity ID"), + _unsigned_ascii(action["target_event_type"], "Recovery target Event type"), + ) + return ( + action_kind_rank, + _ENTITY_KIND_RANK[action["entity_kind"]], + _unsigned_ascii(action["entity_id"], "Recovery entity ID"), + _unsigned_ascii(action["target_event_type"], "Recovery target Event type"), + logical_action, + ) + + +def _canonical_execution_recovery_logical_action_v1(action: dict[str, Any]) -> bytes: + """Return RFC-0012's reservation-independent logical-action bytes.""" + logical = { + key: deepcopy(value) + for key, value in action.items() + if key not in {"ordinal", "target_event_id", "target_sequence"} + } + + def normalize_transition_causes(value: Any) -> None: + if isinstance(value, dict): + if value.get("trigger_kind") == "RECOVERY_DERIVATION": + value["trigger_event_id"] = "SELF_EVENT" + value["effective_sequence"] = "SELF_SEQUENCE" + for member in value.values(): + normalize_transition_causes(member) + elif isinstance(value, list): + for member in value: + normalize_transition_causes(member) + + normalize_transition_causes(logical) + return canonical_json(logical).encode("ascii") + + +def load_execution_recovery_action_set_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + action_set = _load_strict_object(raw, "Execution Recovery action set") + validate_execution_recovery_action_set_v1(action_set) + return action_set + + +def validate_execution_recovery_action_set_supplied_prefix_v1( + action_set: dict[str, Any], + events: list[dict[str, Any]], +) -> None: + """Anchor one sealed action set to a caller-supplied verified prefix. + + The supplied sequence is checked only for its closed wire chain and the + explicitly installed bounded reducer path. It does not establish that the + prefix is complete, current, durable, or authoritative for derivation. + """ + validate_execution_recovery_action_set_v1(action_set) + if not events: + _fail("Execution Recovery action set requires a nonempty supplied prefix") + validate_execution_journal_prefix_wire_v1(events) + last = events[-1] + if ( + action_set["derived_from_journal_id"] != last["journal_id"] + or action_set["derived_through_sequence"] != last["sequence"] + or action_set["derived_through_event_sigil"] != last["event_sigil"] + ): + _fail("Execution Recovery action set disagrees with supplied prefix") + + +def validate_execution_recovery_start_supplied_action_set_v1( + event: dict[str, Any], + action_set: dict[str, Any], + prefix: list[dict[str, Any]], +) -> None: + """Compare a Recovery start with its sealed STARTED set and supplied prefix. + + This is a closed-record relation only: it neither persists the action set, + derives actions, nor grants recovery or append authority. + """ + validate_execution_journal_event_v1(event) + validate_execution_recovery_action_set_supplied_prefix_v1(action_set, prefix) + last = prefix[-1] + payload = event["payload"] + if event["event_type"] != "recovery.started": + _fail("Execution Recovery start binding requires a recovery.started Event") + if ( + event["journal_id"] != last["journal_id"] + or event["sequence"] != last["sequence"] + 1 + or event["previous_event_sigil"] != last["event_sigil"] + or payload["recovery_id"] != action_set["recovery_id"] + or payload["initial_action_set_sigil"] != action_set["action_set_sigil"] + or payload["replay_through_sequence"] != action_set["derived_through_sequence"] + or payload["replay_through_event_sigil"] != action_set["derived_through_event_sigil"] + or action_set["phase"] != "STARTED" + or action_set["supersedes_action_set_sigil"] is not None + ): + _fail("Execution Recovery start disagrees with supplied action set or prefix") + + +def validate_execution_recovery_phase_advance_supplied_action_sets_v1( + state: dict[str, Any], + event: dict[str, Any], + completed_action_set: dict[str, Any], + next_action_set: dict[str, Any], +) -> None: + """Check one Recovery phase event against supplied before/after action sets. + + Completion of every action, durable action-set availability, and the next + set's derivation prefix remain replay and storage authority concerns. This + helper only compares the closed State, Event, and sealed documents supplied + by the caller. + """ + validate_execution_state_v1(state) + validate_execution_journal_event_v1(event) + validate_execution_recovery_action_set_v1(completed_action_set) + validate_execution_recovery_action_set_v1(next_action_set) + active_recovery_id = state["executor"]["active_recovery_id"] + if active_recovery_id is None: + _fail("Execution Recovery phase advance requires an active Recovery") + recovery = next( + item for item in state["recoveries"] if item["recovery_id"] == active_recovery_id + ) + payload = event["payload"] + expected_next = _RECOVERY_NEXT_PHASE.get(recovery["state"]) + expected_revision = [ + { + "entity_kind": "RECOVERY", + "entity_id": recovery["recovery_id"], + "preceding_revision": recovery["revision"], + "next_revision": recovery["revision"] + 1, + } + ] + if ( + event["event_type"] != "recovery.phase_advanced" + or event["recovery_action_binding"] is not None + or event["journal_id"] != state["journal_binding"]["journal_id"] + or event["sequence"] != state["journal_binding"]["through_sequence"] + 1 + or event["previous_event_sigil"] != state["journal_binding"]["through_event_sigil"] + or event["entity_revisions"] != expected_revision + or payload["recovery_id"] != recovery["recovery_id"] + or payload["from_phase"] != recovery["state"] + or payload["to_phase"] != expected_next + or payload["completed_action_set_sigil"] != recovery["current_action_set_sigil"] + or payload["completed_action_set_sigil"] != completed_action_set["action_set_sigil"] + or completed_action_set["recovery_id"] != recovery["recovery_id"] + or completed_action_set["phase"] != recovery["state"] + or payload["next_action_set_sigil"] != next_action_set["action_set_sigil"] + or next_action_set["recovery_id"] != recovery["recovery_id"] + or next_action_set["phase"] != payload["to_phase"] + or next_action_set["supersedes_action_set_sigil"] is not None + ): + _fail("Execution Recovery phase advance disagrees with supplied State or action sets") + + +def validate_execution_recovery_rebase_supplied_action_sets_v1( + state: dict[str, Any], + event: dict[str, Any], + prior_action_set: dict[str, Any], + replacement_action_set: dict[str, Any], +) -> None: + """Check one Recovery rebase against supplied State and sealed action sets. + + This verifies closed bindings only. It does not determine whether carried + completion events remain valid, derive replacement actions, or establish + durable/current action-set availability. + """ + validate_execution_state_v1(state) + validate_execution_journal_event_v1(event) + validate_execution_recovery_action_set_v1(prior_action_set) + validate_execution_recovery_action_set_v1(replacement_action_set) + active_recovery_id = state["executor"]["active_recovery_id"] + if active_recovery_id is None: + _fail("Execution Recovery rebase requires an active Recovery") + recovery = next( + item for item in state["recoveries"] if item["recovery_id"] == active_recovery_id + ) + payload = event["payload"] + expected_revision = [ + { + "entity_kind": "RECOVERY", + "entity_id": recovery["recovery_id"], + "preceding_revision": recovery["revision"], + "next_revision": recovery["revision"] + 1, + } + ] + if ( + event["event_type"] != "recovery.action_set_rebased" + or event["recovery_action_binding"] is not None + or event["journal_id"] != state["journal_binding"]["journal_id"] + or event["sequence"] != state["journal_binding"]["through_sequence"] + 1 + or event["previous_event_sigil"] != state["journal_binding"]["through_event_sigil"] + or event["entity_revisions"] != expected_revision + or payload["recovery_id"] != recovery["recovery_id"] + or payload["phase"] != recovery["state"] + or payload["prior_action_set_sigil"] != recovery["current_action_set_sigil"] + or payload["prior_action_set_sigil"] != prior_action_set["action_set_sigil"] + or prior_action_set["recovery_id"] != recovery["recovery_id"] + or prior_action_set["phase"] != recovery["state"] + or payload["replacement_action_set_sigil"] != replacement_action_set["action_set_sigil"] + or replacement_action_set["recovery_id"] != recovery["recovery_id"] + or replacement_action_set["phase"] != recovery["state"] + or replacement_action_set["supersedes_action_set_sigil"] + != prior_action_set["action_set_sigil"] + or payload["new_epoch"] != event["executor_epoch"] + ): + _fail("Execution Recovery rebase disagrees with supplied State or action sets") + + +def validate_execution_recovery_completion_supplied_action_set_v1( + state: dict[str, Any], + event: dict[str, Any], + finalizing_action_set: dict[str, Any], +) -> None: + """Check a Recovery completion Event against supplied pre-completion facts. + + The Event binds the sealed pre-transition FINALIZING State. The completed + post-State is deterministically sealed after this Event, avoiding an + impossible Event/State self-Sigil cycle. + """ + validate_execution_state_v1(state) + validate_execution_journal_event_v1(event) + validate_execution_recovery_action_set_v1(finalizing_action_set) + active_recovery_id = state["executor"]["active_recovery_id"] + if active_recovery_id is None: + _fail("Execution Recovery completion requires an active Recovery") + recovery = next( + item for item in state["recoveries"] if item["recovery_id"] == active_recovery_id + ) + executor = state["executor"] + payload = event["payload"] + expected_revisions = [ + { + "entity_kind": "EXECUTOR", + "entity_id": executor["executor_instance_id"], + "preceding_revision": executor["revision"], + "next_revision": executor["revision"] + 1, + }, + { + "entity_kind": "RECOVERY", + "entity_id": recovery["recovery_id"], + "preceding_revision": recovery["revision"], + "next_revision": recovery["revision"] + 1, + }, + ] + if ( + event["event_type"] != "recovery.completed" + or event["recovery_action_binding"] is not None + or event["journal_id"] != state["journal_binding"]["journal_id"] + or event["sequence"] != state["journal_binding"]["through_sequence"] + 1 + or event["previous_event_sigil"] != state["journal_binding"]["through_event_sigil"] + or event["executor_instance_id"] != executor["executor_instance_id"] + or event["executor_epoch"] != executor["executor_epoch"] + or event["executor_build_sigil"] + != executor["executor_build_binding"]["executor_build_sigil"] + or event["entity_revisions"] != expected_revisions + or recovery["state"] != "FINALIZING" + or payload["recovery_id"] != recovery["recovery_id"] + or payload["finalizing_state_sigil"] != state["state_sigil"] + or payload["completed_action_set_sigil"] != recovery["current_action_set_sigil"] + or payload["completed_action_set_sigil"] != finalizing_action_set["action_set_sigil"] + or finalizing_action_set["recovery_id"] != recovery["recovery_id"] + or finalizing_action_set["phase"] != "FINALIZING" + ): + _fail("Execution Recovery completion disagrees with supplied State or action set") + + +def _reduce_recovery_completed_v1( + state: dict[str, Any], + event: dict[str, Any], + finalizing_action_set: dict[str, Any], +) -> dict[str, Any]: + """Complete a sealed Recovery from its exact FINALIZING State.""" + validate_execution_recovery_completion_supplied_action_set_v1( + state, event, finalizing_action_set + ) + executor = state["executor"] + recovery_id = executor["active_recovery_id"] + assert recovery_id is not None + reduced = _advance_journal_binding_v1(state, event) + reduced["executor"] = { + **executor, + "revision": executor["revision"] + 1, + "active_recovery_id": None, + "authority_gates": [ + gate for gate in executor["authority_gates"] if gate != "RECOVERY_ACTIVE" + ], + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + reduced["recoveries"] = [ + { + **recovery, + "revision": recovery["revision"] + 1, + "state": "COMPLETED", + "last_event_id": event["event_id"], + "last_event_sigil": event["event_sigil"], + } + if recovery["recovery_id"] == recovery_id + else recovery + for recovery in state["recoveries"] + ] + return build_execution_state_v1(reduced) + + +def validate_execution_state_supplied_recovery_action_set_v1( + state: dict[str, Any], + action_set: dict[str, Any], +) -> None: + """Compare an active Recovery projection with one supplied sealed action set. + + This checks an immutable binding only. It neither establishes the supplied + set's durable availability nor treats any action as completed or executable. + """ + validate_execution_state_v1(state) + validate_execution_recovery_action_set_v1(action_set) + active_recovery_id = state["executor"]["active_recovery_id"] + if active_recovery_id is None: + _fail("Execution State has no active Recovery action-set binding") + recovery = next( + item for item in state["recoveries"] if item["recovery_id"] == active_recovery_id + ) + if ( + action_set["recovery_id"] != recovery["recovery_id"] + or action_set["phase"] != recovery["state"] + or action_set["action_set_sigil"] != recovery["current_action_set_sigil"] + ): + _fail("Execution State Recovery projection disagrees with supplied action set") + + +def validate_execution_recovery_action_supplied_event_v1( + action_set: dict[str, Any], + event: dict[str, Any], +) -> None: + """Compare one caller-supplied Event with its frozen Recovery action. + + Causation, idempotency, durable action-set retrieval, and the Event's + business postcondition remain external authorities; this only checks the + closed action-to-envelope relation RFC-0012 assigns to replay. + """ + validate_execution_recovery_action_set_v1(action_set) + validate_execution_journal_event_v1(event) + binding = event["recovery_action_binding"] + if binding is None: + _fail("Recovery action Event lacks a Recovery action binding") + if ( + binding["recovery_id"] != action_set["recovery_id"] + or binding["phase"] != action_set["phase"] + or binding["action_set_sigil"] != action_set["action_set_sigil"] + ): + _fail("Recovery action Event binding disagrees with supplied action set") + ordinal = binding["action_ordinal"] + if ordinal >= len(action_set["actions"]): + _fail("Recovery action Event ordinal is outside supplied action set") + action = action_set["actions"][ordinal] + if ( + event["event_id"] != action["target_event_id"] + or event["sequence"] != action["target_sequence"] + or event["event_type"] != action["target_event_type"] + ): + _fail("Recovery action Event envelope disagrees with supplied action") + expected_revision = { + "entity_kind": action["entity_kind"], + "entity_id": action["entity_id"], + "preceding_revision": action["expected_revision"], + "next_revision": action["expected_revision"] + 1, + } + if expected_revision not in event["entity_revisions"]: + _fail("Recovery action Event revision effect disagrees with supplied action") + + +def derive_result_ingress_receipt_id_v1(receipt: dict[str, Any]) -> str: + owner = receipt["owner_binding"] + digest = ( + content_sigil( + [ + "execution-result-ingress-receipt-id/1.0", + owner["job_id"], + owner["attempt_id"], + receipt["result_sigil"], + ] + ) + .removeprefix("sha256:") + .upper() + ) + return "OIR-" + digest + + +def validate_execution_result_ingress_receipt_v1(receipt: dict[str, Any]) -> None: + validate_instance("execution-result-ingress-receipt-1.0.json", receipt) + _check_nfc(receipt) + _validate_observation_owner_binding(receipt["owner_binding"]) + if receipt["receiver_identity"]["executor_epoch"] != receipt["owner_binding"]["executor_epoch"]: + _fail("Result ingress receiver epoch disagrees with owner binding") + observation = receipt["result_observation_binding"] + if observation[ + "observation_evidence_subject_sigil" + ] != derive_observation_evidence_subject_sigil_v1(receipt["owner_binding"], observation): + _fail("Result ingress receipt observation subject Sigil mismatch") + if receipt["ingress_receipt_id"] != derive_result_ingress_receipt_id_v1(receipt): + _fail("Result ingress receipt ID mismatch") + verification = receipt["credential_verification"] + expected_verification = content_sigil( + [ + "execution-result-ingress-credential-verification/1.0", + receipt["owner_binding"], + receipt["result_sigil"], + receipt["received_at"], + receipt["control_channel_identity_sigil"], + verification["lease_credential_digest"], + verification["verification_profile_sigil"], + verification["verified_at"], + ] + ) + if verification["verification_sigil"] != expected_verification: + _fail("Result ingress credential verification Sigil mismatch") + if not ( + _parse_time(receipt["received_at"]) + <= _parse_time(verification["verified_at"]) + <= _parse_time(receipt["created_at"]) + ): + _fail("Result ingress receipt time order mismatch") + if receipt["ingress_receipt_sigil"] != content_sigil( + _without(receipt, "ingress_receipt_sigil") + ): + _fail("Result ingress receipt self-Sigil mismatch") + + +def load_execution_result_ingress_receipt_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + receipt = _load_strict_object(raw, "Result ingress receipt") + validate_execution_result_ingress_receipt_v1(receipt) + return receipt + + +def validate_execution_result_ingress_event_intent_v1(intent: dict[str, Any]) -> None: + """Validate a sealed O2 Event candidate without reserving or appending it.""" + validate_instance("execution-result-ingress-event-intent-1.0.json", intent) + _check_nfc(intent) + candidate = intent["event_candidate"] + validate_execution_journal_event_v1(candidate) + if candidate["event_type"] != "attempt.result_ingress_received": + _fail("Result ingress Event intent candidate has the wrong Event type") + if intent["intent_sigil"] != content_sigil(_without(intent, "intent_sigil")): + _fail("Result ingress Event intent self-Sigil mismatch") + + +def load_execution_result_ingress_event_intent_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + intent = _load_strict_object(raw, "Result ingress Event intent") + validate_execution_result_ingress_event_intent_v1(intent) + return intent + + +def validate_execution_result_ingress_index_v1(index: dict[str, Any]) -> None: + """Validate a sealed O2 Index row, never its canonical-path visibility.""" + validate_instance("execution-result-ingress-index-1.0.json", index) + _check_nfc(index) + receipt = index["result_ingress_receipt"] + intent = index["ingress_event_intent"] + validate_execution_result_ingress_receipt_v1(receipt) + validate_execution_result_ingress_event_intent_v1(intent) + receipt_binding = { + "ingress_receipt_id": receipt["ingress_receipt_id"], + "ingress_receipt_sigil": receipt["ingress_receipt_sigil"], + } + if intent["result_ingress_receipt_binding"] != receipt_binding: + _fail("Result ingress Index intent binding disagrees with receipt") + candidate = intent["event_candidate"] + payload = candidate["payload"] + expected_payload = { + "ingress_receipt_id": receipt["ingress_receipt_id"], + "ingress_receipt_sigil": receipt["ingress_receipt_sigil"], + "result_sigil": receipt["result_sigil"], + "observation_evidence_subject_sigil": receipt["result_observation_binding"][ + "observation_evidence_subject_sigil" + ], + "received_at": receipt["received_at"], + } + if payload != expected_payload: + _fail("Result ingress Index candidate payload disagrees with receipt") + if ( + index["attempt_id"] != receipt["owner_binding"]["attempt_id"] + or index["result_sigil"] != receipt["result_sigil"] + or index["event_id"] != candidate["event_id"] + or index["idempotency_key_sigil"] != candidate["idempotency_key_sigil"] + ): + _fail("Result ingress Index top-level binding disagrees with Receipt or candidate") + owner = receipt["owner_binding"] + if ( + candidate["executor_instance_id"] != receipt["receiver_identity"]["executor_instance_id"] + or candidate["executor_epoch"] != owner["executor_epoch"] + or ("ATTEMPT", owner["attempt_id"]) + not in { + (revision["entity_kind"], revision["entity_id"]) + for revision in candidate["entity_revisions"] + } + ): + _fail("Result ingress candidate Event disagrees with Receipt owner") + expected_key = content_sigil( + [ + "execution-result-ingress-key/1.0", + owner["attempt_id"], + receipt["result_sigil"], + ] + ) + if index["idempotency_key_sigil"] != expected_key: + _fail("Result ingress Index idempotency key disagrees with Receipt") + status = index["status"] + if status["kind"] == "PENDING_EVENT": + head = status["expected_journal_head"] + validate_execution_journal_head_v1(head) + if ( + head["journal_id"] != candidate["journal_id"] + or head["last_sequence"] + 1 != candidate["sequence"] + or head["last_event_sigil"] != candidate["previous_event_sigil"] + ): + _fail("Result ingress pending Index Head disagrees with candidate Event") + elif status["kind"] == "COMMITTED": + event_ref = status["actual_event_ref"] + if event_ref != { + "journal_id": candidate["journal_id"], + "event_id": candidate["event_id"], + "sequence": candidate["sequence"], + "event_sigil": candidate["event_sigil"], + }: + _fail("Result ingress committed Index Event reference disagrees with candidate") + if index["index_sigil"] != content_sigil(_without(index, "index_sigil")): + _fail("Result ingress Index self-Sigil mismatch") + + +def load_execution_result_ingress_index_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + index = _load_strict_object(raw, "Result ingress Index") + validate_execution_result_ingress_index_v1(index) + return index + + +def validate_agent_result_acceptance_policy_v1(policy: dict[str, Any]) -> None: + """Validate the immutable RFC-0015 acceptance-policy preimage locally. + + This is deliberately not a Ward evaluation: the predicate inventory is + sealed here, while evaluating its predicates requires the authoritative + Chronicle, Task, Storage, and authentication facts. + """ + validate_instance("agent-result-acceptance-policy-1.0.json", policy) + _check_nfc(policy) + if policy["policy_sigil"] != content_sigil(_without(policy, "policy_sigil")): + _fail("Agent Result acceptance policy self-Sigil mismatch") + + +def validate_agent_result_acceptance_authorization_v1( + authorization: dict[str, Any], +) -> None: + """Validate the local closure of an Agent Result acceptance authorization. + + It never authenticates an invocation, evaluates Ward, resolves approval or + Storage records, or grants acceptance authority. Those are supplied-facts + and live-authority responsibilities outside this closed-document check. + """ + validate_instance("agent-result-acceptance-authorization-1.0.json", authorization) + _check_nfc(authorization) + validate_agent_result_acceptance_policy_v1(authorization["acceptance_policy"]) + if authorization["authorization_sigil"] != content_sigil( + _without(authorization, "authorization_sigil") + ): + _fail("Agent Result acceptance authorization self-Sigil mismatch") + + managed = authorization["managed_blob_sigils"] + if managed != sorted(managed, key=lambda value: value.encode("ascii")): + _fail("Agent Result acceptance managed Blob Sigils must be ASCII-sorted") + if len(managed) != len(set(managed)): + _fail("Agent Result acceptance managed Blob Sigils must be unique") + + expected_request_id = "ATR-" + ( + content_sigil( + [ + "agent-result-acceptance-transition-id/1.0", + authorization["authority_subject"]["task_binding"]["task_id"], + authorization["idempotency_key_sigil"], + ] + ) + .removeprefix("sha256:") + .upper() + ) + if authorization["transition_request_id"] != expected_request_id: + _fail("Agent Result acceptance transition request ID mismatch") + + ward_pass = authorization["ward_pass"] + if ( + ward_pass["evaluated_chronicle_head"] != authorization["expected_chronicle_head"] + or ward_pass["evaluated_at"] != authorization["requested_at"] + ): + _fail("Agent Result acceptance Ward pass disagrees with request Head or time") + approval = authorization["approval"] + if ( + approval["ward_decision_id"] != ward_pass["ward_decision_id"] + or approval["ward_decision_sigil"] != ward_pass["ward_decision_sigil"] + ): + _fail("Agent Result acceptance approval disagrees with Ward pass") + actor = authorization["actor"] + host = authorization["host_invocation"] + if actor["actor_sigil"] != content_sigil(_without(actor, "actor_sigil")): + _fail("Agent Result acceptance Actor self-Sigil mismatch") + if host["invocation_sigil"] != content_sigil(_without(host, "invocation_sigil")): + _fail("Agent Result acceptance Host invocation self-Sigil mismatch") + if actor["authentication_context_sigil"] != host["authentication_context_sigil"]: + _fail("Agent Result acceptance Actor and Host authentication contexts disagree") + if authorization["chronicle_actor"]["actor_id"] != actor["actor_id"]: + _fail("Agent Result acceptance Chronicle Actor disagrees with Actor binding") + allowed_actor_types = { + "USER": {"human"}, + "AGENT": {"agent"}, + "SYSTEM": {"policy", "tool"}, + } + if authorization["chronicle_actor"]["actor_type"] not in allowed_actor_types[actor["kind"]]: + _fail("Agent Result acceptance Chronicle Actor type disagrees with Actor kind") + + storage = authorization["acceptance_storage_binding"] + if storage["validated_blob_sigils"] != managed: + _fail("Agent Result acceptance Storage Blob set disagrees with managed Blob set") + evidence = storage["validation_evidence"] + evidence_sigils = [item["blob_sigil"] for item in evidence] + if evidence_sigils != managed: + _fail("Agent Result acceptance Storage evidence Blob set disagrees with managed Blob set") + if evidence_sigils != sorted(evidence_sigils, key=lambda value: value.encode("ascii")): + _fail("Agent Result acceptance Storage evidence must be ASCII-sorted by Blob Sigil") + if len(evidence_sigils) != len(set(evidence_sigils)): + _fail("Agent Result acceptance Storage evidence Blob Sigils must be unique") + if storage["validation_evidence_set_sigil"] != content_sigil(evidence): + _fail("Agent Result acceptance Storage evidence-set Sigil mismatch") + storage_event = storage["storage_event"] + for item in evidence: + availability = item["availability_event"] + if ( + availability["journal_id"] != storage_event["journal_id"] + or availability["sequence"] > storage_event["sequence"] + ): + _fail("Agent Result acceptance Storage evidence exceeds frozen Storage prefix") + + +def load_agent_result_acceptance_authorization_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + authorization = _load_strict_object(raw, "Agent Result acceptance authorization") + validate_agent_result_acceptance_authorization_v1(authorization) + return authorization + + +def validate_agent_result_v2(result: dict[str, Any]) -> None: + """Validate an RFC-0015 Agent Result v2's local deterministic closure. + + This does not rederive its Job Outcome, resolve frozen Storage facts, or + grant canonical acceptance authority. + """ + validate_instance("agent-result-2.0.json", result) + _check_nfc(result) + if result["result_sigil"] != content_sigil(_without(result, "result_sigil")): + _fail("Agent Result v2 self-Sigil mismatch") + outputs = result["outputs"] + keys = [(item["task_output_id"], item["blob_sigil"]) for item in outputs] + if keys != sorted(keys, key=lambda pair: (pair[0].encode("utf-8"), pair[1].encode("ascii"))): + _fail("Agent Result v2 outputs must be ordered by task output and Blob Sigil") + if len(keys) != len(set(keys)): + _fail("Agent Result v2 outputs must be unique by task output and Blob Sigil") + provenance = result["provenance"] + authorization = provenance["attempt_authorization_state"] + if authorization["kind"] not in {"NONE", "BOUND"}: + _fail("Agent Result v2 cannot contain a pending attempt authorization") + if provenance["storage_observation_binding"]["kind"] != "FROZEN": + _fail("Agent Result v2 requires a frozen Storage observation") + if provenance["control_evidence_set_binding"]["kind"] != "FROZEN": + _fail("Agent Result v2 requires a frozen control-evidence set") + if provenance["quarantine_binding_set_binding"]["kind"] != "FROZEN": + _fail("Agent Result v2 requires a frozen quarantine-binding set") + if provenance["terminalization_storage_manifest_binding"]["kind"] != "FROZEN": + _fail("Agent Result v2 requires a frozen terminalization manifest") + if provenance["output_root_protection"]["kind"] not in {"NO_HOLD", "HELD"}: + _fail("Agent Result v2 requires a terminal output-root protection branch") + + +def validate_agent_result_acceptance_transition_request_v1( + request: dict[str, Any], +) -> None: + """Validate an immutable acceptance candidate's local exact equalities. + + It deliberately does not authenticate its Actor, resolve the Outcome, + approval, Storage, Reference Set, or Chronicle prefix, or append a + canonical Event. Those actions require supplied authoritative facts. + """ + validate_instance("agent-result-acceptance-transition-request-1.0.json", request) + _check_nfc(request) + result = request["agent_result"] + validate_agent_result_v2(result) + authorization = request["acceptance_authorization"] + validate_agent_result_acceptance_authorization_v1(authorization) + if request["transition_request_sigil"] != content_sigil( + _without(request, "transition_request_sigil") + ): + _fail("Agent Result acceptance transition request self-Sigil mismatch") + expected_id = "ATR-" + content_sigil( + [ + "agent-result-acceptance-transition-id/1.0", + result["task_id"], + request["idempotency_key_sigil"], + ] + ).removeprefix("sha256:").upper() + if request["transition_request_id"] != expected_id: + _fail("Agent Result acceptance transition request ID mismatch") + if request["authorization_sigil"] != authorization["authorization_sigil"]: + _fail("Agent Result acceptance transition request authorization Sigil mismatch") + exact_authorization_fields = ( + "transition_request_id", "event_type", "expected_chronicle_head", + "acceptance_request_sigil", "idempotency_key_sigil", "reference_sets", + "managed_blob_sigils", "acceptance_storage_binding", "actor", + "host_invocation", "chronicle_actor", "requested_at", + ) + for field in exact_authorization_fields: + if request[field] != authorization[field]: + _fail(f"Agent Result acceptance transition request {field} disagrees with authorization") + if request["job_outcome_binding"] != result["job_outcome_binding"]: + _fail("Agent Result acceptance transition request Outcome binding disagrees with Agent Result") + subject = authorization["authority_subject"] + expected_subject = { + "task_binding": {"task_id": result["task_id"], "task_capsule_sigil": result["task_capsule_sigil"]}, + "program_id": result["program_id"], + "capability_binding": result["capability_binding"], + "snapshot_binding": result["snapshot_binding"], + "execution_specification_binding": result["execution_specification_binding"], + "job_binding": result["job_binding"], + "job_outcome_binding": result["job_outcome_binding"], + "agent_result_sigil": result["result_sigil"], + } + for field, expected in expected_subject.items(): + if subject[field] != expected: + _fail(f"Agent Result acceptance authority subject {field} disagrees with Agent Result") + + +def load_agent_result_acceptance_transition_request_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + request = _load_strict_object(raw, "Agent Result acceptance transition request") + validate_agent_result_acceptance_transition_request_v1(request) + return request + + +def project_agent_result_record_v2_supplied_facts( + event: dict[str, Any], + request: dict[str, Any], + intent: dict[str, Any], +) -> dict[str, Any]: + """Project one v2 acceptance Event from complete caller-supplied preimages. + + This is a strict supplied-facts comparator, not Chronicle replay or + acceptance authority: callers must separately establish the authoritative + prefix, immutable request lookup, and committed canonical-reference pin. + """ + from .artifact_storage_contracts import validate_artifact_storage_reference_intent_v1 + + validate_instance("chronicle-event-1.1.json", event) + _check_nfc(event) + event_body = {key: value for key, value in event.items() if key not in {"event_body_sigil", "receipt"}} + if event["event_body_sigil"] != content_sigil(event_body): + _fail("Agent Result v2 Event body self-Sigil mismatch") + receipt = event["receipt"] + if receipt["receipt_sigil"] != content_sigil(_without(receipt, "receipt_sigil")): + _fail("Agent Result v2 Receipt self-Sigil mismatch") + if ( + receipt["event_id"] != event["event_id"] + or receipt["event_body_sigil"] != event["event_body_sigil"] + or receipt["previous_receipt_sigil"] != event["previous_receipt_sigil"] + or receipt["accepted_at"] != event["occurred_at"] + ): + _fail("Agent Result v2 Receipt disagrees with Event") + validate_agent_result_acceptance_transition_request_v1(request) + validate_artifact_storage_reference_intent_v1(intent) + if event["type"] != request["event_type"] or event["type"] != intent["canonical_event_type"]: + _fail("Agent Result v2 Event family disagrees with request or intent") + if event["type"] != "agent-result.accepted": + _fail("Agent Result v2 Event has an invalid family") + payload = event["payload"] + expected_payload_keys = { + "agent_result", "program_id", "host_identity_sigil", "capability_contract_sigil", + "snapshot_sigil", "task_capsule_sigil", "job_outcome_sigil", "result_sigil", + "acceptance_request_sigil", "idempotency_key_sigil", "transition_request_id", + "transition_request_sigil", "acceptance_storage_binding", "actor", "host_invocation", + "authorization_sigil", "reference_intent_id", "reference_intent_record_sigil", + "reference_set_id", "reference_set_sigil", "occurred_at", + } + if set(payload) != expected_payload_keys: + _fail("Agent Result v2 Event payload has an invalid field set") + result = request["agent_result"] + exact_payload = { + "agent_result": result, + "program_id": result["program_id"], + "host_identity_sigil": result["host_identity_sigil"], + "capability_contract_sigil": result["capability_binding"]["capability_contract_sigil"], + "snapshot_sigil": result["snapshot_binding"]["snapshot_sigil"], + "task_capsule_sigil": result["task_capsule_sigil"], + "job_outcome_sigil": result["job_outcome_binding"]["outcome_sigil"], + "result_sigil": result["result_sigil"], + "acceptance_request_sigil": request["acceptance_request_sigil"], + "idempotency_key_sigil": request["idempotency_key_sigil"], + "transition_request_id": request["transition_request_id"], + "transition_request_sigil": request["transition_request_sigil"], + "acceptance_storage_binding": request["acceptance_storage_binding"], + "actor": request["actor"], + "host_invocation": request["host_invocation"], + "authorization_sigil": request["authorization_sigil"], + "reference_intent_id": intent["reference_intent_id"], + "reference_intent_record_sigil": intent["record_sigil"], + "reference_set_id": intent["reference_sets"][0]["reference_set_id"], + "reference_set_sigil": intent["reference_sets"][0]["reference_set_sigil"], + "occurred_at": event["occurred_at"], + } + if payload != exact_payload: + _fail("Agent Result v2 Event payload disagrees with supplied request or intent") + if event["actor"] != request["chronicle_actor"] or event["object_id"] != result["task_id"]: + _fail("Agent Result v2 Event Actor or object disagrees with request") + head = request["expected_chronicle_head"] + if head["event_count"] == 9223372036854775807: + _fail("Agent Result v2 expected Chronicle Head is count-exhausted") + if event["sequence"] != head["event_count"] + 1 or event["previous_receipt_sigil"] != head["terminal_receipt_sigil"]: + _fail("Agent Result v2 Event does not continue the expected Head") + if ( + intent["transition_request_id"] != request["transition_request_id"] + or intent["transition_request_sigil"] != request["transition_request_sigil"] + or intent["expected_chronicle_head"] != head + or intent["reference_sets"] != request["reference_sets"] + or intent["blob_sigils"] != request["managed_blob_sigils"] + or intent["actor_id"] != request["actor"]["actor_id"] + or intent["authorization_sigil"] != request["authorization_sigil"] + or intent["idempotency_key_sigil"] != request["idempotency_key_sigil"] + or intent["requested_at"] != request["requested_at"] + ): + _fail("Agent Result v2 Reference Intent disagrees with request") + record = { + "schema_version": "agent-result-record/2.0", + **{key: result[key] for key in ("task_id", "program_id", "task_capsule_sigil", "host_identity_sigil", "capability_binding", "snapshot_binding", "job_binding", "execution_specification_binding", "job_outcome_binding", "terminal_event_sigil", "selected_attempt_id", "assurance_claim_sigil", "terminal_source_binding", "outputs", "provenance", "status")}, + "canonical_reference_binding": {key: payload[key] for key in ("reference_intent_id", "reference_intent_record_sigil", "transition_request_id", "transition_request_sigil", "acceptance_storage_binding", "reference_set_id", "reference_set_sigil")}, + "agent_result_sigil": result["result_sigil"], + "accepted_at": event["occurred_at"], + "acceptance_receipt": receipt["receipt_id"], + } + validate_instance("agent-result-record-2.0.json", record) + return record + + +def derive_execution_storage_root_manifest_id_v1(manifest: dict[str, Any]) -> str: + """Derive an ESM-ID from its immutable owner tuple.""" + digest = ( + content_sigil( + [ + "execution-storage-root-manifest-id/1.0", + manifest["root_kind"], + manifest["job_id"], + manifest["attempt_id"], + manifest["owner_binding"], + ] + ) + .removeprefix("sha256:") + .upper() + ) + return f"ESM-{digest}" + + +def validate_execution_storage_root_manifest_v1(manifest: dict[str, Any]) -> None: + """Validate an ESM's local immutable closure, never Storage authority.""" + validate_instance("execution-storage-root-manifest-1.0.json", manifest) + _check_nfc(manifest) + if manifest["manifest_id"] != derive_execution_storage_root_manifest_id_v1(manifest): + _fail("Execution Storage Root Manifest ID mismatch") + if manifest["manifest_sigil"] != content_sigil(_without(manifest, "manifest_sigil")): + _fail("Execution Storage Root Manifest self-Sigil mismatch") + entries = manifest["entries"] + if len({entry["storage_subject_id"] for entry in entries}) != len(entries): + _fail("Execution Storage Root Manifest storage subject IDs must be unique") + if manifest["root_kind"] in {"JOB_INPUT", "ATTEMPT_INPUT"}: + ordinals = [entry["subject"]["input_ordinal"] for entry in entries] + if ordinals != list(range(len(entries))): + _fail("Execution Storage Root Manifest input ordinals must be contiguous") + expected_blobs: list[dict[str, Any]] = [] + for entry in entries: + if entry["entry_sigil"] != content_sigil(_without(entry, "entry_sigil")): + _fail("Execution Storage Root Manifest entry self-Sigil mismatch") + subject = entry["subject"] + if subject["kind"] != "ATTEMPT_OUTPUT": + expected_subject_id = content_sigil( + [ + "execution-storage-subject-id/1.0", + manifest["root_kind"], + manifest["job_id"], + manifest["attempt_id"], + subject, + ] + ) + if entry["storage_subject_id"] != expected_subject_id: + _fail("Execution Storage Root Manifest storage subject ID mismatch") + origin_kind = entry["storage_origin"]["kind"] + claimed_blob = entry["claimed_blob"] + if (origin_kind == "NOT_STORED") != (claimed_blob is None): + _fail("Execution Storage Root Manifest claimed Blob disagrees with origin") + subject_blob = _execution_storage_subject_blob_ref_v1(subject) + if ( + subject_blob is not None + and origin_kind in {"COMMITTED_BLOB", "QUARANTINE"} + and subject_blob != claimed_blob + ): + _fail("Execution Storage Root Manifest claimed Blob disagrees with subject") + if origin_kind == "COMMITTED_BLOB": + expected_blobs.append(claimed_blob) + expected_blobs.sort(key=lambda blob: (blob["blob_sigil"], blob["size_bytes"])) + if manifest["blob_refs"] != expected_blobs: + _fail("Execution Storage Root Manifest Blob refs disagree with committed entries") + if (manifest["protection_plan"]["kind"] == "NONE") != (not expected_blobs): + _fail("Execution Storage Root Manifest protection plan disagrees with Blob refs") + + +def _execution_storage_subject_blob_ref_v1(subject: dict[str, Any]) -> dict[str, Any] | None: + kind = subject["kind"] + if kind in {"ATTEMPT_OUTPUT", "LOG_STREAM", "RESOURCE_EVIDENCE"}: + return {"blob_sigil": subject["blob_sigil"], "size_bytes": subject["byte_size"]} + if kind == "TERMINAL_SOURCE": + return subject["storage_blob"] + return None + + +def load_execution_storage_root_manifest_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + manifest = _load_strict_object(raw, "Execution Storage Root Manifest") + validate_execution_storage_root_manifest_v1(manifest) + return manifest + + +def derive_execution_root_hold_release_authorization_id_v1( + authorization: dict[str, Any], +) -> str: + """Derive the immutable EHR-ID from the held execution root.""" + digest = ( + content_sigil( + [ + "execution-root-hold-release-authorization-id/1.0", + authorization["storage_root"]["hold_id"], + ] + ) + .removeprefix("sha256:") + .upper() + ) + return f"EHR-{digest}" + + +def validate_execution_root_hold_release_authorization_v1( + authorization: dict[str, Any], +) -> None: + """Validate an EHR's local bindings without authorizing a Storage release.""" + validate_instance("execution-root-hold-release-authorization-1.0.json", authorization) + _check_nfc(authorization) + if authorization[ + "release_authorization_id" + ] != derive_execution_root_hold_release_authorization_id_v1(authorization): + _fail("Execution Root Hold Release Authorization ID mismatch") + if authorization["release_authorization_sigil"] != content_sigil( + _without(authorization, "release_authorization_sigil") + ): + _fail("Execution Root Hold Release Authorization self-Sigil mismatch") + basis = authorization["basis"] + if basis["kind"] == "OWNER_TERMINAL": + validate_execution_journal_head_v1(basis["verification_head"]) + if basis["activation_event_sequence"] >= basis["terminal_event_sequence"]: + _fail("Execution Root Hold Release owner-terminal event order is invalid") + if basis["verification_head"]["last_sequence"] < basis["terminal_event_sequence"]: + _fail("Execution Root Hold Release verification Head predates terminal Event") + elif basis["kind"] == "OUTPUT_DEADLINE": + validate_execution_journal_head_v1(basis["verification_head"]) + if basis["activation_event_sequence"] >= basis["terminal_event_sequence"]: + _fail("Execution Root Hold Release output-deadline event order is invalid") + if basis["verification_head"]["last_sequence"] < basis["terminal_event_sequence"]: + _fail("Execution Root Hold Release verification Head predates terminal Event") + else: + validate_execution_journal_head_v1(basis["absence_head"]) + + +def load_execution_root_hold_release_authorization_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + authorization = _load_strict_object(raw, "Execution Root Hold Release Authorization") + validate_execution_root_hold_release_authorization_v1(authorization) + return authorization + + +def derive_execution_control_evidence_set_id_v1(evidence_set: dict[str, Any]) -> str: + """Derive the immutable CES-ID from its Attempt owner binding.""" + digest = ( + content_sigil( + [ + "execution-control-evidence-set-id/1.0", + evidence_set["job_id"], + evidence_set["attempt_id"], + evidence_set["attempt_binding_sigil"], + ] + ) + .removeprefix("sha256:") + .upper() + ) + return f"CES-{digest}" + + +def validate_execution_control_evidence_set_v1(evidence_set: dict[str, Any]) -> None: + """Validate a frozen CES locally without resolving its evidence records.""" + validate_instance("execution-control-evidence-set-1.0.json", evidence_set) + _check_nfc(evidence_set) + if evidence_set["control_evidence_set_id"] != derive_execution_control_evidence_set_id_v1( + evidence_set + ): + _fail("Execution Control Evidence Set ID mismatch") + if evidence_set["control_evidence_set_sigil"] != content_sigil( + _without(evidence_set, "control_evidence_set_sigil") + ): + _fail("Execution Control Evidence Set self-Sigil mismatch") + refs = evidence_set["control_evidence_refs"] + if [reference["control_dimension"] for reference in refs] != list(_CONTROL_DIMENSION_ORDER): + _fail("Execution Control Evidence Set dimensions are not in matrix order") + ids = [reference["control_evidence_id"] for reference in refs] + if len(set(ids)) != len(ids): + _fail("Execution Control Evidence Set evidence IDs must be unique") + + +def load_execution_control_evidence_set_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + evidence_set = _load_strict_object(raw, "Execution Control Evidence Set") + validate_execution_control_evidence_set_v1(evidence_set) + return evidence_set + + +def derive_execution_quarantine_binding_set_id_v1(binding_set: dict[str, Any]) -> str: + """Derive the immutable QBS-ID from frozen Attempt and storage inputs.""" + digest = ( + content_sigil( + [ + "execution-quarantine-binding-set-id/1.0", + binding_set["job_id"], + binding_set["attempt_id"], + binding_set["attempt_binding_sigil"], + binding_set["quarantine_plan_sigil"], + binding_set["terminalization_storage_manifest_binding"], + ] + ) + .removeprefix("sha256:") + .upper() + ) + return f"QBS-{digest}" + + +def validate_execution_quarantine_binding_set_v1(binding_set: dict[str, Any]) -> None: + """Validate a frozen QBS locally without resolving the Storage projection.""" + validate_instance("execution-quarantine-binding-set-1.0.json", binding_set) + _check_nfc(binding_set) + if binding_set["quarantine_binding_set_id"] != derive_execution_quarantine_binding_set_id_v1( + binding_set + ): + _fail("Execution Quarantine Binding Set ID mismatch") + if binding_set["quarantine_binding_set_sigil"] != content_sigil( + _without(binding_set, "quarantine_binding_set_sigil") + ): + _fail("Execution Quarantine Binding Set self-Sigil mismatch") + bindings = binding_set["bindings"] + if len({binding["storage_subject_id"] for binding in bindings}) != len(bindings): + _fail("Execution Quarantine Binding Set storage subject IDs must be unique") + if len({binding["quarantine_ref"]["quarantine_id"] for binding in bindings}) != len(bindings): + _fail("Execution Quarantine Binding Set Quarantine IDs must be unique") + for binding in bindings: + if binding["quarantine_binding_sigil"] != content_sigil( + _without(binding, "quarantine_binding_sigil") + ): + _fail("Execution Quarantine Binding Set binding self-Sigil mismatch") + origin = binding["storage_origin"] + quarantine = binding["quarantine_ref"] + if ( + origin["quarantine_id"] != quarantine["quarantine_id"] + or origin["transfer"]["transfer_attempt_id"] != quarantine["owner_id"] + ): + _fail("Execution Quarantine Binding Set origin disagrees with Quarantine owner") + if quarantine["origin_event"] != origin["quarantine_origin_event"]: + _fail("Execution Quarantine Binding Set origin Event disagrees with storage origin") + if quarantine["observation_event"]["sequence"] < quarantine["origin_event"]["sequence"]: + _fail("Execution Quarantine Binding Set observation predates origin Event") + + +def load_execution_quarantine_binding_set_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + binding_set = _load_strict_object(raw, "Execution Quarantine Binding Set") + validate_execution_quarantine_binding_set_v1(binding_set) + return binding_set + + +def validate_execution_terminalization_supplied_records_v1( + *, + job_id: str, + attempt_id: str, + attempt_binding_sigil: str, + terminalization_storage_manifest_binding: dict[str, Any], + control_evidence_set_binding: dict[str, Any], + quarantine_binding_set_binding: dict[str, Any], + output_root_protection: dict[str, Any], + manifest: dict[str, Any], + control_evidence_set: dict[str, Any], + quarantine_binding_set: dict[str, Any], +) -> None: + """Compare terminalization's complete caller-supplied immutable records. + + This is intentionally not a Storage resolver or replay authority. It + checks only the exact records the caller already supplied. + """ + validate_execution_storage_root_manifest_v1(manifest) + validate_execution_control_evidence_set_v1(control_evidence_set) + validate_execution_quarantine_binding_set_v1(quarantine_binding_set) + expected_manifest = { + "kind": "FROZEN", "storage_root_manifest_id": manifest["manifest_id"], + "storage_root_manifest_sigil": manifest["manifest_sigil"], + } + expected_ces = { + "kind": "FROZEN", "control_evidence_set_id": control_evidence_set["control_evidence_set_id"], + "control_evidence_set_sigil": control_evidence_set["control_evidence_set_sigil"], + } + expected_qbs = { + "kind": "FROZEN", "quarantine_binding_set_id": quarantine_binding_set["quarantine_binding_set_id"], + "quarantine_binding_set_sigil": quarantine_binding_set["quarantine_binding_set_sigil"], + } + if ( + terminalization_storage_manifest_binding != expected_manifest + or control_evidence_set_binding != expected_ces + or quarantine_binding_set_binding != expected_qbs + or manifest["root_kind"] != "ATTEMPT_OUTPUT" or manifest["job_id"] != job_id + or manifest["attempt_id"] != attempt_id + or manifest["owner_binding"]["attempt_binding_sigil"] != attempt_binding_sigil + or manifest["owner_binding"]["control_evidence_set_binding"] != expected_ces + or control_evidence_set["job_id"] != job_id or control_evidence_set["attempt_id"] != attempt_id + or control_evidence_set["attempt_binding_sigil"] != attempt_binding_sigil + or quarantine_binding_set["job_id"] != job_id or quarantine_binding_set["attempt_id"] != attempt_id + or quarantine_binding_set["attempt_binding_sigil"] != attempt_binding_sigil + or quarantine_binding_set["terminalization_storage_manifest_binding"] != expected_manifest + or output_root_protection.get("kind") not in {"NO_HOLD", "HELD"} + or output_root_protection["terminalization_storage_manifest_binding"] != expected_manifest + ): + _fail("Terminalization supplied records disagree with frozen Attempt bindings") + if output_root_protection["kind"] == "NO_HOLD" and manifest["blob_refs"]: + _fail("Terminalization NO_HOLD protection requires an empty output Manifest") + + +def derive_execution_output_storage_observation_set_id_v1( + observation_set: dict[str, Any], +) -> str: + """Derive the immutable OS-ID from its terminal Attempt inputs.""" + digest = ( + content_sigil( + [ + "execution-output-storage-observation-set-id/1.0", + observation_set["job_id"], + observation_set["attempt_id"], + observation_set["attempt_binding_sigil"], + observation_set["result_binding"], + observation_set["log_closure_sigil"], + observation_set["output_closure_sigil"], + observation_set["control_evidence_set_binding"], + observation_set["quarantine_binding_set_binding"], + observation_set["terminalization_storage_manifest_binding"], + observation_set["output_root_protection"], + observation_set["terminal_source_binding"], + ] + ) + .removeprefix("sha256:") + .upper() + ) + return f"OS-{digest}" + + +def _observation_member_blob_refs_v1(member: dict[str, Any]) -> list[str]: + kind = member["kind"] + if kind in {"ATTEMPT_OUTPUT", "RESOURCE_EVIDENCE"}: + return [member["blob_sigil"]] + if kind == "LOG_STREAM": + return [member["content"]["blob_sigil"]] + if kind == "TERMINAL_SOURCE": + return [member["storage_blob"]["blob_sigil"]] + return [] + + +def _validate_observation_storage_v1( + storage: dict[str, Any], + blob_sigil: str, + size_bytes: int, + storage_event: dict[str, Any], +) -> None: + kind = storage["kind"] + if kind == "NONE": + _fail("Output Storage Observation member with a claimed Blob cannot use NONE storage") + if kind == "BLOB": + if storage["blob_sigil"] != blob_sigil or storage["size_bytes"] != size_bytes: + _fail("Output Storage Observation BLOB storage disagrees with member Blob") + if storage["terminal_storage_status"] != storage["availability"]: + _fail("Output Storage Observation BLOB terminal status disagrees with availability") + integrity = storage["integrity_event_sigils"] + if integrity != sorted( + integrity, key=lambda value: _unsigned_ascii(value, "integrity Event Sigil") + ): + _fail("Output Storage Observation integrity Event Sigils are not unsigned-ASCII sorted") + available_at = storage["availability_as_of"] + if ( + available_at["journal_id"] != storage_event["journal_id"] + or available_at["sequence"] > storage_event["sequence"] + ): + _fail("Output Storage Observation availability is outside the frozen Storage prefix") + return + if storage["claimed_blob_sigil"] != blob_sigil or storage["claimed_size_bytes"] != size_bytes: + _fail("Output Storage Observation Quarantine storage disagrees with member Blob") + if kind == "QUARANTINE_TERMINAL_NEGATIVE": + if storage["origin_event"]["sequence"] > storage["observation_event"]["sequence"]: + _fail("Output Storage Observation Quarantine observation predates its origin") + observed = storage["observation_event"] + else: + observed = storage["quarantine_event"] + if ( + observed["journal_id"] != storage_event["journal_id"] + or observed["sequence"] > storage_event["sequence"] + ): + _fail("Output Storage Observation Quarantine is outside the frozen Storage prefix") + + +def validate_execution_output_storage_observation_set_v1( + observation_set: dict[str, Any], +) -> None: + """Validate an OS document locally, never resolving Storage or Execution history.""" + validate_instance("execution-output-storage-observation-set-1.0.json", observation_set) + _check_nfc(observation_set) + if observation_set[ + "observation_set_id" + ] != derive_execution_output_storage_observation_set_id_v1(observation_set): + _fail("Execution Output Storage Observation Set ID mismatch") + if observation_set["observation_set_sigil"] != content_sigil( + _without(observation_set, "observation_set_sigil") + ): + _fail("Execution Output Storage Observation Set self-Sigil mismatch") + protection = observation_set["output_root_protection"] + if protection["kind"] not in {"NO_HOLD", "HELD"}: + _fail("Output Storage Observation requires a terminal output-root protection branch") + if ( + protection["terminalization_storage_manifest_binding"] + != observation_set["terminalization_storage_manifest_binding"] + ): + _fail("Output Storage Observation protection disagrees with terminalization manifest") + + members = observation_set["members"] + cursor = 0 + result_kind = observation_set["result_binding"]["kind"] + if members[cursor]["kind"] == "ATTEMPT_OUTPUTS_NONE": + expected_reason = { + "NONE": "NO_RESULT", + "REJECTED": "RESULT_REJECTED", + }.get(result_kind, "OUTPUT_ARRAY_EMPTY") + if members[cursor]["reason"] != expected_reason: + _fail("Output Storage Observation output sentinel disagrees with Result binding") + cursor += 1 + else: + start = cursor + while cursor < len(members) and members[cursor]["kind"] == "ATTEMPT_OUTPUT": + cursor += 1 + outputs = members[start:cursor] + if not outputs or result_kind != "ACCEPTED": + _fail("Output Storage Observation output members require an accepted Result") + output_keys = [ + (_unsigned_ascii(member["logical_name"], "output logical name"), member["blob_sigil"]) + for member in outputs + ] + if output_keys != sorted(output_keys) or len(set(output_keys)) != len(output_keys): + _fail("Output Storage Observation output members are not uniquely sorted") + + logs = members[cursor : cursor + 3] + if len(logs) != 3 or [member["kind"] for member in logs] != ["LOG_STREAM"] * 3: + _fail("Output Storage Observation must contain exactly three Log streams") + if [member["stream"] for member in logs] != ["STDOUT", "STDERR", "STRUCTURED"]: + _fail("Output Storage Observation Log streams are not in fixed order") + if len({member["log_stream_id"] for member in logs}) != 3: + _fail("Output Storage Observation Log stream IDs must be unique") + for log in logs: + content = log["content"] + if content["kind"] == "EMPTY": + if log["final_sequence"] is not None or log["captured_bytes"] != 0: + _fail("Output Storage Observation empty Log has non-empty closure") + elif log["final_sequence"] is None or log["captured_bytes"] == 0: + _fail("Output Storage Observation captured Log lacks a non-empty closure") + cursor += 3 + + if cursor >= len(members): + _fail("Output Storage Observation omits its resource-evidence group") + if members[cursor]["kind"] == "RESOURCE_EVIDENCE_NONE": + cursor += 1 + else: + start = cursor + while cursor < len(members) and members[cursor]["kind"] == "RESOURCE_EVIDENCE": + cursor += 1 + resources = members[start:cursor] + if not resources: + _fail("Output Storage Observation resource-evidence group is invalid") + keys = [ + ( + _unsigned_ascii(member["control_evidence_id"], "control evidence ID"), + _CONTROL_PHASE_RANK[member["phase"]], + _CONTROL_EVIDENCE_KIND_RANK[member["evidence_kind"]], + member["phase_evidence_entry_sigil"], + ) + for member in resources + ] + if keys != sorted(keys) or len(set(keys)) != len(keys): + _fail("Output Storage Observation resource evidence is not uniquely sorted") + + terminal_members = members[cursor:] + if len(terminal_members) != 1: + _fail("Output Storage Observation must end with one terminal-source member") + terminal = terminal_members[0] + terminal_binding = observation_set["terminal_source_binding"] + if terminal["kind"] == "TERMINAL_SOURCE_NOT_APPLICABLE": + if terminal_binding["kind"] != "NOT_APPLICABLE": + _fail("Output Storage Observation terminal-source sentinel disagrees with binding") + elif terminal["kind"] == "TERMINAL_SOURCE_NONE": + if ( + terminal_binding["kind"] != "QUARANTINED" + or any( + terminal_binding[field] is not None + for field in ( + "terminal_source_identity", + "terminal_source_sigil", + "storage_blob", + ) + ) + or terminal_binding["file_count"] != 0 + or terminal_binding["byte_count"] != 0 + or terminal["reason_codes"] != terminal_binding["reason_codes"] + ): + _fail("Output Storage Observation terminal-source NONE disagrees with binding") + else: + if terminal_binding["kind"] not in {"VERIFIED", "QUARANTINED"}: + _fail("Output Storage Observation terminal source lacks a compatible binding") + copied = ( + "terminal_source_identity", + "terminal_source_sigil", + "storage_blob", + "retention_policy_sigil", + "file_count", + "byte_count", + ) + if any(terminal[field] != terminal_binding[field] for field in copied): + _fail("Output Storage Observation terminal source disagrees with binding") + if terminal["disposition"] != terminal_binding["kind"]: + _fail("Output Storage Observation terminal source disposition disagrees with binding") + if terminal_binding["kind"] == "VERIFIED" and terminal["storage"]["kind"] != "BLOB": + _fail("Output Storage Observation verified terminal source requires BLOB storage") + + for member in members: + kind = member["kind"] + if kind in {"ATTEMPT_OUTPUT", "RESOURCE_EVIDENCE"}: + _validate_observation_storage_v1( + member["storage"], + member["blob_sigil"], + member["byte_size"], + observation_set["storage_event"], + ) + elif kind == "LOG_STREAM": + _validate_observation_storage_v1( + member["content"]["storage"], + member["content"]["blob_sigil"], + member["captured_bytes"], + observation_set["storage_event"], + ) + elif kind == "TERMINAL_SOURCE": + _validate_observation_storage_v1( + member["storage"], + member["storage_blob"]["blob_sigil"], + member["storage_blob"]["size_bytes"], + observation_set["storage_event"], + ) + + expected_blob_sigils = sorted( + { + blob_sigil + for member in members + for blob_sigil in _observation_member_blob_refs_v1(member) + }, + key=lambda value: _unsigned_ascii(value, "Blob Sigil"), + ) + if observation_set["blob_sigils"] != expected_blob_sigils: + _fail("Output Storage Observation Blob Sigils disagree with members") + + +def load_execution_output_storage_observation_set_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + observation_set = _load_strict_object(raw, "Execution Output Storage Observation Set") + validate_execution_output_storage_observation_set_v1(observation_set) + return observation_set + + +def derive_observation_evidence_subject_sigil_v1( + owner_binding: dict[str, Any], result_observation_binding: dict[str, Any] +) -> str: + return content_sigil( + [ + "execution-result-observation-subject/1.0", + owner_binding, + result_observation_binding["runtime_observation"], + result_observation_binding["termination_observation"], + ] + ) + + +def derive_observation_evidence_id_v1(evidence: dict[str, Any]) -> str: + digest = ( + content_sigil( + [ + "execution-observation-evidence-id/1.0", + evidence["job_id"], + evidence["attempt_id"], + evidence["result_ingress_receipt_binding"]["ingress_receipt_id"], + evidence["result_observation_binding"]["observation_evidence_subject_sigil"], + ] + ) + .removeprefix("sha256:") + .upper() + ) + return "OVE-" + digest + + +def _observation_owner(evidence: dict[str, Any]) -> dict[str, Any]: + members = ( + "job_id", + "job_binding_sigil", + "attempt_id", + "attempt_binding_sigil", + "lease_id", + "lease_binding_sigil", + "worker_id", + "worker_binding_sigil", + "worker_session_id", + "worker_session_binding_sigil", + "executor_epoch", + "fence_tuple", + ) + return {member: evidence[member] for member in members} + + +def _validate_observation_owner_binding(owner: dict[str, Any]) -> None: + """Check local equality inside an O1/O2 owner binding. + + This is deliberately a closed-record check only: it does not resolve any + Job, Attempt, Lease, Worker, or Journal record. + """ + fence = owner["fence_tuple"] + for member in ("job_id", "attempt_id", "lease_id", "executor_epoch"): + if fence[member] != owner[member]: + _fail(f"Observation owner binding disagrees with fence_tuple: {member}") + + +def validate_execution_observation_evidence_v1(evidence: dict[str, Any]) -> None: + validate_instance("execution-observation-evidence-1.0.json", evidence) + _check_nfc(evidence) + owner = _observation_owner(evidence) + _validate_observation_owner_binding(owner) + binding = evidence["result_observation_binding"] + if binding[ + "observation_evidence_subject_sigil" + ] != derive_observation_evidence_subject_sigil_v1(owner, binding): + _fail("Observation Evidence subject Sigil mismatch") + if evidence["observation_evidence_id"] != derive_observation_evidence_id_v1(evidence): + _fail("Observation Evidence ID mismatch") + runtime = binding["runtime_observation"] + termination = binding["termination_observation"] + if not ( + _parse_time(runtime["started_at"]) + <= _parse_time(runtime["ended_at"]) + <= _parse_time(termination["observed_at"]) + <= _parse_time(evidence["created_at"]) + ): + _fail("Observation Evidence time order mismatch") + assessment = evidence["assessment"] + if assessment["kind"] == "MATCHED": + if assessment["reason_bindings"]: + _fail("MATCHED Observation Evidence must have no reasons") + if ( + assessment["verified_runtime_observation"] != runtime + or assessment["verified_termination_observation"] != termination + ): + _fail("MATCHED Observation Evidence must copy the Result observation") + if ( + assessment["verified_source_binding"]["source_kind"] + != termination["observation_source"] + ): + _fail("MATCHED Observation Evidence source does not match termination observation") + if assessment["kind"] == "MISMATCHED" and any( + reason["reason_code"] != "MISMATCH" for reason in assessment["reason_bindings"] + ): + _fail("MISMATCHED Observation Evidence contains a non-MISMATCH reason") + if evidence["observation_evidence_sigil"] != content_sigil( + _without(evidence, "observation_evidence_sigil") + ): + _fail("Observation Evidence self-Sigil mismatch") + + +def load_execution_observation_evidence_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + evidence = _load_strict_object(raw, "Observation Evidence") + validate_execution_observation_evidence_v1(evidence) + return evidence + + +def validate_execution_observation_evidence_supplied_receipt_v1( + evidence: dict[str, Any], receipt: dict[str, Any] +) -> None: + """Compare an O1 record with one complete caller-supplied O2 receipt. + + It intentionally grants no acceptance, append, replay, or resolver + authority; callers must independently establish that the supplied receipt + is the applicable durable record. + """ + validate_execution_observation_evidence_v1(evidence) + validate_execution_result_ingress_receipt_v1(receipt) + binding = evidence["result_ingress_receipt_binding"] + expected_binding = { + "ingress_receipt_id": receipt["ingress_receipt_id"], + "ingress_receipt_sigil": receipt["ingress_receipt_sigil"], + } + if binding != expected_binding: + _fail("Observation Evidence ingress receipt binding disagrees with supplied receipt") + if _observation_owner(evidence) != receipt["owner_binding"]: + _fail("Observation Evidence owner binding disagrees with supplied receipt") + if evidence["result_observation_binding"] != receipt["result_observation_binding"]: + _fail("Observation Evidence result observation disagrees with supplied receipt") + + +def _context_value(context: dict[str, Any], key: str) -> Any: + value = context.get(key, _MISSING) + if value is _MISSING: + _fail(f"Journal Event semantic dependency is unresolved: {key}") + return value + + +def expected_event_causation_v1(event: dict[str, Any], context: dict[str, Any]) -> str | None: + """Evaluate JEW2 in priority order from explicit authenticated dependencies.""" + event_type = event["event_type"] + payload = event["payload"] + candidates: list[str | None] = [] + if event_type == "attempt.output_staging_preallocated": + candidates.append(_context_value(context, "attempt_running_event_id")) + if event_type == "attempt.result_ingress_received": + candidates.append(_context_value(context, "attempt_running_event_id")) + if event_type == "attempt.result_accepted" or ( + event_type == "attempt.result_rejected" + and payload.get("disposition_kind") == "FIRST_DISPOSITION_REJECTION" + ): + candidates.append(_context_value(context, "result_ingress_event_id")) + if ( + event_type == "attempt.result_rejected" + and payload.get("disposition_kind") == "LATE_OR_CONFLICTING_REJECTION" + ): + candidates.append(_context_value(context, "pre_event_attempt_last_event_id")) + if context.get("heartbeat_collision_dependent", False): + candidates.append(_context_value(context, "heartbeat_collision_event_id")) + if context.get("ordinary_l12_suffix", False): + candidates.append( + None + if context.get("ordinary_l12_anchor", False) + else _context_value(context, "l12_preceding_event_id") + ) + if context.get("missing_intent_recovery", False) or event_type in { + "log.closure_recovery_closed", + "log.intake_recovery_terminalized", + }: + candidates.append(_context_value(context, "recovery_opening_event_id")) + elif event["recovery_action_binding"] is not None: + candidates.append(_context_value(context, "recovery_opening_event_id")) + cause = payload.get("transition_cause") + if isinstance(cause, dict): + if cause["trigger_kind"] == "PRIOR_EVENT": + candidates.append(cause["trigger_event_id"]) + elif event["recovery_action_binding"] is None: + if ( + cause["trigger_event_id"] != event["event_id"] + or cause["effective_sequence"] != event["sequence"] + ): + _fail("non-prior transition cause does not bind the enclosing Event") + candidates.append(None) + if len({candidate for candidate in candidates}) > 1: + _fail("contradictory JEW2 causation rules") + return candidates[0] if candidates else None + + +def expected_event_idempotency_v1(event: dict[str, Any], context: dict[str, Any]) -> str | None: + """Evaluate JEW3 from locally derivable fields and explicit durable resolvers.""" + event_type = event["event_type"] + payload = event["payload"] + if event_type == "execution.heartbeat_collision_authority_closed" or context.get( + "heartbeat_collision_dependent", False + ): + return _context_value(context, "candidate_inventory_bytes_sigil") + if event_type == "attempt.output_staging_preallocated": + return content_sigil( + [ + "execution-output-staging-preallocation-key/1.0", + payload["job_id"], + payload["attempt_id"], + payload["output_handle_id"], + ] + ) + attempt_id = context.get("attempt_id") + if event_type == "attempt.result_ingress_received": + return content_sigil( + [ + "execution-result-ingress-key/1.0", + _context_value(context, "attempt_id"), + payload["result_sigil"], + ] + ) + if event_type == "attempt.result_accepted" or ( + event_type == "attempt.result_rejected" + and payload.get("disposition_kind") == "FIRST_DISPOSITION_REJECTION" + ): + result_sigil = payload.get("result_sigil", payload.get("claimed_result_sigil")) + return content_sigil( + [ + "execution-result-disposition-key/1.0", + _context_value(context, "attempt_id"), + result_sigil, + ] + ) + if ( + event_type == "attempt.result_rejected" + and payload.get("disposition_kind") == "LATE_OR_CONFLICTING_REJECTION" + ): + return content_sigil( + [ + "execution-result-rejection-message-key/1.0", + _context_value(context, "attempt_id"), + payload["message_sigil"], + ] + ) + del attempt_id + if context.get("ordinary_l12_suffix", False): + return ( + _context_value(context, "l12_idempotency_key_sigil") + if context.get("ordinary_l12_anchor", False) + else None + ) + if context.get("missing_intent_recovery", False) and event_type in { + "log.chunk_rejected", + "log.eof_rejected", + }: + return _context_value(context, "original_idempotency_key_sigil") + if event_type == "log.intake_recovery_terminalized": + return ( + None + if context.get("original_anchor_survived", False) + else _context_value(context, "original_idempotency_key_sigil") + ) + if event_type in {"log.closed", "log.closure_recovery_closed"}: + return None + if event_type in {"log.eof_accepted", "log.eof_rejected"}: + return _context_value(context, "close_log_stream_idempotency_key_sigil") + if context.get("state_disposition_event", False): + return _context_value(context, "state_idempotency_key_sigil") + return None + + +_ATTEMPT_TERMINAL_EVENT_STATES_V1 = { + "attempt.succeeded": "SUCCEEDED", "attempt.failed": "FAILED", "attempt.cancelled": "CANCELLED", + "attempt.timed_out": "TIMED_OUT", "attempt.policy_violated": "POLICY_VIOLATION", + "attempt.lease_expired": "LEASE_EXPIRED", "attempt.lost": "LOST", "attempt.fenced": "FENCED", + "attempt.rejected": "REJECTED", +} + + +def _validate_attempt_terminal_evidence_v1(event: dict[str, Any]) -> None: + """Check terminal payload self-consistency before any replay authority.""" + state = _ATTEMPT_TERMINAL_EVENT_STATES_V1.get(event["event_type"]) + if state is None: + return + payload = event["payload"] + evidence = payload["attempt_terminal_evidence"] + frozen = evidence["storage_observation_binding"] + manifest = evidence["terminalization_storage_manifest_binding"] + protection = evidence["output_root_protection"] + if ( + evidence["control_evidence_set_binding"].get("kind") != "FROZEN" + or evidence["quarantine_binding_set_binding"].get("kind") != "FROZEN" + or manifest.get("kind") != "FROZEN" or frozen.get("kind") != "FROZEN" + or evidence["accounting_capture_event_id"] == event["event_id"] + or evidence["accounting_capture_event_sigil"] == event["event_sigil"] + or payload["fencing_generation"] < 0 + or payload["final_fence_floor"] < payload["fencing_generation"] + or evidence["output_root_protection"] .get("kind") not in {"NO_HOLD", "HELD"} + or protection["terminalization_storage_manifest_binding"] != manifest + ): + _fail("Attempt terminal Event has invalid frozen finalization evidence") + roots = payload["output_storage_roots"] + if protection["kind"] == "NO_HOLD": + if roots: + _fail("Attempt terminal Event NO_HOLD must not activate output roots") + elif roots != [protection["storage_root_binding"]]: + _fail("Attempt terminal Event HELD root disagrees with protection") + cause = evidence["transition_cause"] + if state == "SUCCEEDED": + anchor = evidence["completion_anchor_binding"] + if ( + cause["code"] != "COMPLETION_ESTABLISHED" or cause["trigger_kind"] != "PRIOR_EVENT" + or anchor.get("kind") not in {"RESULT_ACCEPTED", "NO_RESULT"} + or cause["trigger_event_id"] != anchor["event_id"] + or cause["effective_sequence"] != anchor["sequence"] + ): + _fail("Succeeded Attempt terminal cause must bind its completion anchor") + elif cause["code"] == "COMPLETION_ESTABLISHED": + _fail("Only succeeded Attempt terminal events may establish completion") + + +def validate_execution_journal_event_v1( + event: dict[str, Any], *, context: dict[str, Any] | None = None +) -> None: + """Validate a closed Event and, when supplied, the JEW2/JEW3 dependency matrix.""" + validate_instance("execution-journal-event-1.0.json", event) + _check_nfc(event) + revisions = [ + ( + _ENTITY_KIND_RANK[item["entity_kind"]], + _unsigned_ascii(item["entity_id"], "entity revision ID"), + ) + for item in event["entity_revisions"] + ] + if revisions != sorted(revisions) or len(revisions) != len(set(revisions)): + _fail("entity_revisions are not strictly sorted and unique") + for revision in event["entity_revisions"]: + preceding = revision["preceding_revision"] + following = revision["next_revision"] + if preceding is None: + if following != 0: + _fail("created entity revision must be null then zero") + elif following not in (preceding, preceding + 1): + _fail("entity revision must be unchanged or advance by exactly one") + if event["sequence"] == 1: + if event["previous_event_sigil"] is not None: + _fail("sequence-one Event must have null previous_event_sigil") + elif event["previous_event_sigil"] is None: + _fail("noninitial Event must bind previous_event_sigil") + if event["causation_event_id"] == event["event_id"]: + _fail("Event self-causation is forbidden") + _validate_attempt_terminal_evidence_v1(event) + if context is not None: + if event["causation_event_id"] != expected_event_causation_v1(event, context): + _fail("Journal Event causation_event_id violates JEW2") + if event["idempotency_key_sigil"] != expected_event_idempotency_v1(event, context): + _fail("Journal Event idempotency_key_sigil violates JEW3") + if event["event_sigil"] != content_sigil(_without(event, "event_sigil")): + _fail("Execution Journal Event self-Sigil mismatch") + + +def load_execution_journal_event_v1( + raw: str | bytes | bytearray, *, context: dict[str, Any] | None = None +) -> dict[str, Any]: + event = _load_strict_object(raw, "Execution Journal Event") + validate_execution_journal_event_v1(event, context=context) + return event + + +def build_execution_journal_event_v1( + unsigned_event: dict[str, Any], *, context: dict[str, Any] | None = None +) -> dict[str, Any]: + if "event_sigil" in unsigned_event: + _fail("unsigned Execution Journal Event must not contain event_sigil") + event = {**unsigned_event, "event_sigil": content_sigil(unsigned_event)} + validate_execution_journal_event_v1(event, context=context) + return event diff --git a/src/benchwork/execution_job_outcome.py b/src/benchwork/execution_job_outcome.py new file mode 100644 index 0000000..3a5a6e7 --- /dev/null +++ b/src/benchwork/execution_job_outcome.py @@ -0,0 +1,900 @@ +"""Pure RFC-0015 Execution Job Outcome contract helpers. + +This module validates the closed public record and facts decidable from one +supplied Outcome. It does not replay an Execution Journal, resolve current +storage or control records, decide acceptance eligibility from live evidence, +accept a Result, or grant execution or scientific authority. +""" + +from __future__ import annotations + +import hashlib +import math +import unicodedata +from typing import Any, NoReturn +from urllib.parse import urldefrag + +from .athanor import AthanorError, canonical_json, content_sigil +from .execution_contracts import validate_execution_budget_ledger_v1 +from .schema_validation import validate_instance + + +_SCHEMA_NAME = "execution-job-outcome-1.0.json" +_SCHEMA_ID = "https://benchwork.dev/schemas/execution-job-outcome/1.0" +_ROOT_MEMBERS = { + "schema_version", + "outcome_id", + "job_id", + "job_binding_sigil", + "job_terminal", + "task_binding", + "program_id", + "capability_binding", + "snapshot_binding", + "circle_binding", + "approval_binding", + "execution_specification_binding", + "attempt_summaries", + "selected_attempt_binding", + "result_binding", + "completion_anchor_binding", + "first_stop_or_fence_binding", + "lease_terminal_binding", + "authority_binding", + "final_fence_binding", + "runtime_outcome", + "terminal_source_binding", + "terminal_source_observation", + "assurance_context_binding", + "attempt_assurance_binding", + "job_assurance_binding", + "control_evidence_set_binding", + "quarantine_binding_set_binding", + "terminalization_storage_manifest_binding", + "output_root_protection", + "budget_binding", + "outputs", + "storage_observation_binding", + "logs", + "resource_evidence", + "acceptance_eligible", + "ineligibility_reasons", + "derivation_profile", + "terminal_recorded_at", + "outcome_sigil", +} +_DERIVED_MEMBERS = { + "schema_version", + "outcome_id", + "acceptance_eligible", + "ineligibility_reasons", + "derivation_profile", + "outcome_sigil", +} +_REPLAY_FACT_MEMBERS = (_ROOT_MEMBERS - _DERIVED_MEMBERS) | { + "expected_ineligibility_reasons", + "output_storage_observation_set", +} +_REASON_ORDER = ( + "JOB_NOT_SUCCEEDED", + "ATTEMPT_ABSENT", + "ATTEMPT_NOT_SUCCEEDED", + "RESULT_REQUIREMENT_UNMET", + "COMPLETION_NOT_ESTABLISHED", + "AUTHORITY_LOST_BEFORE_COMPLETION", + "ATTEMPT_AUTHORIZATION_INVALID", + "WORKER_SESSION_EVIDENCE_MISSING", + "LEASE_TERMINAL_EVIDENCE_MISSING", + "FINAL_FENCE_EVIDENCE_MISSING", + "BUDGET_UNSETTLED", + "BUDGET_EXCEEDED", + "ACCOUNTING_UNVERIFIED", + "TERMINATION_UNVERIFIED", + "HANDLE_REVOCATION_UNVERIFIED", + "CLEANUP_UNVERIFIED", + "MUTABLE_RESOURCE_UNSAFE", + "OUTPUT_INVALID", + "OUTPUT_UNAVAILABLE", + "OUTPUT_QUARANTINED", + "TERMINAL_SOURCE_INVALID", + "TERMINAL_SOURCE_QUARANTINED", + "ASSURANCE_UNMET", + "ASSURANCE_UNVERIFIABLE", + "CONTROL_EVIDENCE_INVALID", + "STORAGE_OBSERVATION_INVALID", + "INTEGRITY_FAILURE", +) +_REASON_RANK = {reason: rank for rank, reason in enumerate(_REASON_ORDER)} +_ALGORITHM_PREIMAGE = [ + "execution-job-outcome-derivation-algorithm/1.0", + "VALIDATE_SOURCE_PREFIX", + "COPY_CLOSED_BINDINGS", + "RECONSTRUCT_SELECTED_OBSERVATION", + "EVALUATE_ALL_REASONS_IN_ENUM_ORDER", + "SET_ELIGIBLE_IFF_EMPTY", + "DERIVE_OJ_ID", + "DERIVE_OUTCOME_SIGIL", +] +_NO_ATTEMPT_RUNTIME = { + "kind": "NO_ATTEMPT", + "computation_status": "NOT_STARTED", + "worker_status": "NOT_REPORTED", + "process_termination_status": "NOT_STARTED", + "handle_revocation_status": "NOT_APPLICABLE", + "cleanup_status": "NOT_APPLICABLE", + "mutable_resource_isolation_status": "NOT_APPLICABLE", + "output_publication_status": "NOT_APPLICABLE", + "quarantine_status": "NOT_REQUIRED", + "termination_evidence_sigil": None, + "handle_disposition_evidence_sigil": None, + "cleanup_summary_sigil": None, + "quarantine_evidence_sigil": None, + "log_closure_sigil": None, + "output_closure_sigil": None, + "accounting_capture_event_id": None, + "accounting_capture_event_sigil": None, +} +_RESOURCE_PHASE_RANK = { + value: rank + for rank, value in enumerate(("PREFLIGHT", "RUNTIME", "TERMINATION", "CLEANUP")) +} +_RESOURCE_EVIDENCE_KIND_RANK = { + value: rank + for rank, value in enumerate( + ( + "TASK_BINDING", + "CAPABILITY_BINDING", + "SNAPSHOT_BINDING", + "WARD_DECISION", + "APPROVAL_RECEIPT", + "BACKEND_CONFIGURATION", + "HOST_IDENTITY", + "POLICY_RESOLUTION", + "BASE_IDENTITY", + "INPUT_IDENTITY", + "MATERIALIZATION_IDENTITY", + "ENVIRONMENT_CONSTRUCTION", + "FILESYSTEM_POLICY", + "NETWORK_POLICY", + "EXECUTABLE_SELECTION", + "PROCESS_TREE", + "WALL_TIME_ENFORCEMENT", + "RESOURCE_ACCOUNTING", + "CREDENTIAL_NONINHERITANCE", + "LOG_CAPTURE", + "OUTPUT_VALIDATION", + "STORAGE_OBSERVATION", + "FENCE_TOMBSTONE", + "TERMINATION", + "HANDLE_REVOCATION", + "CLEANUP", + "QUARANTINE", + "TERMINAL_SOURCE_VERIFICATION", + "CONFORMANCE_FIXTURE", + ) + ) +} + + +def _fail(message: str) -> NoReturn: + raise AthanorError(message) + + +def _validate_authority_equalities(outcome: dict[str, Any]) -> None: + selected = outcome["selected_attempt_binding"] + authority = outcome["authority_binding"] + fence = outcome["final_fence_binding"] + lease = outcome["lease_terminal_binding"] + if authority["kind"] == "NO_ATTEMPT": + return + if selected["kind"] != "SELECTED": + _fail("Outcome authority exists without a selected Attempt") + if authority["kind"] == "ASSIGNED_NO_LEASE": + if ( + authority["job_id"] != outcome["job_id"] + or authority["attempt_id"] != selected["attempt_id"] + or fence["attempt_id"] != selected["attempt_id"] + or fence["attempt_terminal_event_sigil"] + != selected["attempt_terminal_event_sigil"] + or fence["final_fence_floor"] != authority["fencing_generation"] + ): + _fail("Outcome assigned-no-Lease authority bindings disagree") + return + + public_fence = authority["public_fence_tuple"] + if ( + authority["executor_epoch"] != public_fence["executor_epoch"] + or public_fence["job_id"] != outcome["job_id"] + or public_fence["attempt_id"] != selected["attempt_id"] + or public_fence["lease_id"] != lease["lease_id"] + or lease["lease_id"] != fence["lease_id"] + or lease["terminal_event_sigil"] != fence["lease_terminal_event_sigil"] + or lease["tombstone_event_sigil"] != fence["tombstone_event_sigil"] + or lease["final_fence_floor"] != fence["final_fence_floor"] + or public_fence["fencing_generation"] > fence["final_fence_floor"] + ): + _fail("Outcome leased authority, Lease terminal, or final fence bindings disagree") + + +def _validate_terminal_source_copy(outcome: dict[str, Any]) -> None: + if outcome["selected_attempt_binding"]["kind"] == "NONE": + return + binding = outcome["terminal_source_binding"] + observation = outcome["terminal_source_observation"] + if binding["kind"] == "NOT_APPLICABLE": + if observation != {"kind": "TERMINAL_SOURCE_NOT_APPLICABLE"}: + _fail("Outcome terminal-source observation contradicts NOT_APPLICABLE") + return + nullable = ( + binding["terminal_source_identity"], + binding["terminal_source_sigil"], + binding["storage_blob"], + ) + if binding["kind"] == "QUARANTINED" and nullable == (None, None, None): + if observation != { + "kind": "TERMINAL_SOURCE_NONE", + "reason_codes": binding["reason_codes"], + }: + _fail("Outcome absent terminal-source observation contradicts its binding") + return + if any(value is None for value in nullable) or observation["kind"] != "TERMINAL_SOURCE": + _fail("Outcome terminal-source observation has an invalid identity matrix") + copied = ( + "terminal_source_identity", + "terminal_source_sigil", + "storage_blob", + "retention_policy_sigil", + "file_count", + "byte_count", + ) + if observation["disposition"] != binding["kind"] or any( + observation[member] != binding[member] for member in copied + ): + _fail("Outcome terminal-source observation contradicts its direct binding") + + +def _validate_terminalization_copies(outcome: dict[str, Any]) -> None: + if outcome["selected_attempt_binding"]["kind"] == "NONE": + return + protection = outcome["output_root_protection"] + if ( + protection["terminalization_storage_manifest_binding"] + != outcome["terminalization_storage_manifest_binding"] + ): + _fail("Outcome output-root protection contradicts its frozen manifest") + + +def _check_nfc_and_numbers(value: Any, label: str) -> None: + if isinstance(value, str): + try: + value.encode("utf-8", errors="strict") + except UnicodeEncodeError: + _fail(f"{label} contains a non-Unicode-scalar string") + if unicodedata.normalize("NFC", value) != value: + _fail(f"{label} contains a non-NFC string") + elif isinstance(value, dict): + for key, member in value.items(): + _check_nfc_and_numbers(key, label) + _check_nfc_and_numbers(member, label) + elif isinstance(value, list): + for member in value: + _check_nfc_and_numbers(member, label) + elif isinstance(value, float): + if not math.isfinite(value): + _fail(f"{label} contains a non-finite JSON number") + _fail(f"{label} contains a float where the closed wire permits no float") + + +def _load_strict_object(raw: str | bytes | bytearray) -> dict[str, Any]: + from .execution_contracts import _load_strict_object as load_strict_object + + decoded: str + if isinstance(raw, (bytes, bytearray)): + encoded = bytes(raw) + if encoded.startswith( + (b"\xff\xfe", b"\xfe\xff", b"\x00\x00\xfe\xff", b"\xff\xfe\x00\x00") + ): + _fail("invalid Execution Job Outcome JSON: non-UTF-8 encoding is forbidden") + try: + decoded = encoded.decode("utf-8", errors="strict") + except UnicodeDecodeError: + _fail("invalid Execution Job Outcome JSON: non-UTF-8 encoding is forbidden") + else: + decoded = raw + return load_strict_object(decoded, "Execution Job Outcome") + + +def derive_execution_job_outcome_id_v1(job_id: str, terminal_event_sigil: str) -> str: + """Derive the canonical OJ-ID from Job identity and terminal Event Sigil.""" + preimage = ["execution-job-outcome-id/1.0", job_id, terminal_event_sigil] + digest = hashlib.sha256(canonical_json(preimage).encode("utf-8")).hexdigest().upper() + return f"OJ-{digest}" + + +def derive_execution_job_outcome_sigil_v1(outcome: dict[str, Any]) -> str: + """Derive the Outcome self-Sigil over every member except outcome_sigil.""" + return content_sigil( + {key: value for key, value in outcome.items() if key != "outcome_sigil"} + ) + + +def execution_job_outcome_algorithm_sigil_v1() -> str: + """Return the canonical RFC-0015 derivation-algorithm Sigil.""" + return content_sigil(_ALGORITHM_PREIMAGE) + + +def _resolve_pointer(document: Any, fragment: str) -> Any: + if not fragment: + return document + if not fragment.startswith("/"): + _fail(f"unsupported non-JSON-Pointer Schema fragment #{fragment}") + current = document + for token in fragment[1:].split("/"): + decoded = token.replace("~1", "/").replace("~0", "~") + try: + current = current[int(decoded)] if isinstance(current, list) else current[decoded] + except (KeyError, IndexError, ValueError, TypeError): + _fail(f"unresolvable Schema fragment #{fragment}") + return current + + +def execution_job_outcome_imported_schema_set_v1() -> list[dict[str, str]]: + """Return every unique external Schema transitively reachable by ``$ref``.""" + from .schema_validation import _schemas + + schemas, _ = _schemas() + by_id = {schema["$id"]: schema for schema in schemas.values()} + try: + root = schemas[_SCHEMA_NAME] + except KeyError: + _fail("installed execution-job-outcome/1.0 Schema is missing") + + imported: set[str] = set() + visited: set[tuple[str, str]] = set() + + def walk(value: Any, document_id: str, location: str) -> None: + visit_key = (document_id, location) + if visit_key in visited: + return + visited.add(visit_key) + if isinstance(value, dict): + reference = value.get("$ref") + if isinstance(reference, str): + base, fragment = urldefrag(reference) + target_id = base or document_id + if target_id not in by_id: + _fail(f"Outcome imports an unavailable Schema {target_id}") + if target_id != _SCHEMA_ID: + imported.add(target_id) + target = _resolve_pointer(by_id[target_id], fragment) + walk(target, target_id, f"#{fragment}") + for key, member in value.items(): + if key != "$ref": + walk(member, document_id, f"{location}/{key}") + elif isinstance(value, list): + for index, member in enumerate(value): + walk(member, document_id, f"{location}/{index}") + + walk(root, _SCHEMA_ID, "#") + return [ + {"schema_id": schema_id, "schema_sigil": content_sigil(by_id[schema_id])} + for schema_id in sorted(imported, key=lambda item: item.encode("utf-8")) + ] + + +def derive_execution_job_outcome_derivation_profile_v1() -> dict[str, str]: + """Derive the one installed RFC-0015 Outcome profile.""" + from .schema_validation import _schemas + + schemas, _ = _schemas() + try: + schema = schemas[_SCHEMA_NAME] + except KeyError: + _fail("installed execution-job-outcome/1.0 Schema is missing") + return { + "profile_id": "execution-job-outcome-v1", + "profile_version": "1.0", + "algorithm_sigil": execution_job_outcome_algorithm_sigil_v1(), + "outcome_schema_sigil": content_sigil(schema), + "imported_schema_set_sigil": content_sigil( + execution_job_outcome_imported_schema_set_v1() + ), + } + + +def _validate_attempt_selection(outcome: dict[str, Any]) -> None: + summaries = outcome["attempt_summaries"] + ordinals = [row["retry_ordinal"] for row in summaries] + if ( + any(ordinal < 1 for ordinal in ordinals) + or ordinals != sorted(ordinals) + or len(ordinals) != len(set(ordinals)) + ): + _fail("Outcome Attempt summaries are not unique and ordered by retry ordinal") + ids = [row["attempt_id"] for row in summaries] + if len(ids) != len(set(ids)): + _fail("Outcome Attempt summaries contain a duplicate Attempt identity") + + selected = outcome["selected_attempt_binding"] + if not summaries: + if selected != {"kind": "NONE"}: + _fail("Outcome without Attempt summaries must select NONE") + return + if selected["kind"] != "SELECTED": + _fail("Outcome with Attempt summaries must select an Attempt") + summary = summaries[-1] + copied = { + "attempt_id": "attempt_id", + "attempt_binding_sigil": "attempt_binding_sigil", + "attempt_terminal_event_id": "terminal_event_id", + "attempt_terminal_event_sigil": "terminal_event_sigil", + "attempt_authorization_state": "attempt_authorization_state", + "worker_session_binding": "worker_session_binding", + } + for selected_member, summary_member in copied.items(): + if selected[selected_member] != summary[summary_member]: + _fail(f"Outcome selected Attempt contradicts summary {summary_member}") + for member in ( + "result_binding", + "completion_anchor_binding", + "first_stop_or_fence_binding", + "storage_observation_binding", + ): + if outcome[member] != selected[member]: + _fail(f"Outcome direct {member} does not equal the selected Attempt copy") + + +def _validate_no_attempt_matrix(outcome: dict[str, Any]) -> None: + if outcome["attempt_summaries"]: + return + exact = { + "result_binding": {"kind": "NONE"}, + "completion_anchor_binding": {"kind": "NOT_ESTABLISHED"}, + "lease_terminal_binding": {"kind": "NONE"}, + "authority_binding": {"kind": "NO_ATTEMPT"}, + "final_fence_binding": {"kind": "NO_ATTEMPT", "final_fence_floor": 0}, + "runtime_outcome": _NO_ATTEMPT_RUNTIME, + "terminal_source_observation": {"kind": "NO_ATTEMPT"}, + "attempt_assurance_binding": {"kind": "NONE"}, + "control_evidence_set_binding": {"kind": "NOT_APPLICABLE"}, + "quarantine_binding_set_binding": {"kind": "NOT_APPLICABLE"}, + "terminalization_storage_manifest_binding": {"kind": "NOT_APPLICABLE"}, + "output_root_protection": {"kind": "NOT_APPLICABLE"}, + "storage_observation_binding": {"kind": "NOT_APPLICABLE"}, + } + for member, expected in exact.items(): + if outcome[member] != expected: + _fail(f"Outcome no-Attempt {member} is not the canonical branch") + if outcome["job_assurance_binding"]["kind"] != "NOT_APPLICABLE": + _fail("Outcome no-Attempt Job assurance is not NOT_APPLICABLE") + for member in ("outputs", "logs", "resource_evidence"): + if outcome[member]: + _fail(f"Outcome no-Attempt {member} must be empty") + if outcome["assurance_context_binding"]["kind"] != "NO_ATTEMPT": + _fail("Outcome no-Attempt assurance context is not NO_ATTEMPT") + if outcome["budget_binding"]["selected_attempt_settlement"] != {"kind": "NONE"}: + _fail("Outcome no-Attempt budget settlement is not NONE") + + +def _validate_selected_observation_groups(outcome: dict[str, Any]) -> None: + if not outcome["attempt_summaries"]: + return + if outcome["runtime_outcome"]["kind"] != "ATTEMPT": + _fail("Outcome selected Attempt lacks ATTEMPT runtime evidence") + if outcome["assurance_context_binding"]["kind"] != "ATTEMPT": + _fail("Outcome selected Attempt lacks ATTEMPT assurance context") + if outcome["attempt_assurance_binding"]["kind"] in {"NONE", "PENDING"}: + _fail("Outcome selected Attempt lacks terminal Attempt assurance") + if outcome["job_assurance_binding"]["kind"] in {"NOT_APPLICABLE", "PENDING"}: + _fail("Outcome selected Attempt lacks terminal Job assurance") + for member in ( + "control_evidence_set_binding", + "quarantine_binding_set_binding", + "terminalization_storage_manifest_binding", + ): + if outcome[member]["kind"] != "FROZEN": + _fail(f"Outcome selected Attempt {member} is not FROZEN") + if outcome["output_root_protection"]["kind"] not in {"NO_HOLD", "HELD"}: + _fail("Outcome selected Attempt output-root protection is not terminal") + if outcome["budget_binding"]["selected_attempt_settlement"]["kind"] != "SETTLED": + _fail("Outcome selected Attempt budget settlement is not SETTLED") + + outputs = outcome["outputs"] + if not outputs: + _fail("Outcome selected Attempt has no output observation group") + output_kinds = [member["kind"] for member in outputs] + if output_kinds == ["ATTEMPT_OUTPUTS_NONE"]: + pass + elif any(kind != "ATTEMPT_OUTPUT" for kind in output_kinds): + _fail("Outcome output group mixes the NONE sentinel with output members") + else: + logical_names = [member["logical_name"] for member in outputs] + if logical_names != sorted(logical_names, key=lambda item: item.encode("utf-8")): + _fail("Outcome output observations are not ordered by logical_name") + if len(logical_names) != len(set(logical_names)): + _fail("Outcome output observations contain duplicate logical names") + + if [member["stream"] for member in outcome["logs"]] != [ + "STDOUT", + "STDERR", + "STRUCTURED", + ]: + _fail("Outcome selected Attempt must expose exactly three ordered Log streams") + + resources = outcome["resource_evidence"] + if resources[0]["kind"] == "RESOURCE_EVIDENCE": + keys = [ + ( + member["control_evidence_id"], + _RESOURCE_PHASE_RANK[member["phase"]], + _RESOURCE_EVIDENCE_KIND_RANK[member["evidence_kind"]], + member["phase_evidence_entry_sigil"], + ) + for member in resources + ] + if keys != sorted(keys) or len(keys) != len(set(keys)): + _fail("Outcome resource-evidence observations are not sorted and unique") + if len(outputs) + len(outcome["logs"]) + len(resources) + 1 > 4096: + _fail("Outcome observation-member reconstruction exceeds 4096 members") + + +def _validate_reason_order_and_local_predicates(outcome: dict[str, Any]) -> None: + reasons = outcome["ineligibility_reasons"] + if reasons != sorted(reasons, key=_REASON_RANK.__getitem__) or len(reasons) != len( + set(reasons) + ): + _fail("Outcome ineligibility reasons are not unique and in canonical order") + if outcome["acceptance_eligible"] != (reasons == []): + _fail("Outcome acceptance eligibility does not equal an empty reason set") + + exact_predicates = { + "JOB_NOT_SUCCEEDED": outcome["job_terminal"]["state"] != "SUCCEEDED", + "ATTEMPT_ABSENT": outcome["selected_attempt_binding"]["kind"] == "NONE", + } + required_predicates: dict[str, bool] = {} + selected_attempt_id = outcome["selected_attempt_binding"].get("attempt_id") + required_predicates["ATTEMPT_AUTHORIZATION_INVALID"] = any( + ( + summary["attempt_authorization_requirement"]["kind"] == "NONE" + and summary["attempt_authorization_state"]["kind"] != "NONE" + ) + or ( + summary["attempt_authorization_requirement"]["kind"] == "REQUIRED" + and summary["attempt_authorization_state"]["kind"] == "NONE" + ) + or ( + summary["attempt_authorization_state"]["kind"] == "PENDING" + and ( + summary["attempt_id"] == selected_attempt_id + or summary["terminal_state"] == "SUCCEEDED" + ) + ) + for summary in outcome["attempt_summaries"] + ) + if outcome["selected_attempt_binding"]["kind"] == "SELECTED": + selected_id = outcome["selected_attempt_binding"]["attempt_id"] + summary = next(row for row in outcome["attempt_summaries"] if row["attempt_id"] == selected_id) + exact_predicates["ATTEMPT_NOT_SUCCEEDED"] = ( + summary["terminal_state"] != "SUCCEEDED" + ) + completion = outcome["completion_anchor_binding"] + result = outcome["result_binding"] + if result["kind"] == "ACCEPTED": + completion_invalid = completion["kind"] != "RESULT_ACCEPTED" or any( + completion.get(completion_member) != result[result_member] + for completion_member, result_member in ( + ("event_id", "disposition_event_id"), + ("event_sigil", "disposition_event_sigil"), + ("sequence", "disposition_sequence"), + ("result_sigil", "result_sigil"), + ) + ) + elif result["kind"] == "NONE": + completion_invalid = completion["kind"] != "NO_RESULT" + else: + completion_invalid = True + required_predicates["COMPLETION_NOT_ESTABLISHED"] = ( + completion_invalid + or ( + completion["kind"] != "NOT_ESTABLISHED" + and completion["sequence"] > outcome["job_terminal"]["event_sequence"] + ) + ) + required_predicates["AUTHORITY_LOST_BEFORE_COMPLETION"] = ( + completion["kind"] != "NOT_ESTABLISHED" + and outcome["first_stop_or_fence_binding"]["kind"] == "PRESENT" + and outcome["first_stop_or_fence_binding"]["effective_sequence"] + <= completion["sequence"] + ) + selected_succeeded = summary["terminal_state"] == "SUCCEEDED" + required_predicates["WORKER_SESSION_EVIDENCE_MISSING"] = ( + selected_succeeded + and outcome["selected_attempt_binding"]["worker_session_binding"]["kind"] + != "BOUND" + ) + required_predicates["LEASE_TERMINAL_EVIDENCE_MISSING"] = ( + selected_succeeded and outcome["lease_terminal_binding"]["kind"] != "TERMINAL" + ) + else: + exact_predicates["ATTEMPT_NOT_SUCCEEDED"] = False + exact_predicates["BUDGET_EXCEEDED"] = any( + dimension["exhaustion_status"] == "EXCEEDED" + for name, dimension in outcome["budget_binding"]["job_budget_ledger"].items() + if name != "budget_ledger_sigil" + ) + if outcome["selected_attempt_binding"]["kind"] == "SELECTED": + runtime = outcome["runtime_outcome"] + settlement = outcome["budget_binding"]["selected_attempt_settlement"] + required_predicates["ACCOUNTING_UNVERIFIED"] = ( + settlement["usage_status"] != "MEASURED" + or settlement["accounting_capture_event_id"] + != runtime["accounting_capture_event_id"] + or settlement["accounting_capture_event_sigil"] + != runtime["accounting_capture_event_sigil"] + ) + required_predicates["TERMINATION_UNVERIFIED"] = runtime[ + "process_termination_status" + ] not in {"EXITED", "TERMINATED"} + required_predicates["HANDLE_REVOCATION_UNVERIFIED"] = runtime[ + "handle_revocation_status" + ] not in {"NOT_APPLICABLE", "REVOKED", "FENCED"} + required_predicates["CLEANUP_UNVERIFIED"] = ( + runtime["cleanup_status"] != "VERIFIED" + ) + exact_predicates["MUTABLE_RESOURCE_UNSAFE"] = runtime[ + "mutable_resource_isolation_status" + ] not in {"NOT_APPLICABLE", "VERIFIED_ISOLATED"} + outputs = outcome["outputs"] + if outputs[0]["kind"] == "ATTEMPT_OUTPUTS_NONE": + output_group_invalid = outputs[0]["reason"] != { + "NONE": "NO_RESULT", + "REJECTED": "RESULT_REJECTED", + "ACCEPTED": "OUTPUT_ARRAY_EMPTY", + }[result["kind"]] + else: + output_group_invalid = result["kind"] != "ACCEPTED" + required_predicates["OUTPUT_INVALID"] = ( + runtime["output_publication_status"] == "FAILED" + or output_group_invalid + or any( + member["kind"] == "ATTEMPT_OUTPUT" + and ( + member["storage"]["kind"] == "NONE" + or ( + member["storage"]["kind"] == "BLOB" + and ( + member["storage"]["blob_sigil"] != member["blob_sigil"] + or member["storage"]["size_bytes"] != member["byte_size"] + ) + ) + ) + for member in outputs + ) + ) + output_storages = [ + member["storage"] + for member in outputs + if member["kind"] == "ATTEMPT_OUTPUT" + ] + required_predicates["OUTPUT_UNAVAILABLE"] = any( + storage["kind"] == "QUARANTINE_TERMINAL_NEGATIVE" + or ( + storage["kind"] == "BLOB" + and ( + storage["terminal_storage_status"] != "AVAILABLE" + or storage["availability"] != "AVAILABLE" + or storage["replica"]["kind"] != "SELECTED" + ) + ) + for storage in output_storages + ) + required_predicates["OUTPUT_QUARANTINED"] = ( + runtime["output_publication_status"] == "QUARANTINED" + or any(storage["kind"] == "QUARANTINED" for storage in output_storages) + ) + + evidence_storages = [ + member["content"]["storage"] for member in outcome["logs"] + ] + [ + member["storage"] + for member in outcome["resource_evidence"] + if member["kind"] == "RESOURCE_EVIDENCE" + ] + required_predicates["STORAGE_OBSERVATION_INVALID"] = any( + storage["kind"] in { + "NONE", + "QUARANTINED", + "QUARANTINE_TERMINAL_NEGATIVE", + } + or ( + storage["kind"] == "BLOB" + and ( + storage["terminal_storage_status"] != "AVAILABLE" + or storage["availability"] != "AVAILABLE" + or storage["replica"]["kind"] != "SELECTED" + ) + ) + for storage in evidence_storages + ) + all_storages = [*output_storages, *evidence_storages] + terminal_observation = outcome["terminal_source_observation"] + if terminal_observation["kind"] == "TERMINAL_SOURCE": + all_storages.append(terminal_observation["storage"]) + required_predicates["INTEGRITY_FAILURE"] = any( + storage["kind"] == "BLOB" + and ( + storage["terminal_storage_status"] == "INCIDENT" + or storage["availability"] == "INCIDENT" + ) + for storage in all_storages + ) + + exact_predicates["TERMINAL_SOURCE_QUARANTINED"] = ( + outcome["terminal_source_binding"]["kind"] == "QUARANTINED" + or ( + outcome["terminal_source_observation"]["kind"] == "TERMINAL_SOURCE" + and outcome["terminal_source_observation"]["disposition"] + == "QUARANTINED" + ) + ) + required_predicates["ASSURANCE_UNMET"] = ( + outcome["attempt_assurance_binding"]["kind"] == "UNMET" + or outcome["job_assurance_binding"]["kind"] == "UNMET" + ) + exact_predicates["ASSURANCE_UNVERIFIABLE"] = ( + outcome["attempt_assurance_binding"]["kind"] == "UNVERIFIABLE" + or outcome["job_assurance_binding"]["kind"] == "UNVERIFIABLE" + ) + present = set(reasons) + for reason, expected in exact_predicates.items(): + if (reason in present) != expected: + _fail(f"Outcome reason {reason} contradicts its locally decidable predicate") + for reason, required in required_predicates.items(): + if required and reason not in present: + _fail(f"Outcome omits locally required reason {reason}") + + +def validate_execution_job_outcome_v1(outcome: dict[str, Any]) -> None: + """Validate the RFC-0015 wire plus all locally decidable invariants.""" + validate_instance(_SCHEMA_NAME, outcome) + if set(outcome) != _ROOT_MEMBERS: + _fail("Execution Job Outcome is not the exact closed 40-member object") + _check_nfc_and_numbers(outcome, "Execution Job Outcome") + validate_execution_budget_ledger_v1(outcome["budget_binding"]["job_budget_ledger"]) + expected_id = derive_execution_job_outcome_id_v1( + outcome["job_id"], outcome["job_terminal"]["event_sigil"] + ) + if outcome["outcome_id"] != expected_id: + _fail("Execution Job Outcome ID does not match the canonical preimage") + if outcome["derivation_profile"] != derive_execution_job_outcome_derivation_profile_v1(): + _fail("Execution Job Outcome derivation profile is not the installed profile") + if outcome["outcome_sigil"] != derive_execution_job_outcome_sigil_v1(outcome): + _fail("Execution Job Outcome self-Sigil is invalid") + _validate_attempt_selection(outcome) + _validate_no_attempt_matrix(outcome) + _validate_selected_observation_groups(outcome) + _validate_authority_equalities(outcome) + _validate_terminal_source_copy(outcome) + _validate_terminalization_copies(outcome) + _validate_reason_order_and_local_predicates(outcome) + + +def load_execution_job_outcome_v1( + raw: str | bytes | bytearray, +) -> dict[str, Any]: + """Strictly decode and validate one Execution Job Outcome.""" + outcome = _load_strict_object(raw) + validate_execution_job_outcome_v1(outcome) + return outcome + + +def validate_execution_job_outcome_fixed_retry_v1( + prior: dict[str, Any], candidate: dict[str, Any] +) -> None: + """Require one terminal Job prefix to produce identical canonical bytes.""" + validate_execution_job_outcome_v1(prior) + validate_execution_job_outcome_v1(candidate) + if prior["outcome_id"] != candidate["outcome_id"]: + _fail("Execution Job Outcome retry changed deterministic Outcome identity") + if canonical_json(prior) != canonical_json(candidate): + _fail("Execution Job Outcome retry is not byte-for-byte deterministic") + + +def validate_execution_job_outcome_replayed_facts_v1( + outcome: dict[str, Any], replayed_facts: dict[str, Any] +) -> None: + """Compare an Outcome with a complete caller-supplied replay result. + + The caller remains responsible for authenticating and replaying the fixed + Journal prefix and resolving every referenced immutable record. Passing + arbitrary dictionaries here grants no Journal, storage, acceptance, + runtime, Result, or scientific authority. + """ + validate_execution_job_outcome_v1(outcome) + if set(replayed_facts) != _REPLAY_FACT_MEMBERS: + _fail("Outcome replay facts do not have the exact closed field set") + _check_nfc_and_numbers(replayed_facts, "Execution Job Outcome replay facts") + for member in _ROOT_MEMBERS - _DERIVED_MEMBERS: + if outcome[member] != replayed_facts[member]: + _fail(f"Execution Job Outcome contradicts replayed {member}") + expected_reasons = replayed_facts["expected_ineligibility_reasons"] + if expected_reasons != outcome["ineligibility_reasons"]: + _fail("Execution Job Outcome contradicts replayed ineligibility predicates") + + observation_set = replayed_facts["output_storage_observation_set"] + if outcome["selected_attempt_binding"]["kind"] == "NONE": + if observation_set is not None: + _fail("No-Attempt Outcome must not resolve an observation set") + return + if not isinstance(observation_set, dict): + _fail("Selected-Attempt Outcome replay facts omit the observation set") + from . import execution_contracts + + validator = getattr( + execution_contracts, + "validate_execution_output_storage_observation_set_v1", + None, + ) + if not callable(validator): + _fail("Outcome Observation Set validator is unavailable") + validator(observation_set) + selected = outcome["selected_attempt_binding"] + runtime = outcome["runtime_outcome"] + copied_observation_fields = { + "job_id": outcome["job_id"], + "attempt_id": selected["attempt_id"], + "attempt_binding_sigil": selected["attempt_binding_sigil"], + "result_binding": outcome["result_binding"], + "log_closure_sigil": runtime["log_closure_sigil"], + "output_closure_sigil": runtime["output_closure_sigil"], + "control_evidence_set_binding": outcome["control_evidence_set_binding"], + "quarantine_binding_set_binding": outcome[ + "quarantine_binding_set_binding" + ], + "terminalization_storage_manifest_binding": outcome[ + "terminalization_storage_manifest_binding" + ], + "output_root_protection": outcome["output_root_protection"], + "terminal_source_binding": outcome["terminal_source_binding"], + } + for member, expected in copied_observation_fields.items(): + if observation_set[member] != expected: + _fail(f"Outcome contradicts observation-set {member}") + binding = outcome["storage_observation_binding"] + if binding["kind"] != "FROZEN": + _fail("Selected-Attempt Outcome lacks a frozen observation binding") + expected_binding = { + "kind": "FROZEN", + "storage_journal_id": observation_set["storage_event"]["journal_id"], + "through_sequence": observation_set["storage_event"]["sequence"], + "through_event_sigil": observation_set["storage_event"]["event_sigil"], + "output_storage_observation_set_id": observation_set["observation_set_id"], + "output_storage_observation_set_sigil": observation_set[ + "observation_set_sigil" + ], + } + if binding != expected_binding: + _fail("Outcome storage-observation binding contradicts the supplied set") + reconstructed = [ + *outcome["outputs"], + *outcome["logs"], + *outcome["resource_evidence"], + outcome["terminal_source_observation"], + ] + if reconstructed != observation_set["members"]: + _fail("Outcome observation groups do not reconstruct the supplied set") + + +def require_execution_job_outcome_journal_derivation_v1() -> NoReturn: + """Fail closed: this contract module never replays an Execution Journal.""" + _fail("Execution Job Outcome Journal derivation is unavailable in contract-only scope") + + +def require_execution_job_outcome_acceptance_eligibility_authority_v1() -> NoReturn: + """Fail closed: local validation is not acceptance-eligibility authority.""" + _fail("Execution Job Outcome validation grants no acceptance-eligibility authority") + + +def require_execution_job_outcome_runtime_authority_v1() -> NoReturn: + """Fail closed: a valid public Outcome is not execution authority.""" + _fail("Execution Job Outcome validation grants no runtime authority") diff --git a/src/benchwork/patch_promotion_contracts.py b/src/benchwork/patch_promotion_contracts.py new file mode 100644 index 0000000..d0cae18 --- /dev/null +++ b/src/benchwork/patch_promotion_contracts.py @@ -0,0 +1,589 @@ +"""Fail-closed local validators for RFC-0014 Promotion Journal wires. + +These helpers validate immutable wire and caller-supplied prefix facts only. +They neither replay promotion state nor authorize a target mutation, recovery, +Storage operation, Chronicle write, or Patch promotion. +""" + +from __future__ import annotations + +from datetime import datetime +import hashlib +from typing import Any, NoReturn + +from .athanor import AthanorError, canonical_json, content_sigil +from .execution_contracts import _check_nfc, _load_strict_object +from .schema_validation import validate_instance + + +def _fail(message: str) -> NoReturn: + raise AthanorError(message) + + +def _without(value: dict[str, Any], member: str) -> dict[str, Any]: + return {key: item for key, item in value.items() if key != member} + + +def _time(value: str) -> datetime: + try: + return datetime.fromisoformat(value.replace("Z", "+00:00")) + except ValueError as error: + raise AthanorError("Patch Promotion Journal Event recorded_at is invalid") from error + + +def _blob_key(blob: dict[str, Any]) -> bytes: + return blob["sigil"].encode("ascii") + + +def _require_sorted_unique_blobs(blobs: list[dict[str, Any]], name: str) -> None: + keys = [_blob_key(blob) for blob in blobs] + if keys != sorted(keys) or len(set(keys)) != len(keys): + _fail(f"Patch Bundle {name} must be sorted and unique by Sigil") + + +def _entry_payload(entry: dict[str, Any]) -> dict[str, Any] | None: + """Return the one RFC-0014 payload Blob required by a postimage entry.""" + kind = entry["kind"] + if kind == "FILE": + return { + "sigil": entry["blob_sigil"], + "size_bytes": entry["size_bytes"], + "media_type": "application/octet-stream", + } + if kind == "SYMLINK": + target = entry["target"].encode("utf-8") + sigil = "sha256:" + hashlib.sha256(target).hexdigest() + if entry["target_sigil"] != sigil: + _fail("Patch Bundle SYMLINK target Sigil does not match UTF-8 target bytes") + return { + "sigil": sigil, + "size_bytes": len(target), + "media_type": "application/octet-stream", + } + return None + + +def validate_patch_bundle_v1(bundle: dict[str, Any]) -> None: + """Validate local RFC-0014 Patch Bundle invariants without resolving Blobs.""" + validate_instance("patch-bundle-1.0.json", bundle) + _check_nfc(bundle) + if bundle["bundle_sigil"] != content_sigil(_without(bundle, "bundle_sigil")): + _fail("Patch Bundle self-Sigil mismatch") + + operations = bundle["operations"] + paths = [operation["path_bytes"].encode("utf-8") for operation in operations] + if paths != sorted(paths) or len(set(paths)) != len(paths): + _fail("Patch Bundle operations must be sorted and unique by path_bytes") + if len(operations) > bundle["limits"]["max_paths"]: + _fail("Patch Bundle operation count exceeds max_paths") + + expected_payloads: dict[str, dict[str, Any]] = {} + for operation in operations: + before = operation["preimage"]["kind"] + after = operation["postimage"]["kind"] + transition = operation["operation"] + valid_transition = ( + (transition == "ADD" and before == "ABSENT" and after != "ABSENT") + or (transition == "DELETE" and before != "ABSENT" and after == "ABSENT") + or (transition == "MODIFY" and before != "ABSENT" and before == after) + or ( + transition == "TYPE_CHANGE" + and before != "ABSENT" + and after != "ABSENT" + and before != after + ) + ) + if not valid_transition: + _fail("Patch Bundle operation disagrees with its preimage and postimage kinds") + payload = _entry_payload(operation["postimage"]) + if (operation["payload_sigil"] is None) != (payload is None): + _fail("Patch Bundle operation payload presence disagrees with postimage kind") + if payload is not None: + if operation["payload_sigil"] != payload["sigil"]: + _fail("Patch Bundle operation payload Sigil disagrees with postimage") + previous = expected_payloads.setdefault(payload["sigil"], payload) + if previous != payload: + _fail("Patch Bundle reuses one payload Sigil with inconsistent Blob metadata") + + payloads = bundle["payloads"] + renderings = bundle["renderings"] + attachments = bundle["attachments"] + _require_sorted_unique_blobs(payloads, "payloads") + _require_sorted_unique_blobs(renderings, "renderings") + _require_sorted_unique_blobs(attachments, "attachments") + actual_payloads = {blob["sigil"]: blob for blob in payloads} + if actual_payloads != expected_payloads: + _fail("Patch Bundle payloads are not the exact postimage payload set") + if len(payloads) > bundle["limits"]["max_blobs"]: + _fail("Patch Bundle payload count exceeds max_blobs") + if any(blob["size_bytes"] > bundle["limits"]["max_payload_bytes"] for blob in payloads): + _fail("Patch Bundle payload exceeds max_payload_bytes") + + blob_union: dict[str, dict[str, Any]] = {} + for blob in payloads + renderings + attachments: + previous = blob_union.setdefault(blob["sigil"], blob) + if previous != blob: + _fail("Patch Bundle Blob union has inconsistent metadata for one Sigil") + if ( + sum(blob["size_bytes"] for blob in blob_union.values()) + > bundle["limits"]["max_total_bytes"] + ): + _fail("Patch Bundle Blob union exceeds max_total_bytes") + + +def load_patch_bundle_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + bundle = _load_strict_object(raw, "Patch Bundle") + validate_patch_bundle_v1(bundle) + return bundle + + +def validate_patch_promotion_checkpoint_v1(checkpoint: dict[str, Any]) -> None: + """Validate local checkpoint/blob closure without resolving target observations.""" + validate_instance("patch-promotion-checkpoint-1.0.json", checkpoint) + _check_nfc(checkpoint) + if checkpoint["checkpoint_sigil"] != content_sigil(_without(checkpoint, "checkpoint_sigil")): + _fail("Patch Promotion Checkpoint self-Sigil mismatch") + if _time(checkpoint["verified_at"]) < _time(checkpoint["created_at"]): + _fail("Patch Promotion Checkpoint verified_at precedes created_at") + + affected_paths = [path.encode("utf-8") for path in checkpoint["affected_paths"]] + entries = checkpoint["entries"] + entry_paths = [entry["path_bytes"].encode("utf-8") for entry in entries] + if affected_paths != sorted(affected_paths) or len(set(affected_paths)) != len(affected_paths): + _fail("Patch Promotion Checkpoint affected_paths must be sorted and unique") + if entry_paths != sorted(entry_paths) or len(set(entry_paths)) != len(entry_paths): + _fail("Patch Promotion Checkpoint entries must be sorted and unique by path_bytes") + if entry_paths != affected_paths: + _fail("Patch Promotion Checkpoint entries are not the exact affected path set") + + expected_blobs: dict[str, dict[str, Any]] = {} + for entry in entries: + expected = _entry_payload(entry["preimage"]) + actual = entry["checkpoint_blob"] + if (actual is None) != (expected is None): + _fail("Patch Promotion Checkpoint Blob presence disagrees with preimage kind") + if actual is not None: + if actual != expected: + _fail("Patch Promotion Checkpoint Blob disagrees with preimage") + previous = expected_blobs.setdefault(actual["sigil"], actual) + if previous != actual: + _fail("Patch Promotion Checkpoint reuses one Blob Sigil with inconsistent metadata") + blobs = checkpoint["checkpoint_blobs"] + _require_sorted_unique_blobs(blobs, "checkpoint_blobs") + if {blob["sigil"]: blob for blob in blobs} != expected_blobs: + _fail("Patch Promotion Checkpoint blobs are not the exact preimage Blob set") + + +def load_patch_promotion_checkpoint_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + checkpoint = _load_strict_object(raw, "Patch Promotion Checkpoint") + validate_patch_promotion_checkpoint_v1(checkpoint) + return checkpoint + + +def validate_patch_promotion_mutation_intent_v1(intent: dict[str, Any]) -> None: + """Validate local write-ahead Intent consistency without a target mutation.""" + validate_instance("patch-promotion-mutation-intent-1.0.json", intent) + _check_nfc(intent) + if intent["intent_sigil"] != content_sigil(_without(intent, "intent_sigil")): + _fail("Patch Promotion Mutation Intent self-Sigil mismatch") + plan = intent["topology_plan"] + if plan["root_identity"] != intent["root_identity"]: + _fail("Patch Promotion Mutation Intent topology root disagrees with root identity") + if plan["target_wide_generation"] != intent["target_content_generation"]: + _fail("Patch Promotion Mutation Intent topology generation disagrees with target") + operation_order = [path.encode("utf-8") for path in plan["operation_order"]] + if len(operation_order) != len(set(operation_order)): + _fail("Patch Promotion Mutation Intent topology operation order has duplicates") + ancestors = intent["ancestor_identities"] + ancestor_paths = [ancestor["path_bytes"].encode("utf-8") for ancestor in ancestors] + if ancestor_paths != sorted(ancestor_paths) or len(ancestor_paths) != len(set(ancestor_paths)): + _fail("Patch Promotion Mutation Intent ancestors must be sorted and unique") + method = intent["verification_method"] + if ( + method["identity_profile"] != intent["postimage"]["identity_profile"] + or method["expected_tree"] != intent["postimage"]["tree"] + ): + _fail("Patch Promotion Mutation Intent verification method disagrees with postimage") + + +def load_patch_promotion_mutation_intent_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + intent = _load_strict_object(raw, "Patch Promotion Mutation Intent") + validate_patch_promotion_mutation_intent_v1(intent) + return intent + + +def validate_patch_promotion_target_guard_v1(guard: dict[str, Any]) -> None: + """Validate local target-guard invariants without asserting physical ownership.""" + validate_instance("patch-promotion-target-guard-1.0.json", guard) + _check_nfc(guard) + if guard["guard_sigil"] != content_sigil(_without(guard, "guard_sigil")): + _fail("Patch Promotion Target Guard self-Sigil mismatch") + anchors = (guard["clock_anchor_evidence_sigil"], guard["original_remaining_ns"]) + if any(value is None for value in anchors) and not all(value is None for value in anchors): + _fail("Patch Promotion Target Guard anchor fields must be jointly null or present") + times = (guard["acquired_at"], guard["expires_at"]) + if any(value is None for value in times) and not all(value is None for value in times): + _fail("Patch Promotion Target Guard acquisition times must be jointly null or present") + if times[0] is not None and _time(times[1]) < _time(times[0]): + _fail("Patch Promotion Target Guard expires before acquisition") + active = {"HELD", "RENEWING", "RELEASING", "FENCING", "RECOVERING"} + if guard["state"] in active and ( + any(value is None for value in anchors) or any(value is None for value in times) + ): + _fail("Patch Promotion active Target Guard lacks a deadline anchor") + if guard["fence_floor"] > guard["fencing_generation"]: + _fail("Patch Promotion Target Guard fence floor exceeds fencing generation") + if guard["state"] == "NONE" and any((guard["backend_generation"], *anchors, *times)): + _fail("Patch Promotion empty Target Guard has active physical fields") + + +def load_patch_promotion_target_guard_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + guard = _load_strict_object(raw, "Patch Promotion Target Guard") + validate_patch_promotion_target_guard_v1(guard) + return guard + + +def validate_patch_promotion_authorization_v1(authorization: dict[str, Any]) -> None: + """Validate local immutable Authorization bytes, without resolving its Preview.""" + validate_instance("patch-promotion-authorization-1.0.json", authorization) + _check_nfc(authorization) + if authorization["authorization_sigil"] != content_sigil( + _without(authorization, "authorization_sigil") + ): + _fail("Patch Promotion Authorization self-Sigil mismatch") + paths = [path.encode("utf-8") for path in authorization["affected_paths"]] + if paths != sorted(paths) or len(paths) != len(set(paths)): + _fail("Patch Promotion Authorization affected paths must be sorted and unique") + evidence = authorization["validation"]["evidence"] + evidence_ids = [item["id"].encode("ascii") for item in evidence] + if evidence_ids != sorted(evidence_ids) or len(evidence_ids) != len(set(evidence_ids)): + _fail("Patch Promotion Authorization validation evidence must be sorted and unique") + if _time(authorization["decision_at"]) > _time(authorization["expires_at"]): + _fail("Patch Promotion Authorization expires before its decision") + + +def validate_patch_promotion_attempt_v1(attempt: dict[str, Any]) -> None: + """Validate one immutable Promotion Attempt without replaying its transitions.""" + validate_instance("patch-promotion-attempt-1.0.json", attempt) + _check_nfc(attempt) + if attempt["attempt_sigil"] != content_sigil(_without(attempt, "attempt_sigil")): + _fail("Patch Promotion Attempt self-Sigil mismatch") + + +def validate_patch_promotion_attempt_supplied_authorization_v1( + attempt: dict[str, Any], + authorization: dict[str, Any], +) -> None: + """Bind an allocated Attempt to its exact supplied Authorization document.""" + validate_patch_promotion_attempt_v1(attempt) + validate_patch_promotion_authorization_v1(authorization) + if ( + attempt["authorization"] + != {"id": authorization["authorization_id"], "sigil": authorization["authorization_sigil"]} + or attempt["operation_sigil"] != authorization["operation_sigil"] + or attempt["target"] != authorization["target"] + or attempt["target_content_generation"] != authorization["target_content_generation"] + or attempt["adapter"] != authorization["adapter"] + or attempt["mode"] != authorization["mode"] + ): + _fail("Patch Promotion Attempt disagrees with supplied Authorization") + + +def derive_patch_promotion_outcome_id_v1( + attempt_id: str, + terminal_event_id: str, + terminal_event_sigil: str, +) -> str: + """Derive the immutable Outcome identity from its terminal attempt Event.""" + preimage = "benchwork:patch-promotion-outcome:v1\0" + canonical_json( + [attempt_id, terminal_event_id, terminal_event_sigil] + ) + return "PO-" + hashlib.sha256(preimage.encode("utf-8")).hexdigest()[:32] + + +def validate_patch_promotion_outcome_v1(outcome: dict[str, Any]) -> None: + """Validate local terminal Outcome closure without resolving its Journal Event.""" + validate_instance("patch-promotion-outcome-1.0.json", outcome) + _check_nfc(outcome) + if outcome["outcome_sigil"] != content_sigil(_without(outcome, "outcome_sigil")): + _fail("Patch Promotion Outcome self-Sigil mismatch") + expected_id = derive_patch_promotion_outcome_id_v1( + outcome["attempt_id"], + outcome["terminal_journal_event_id"], + outcome["terminal_journal_event_sigil"], + ) + if outcome["outcome_id"] != expected_id: + _fail("Patch Promotion Outcome ID does not match its terminal Event") + times = outcome["timestamps"] + ordered_times = [times["created_at"]] + ordered_times.extend( + value + for value in (times["mutation_started_at"], times["verification_started_at"]) + if value is not None + ) + ordered_times.append(times["terminal_at"]) + if [_time(value) for value in ordered_times] != sorted(_time(value) for value in ordered_times): + _fail("Patch Promotion Outcome timestamps are not non-decreasing") + observations = outcome["path_observations"] + paths = [item["path_bytes"].encode("utf-8") for item in observations] + if paths != sorted(paths) or len(paths) != len(set(paths)): + _fail("Patch Promotion Outcome path observations must be sorted and unique") + verifier = outcome["verifier_evidence"] + verifier_sigils = [item["sigil"].encode("ascii") for item in verifier] + if verifier_sigils != sorted(verifier_sigils) or len(verifier_sigils) != len( + set(verifier_sigils) + ): + _fail("Patch Promotion Outcome verifier evidence must be sorted and unique") + adapter_evidence = outcome["adapter_write_evidence"] + if adapter_evidence is not None: + if ( + adapter_evidence["before_generation"] != outcome["before_generation"] + or adapter_evidence["after_generation"] != outcome["after_generation"] + ): + _fail("Patch Promotion Outcome adapter evidence disagrees with generations") + receipts = adapter_evidence["receipt_sigils"] + if receipts != sorted(receipts) or len(receipts) != len(set(receipts)): + _fail("Patch Promotion Outcome adapter receipt Sigils must be sorted and unique") + if adapter_evidence["mode"] != "FULL_TREE_ATOMIC_CAS" and len(receipts) != len( + observations + ): + _fail("Patch Promotion Outcome per-entry evidence must cover every path observation") + + +def validate_patch_promotion_outcome_supplied_attempt_v1( + outcome: dict[str, Any], + attempt: dict[str, Any], +) -> None: + """Bind a terminal Outcome to its exact caller-supplied Promotion Attempt.""" + validate_patch_promotion_outcome_v1(outcome) + validate_patch_promotion_attempt_v1(attempt) + terminal_states = { + "APPLIED", + "RECOVERED_POSTIMAGE_OBSERVED", + "ALREADY_APPLIED", + "STALE", + "CONFLICT", + "FAILED", + "PARTIAL", + "CANCELLED", + } + if attempt["state"] not in terminal_states: + _fail("Patch Promotion Outcome requires a terminal supplied Attempt") + if ( + outcome["attempt_id"] != attempt["attempt_id"] + or outcome["operation_sigil"] != attempt["operation_sigil"] + or outcome["adapter"] != attempt["adapter"] + or outcome["timestamps"]["created_at"] != attempt["created_at"] + or outcome["status"] != attempt["state"] + ): + _fail("Patch Promotion Outcome disagrees with supplied Attempt") + + +def derive_patch_promotion_recovery_record_id_v1( + recovery_attempt_id: str, + terminal_event_id: str, + terminal_event_sigil: str, +) -> str: + """Derive immutable Recovery Record identity from its terminal Event.""" + preimage = "benchwork:patch-promotion-recovery-record:v1\0" + canonical_json( + [recovery_attempt_id, terminal_event_id, terminal_event_sigil] + ) + return "PRR-" + hashlib.sha256(preimage.encode("utf-8")).hexdigest()[:32] + + +def validate_patch_promotion_recovery_attempt_v1(attempt: dict[str, Any]) -> None: + """Validate one immutable Recovery Attempt without replaying transitions.""" + validate_instance("patch-promotion-recovery-attempt-1.0.json", attempt) + _check_nfc(attempt) + if attempt["recovery_attempt_sigil"] != content_sigil( + _without(attempt, "recovery_attempt_sigil") + ): + _fail("Patch Promotion Recovery Attempt self-Sigil mismatch") + + +def validate_patch_promotion_recovery_record_v1(record: dict[str, Any]) -> None: + """Validate local terminal Recovery Record closure without Journal replay.""" + validate_instance("patch-promotion-recovery-record-1.0.json", record) + _check_nfc(record) + if record["recovery_record_sigil"] != content_sigil(_without(record, "recovery_record_sigil")): + _fail("Patch Promotion Recovery Record self-Sigil mismatch") + expected_id = derive_patch_promotion_recovery_record_id_v1( + record["recovery_attempt_id"], + record["terminal_journal_event_id"], + record["terminal_journal_event_sigil"], + ) + if record["recovery_record_id"] != expected_id: + _fail("Patch Promotion Recovery Record ID does not match its terminal Event") + sigils = [item["sigil"].encode("ascii") for item in record["verifier_evidence"]] + if sigils != sorted(sigils) or len(sigils) != len(set(sigils)): + _fail("Patch Promotion Recovery Record verifier evidence must be sorted and unique") + disposition = record["abandonment_disposition"] + if (record["status"] == "ABANDONED") != (disposition is not None): + _fail("Patch Promotion Recovery Record abandonment disposition disagrees with status") + if disposition is None: + return + if disposition["disposition_sigil"] != content_sigil( + _without(disposition, "disposition_sigil") + ): + _fail("Patch Promotion Recovery Record abandonment disposition self-Sigil mismatch") + if disposition["terminal_event"]["event_type"] != "recovery.abandoned": + _fail("Patch Promotion Recovery Record abandonment terminal Event type is invalid") + expected_guard_events = { + "RELEASED": "target.guard-released", + "FENCED": "target.guard-fenced", + "FAILED": "target.guard-failed", + } + if expected_guard_events[disposition["guard_completion"]["terminal_state"]] != ( + disposition["guard_completion"]["terminal_event"]["event_type"] + ): + _fail("Patch Promotion Recovery Record guard completion Event type is invalid") + root_ids = [item["operational_root_id"].encode("ascii") for item in disposition["root_dispositions"]] + if root_ids != sorted(root_ids) or len(root_ids) != len(set(root_ids)): + _fail("Patch Promotion Recovery Record abandonment roots must be sorted and unique") + if ( + disposition["recovery_attempt_id"] != record["recovery_attempt_id"] + or disposition["parent_attempt_id"] != record["parent_attempt_id"] + or disposition["authorization_receipt"] != record["authorization_receipt"] + or disposition["terminal_event"]["event_id"] != record["terminal_journal_event_id"] + or disposition["terminal_event"]["event_sigil"] != record["terminal_journal_event_sigil"] + or disposition["observed_partial_identity"] != record["before_identity"] + or record["after_identity"] != record["before_identity"] + or disposition["observed_generation"] != record["before_generation"] + or record["after_generation"] != record["before_generation"] + or disposition["logical_fence_generation"] != record["resulting_logical_fence_generation"] + or disposition["logical_fence_generation"] != record["lineage"]["logical_fence_generation"] + or disposition["guard_completion"]["guard"] != record["guard"] + ): + _fail("Patch Promotion Recovery Record abandonment disposition disagrees with record") + + +def validate_patch_promotion_recovery_record_supplied_attempt_v1( + record: dict[str, Any], + attempt: dict[str, Any], +) -> None: + """Bind Recovery Record fields to its exact supplied terminal Attempt.""" + validate_patch_promotion_recovery_record_v1(record) + validate_patch_promotion_recovery_attempt_v1(attempt) + terminal_states = { + "BASE_RESTORED", + "POSTIMAGE_ACCEPTED", + "ABANDONED", + "STALE", + "FAILED", + "PARTIAL", + "CANCELLED", + } + if attempt["state"] not in terminal_states: + _fail("Patch Promotion Recovery Record requires a terminal supplied Attempt") + if ( + record["recovery_attempt_id"] != attempt["recovery_attempt_id"] + or record["parent_attempt_id"] != attempt["parent_attempt_id"] + or record["parent_outcome_receipt"] != attempt["parent_outcome_receipt"] + or record["action"] != attempt["action"] + or record["checkpoint"] != attempt["checkpoint"] + or record["lineage"] != attempt["lineage"] + or record["status"] != attempt["state"] + ): + _fail("Patch Promotion Recovery Record disagrees with supplied Attempt") + + +def validate_patch_promotion_journal_event_v1(event: dict[str, Any]) -> None: + """Validate one closed self-authenticating Promotion Journal Event.""" + validate_instance("patch-promotion-journal-event-1.0.json", event) + _check_nfc(event) + if event["event_sigil"] != content_sigil(_without(event, "event_sigil")): + _fail("Patch Promotion Journal Event self-Sigil mismatch") + revision_keys: set[tuple[str, str]] = set() + u64_max = 18_446_744_073_709_551_615 + for revision in event["entity_revisions"]: + key = (revision["entity_type"], revision["entity_id"]) + if key in revision_keys: + _fail("Patch Promotion Journal Event has duplicate entity revisions") + revision_keys.add(key) + if ( + revision["prior_revision"] == u64_max + or revision["next_revision"] != revision["prior_revision"] + 1 + ): + _fail("Patch Promotion Journal Event revision algebra is invalid") + + +def load_patch_promotion_journal_event_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + event = _load_strict_object(raw, "Patch Promotion Journal Event") + validate_patch_promotion_journal_event_v1(event) + return event + + +def validate_patch_promotion_journal_head_v1(head: dict[str, Any]) -> None: + """Validate one closed Head cache record without reading frames.""" + validate_instance("patch-promotion-journal-head-1.0.json", head) + _check_nfc(head) + if head["head_sigil"] != content_sigil(_without(head, "head_sigil")): + _fail("Patch Promotion Journal Head self-Sigil mismatch") + empty = head["event_count"] == 0 + if empty != (head["last_sequence"] == 0 and head["last_event_sigil"] is None): + _fail("Patch Promotion Journal Head empty fields disagree") + if not empty and ( + head["last_sequence"] != head["event_count"] or head["last_event_sigil"] is None + ): + _fail("Patch Promotion Journal Head terminal fields disagree") + + +def load_patch_promotion_journal_head_v1(raw: str | bytes | bytearray) -> dict[str, Any]: + head = _load_strict_object(raw, "Patch Promotion Journal Head") + validate_patch_promotion_journal_head_v1(head) + return head + + +def validate_patch_promotion_journal_prefix_v1( + events: list[dict[str, Any]], + *, + head: dict[str, Any] | None = None, +) -> None: + """Validate one complete caller-supplied contiguous Promotion prefix.""" + if not events: + _fail("Patch Promotion Journal prefix requires a nonempty sequence") + journal_id: str | None = None + coordinator: tuple[str, int] | None = None + previous_sigil: str | None = None + previous_time: datetime | None = None + event_ids: set[str] = set() + for sequence, event in enumerate(events, 1): + validate_patch_promotion_journal_event_v1(event) + if sequence == 1 and event["event_type"] != "coordinator.epoch-started": + _fail("Patch Promotion Journal prefix must begin with coordinator.epoch-started") + if journal_id is None: + journal_id = event["journal_id"] + coordinator = (event["coordinator_id"], event["coordinator_epoch"]) + if ( + event["journal_id"] != journal_id + or (event["coordinator_id"], event["coordinator_epoch"]) != coordinator + ): + _fail("Patch Promotion Journal prefix has inconsistent identity or coordinator epoch") + if event["event_id"] in event_ids: + _fail("Patch Promotion Journal prefix has a duplicate Event identity") + if event["sequence"] != sequence or event["previous_event_sigil"] != previous_sigil: + _fail("Patch Promotion Journal prefix has a sequence gap or broken Event chain") + recorded_at = _time(event["recorded_at"]) + if previous_time is not None and recorded_at < previous_time: + _fail("Patch Promotion Journal prefix has decreasing recorded_at time") + event_ids.add(event["event_id"]) + previous_sigil = event["event_sigil"] + previous_time = recorded_at + if head is not None: + validate_patch_promotion_journal_head_v1(head) + last = events[-1] + if coordinator is None: + _fail("Patch Promotion Journal prefix has no coordinator") + if ( + head["journal_id"] != journal_id + or head["coordinator_epoch"] != coordinator[1] + or head["event_count"] != last["sequence"] + or head["last_sequence"] != last["sequence"] + or head["last_event_sigil"] != last["event_sigil"] + ): + _fail("Patch Promotion Journal Head disagrees with supplied prefix") + + +def require_patch_promotion_runtime_authority_v1() -> NoReturn: + """Fail closed: local Promotion wire validation authorizes no mutation.""" + _fail("Patch Promotion runtime authority is unavailable in contract-only scope") diff --git a/tests/fixtures/phase3/rfc0012/execution-journal-event-v1/invalid-duplicate-key.json b/tests/fixtures/phase3/rfc0012/execution-journal-event-v1/invalid-duplicate-key.json new file mode 100644 index 0000000..0f82c74 --- /dev/null +++ b/tests/fixtures/phase3/rfc0012/execution-journal-event-v1/invalid-duplicate-key.json @@ -0,0 +1 @@ +{"schema_version":"execution-journal-event/1.0","payload":{"x":1,"x":2}} diff --git a/tests/fixtures/phase3/rfc0012/execution-journal-event-v1/valid-initial.json b/tests/fixtures/phase3/rfc0012/execution-journal-event-v1/valid-initial.json new file mode 100644 index 0000000..39ddecb --- /dev/null +++ b/tests/fixtures/phase3/rfc0012/execution-journal-event-v1/valid-initial.json @@ -0,0 +1 @@ +{"schema_version":"execution-journal-event/1.0","journal_id":"EJ-ONE","event_id":"JE-ONE","sequence":1,"event_type":"executor.epoch_started","executor_instance_id":"XI-ONE","executor_epoch":1,"executor_build_sigil":"sha256:2c0301cf657fe71300d0c2d295b0bb2cfcedb75803e355258ed543f907e55d20","recorded_at":"2026-08-06T00:00:00Z","observed_at":null,"entity_revisions":[{"entity_kind":"EXECUTOR","entity_id":"XI-ONE","preceding_revision":null,"next_revision":0}],"causation_event_id":null,"idempotency_key_sigil":null,"recovery_action_binding":null,"payload":{"prior_epoch":0,"new_epoch":1,"startup_reason":"INITIAL_START","host_identity_sigil":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","executor_build_binding":{"implementation_id":"LOCAL-EXECUTOR","implementation_version":"V1","source_revision_sigil":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","executable_artifact_sigil":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","dependency_set_sigil":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","build_configuration_sigil":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","executor_build_sigil":"sha256:2c0301cf657fe71300d0c2d295b0bb2cfcedb75803e355258ed543f907e55d20"}},"previous_event_sigil":null,"event_sigil":"sha256:ab35540a99f75c38d45a733a6ef79bfd8a751cc82ef5210a407f6bb79ef2994d"} diff --git a/tests/fixtures/phase3/rfc0012/execution-journal-head-v1/valid-initial.json b/tests/fixtures/phase3/rfc0012/execution-journal-head-v1/valid-initial.json new file mode 100644 index 0000000..c47eda5 --- /dev/null +++ b/tests/fixtures/phase3/rfc0012/execution-journal-head-v1/valid-initial.json @@ -0,0 +1 @@ +{"schema_version":"execution-journal-head/1.0","limit_profile":"EXECUTION_JOURNAL_V1_FIXED_LIMITS","journal_id":"EJ-ONE","last_sequence":1,"last_event_id":"JE-ONE","last_event_sigil":"sha256:ab35540a99f75c38d45a733a6ef79bfd8a751cc82ef5210a407f6bb79ef2994d","updated_at":"2026-08-06T00:00:00Z","head_sigil":"sha256:479cf50ece60c4728eeb4cd6b2d8240f2dfb3541bfa42aee143111b972787847"} diff --git a/tests/fixtures/phase3/rfc0012/execution-observation-evidence-v1/invalid-duplicate-key.json b/tests/fixtures/phase3/rfc0012/execution-observation-evidence-v1/invalid-duplicate-key.json new file mode 100644 index 0000000..21bc5bd --- /dev/null +++ b/tests/fixtures/phase3/rfc0012/execution-observation-evidence-v1/invalid-duplicate-key.json @@ -0,0 +1 @@ +{"schema_version":"execution-observation-evidence/1.0","assessment":{"kind":"MATCHED","kind":"UNAVAILABLE"}} diff --git a/tests/fixtures/phase3/rfc0012/execution-output-storage-observation-set-v1/valid-minimal.json b/tests/fixtures/phase3/rfc0012/execution-output-storage-observation-set-v1/valid-minimal.json new file mode 100644 index 0000000..a7eb2d9 --- /dev/null +++ b/tests/fixtures/phase3/rfc0012/execution-output-storage-observation-set-v1/valid-minimal.json @@ -0,0 +1,27 @@ +{ + "schema_version": "execution-output-storage-observation-set/1.0", + "observation_set_id": "OS-B3E6EDA727AD1F0AEB01C7A28AEC93637E9AF3C08113BC6952024777183E7752", + "job_id": "JB-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "attempt_id": "AT-OS1", + "attempt_binding_sigil": "sha256:1111111111111111111111111111111111111111111111111111111111111111", + "result_binding": {"kind": "NONE"}, + "log_closure_sigil": "sha256:2222222222222222222222222222222222222222222222222222222222222222", + "output_closure_sigil": "sha256:3333333333333333333333333333333333333333333333333333333333333333", + "control_evidence_set_binding": {"kind": "FROZEN", "control_evidence_set_id": "CES-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "control_evidence_set_sigil": "sha256:4444444444444444444444444444444444444444444444444444444444444444"}, + "quarantine_binding_set_binding": {"kind": "FROZEN", "quarantine_binding_set_id": "QBS-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", "quarantine_binding_set_sigil": "sha256:5555555555555555555555555555555555555555555555555555555555555555"}, + "terminalization_storage_manifest_binding": {"kind": "FROZEN", "storage_root_manifest_id": "ESM-CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", "storage_root_manifest_sigil": "sha256:6666666666666666666666666666666666666666666666666666666666666666"}, + "output_root_protection": {"kind": "NO_HOLD", "terminalization_storage_manifest_binding": {"kind": "FROZEN", "storage_root_manifest_id": "ESM-CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", "storage_root_manifest_sigil": "sha256:6666666666666666666666666666666666666666666666666666666666666666"}}, + "terminal_source_binding": {"kind": "NOT_APPLICABLE"}, + "storage_event": {"journal_id": "SJ-OS", "event_id": "SE-OS-7", "sequence": 7, "event_sigil": "sha256:7777777777777777777777777777777777777777777777777777777777777777"}, + "storage_state_sigil": "sha256:8888888888888888888888888888888888888888888888888888888888888888", + "members": [ + {"kind": "ATTEMPT_OUTPUTS_NONE", "reason": "NO_RESULT"}, + {"kind": "LOG_STREAM", "storage_subject_id": "sha256:9011111111111111111111111111111111111111111111111111111111111111", "manifest_entry_sigil": "sha256:9111111111111111111111111111111111111111111111111111111111111111", "stream": "STDOUT", "log_stream_id": "LG-OSSTDOUT", "final_sequence": null, "captured_bytes": 0, "dropped_bytes": 0, "truncated": false, "stream_set_sigil": "sha256:a111111111111111111111111111111111111111111111111111111111111111", "closure_event_id": "JE-OSSTDOUT", "closure_event_sigil": "sha256:b111111111111111111111111111111111111111111111111111111111111111", "storage_origin": {"kind": "NOT_STORED", "transfer": null, "terminal_reason": {"code": "PAYLOAD_LOST", "evidence_sigils": ["sha256:c111111111111111111111111111111111111111111111111111111111111111"]}, "evidence_sigil": "sha256:c111111111111111111111111111111111111111111111111111111111111111"}, "content": {"kind": "EMPTY", "blob_sigil": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "storage": {"kind": "BLOB", "terminal_storage_status": "AVAILABLE", "blob_sigil": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size_bytes": 0, "blob_record_sigil": "sha256:8888888888888888888888888888888888888888888888888888888888888888", "availability": "AVAILABLE", "availability_as_of": {"journal_id": "SJ-OS", "event_id": "SE-OS-7", "sequence": 7, "event_sigil": "sha256:7777777777777777777777777777777777777777777777777777777777777777"}, "availability_basis_sigil": "sha256:8888888888888888888888888888888888888888888888888888888888888888", "integrity_event_sigils": [], "quarantine": {"kind": "NONE"}, "replica": {"kind": "NONE"}}}}, + {"kind": "LOG_STREAM", "storage_subject_id": "sha256:9022222222222222222222222222222222222222222222222222222222222222", "manifest_entry_sigil": "sha256:9222222222222222222222222222222222222222222222222222222222222222", "stream": "STDERR", "log_stream_id": "LG-OSSTDERR", "final_sequence": null, "captured_bytes": 0, "dropped_bytes": 0, "truncated": false, "stream_set_sigil": "sha256:a222222222222222222222222222222222222222222222222222222222222222", "closure_event_id": "JE-OSSTDERR", "closure_event_sigil": "sha256:b222222222222222222222222222222222222222222222222222222222222222", "storage_origin": {"kind": "NOT_STORED", "transfer": null, "terminal_reason": {"code": "PAYLOAD_LOST", "evidence_sigils": ["sha256:c222222222222222222222222222222222222222222222222222222222222222"]}, "evidence_sigil": "sha256:c222222222222222222222222222222222222222222222222222222222222222"}, "content": {"kind": "EMPTY", "blob_sigil": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "storage": {"kind": "BLOB", "terminal_storage_status": "AVAILABLE", "blob_sigil": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size_bytes": 0, "blob_record_sigil": "sha256:8888888888888888888888888888888888888888888888888888888888888888", "availability": "AVAILABLE", "availability_as_of": {"journal_id": "SJ-OS", "event_id": "SE-OS-7", "sequence": 7, "event_sigil": "sha256:7777777777777777777777777777777777777777777777777777777777777777"}, "availability_basis_sigil": "sha256:8888888888888888888888888888888888888888888888888888888888888888", "integrity_event_sigils": [], "quarantine": {"kind": "NONE"}, "replica": {"kind": "NONE"}}}}, + {"kind": "LOG_STREAM", "storage_subject_id": "sha256:9033333333333333333333333333333333333333333333333333333333333333", "manifest_entry_sigil": "sha256:9333333333333333333333333333333333333333333333333333333333333333", "stream": "STRUCTURED", "log_stream_id": "LG-OSSTRUCTURED", "final_sequence": null, "captured_bytes": 0, "dropped_bytes": 0, "truncated": false, "stream_set_sigil": "sha256:a333333333333333333333333333333333333333333333333333333333333333", "closure_event_id": "JE-OSSTRUCTURED", "closure_event_sigil": "sha256:b333333333333333333333333333333333333333333333333333333333333333", "storage_origin": {"kind": "NOT_STORED", "transfer": null, "terminal_reason": {"code": "PAYLOAD_LOST", "evidence_sigils": ["sha256:c333333333333333333333333333333333333333333333333333333333333333"]}, "evidence_sigil": "sha256:c333333333333333333333333333333333333333333333333333333333333333"}, "content": {"kind": "EMPTY", "blob_sigil": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "storage": {"kind": "BLOB", "terminal_storage_status": "AVAILABLE", "blob_sigil": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size_bytes": 0, "blob_record_sigil": "sha256:8888888888888888888888888888888888888888888888888888888888888888", "availability": "AVAILABLE", "availability_as_of": {"journal_id": "SJ-OS", "event_id": "SE-OS-7", "sequence": 7, "event_sigil": "sha256:7777777777777777777777777777777777777777777777777777777777777777"}, "availability_basis_sigil": "sha256:8888888888888888888888888888888888888888888888888888888888888888", "integrity_event_sigils": [], "quarantine": {"kind": "NONE"}, "replica": {"kind": "NONE"}}}}, + {"kind": "RESOURCE_EVIDENCE_NONE"}, + {"kind": "TERMINAL_SOURCE_NOT_APPLICABLE"} + ], + "blob_sigils": ["sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"], + "observation_set_sigil": "sha256:ea9258abf8c66e0d9bb3b6610c111f2743a719fd4cc12ba59ea3e9be49061ec1" +} diff --git a/tests/fixtures/phase3/rfc0012/execution-result-ingress-receipt-v1/invalid-duplicate-key.json b/tests/fixtures/phase3/rfc0012/execution-result-ingress-receipt-v1/invalid-duplicate-key.json new file mode 100644 index 0000000..10fb317 --- /dev/null +++ b/tests/fixtures/phase3/rfc0012/execution-result-ingress-receipt-v1/invalid-duplicate-key.json @@ -0,0 +1 @@ +{"schema_version":"execution-result-ingress-receipt/1.0","owner_binding":{"job_id":"JB-A","job_id":"JB-B"}} diff --git a/tests/fixtures/phase3/rfc0012/execution-state-v1/invalid-duplicate-key.json b/tests/fixtures/phase3/rfc0012/execution-state-v1/invalid-duplicate-key.json new file mode 100644 index 0000000..072a83b --- /dev/null +++ b/tests/fixtures/phase3/rfc0012/execution-state-v1/invalid-duplicate-key.json @@ -0,0 +1 @@ +{"schema_version":"execution-state/1.0","schema_version":"execution-state/0.9"} diff --git a/tests/fixtures/phase3/rfc0012/execution-state-v1/valid-initial.json b/tests/fixtures/phase3/rfc0012/execution-state-v1/valid-initial.json new file mode 100644 index 0000000..6ab317e --- /dev/null +++ b/tests/fixtures/phase3/rfc0012/execution-state-v1/valid-initial.json @@ -0,0 +1 @@ +{"schema_version":"execution-state/1.0","limit_profile":"EXECUTION_JOURNAL_V1_FIXED_LIMITS","journal_binding":{"journal_id":"EJ-ONE","through_sequence":1,"through_event_id":"JE-ONE","through_event_sigil":"sha256:ab35540a99f75c38d45a733a6ef79bfd8a751cc82ef5210a407f6bb79ef2994d"},"executor":{"executor_instance_id":"XI-ONE","executor_epoch":1,"executor_build_binding":{"implementation_id":"LOCAL-EXECUTOR","implementation_version":"V1","source_revision_sigil":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","executable_artifact_sigil":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","dependency_set_sigil":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","build_configuration_sigil":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","executor_build_sigil":"sha256:2c0301cf657fe71300d0c2d295b0bb2cfcedb75803e355258ed543f907e55d20"},"revision":0,"clock_state":"TRUSTED","last_trusted_utc":"2026-08-06T00:00:00Z","clock_uncertain_event_id":null,"active_recovery_id":null,"authority_gates":[],"last_event_id":"JE-ONE","last_event_sigil":"sha256:ab35540a99f75c38d45a733a6ef79bfd8a751cc82ef5210a407f6bb79ef2994d"},"recoveries":[],"workers":[],"worker_sessions":[],"jobs":[],"attempts":[],"leases":[],"log_streams":[],"deadlines":[],"idempotency_records":[],"state_sigil":"sha256:1d9e957d006870deec9f24f458f454b70bb89c38eb1866722434ca423b6f1c2e"} diff --git a/tests/fixtures/phase3/rfc0015/execution-job-outcome-v1/valid-no-attempt.json b/tests/fixtures/phase3/rfc0015/execution-job-outcome-v1/valid-no-attempt.json new file mode 100644 index 0000000..a782274 --- /dev/null +++ b/tests/fixtures/phase3/rfc0015/execution-job-outcome-v1/valid-no-attempt.json @@ -0,0 +1,206 @@ +{ + "schema_version": "execution-job-outcome/1.0", + "outcome_id": "OJ-D7AFDAE5DDE0D4F74D68AA4ACDBA07FB14FAAD4C9B96C3DB5536992BB62B3015", + "job_id": "JB-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "job_binding_sigil": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "job_terminal": { + "job_revision": 3, + "state": "FAILED", + "transition_cause": { + "code": "PREFLIGHT_REJECTED", + "trigger_kind": "PRIOR_EVENT", + "trigger_event_id": "JE-PREFLIGHTREJECTED", + "effective_sequence": 1, + "evidence_sigil": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "event_id": "JE-JOBFAILED", + "event_sequence": 3, + "event_sigil": "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + }, + "task_binding": { + "task_id": "TK-TASK", + "task_capsule_sigil": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "program_id": "RP-PROGRAM", + "capability_binding": { + "capability_id": "bench.core.echo", + "contract_version": "2.0", + "capability_contract_sigil": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + "snapshot_binding": { + "snapshot_id": "SS-SNAPSHOT", + "snapshot_sigil": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + "circle_binding": { + "circle_id": "CI-CIRCLE", + "circle_sigil": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + }, + "approval_binding": { + "kind": "NOT_REQUIRED", + "ward_decision_id": "WD-DECISION", + "ward_decision_sigil": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "execution_specification_binding": { + "specification_id": "ES-01ARZ3NDEKTSV4RRFFQ69G5FAV", + "specification_sigil": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "attempt_summaries": [], + "selected_attempt_binding": { + "kind": "NONE" + }, + "result_binding": { + "kind": "NONE" + }, + "completion_anchor_binding": { + "kind": "NOT_ESTABLISHED" + }, + "first_stop_or_fence_binding": { + "kind": "PRESENT", + "event_id": "JE-PREFLIGHTREJECTED", + "event_type": "job.failed", + "event_sigil": "sha256:3333333333333333333333333333333333333333333333333333333333333333", + "effective_sequence": 1 + }, + "lease_terminal_binding": { + "kind": "NONE" + }, + "authority_binding": { + "kind": "NO_ATTEMPT" + }, + "final_fence_binding": { + "kind": "NO_ATTEMPT", + "final_fence_floor": 0 + }, + "runtime_outcome": { + "kind": "NO_ATTEMPT", + "computation_status": "NOT_STARTED", + "worker_status": "NOT_REPORTED", + "process_termination_status": "NOT_STARTED", + "handle_revocation_status": "NOT_APPLICABLE", + "cleanup_status": "NOT_APPLICABLE", + "mutable_resource_isolation_status": "NOT_APPLICABLE", + "output_publication_status": "NOT_APPLICABLE", + "quarantine_status": "NOT_REQUIRED", + "termination_evidence_sigil": null, + "handle_disposition_evidence_sigil": null, + "cleanup_summary_sigil": null, + "quarantine_evidence_sigil": null, + "log_closure_sigil": null, + "output_closure_sigil": null, + "accounting_capture_event_id": null, + "accounting_capture_event_sigil": null + }, + "terminal_source_binding": { + "kind": "NOT_APPLICABLE" + }, + "terminal_source_observation": { + "kind": "NO_ATTEMPT" + }, + "assurance_context_binding": { + "kind": "NO_ATTEMPT", + "requested_level": "SANCTUM-A1", + "profile_version": "1.0", + "profile_sigil": "sha256:4444444444444444444444444444444444444444444444444444444444444444", + "conformance_suite_id": "CS-DEFAULT", + "conformance_suite_sigil": "sha256:5555555555555555555555555555555555555555555555555555555555555555" + }, + "attempt_assurance_binding": { + "kind": "NONE" + }, + "job_assurance_binding": { + "kind": "NOT_APPLICABLE", + "evaluation_event_id": "JE-JOBASSURANCE", + "evaluation_event_sigil": "sha256:6666666666666666666666666666666666666666666666666666666666666666", + "evaluation_sequence": 2, + "reason": "NO_ATTEMPT_ALLOCATED", + "evidence_set_sigil": "sha256:7777777777777777777777777777777777777777777777777777777777777777" + }, + "control_evidence_set_binding": { + "kind": "NOT_APPLICABLE" + }, + "quarantine_binding_set_binding": { + "kind": "NOT_APPLICABLE" + }, + "terminalization_storage_manifest_binding": { + "kind": "NOT_APPLICABLE" + }, + "output_root_protection": { + "kind": "NOT_APPLICABLE" + }, + "budget_binding": { + "job_budget_ledger": { + "attempts": { + "limit": 1, + "reserved": 0, + "consumed": 0, + "exhaustion_status": "AVAILABLE" + }, + "cpu_time_seconds": { + "limit": 60, + "reserved": 0, + "consumed": 0, + "exhaustion_status": "AVAILABLE" + }, + "storage_bytes_written": { + "limit": 1024, + "reserved": 0, + "consumed": 0, + "exhaustion_status": "AVAILABLE" + }, + "output_bytes": { + "limit": 1024, + "reserved": 0, + "consumed": 0, + "exhaustion_status": "AVAILABLE" + }, + "log_bytes": { + "limit": 1024, + "reserved": 0, + "consumed": 0, + "exhaustion_status": "AVAILABLE" + }, + "process_starts": { + "limit": 1, + "reserved": 0, + "consumed": 0, + "exhaustion_status": "AVAILABLE" + }, + "network_egress_bytes": { + "limit": 0, + "reserved": 0, + "consumed": 0, + "exhaustion_status": "EXHAUSTED" + }, + "network_requests": { + "limit": 0, + "reserved": 0, + "consumed": 0, + "exhaustion_status": "EXHAUSTED" + }, + "budget_ledger_sigil": "sha256:fc667a4191a312220c9c7c5bdc483df4fcb08e09d7a453ddde6c5bcd4e032dab" + }, + "selected_attempt_settlement": { + "kind": "NONE" + } + }, + "outputs": [], + "storage_observation_binding": { + "kind": "NOT_APPLICABLE" + }, + "logs": [], + "resource_evidence": [], + "acceptance_eligible": false, + "ineligibility_reasons": [ + "JOB_NOT_SUCCEEDED", + "ATTEMPT_ABSENT" + ], + "derivation_profile": { + "profile_id": "execution-job-outcome-v1", + "profile_version": "1.0", + "algorithm_sigil": "sha256:2bec4db5be71e36d9b5019b30e1d58a4990d2cc3ae6a8f0c124311195aca964f", + "outcome_schema_sigil": "sha256:6dd9b5ca722395466355680484d763d6a2451f222d9d944235ef227bd93d41e0", + "imported_schema_set_sigil": "sha256:ec755709a3fc028dc6fecc6b1bc6d85454742756a410207ab4c4c59b48bb07ea" + }, + "terminal_recorded_at": "2026-08-06T00:00:03Z", + "outcome_sigil": "sha256:e74f4d8ce1c43b6037c458f3f523484f50108d1cc7b966b3c7719e8c9bbaa3e1" +} diff --git a/tests/test_agent_result_v2_contract.py b/tests/test_agent_result_v2_contract.py new file mode 100644 index 0000000..96147f0 --- /dev/null +++ b/tests/test_agent_result_v2_contract.py @@ -0,0 +1,166 @@ +from __future__ import annotations + +from copy import deepcopy + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.execution_contracts import ( + project_agent_result_record_v2_supplied_facts, + validate_agent_result_acceptance_transition_request_v1, + validate_agent_result_v2, +) +from benchwork.schema_validation import validate_instance + + +SIGIL = "sha256:" + "a" * 64 + + +def _result() -> dict[str, object]: + manifest = {"kind": "FROZEN", "storage_root_manifest_id": "ESM-" + "A" * 64, "storage_root_manifest_sigil": SIGIL} + return { + "schema_version": "agent-result/2.0", "task_id": "TK-ONE", "program_id": "RP-ONE", + "task_capsule_sigil": SIGIL, "host_identity_sigil": SIGIL, + "capability_binding": {"capability_id": "bench.work.exec", "contract_version": "2.0", "capability_contract_sigil": SIGIL}, + "snapshot_binding": {"snapshot_id": "SS-ONE", "snapshot_sigil": SIGIL}, + "job_binding": {"job_id": "JB-" + "A" * 64, "job_binding_sigil": SIGIL}, + "execution_specification_binding": {"specification_id": "ES-" + "0" * 26, "specification_sigil": SIGIL}, + "job_outcome_binding": {"outcome_id": "OJ-" + "A" * 64, "outcome_sigil": SIGIL}, + "terminal_event_sigil": SIGIL, "selected_attempt_id": "AT-" + "0" * 26, + "assurance_claim_sigil": SIGIL, "terminal_source_binding": {"kind": "NOT_APPLICABLE"}, + "status": "COMPLETED", "outputs": [ + {"task_output_id": "alpha", "declared_schema_id": "result/1.0", "declared_schema_sigil": SIGIL, "blob_sigil": "sha256:" + "b" * 64, "size_bytes": 1, "source_observation_member_sigil": SIGIL, "storage_integrity_evidence_sigil": SIGIL}, + {"task_output_id": "beta", "declared_schema_id": "result/1.0", "declared_schema_sigil": SIGIL, "blob_sigil": "sha256:" + "c" * 64, "size_bytes": 1, "source_observation_member_sigil": SIGIL, "storage_integrity_evidence_sigil": SIGIL}, + ], + "provenance": { + "executor_instance_id": "XI-ONE", "executor_epoch": 1, "executor_build_sigil": SIGIL, + "worker_id": "WK-ONE", "worker_binding_sigil": SIGIL, "worker_session_id": "WS-0123456789ABCDEFGHJKMNPQRS", + "worker_session_binding_sigil": SIGIL, "backend_identity": "BACKEND", "backend_configuration_sigil": SIGIL, + "requested_assurance_level": "SANCTUM-A1", "assurance_profile_sigil": SIGIL, + "conformance_suite_sigil": SIGIL, "attempt_authorization_state": {"kind": "NONE"}, + "budget_settlement_event_sigil": SIGIL, "job_budget_ledger_sigil": SIGIL, + "storage_observation_binding": {"kind": "FROZEN", "storage_journal_id": "SJ-ONE", "through_sequence": 1, "through_event_sigil": SIGIL, "output_storage_observation_set_id": "OS-ONE", "output_storage_observation_set_sigil": SIGIL}, + "control_evidence_set_binding": {"kind": "FROZEN", "control_evidence_set_id": "CES-" + "A" * 64, "control_evidence_set_sigil": SIGIL}, + "quarantine_binding_set_binding": {"kind": "FROZEN", "quarantine_binding_set_id": "QBS-" + "A" * 64, "quarantine_binding_set_sigil": SIGIL}, + "terminalization_storage_manifest_binding": manifest, + "output_root_protection": {"kind": "NO_HOLD", "terminalization_storage_manifest_binding": manifest}, + }, "result_sigil": "", + } + + +def _seal_result(result: dict[str, object]) -> dict[str, object]: + result["result_sigil"] = content_sigil({key: value for key, value in result.items() if key != "result_sigil"}) + return result + + +def _authorization(result: dict[str, object]) -> dict[str, object]: + blobs = ["sha256:" + "b" * 64] + head = {"schema_version": "chronicle-head/1.1", "event_count": 1, "terminal_receipt_sigil": SIGIL} + evidence = [{"blob_sigil": blobs[0], "size_bytes": 1, "replica_id": "SR-ONE", "backend_id": "BACKEND", "backend_generation": "1", "availability_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, "event_sigil": SIGIL}, "integrity_evidence_sigil": SIGIL, "quarantine_status": "CLEAR"}] + policy = {"schema_version": "agent-result-acceptance-policy/1.0", "policy_id": "agent-result-acceptance", "policy_version": "1.0", "canonical_event_type": "agent-result.accepted", "transition_request_schema": "agent-result-acceptance-transition-request/1.0", "authorization_schema": "agent-result-acceptance-authorization/1.0", "agent_result_schema": "agent-result/2.0", "job_outcome_schema": "execution-job-outcome/1.0", "reference_intent_schema": "artifact-storage-reference-intent/1.0", "chronicle_event_schema": "chronicle-event/1.1", "receipt_schema": "receipt/1.1", "ward_evaluator_profile": "sanctum-authority-intersection/1.0", "actor_authentication_profile": "mcp-authenticated-invocation/1.0", "predicate_profile": "agent-result-acceptance-predicates/1.0", "predicates": ["EXPECTED_HEAD_ADMISSIBLE", "AUTHENTICATED_INVOCATION_MATCH", "TASK_AUTHORITY_CHAIN_VALID", "CURRENT_WARD_PASS", "APPROVAL_CHAIN_VALID", "OUTCOME_REDERIVATION_MATCH", "TERMINAL_SUCCESS_ELIGIBLE", "EXECUTION_EVIDENCE_VALID", "BUDGET_SETTLED", "ASSURANCE_EVIDENCE_VALID", "STORAGE_OBSERVATION_VALID", "TERMINAL_SOURCE_VALID", "EVIDENCE_SELECTION_FINAL", "AGENT_RESULT_DERIVATION_MATCH", "REFERENCE_SET_CLOSURE_VALID", "ACCEPTANCE_STORAGE_PREFIX_VALID"], "policy_sigil": ""} + policy["policy_sigil"] = content_sigil({key: value for key, value in policy.items() if key != "policy_sigil"}) + authorization: dict[str, object] = { + "schema_version": "agent-result-acceptance-authorization/1.0", "transition_request_id": "", "event_type": "agent-result.accepted", "expected_chronicle_head": head, + "authority_subject": {"registry_binding": {"registry_id": "CR-ONE", "registry_revision": 1, "registry_sigil": SIGIL}, "task_binding": {"task_id": result["task_id"], "task_capsule_sigil": result["task_capsule_sigil"]}, "program_id": result["program_id"], "capability_binding": result["capability_binding"], "snapshot_binding": result["snapshot_binding"], "circle_binding": {"circle_id": "CI-ONE", "circle_sigil": SIGIL}, "execution_specification_binding": result["execution_specification_binding"], "job_binding": result["job_binding"], "job_outcome_binding": result["job_outcome_binding"], "agent_result_sigil": result["result_sigil"]}, + "ward_pass": {"status": "PASS", "ward_decision_id": "WD-ONE", "ward_decision_sigil": SIGIL, "resolved_permission_set_sigil": SIGIL, "evaluated_chronicle_head": head, "evaluated_at": "2026-08-06T00:00:00Z"}, + "approval": {"kind": "NOT_REQUIRED", "ward_decision_id": "WD-ONE", "ward_decision_sigil": SIGIL}, "acceptance_policy": policy, "acceptance_request_sigil": SIGIL, "idempotency_key_sigil": SIGIL, "reference_sets": [{"reference_set_id": "RS-ONE", "reference_set_sigil": SIGIL}], "managed_blob_sigils": blobs, + "acceptance_storage_binding": {"storage_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, "event_sigil": SIGIL}, "storage_state_sigil": SIGIL, "validated_blob_sigils": blobs, "validation_evidence": evidence, "validation_evidence_set_sigil": content_sigil(evidence)}, + "actor": {"kind": "AGENT", "actor_id": "ACTOR", "authentication_context_sigil": SIGIL, "actor_sigil": ""}, "host_invocation": {"host_identity_sigil": SIGIL, "invocation_id": "INVOCATION", "authentication_context_sigil": SIGIL, "invocation_sigil": ""}, "chronicle_actor": {"actor_id": "ACTOR", "actor_type": "agent", "host": "codex", "authenticated_by": "MCP"}, "requested_at": "2026-08-06T00:00:00Z", "authorization_sigil": "", + } + authorization["transition_request_id"] = "ATR-" + content_sigil(["agent-result-acceptance-transition-id/1.0", result["task_id"], SIGIL]).removeprefix("sha256:").upper() + authorization["actor"]["actor_sigil"] = content_sigil({key: value for key, value in authorization["actor"].items() if key != "actor_sigil"}) # type: ignore[index,union-attr] + authorization["host_invocation"]["invocation_sigil"] = content_sigil({key: value for key, value in authorization["host_invocation"].items() if key != "invocation_sigil"}) # type: ignore[index,union-attr] + authorization["authorization_sigil"] = content_sigil({key: value for key, value in authorization.items() if key != "authorization_sigil"}) + return authorization + + +def _request() -> dict[str, object]: + result = _seal_result(_result()) + authorization = _authorization(result) + request: dict[str, object] = {"schema_version": "agent-result-acceptance-transition-request/1.0", "transition_request_id": authorization["transition_request_id"], "event_type": "agent-result.accepted", "expected_chronicle_head": authorization["expected_chronicle_head"], "agent_result": result, "job_outcome_binding": result["job_outcome_binding"], "acceptance_request_sigil": SIGIL, "idempotency_key_sigil": SIGIL, "reference_sets": authorization["reference_sets"], "managed_blob_sigils": authorization["managed_blob_sigils"], "acceptance_storage_binding": authorization["acceptance_storage_binding"], "actor": authorization["actor"], "host_invocation": authorization["host_invocation"], "chronicle_actor": authorization["chronicle_actor"], "acceptance_authorization": authorization, "authorization_sigil": authorization["authorization_sigil"], "requested_at": authorization["requested_at"], "transition_request_sigil": ""} + request["transition_request_sigil"] = content_sigil({key: value for key, value in request.items() if key != "transition_request_sigil"}) + return request + + +def test_agent_result_v2_local_closure_rejects_reordered_outputs_and_pending_authorization() -> None: + result = _seal_result(_result()) + validate_agent_result_v2(result) + pending = deepcopy(result) + pending["provenance"]["attempt_authorization_state"] = {"kind": "PENDING"} # type: ignore[index] + pending["result_sigil"] = content_sigil({key: value for key, value in pending.items() if key != "result_sigil"}) + with pytest.raises(AthanorError, match="pending"): + validate_agent_result_v2(pending) + unordered = deepcopy(result) + unordered["outputs"] = list(reversed(unordered["outputs"])) # type: ignore[index] + unordered["result_sigil"] = content_sigil({key: value for key, value in unordered.items() if key != "result_sigil"}) + with pytest.raises(AthanorError, match="ordered"): + validate_agent_result_v2(unordered) + + +def test_transition_request_requires_exact_authorization_and_result_bindings() -> None: + request = _request() + validate_agent_result_acceptance_transition_request_v1(request) + mismatch = deepcopy(request) + mismatch["managed_blob_sigils"] = ["sha256:" + "c" * 64] + mismatch["transition_request_sigil"] = content_sigil({key: value for key, value in mismatch.items() if key != "transition_request_sigil"}) + with pytest.raises(AthanorError, match="managed_blob_sigils"): + validate_agent_result_acceptance_transition_request_v1(mismatch) + + +def test_agent_result_record_v2_receipt_domain_is_closed() -> None: + record = {"schema_version": "agent-result-record/2.0", "task_id": "TK-ONE", "program_id": "RP-ONE", "task_capsule_sigil": SIGIL, "host_identity_sigil": SIGIL, "capability_binding": _result()["capability_binding"], "snapshot_binding": _result()["snapshot_binding"], "job_binding": _result()["job_binding"], "execution_specification_binding": _result()["execution_specification_binding"], "job_outcome_binding": _result()["job_outcome_binding"], "terminal_event_sigil": SIGIL, "selected_attempt_id": "AT-" + "0" * 26, "assurance_claim_sigil": SIGIL, "canonical_reference_binding": {"reference_intent_id": "RI-ONE", "reference_intent_record_sigil": SIGIL, "transition_request_id": "ATR-" + "A" * 64, "transition_request_sigil": SIGIL, "acceptance_storage_binding": _authorization(_seal_result(_result()))["acceptance_storage_binding"], "reference_set_id": "RS-ONE", "reference_set_sigil": SIGIL}, "terminal_source_binding": {"kind": "NOT_APPLICABLE"}, "outputs": _result()["outputs"], "provenance": _result()["provenance"], "status": "COMPLETED", "agent_result_sigil": SIGIL, "accepted_at": "2026-08-06T00:00:00Z", "acceptance_receipt": "RC-ABC1"} + validate_instance("agent-result-record-2.0.json", record) + record["acceptance_receipt"] = "RC-lower.case" + with pytest.raises(AthanorError, match="validation failed"): + validate_instance("agent-result-record-2.0.json", record) + + +def test_v2_acceptance_event_projects_record_from_exact_supplied_facts() -> None: + request = _request() + intent: dict[str, object] = { + "schema_version": "artifact-storage-reference-intent/1.0", "reference_intent_id": "", + "transition_request_id": request["transition_request_id"], "transition_request_sigil": request["transition_request_sigil"], + "canonical_event_type": "agent-result.accepted", "expected_chronicle_head": request["expected_chronicle_head"], + "reference_sets": request["reference_sets"], "blob_sigils": request["managed_blob_sigils"], "actor_id": "ACTOR", + "authorization_sigil": request["authorization_sigil"], "idempotency_key_sigil": request["idempotency_key_sigil"], + "requested_at": request["requested_at"], "record_sigil": "", + } + intent["reference_intent_id"] = "RI-" + content_sigil(["artifact-storage-reference-intent-id/1.0", "agent-result.accepted", request["transition_request_id"]]).removeprefix("sha256:").upper() + intent["record_sigil"] = content_sigil({key: value for key, value in intent.items() if key != "record_sigil"}) + result = request["agent_result"] + payload = {"agent_result": result, "program_id": result["program_id"], "host_identity_sigil": result["host_identity_sigil"], "capability_contract_sigil": result["capability_binding"]["capability_contract_sigil"], "snapshot_sigil": result["snapshot_binding"]["snapshot_sigil"], "task_capsule_sigil": result["task_capsule_sigil"], "job_outcome_sigil": result["job_outcome_binding"]["outcome_sigil"], "result_sigil": result["result_sigil"], "acceptance_request_sigil": request["acceptance_request_sigil"], "idempotency_key_sigil": request["idempotency_key_sigil"], "transition_request_id": request["transition_request_id"], "transition_request_sigil": request["transition_request_sigil"], "acceptance_storage_binding": request["acceptance_storage_binding"], "actor": request["actor"], "host_invocation": request["host_invocation"], "authorization_sigil": request["authorization_sigil"], "reference_intent_id": intent["reference_intent_id"], "reference_intent_record_sigil": intent["record_sigil"], "reference_set_id": intent["reference_sets"][0]["reference_set_id"], "reference_set_sigil": intent["reference_sets"][0]["reference_set_sigil"], "occurred_at": "2026-08-06T00:00:01Z"} + event: dict[str, object] = {"schema_version": "chronicle-event/1.1", "event_id": "CE-ONE", "sequence": 2, "type": "agent-result.accepted", "object_id": "TK-ONE", "occurred_at": "2026-08-06T00:00:01Z", "previous_receipt_sigil": SIGIL, "actor": request["chronicle_actor"], "payload": payload, "event_body_sigil": "", "receipt": {"schema_version": "receipt/1.1", "receipt_id": "RC-ONE", "event_id": "CE-ONE", "event_body_sigil": "", "previous_receipt_sigil": SIGIL, "accepted_at": "2026-08-06T00:00:01Z", "receipt_sigil": ""}} + event["event_body_sigil"] = content_sigil({key: value for key, value in event.items() if key not in {"event_body_sigil", "receipt"}}) + event["receipt"]["event_body_sigil"] = event["event_body_sigil"] # type: ignore[index] + event["receipt"]["receipt_sigil"] = content_sigil({key: value for key, value in event["receipt"].items() if key != "receipt_sigil"}) # type: ignore[index] + record = project_agent_result_record_v2_supplied_facts(event, request, intent) + assert record["schema_version"] == "agent-result-record/2.0" + tampered = deepcopy(event) + tampered["payload"]["reference_set_id"] = "RS-TWO" # type: ignore[index] + tampered["event_body_sigil"] = content_sigil({key: value for key, value in tampered.items() if key not in {"event_body_sigil", "receipt"}}) + tampered["receipt"]["event_body_sigil"] = tampered["event_body_sigil"] # type: ignore[index] + tampered["receipt"]["receipt_sigil"] = content_sigil({key: value for key, value in tampered["receipt"].items() if key != "receipt_sigil"}) # type: ignore[index] + with pytest.raises(AthanorError, match="payload disagrees"): + project_agent_result_record_v2_supplied_facts(tampered, request, intent) + exhausted_request = deepcopy(request) + exhausted_request["expected_chronicle_head"]["event_count"] = 9223372036854775807 # type: ignore[index] + exhausted_request["acceptance_authorization"]["expected_chronicle_head"] = exhausted_request["expected_chronicle_head"] # type: ignore[index] + exhausted_request["acceptance_authorization"]["ward_pass"]["evaluated_chronicle_head"] = exhausted_request["expected_chronicle_head"] # type: ignore[index] + exhausted_request["acceptance_authorization"]["authorization_sigil"] = content_sigil({key: value for key, value in exhausted_request["acceptance_authorization"].items() if key != "authorization_sigil"}) # type: ignore[index] + exhausted_request["authorization_sigil"] = exhausted_request["acceptance_authorization"]["authorization_sigil"] # type: ignore[index] + exhausted_request["transition_request_sigil"] = content_sigil({key: value for key, value in exhausted_request.items() if key != "transition_request_sigil"}) + exhausted_intent = deepcopy(intent) + exhausted_intent["expected_chronicle_head"] = exhausted_request["expected_chronicle_head"] + exhausted_intent["record_sigil"] = content_sigil({key: value for key, value in exhausted_intent.items() if key != "record_sigil"}) + exhausted_event = deepcopy(event) + exhausted_event["sequence"] = 9223372036854775808 + exhausted_event["previous_receipt_sigil"] = SIGIL + exhausted_event["payload"]["authorization_sigil"] = exhausted_request["authorization_sigil"] # type: ignore[index] + exhausted_event["payload"]["transition_request_sigil"] = exhausted_request["transition_request_sigil"] # type: ignore[index] + exhausted_event["payload"]["transition_request_id"] = exhausted_request["transition_request_id"] # type: ignore[index] + exhausted_event["payload"]["reference_intent_record_sigil"] = exhausted_intent["record_sigil"] # type: ignore[index] + exhausted_event["event_body_sigil"] = content_sigil({key: value for key, value in exhausted_event.items() if key not in {"event_body_sigil", "receipt"}}) + exhausted_event["receipt"]["event_body_sigil"] = exhausted_event["event_body_sigil"] # type: ignore[index] + exhausted_event["receipt"]["receipt_sigil"] = content_sigil({key: value for key, value in exhausted_event["receipt"].items() if key != "receipt_sigil"}) # type: ignore[index] + with pytest.raises(AthanorError, match="count-exhausted"): + project_agent_result_record_v2_supplied_facts(exhausted_event, exhausted_request, exhausted_intent) diff --git a/tests/test_artifact_storage_journal_v1_contract.py b/tests/test_artifact_storage_journal_v1_contract.py new file mode 100644 index 0000000..6f29ec2 --- /dev/null +++ b/tests/test_artifact_storage_journal_v1_contract.py @@ -0,0 +1,2797 @@ +import json +from copy import deepcopy +from typing import Any + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.artifact_storage_contracts import ( + derive_artifact_storage_reference_intent_id_v1, + derive_artifact_storage_reference_set_id_v1, + load_artifact_storage_journal_event_v1, + load_artifact_storage_journal_head_v1, + load_artifact_storage_disposition_v1, + load_artifact_gc_plan_v1, + load_artifact_provenance_v1, + load_artifact_provenance_policy_v1, + load_artifact_storage_backend_v1, + load_artifact_storage_doctor_report_v1, + load_artifact_transfer_v1, + load_artifact_retention_policy_v1, + load_artifact_storage_legacy_protection_v1, + load_artifact_storage_recovery_marker_v1, + load_artifact_storage_reference_intent_v1, + load_artifact_storage_reference_set_v1, + load_artifact_storage_tail_evidence_v1, + load_artifact_storage_state_v1, + require_artifact_storage_journal_replay_authority_v1, + require_artifact_storage_runtime_authority_v1, + replay_artifact_storage_initial_prefix_v1, + replay_artifact_storage_journal_prefix_v1, + validate_artifact_storage_journal_event_v1, + validate_artifact_storage_journal_head_supplied_event_v1, + validate_artifact_storage_journal_head_supplied_prefix_v1, + validate_artifact_storage_journal_head_v1, + validate_artifact_storage_journal_prefix_v1, + validate_artifact_storage_disposition_v1, + validate_artifact_gc_plan_v1, + validate_artifact_provenance_v1, + validate_artifact_provenance_policy_v1, + validate_artifact_storage_state_supplied_provenance_policies_v1, + validate_artifact_storage_backend_v1, + validate_artifact_storage_doctor_report_v1, + validate_artifact_transfer_v1, + validate_artifact_storage_state_supplied_transfers_v1, + validate_artifact_storage_state_supplied_transfer_attempts_v1, + validate_artifact_storage_state_supplied_provenance_v1, + validate_artifact_retention_policy_v1, + validate_artifact_storage_state_supplied_retention_policies_v1, + validate_artifact_storage_legacy_protection_v1, + validate_artifact_storage_recovery_marker_v1, + validate_artifact_storage_head_supplied_state_v1, + validate_artifact_storage_state_v1, + validate_artifact_storage_reference_intent_v1, + validate_artifact_storage_reference_set_v1, + validate_artifact_storage_state_supplied_control_records_v1, + validate_artifact_storage_state_supplied_reference_sets_v1, + validate_artifact_storage_tail_evidence_v1, + validate_canonical_reference_commit_supplied_facts_v1, + validate_canonical_reference_release_supplied_facts_v1, +) + + +SIGIL = "sha256:" + "a" * 64 +SIGIL_B = "sha256:" + "b" * 64 +STAMP = "2026-08-06T00:00:00Z" + + +def _event() -> dict[str, object]: + event: dict[str, object] = { + "schema_version": "artifact-storage-journal-event/1.0", + "journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_type": "storage.message_rejected", "coordinator_id": "COORDINATOR", + "epoch": 1, "recorded_at": STAMP, "observed_at": None, + "entity_revisions": [{ + "entity_type": "STORE", "entity_id": "STORE", "previous_revision": None, + "next_revision": 1, + }], "causation_event_id": None, "idempotency_key_sigil": None, + "quota_effects": [], "payload": { + "message_class": "test", "message_sigil": None, + "reason": {"code": "BACKEND_UNAVAILABLE", "evidence_sigils": []}, + }, "previous_event_sigil": None, "event_sigil": "", + } + event["event_sigil"] = content_sigil({ + key: member for key, member in event.items() if key != "event_sigil" + }) + return event + + +def _head(event: dict[str, object]) -> dict[str, object]: + return { + "schema_version": "artifact-storage-journal-head/1.0", "journal_id": "SJ-ONE", + "storage_format_version": "1.0", "event_count": 1, "last_sequence": 1, + "last_event_sigil": event["event_sigil"], "committed_byte_length": 1, + "current_epoch": 1, "state_sigil": SIGIL, "updated_at": STAMP, + } + + +def _next_event(previous: dict[str, object]) -> dict[str, object]: + event = _event() + event.update({ + "event_id": "SE-TWO", "sequence": 2, "recorded_at": "2026-08-06T00:00:01Z", + "previous_event_sigil": previous["event_sigil"], + }) + event["event_sigil"] = content_sigil({ + key: member for key, member in event.items() if key != "event_sigil" + }) + return event + + +def _initial_event() -> dict[str, object]: + event = _event() + event.update({ + "event_type": "storage.initialized", + "payload": { + "project_id": "PROJECT", "storage_format_version": "1.0", + "backend": {"schema_version": "backend/1.0", "record_id": "BACKEND", "record_sigil": SIGIL}, + "conformance_profile_id": "PROFILE", "conformance_suite_sigil": SIGIL, + "quota_snapshots": [], "tail_recovery": None, + "clock": { + "utc": STAMP, "monotonic_anchor_id": "CLOCK", "monotonic_ticks": 0, + "monotonic_frequency_hz": 1, "uncertainty_micros": 0, + "observation_sigil": SIGIL, + }, + }, + }) + event["event_sigil"] = content_sigil({ + key: member for key, member in event.items() if key != "event_sigil" + }) + return event + + +def _state() -> dict[str, object]: + quota_pairs = ( + ("JOURNAL", "JOURNAL_BYTE"), ("CONTROL_RECORD", "CONTROL_RECORD_BYTE"), + ("STAGING", "BYTE"), ("STAGING", "OBJECT"), ("QUARANTINE", "BYTE"), + ("QUARANTINE", "OBJECT"), ("COMMITTED", "BYTE"), ("COMMITTED", "OBJECT"), + ("MATERIALIZATION", "BYTE"), ("MATERIALIZATION", "OBJECT"), + ("STREAM", "STREAM"), ("INODE", "INODE"), + ) + clock = { + "utc": STAMP, "monotonic_anchor_id": "CLOCK", "monotonic_ticks": 0, + "monotonic_frequency_hz": 1, "uncertainty_micros": 0, "observation_sigil": SIGIL, + } + state: dict[str, object] = { + "schema_version": "artifact-storage-state/1.0", "journal_id": "SJ-ONE", + "storage_format_version": "1.0", "project_id": "PROJECT", "backend_profile_id": "BACKEND", + "backend_profile_sigil": SIGIL, "conformance_profile_id": "PROFILE", + "conformance_suite_sigil": SIGIL, "store_status": "INITIALIZING", + "active_recovery_id": None, "recovery_origin_status": None, "clock_status": "TRUSTED", + "clock_anchor": clock, "current_epoch": 1, "applied_event_count": 1, + "last_event_sigil": SIGIL_B, + "recoveries": [], "blobs": [], "replicas": [], "transfer_requests": [], + "transfer_attempts": [], "materializations": [], "quarantines": [], "provenance": [], + "provenance_policies": [], "retention_policies": [], "holds": [], "reference_sets": [], + "legacy_v1_protections": [], "gc_plans": [], "canonical_reference_intents": [], + "dispositions": [], "quota_reservations": [], "open_intents": [], "incidents": [], + "availability_counters": { + "available_blobs": 0, "degraded_blobs": 0, "unavailable_blobs": 0, + "incident_blobs": 0, + }, "quota_counters": [ + {"quota_class": kind, "dimension": dimension, "limit": 0, "used": 0, + "reserved": 0, "pressure_state": "CLEAR"} + for kind, dimension in quota_pairs + ], "state_sigil": "", + } + state["state_sigil"] = content_sigil({ + key: member for key, member in state.items() if key != "state_sigil" + }) + return state + + +def _initial_replay_event() -> dict[str, object]: + event = _initial_event() + pairs = ( + ("JOURNAL", "JOURNAL_BYTE"), ("CONTROL_RECORD", "CONTROL_RECORD_BYTE"), + ("STAGING", "BYTE"), ("STAGING", "OBJECT"), ("QUARANTINE", "BYTE"), + ("QUARANTINE", "OBJECT"), ("COMMITTED", "BYTE"), ("COMMITTED", "OBJECT"), + ("MATERIALIZATION", "BYTE"), ("MATERIALIZATION", "OBJECT"), + ("STREAM", "STREAM"), ("INODE", "INODE"), + ) + snapshots = [ + {"quota_class": quota_class, "dimension": dimension, "limit": 0, "used": 0, + "reserved": 0, "pressure_state": "CLEAR"} + for quota_class, dimension in pairs + ] + event["payload"]["quota_snapshots"] = snapshots # type: ignore[index] + event["quota_effects"] = [{"kind": "INITIALIZE", "snapshot": snapshot} for snapshot in snapshots] + event["entity_revisions"] = [ + {"entity_type": "STORE", "entity_id": "STORE", "previous_revision": None, "next_revision": 1}, + *[ + {"entity_type": "QUOTA", "entity_id": f"quota-counter:{quota_class}:{dimension}", + "previous_revision": None, "next_revision": 1} + for quota_class, dimension in pairs + ], + ] + event["event_sigil"] = content_sigil({key: value for key, value in event.items() if key != "event_sigil"}) + return event + + +def test_storage_initial_replay_builds_the_exact_empty_state() -> None: + event = _initial_replay_event() + state = replay_artifact_storage_initial_prefix_v1([event]) + assert state["journal_id"] == event["journal_id"] + assert state["store_status"] == "INITIALIZING" + assert state["current_epoch"] == 1 + assert state["last_event_sigil"] == event["event_sigil"] + assert state["quota_counters"] == event["payload"]["quota_snapshots"] + assert state["blobs"] == [] + + wrong_effects = deepcopy(event) + wrong_effects["quota_effects"] = [] + wrong_effects["event_sigil"] = content_sigil({ + key: value for key, value in wrong_effects.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="quota effects"): + replay_artifact_storage_initial_prefix_v1([wrong_effects]) + + recovered = deepcopy(event) + recovered["payload"]["tail_recovery"] = {"recovery_id": "RECOVERY"} # type: ignore[index] + recovered["event_sigil"] = content_sigil({ + key: value for key, value in recovered.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="validation failed|tail recovery"): + replay_artifact_storage_initial_prefix_v1([recovered]) + + +def test_storage_replay_activates_the_empty_initialized_store() -> None: + initial = _initial_replay_event() + activation = _next_event(initial) + activation["event_type"] = "storage.activation_completed" + activation["entity_revisions"] = [{ + "entity_type": "STORE", "entity_id": "STORE", "previous_revision": 1, "next_revision": 2, + }] + activation["payload"] = { + "legacy_protection_ids": [], "activation_evidence_sigil": SIGIL, + "clock": initial["payload"]["clock"], + } + activation["quota_effects"] = [] + activation["event_sigil"] = content_sigil({ + key: value for key, value in activation.items() if key != "event_sigil" + }) + state = replay_artifact_storage_journal_prefix_v1([initial, activation]) + assert state["store_status"] == "ACTIVE" + assert state["applied_event_count"] == 2 + assert state["last_event_sigil"] == activation["event_sigil"] + + wrong_revision = deepcopy(activation) + wrong_revision["entity_revisions"][0]["next_revision"] = 3 + wrong_revision["event_sigil"] = content_sigil({ + key: value for key, value in wrong_revision.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="invalid Store revision"): + replay_artifact_storage_journal_prefix_v1([initial, wrong_revision]) + + +def test_storage_replay_projects_exact_provenance_policy_record() -> None: + initial = _initial_replay_event() + activation = _next_event(initial) + activation["event_type"] = "storage.activation_completed" + activation["entity_revisions"] = [{ + "entity_type": "STORE", "entity_id": "STORE", "previous_revision": 1, + "next_revision": 2, + }] + activation["payload"] = { + "legacy_protection_ids": [], "activation_evidence_sigil": SIGIL, + "clock": initial["payload"]["clock"], + } + activation["quota_effects"] = [] + activation["event_sigil"] = content_sigil({ + key: value for key, value in activation.items() if key != "event_sigil" + }) + policy = _provenance_policy() + registered = _next_event(activation) + registered["event_id"] = "SE-THREE" + registered["sequence"] = 3 + policy["registered_at"] = registered["recorded_at"] + policy["record_sigil"] = content_sigil({ + key: value for key, value in policy.items() if key != "record_sigil" + }) + registered["event_type"] = "provenance.policy_registered" + registered["entity_revisions"] = [{ + "entity_type": "PROVENANCE_POLICY", "entity_id": policy["provenance_policy_id"], + "previous_revision": None, "next_revision": 1, + }] + registered["payload"] = {"provenance_policy": { + "schema_version": policy["schema_version"], + "record_id": policy["provenance_policy_id"], + "record_sigil": policy["record_sigil"], + }} + registered["quota_effects"] = [] + registered["event_sigil"] = content_sigil({ + key: value for key, value in registered.items() if key != "event_sigil" + }) + state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered], supplied_provenance_policies=[policy] + ) + assert state["provenance_policies"] == [{ + "provenance_policy_id": policy["provenance_policy_id"], + "record_sigil": policy["record_sigil"], "revision": 1, + "last_event_sigil": registered["event_sigil"], + }] + + mismatched = deepcopy(registered) + mismatched["payload"]["provenance_policy"]["record_sigil"] = SIGIL_B + mismatched["event_sigil"] = content_sigil({ + key: value for key, value in mismatched.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="registration Event disagrees with record"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, mismatched], supplied_provenance_policies=[policy] + ) + + extra = deepcopy(policy) + extra["provenance_policy_id"] = "SPP-EXTRA" + extra["record_sigil"] = content_sigil({ + key: value for key, value in extra.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="do not exactly match State projections"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered], supplied_provenance_policies=[policy, extra] + ) + + +def test_storage_replay_projects_only_exact_active_project_retention_policy() -> None: + initial = _initial_replay_event() + activation = _next_event(initial) + activation["event_type"] = "storage.activation_completed" + activation["entity_revisions"] = [{ + "entity_type": "STORE", "entity_id": "STORE", "previous_revision": 1, + "next_revision": 2, + }] + activation["payload"] = { + "legacy_protection_ids": [], "activation_evidence_sigil": SIGIL, + "clock": initial["payload"]["clock"], + } + activation["quota_effects"] = [] + activation["event_sigil"] = content_sigil({ + key: value for key, value in activation.items() if key != "event_sigil" + }) + policy = _retention_policy() + registered = _next_event(activation) + registered["event_id"] = "SE-THREE" + registered["sequence"] = 3 + policy["registered_at"] = registered["recorded_at"] + policy["record_sigil"] = content_sigil({ + key: value for key, value in policy.items() if key != "record_sigil" + }) + registered["event_type"] = "retention.policy_registered" + registered["entity_revisions"] = [{ + "entity_type": "RETENTION_POLICY", "entity_id": policy["policy_id"], + "previous_revision": None, "next_revision": 1, + }] + registered["payload"] = {"policy": { + "schema_version": policy["schema_version"], + "record_id": policy["policy_id"], + "record_sigil": policy["record_sigil"], + }} + registered["quota_effects"] = [] + registered["event_sigil"] = content_sigil({ + key: value for key, value in registered.items() if key != "event_sigil" + }) + state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered], supplied_retention_policies=[policy] + ) + assert state["retention_policies"] == [{ + "policy_id": policy["policy_id"], "record_sigil": policy["record_sigil"], + "revision": 1, "last_event_sigil": registered["event_sigil"], + }] + + for scope in ( + {"kind": "PROJECT", "project_id": "OTHER_PROJECT"}, + {"kind": "PROGRAM", "program_id": "PROGRAM"}, + {"kind": "BLOB", "blob_sigil": SIGIL}, + {"kind": "REFERENCE_SET", "reference_set_id": "RS-ONE", "reference_set_sigil": SIGIL}, + ): + wrong_scope = deepcopy(policy) + wrong_scope["scope"] = scope + wrong_scope["record_sigil"] = content_sigil({ + key: value for key, value in wrong_scope.items() if key != "record_sigil" + }) + wrong_event = deepcopy(registered) + wrong_event["payload"]["policy"]["record_sigil"] = wrong_scope["record_sigil"] + wrong_event["event_sigil"] = content_sigil({ + key: value for key, value in wrong_event.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="scope is not locally closed"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, wrong_event], supplied_retention_policies=[wrong_scope] + ) + + initializing_registration = deepcopy(registered) + initializing_registration["event_id"] = "SE-TWO" + initializing_registration["sequence"] = 2 + initializing_registration["previous_event_sigil"] = initial["event_sigil"] + policy_in_initializing = deepcopy(policy) + policy_in_initializing["registered_at"] = initializing_registration["recorded_at"] + policy_in_initializing["record_sigil"] = content_sigil({ + key: value for key, value in policy_in_initializing.items() if key != "record_sigil" + }) + initializing_registration["payload"]["policy"]["record_sigil"] = policy_in_initializing["record_sigil"] + initializing_registration["event_sigil"] = content_sigil({ + key: value for key, value in initializing_registration.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="requires an active Store"): + replay_artifact_storage_journal_prefix_v1( + [initial, initializing_registration], supplied_retention_policies=[policy_in_initializing] + ) + + wrong_ref = deepcopy(registered) + wrong_ref["payload"]["policy"]["record_id"] = "SP-OTHER" + wrong_ref["event_sigil"] = content_sigil({ + key: value for key, value in wrong_ref.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="requires exactly one supplied record"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, wrong_ref], supplied_retention_policies=[policy] + ) + + extra = deepcopy(policy) + extra["policy_id"] = "SP-EXTRA" + extra["record_sigil"] = content_sigil({ + key: value for key, value in extra.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="do not exactly match State projections"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered], supplied_retention_policies=[policy, extra] + ) + + +def test_storage_replay_retains_failed_legacy_protection_and_blocks_activation() -> None: + initial = _initial_replay_event() + failed = _next_event(initial) + failed["event_type"] = "legacy_v1.protection_failed" + failed["entity_revisions"] = [{ + "entity_type": "LEGACY_PROTECTION", "entity_id": "PROTECTION", + "previous_revision": None, "next_revision": 1, + }] + failed["quota_effects"] = [] + failed["payload"] = { + "protection_id": "PROTECTION", "artifact_id": "ARTIFACT", + "receipt_sigil": None, + "reason": {"code": "BACKEND_UNAVAILABLE", "evidence_sigils": []}, + } + failed["event_sigil"] = content_sigil({ + key: value for key, value in failed.items() if key != "event_sigil" + }) + failed_state = replay_artifact_storage_journal_prefix_v1([initial, failed]) + assert failed_state["legacy_v1_protections"] == [{ + "protection_id": "PROTECTION", "artifact_id": "ARTIFACT", + "state": "FAILED", "record": None, "receipt_sigil": None, + "reason": failed["payload"]["reason"], "revision": 1, + "last_event_sigil": failed["event_sigil"], + }] + + activation = _next_event(failed) + activation["event_id"] = "SE-THREE" + activation["sequence"] = 3 + activation["event_type"] = "storage.activation_completed" + activation["entity_revisions"] = [{ + "entity_type": "STORE", "entity_id": "STORE", "previous_revision": 1, "next_revision": 2, + }] + activation["quota_effects"] = [] + activation["payload"] = { + "legacy_protection_ids": ["PROTECTION"], "activation_evidence_sigil": SIGIL, + "clock": initial["payload"]["clock"], + } + activation["event_sigil"] = content_sigil({ + key: value for key, value in activation.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="failed legacy protection"): + replay_artifact_storage_journal_prefix_v1([initial, failed, activation]) + + duplicate = deepcopy(failed) + duplicate["event_id"] = "SE-FOUR" + duplicate["sequence"] = 3 + duplicate["previous_event_sigil"] = failed["event_sigil"] + duplicate["event_sigil"] = content_sigil({ + key: value for key, value in duplicate.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="disagrees"): + replay_artifact_storage_journal_prefix_v1([initial, failed, duplicate]) + + +def test_storage_replay_completes_an_empty_recovery_to_its_frozen_origin() -> None: + initial = _initial_replay_event() + activation = _next_event(initial) + activation["event_type"] = "storage.activation_completed" + activation["entity_revisions"] = [{ + "entity_type": "STORE", "entity_id": "STORE", + "previous_revision": 1, "next_revision": 2, + }] + activation["payload"] = { + "legacy_protection_ids": [], "activation_evidence_sigil": SIGIL, + "clock": initial["payload"]["clock"], + } + activation["quota_effects"] = [] + activation["event_sigil"] = content_sigil({ + key: value for key, value in activation.items() if key != "event_sigil" + }) + started = _next_event(activation) + started.update({ + "event_id": "SE-THREE", "sequence": 3, "event_type": "storage.recovery_started", + "epoch": 2, "recorded_at": "2026-08-06T00:00:02Z", + "observed_at": "2026-08-06T00:00:01Z", + "entity_revisions": [{ + "entity_type": "STORE", "entity_id": "STORE", + "previous_revision": 2, "next_revision": 3, + }], + "quota_effects": [], + "payload": { + "recovery_id": "RECOVERY", "origin_status": "ACTIVE", + "previous_epoch": 1, "next_epoch": 2, "tail_recovery": None, + "open_intent_ids": [], + "clock": {**initial["payload"]["clock"], "utc": "2026-08-06T00:00:01Z"}, + }, + }) + started["event_sigil"] = content_sigil({ + key: value for key, value in started.items() if key != "event_sigil" + }) + recovering = replay_artifact_storage_journal_prefix_v1([initial, activation, started]) + assert recovering["store_status"] == "RECOVERING" + assert recovering["active_recovery_id"] == "RECOVERY" + restarted = _next_event(started) + restarted.update({ + "event_id": "SE-RESTART", "sequence": 4, "event_type": "storage.epoch_started", + "epoch": 3, "recorded_at": "2026-08-06T00:00:03Z", + "observed_at": "2026-08-06T00:00:02Z", + "entity_revisions": [{ + "entity_type": "STORE", "entity_id": "STORE", + "previous_revision": 3, "next_revision": 4, + }], "quota_effects": [], + "payload": { + "previous_epoch": 2, "next_epoch": 3, "active_recovery_id": "RECOVERY", + "tail_recovery": None, + "reason": {"code": "BACKEND_UNAVAILABLE", "evidence_sigils": []}, + "clock": {**started["payload"]["clock"], "utc": "2026-08-06T00:00:02Z"}, + }, + }) + restarted["event_sigil"] = content_sigil({ + key: value for key, value in restarted.items() if key != "event_sigil" + }) + restarted_state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, started, restarted] + ) + assert restarted_state["current_epoch"] == 3 + assert restarted_state["recoveries"][0]["epoch_ids"] == [2, 3] + completed = _next_event(started) + completed.update({ + "event_id": "SE-FOUR", "sequence": 4, "event_type": "storage.recovery_completed", + "epoch": 2, "recorded_at": "2026-08-06T00:00:03Z", + "observed_at": "2026-08-06T00:00:02Z", + "entity_revisions": [{ + "entity_type": "STORE", "entity_id": "STORE", + "previous_revision": 3, "next_revision": 4, + }], + "quota_effects": [], + "payload": { + "recovery_id": "RECOVERY", "epoch": 2, "resume_status": "ACTIVE", + "resolved_intent_ids": [], "evidence_sigils": [], + "clock": {**started["payload"]["clock"], "utc": "2026-08-06T00:00:02Z"}, + }, + }) + completed["event_sigil"] = content_sigil({ + key: value for key, value in completed.items() if key != "event_sigil" + }) + state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, started, completed] + ) + assert state["store_status"] == "ACTIVE" + assert state["active_recovery_id"] is None + assert state["recoveries"][0]["state"] == "COMPLETED" + + wrong_origin = deepcopy(completed) + wrong_origin["payload"]["resume_status"] = "INITIALIZING" + wrong_origin["event_sigil"] = content_sigil({ + key: value for key, value in wrong_origin.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="recovery completion"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, started, wrong_origin] + ) + + later_rejection = _next_event(completed) + later_rejection.update({ + "event_id": "SE-FIVE", "sequence": 5, + "recorded_at": "2026-08-06T00:00:04Z", "epoch": 2, + "entity_revisions": [], "quota_effects": [], "observed_at": None, + "payload": { + "message_class": "test", "message_sigil": None, + "reason": {"code": "BACKEND_UNAVAILABLE", "evidence_sigils": []}, + }, + }) + later_rejection["event_sigil"] = content_sigil({ + key: value for key, value in later_rejection.items() if key != "event_sigil" + }) + assert replay_artifact_storage_journal_prefix_v1( + [initial, activation, started, completed, later_rejection] + )["applied_event_count"] == 5 + + +def test_storage_replay_applies_empty_clock_gate_round_trip() -> None: + initial = _initial_replay_event() + activation = _next_event(initial) + activation["event_type"] = "storage.activation_completed" + activation["entity_revisions"] = [{ + "entity_type": "STORE", "entity_id": "STORE", "previous_revision": 1, "next_revision": 2, + }] + activation["payload"] = {"legacy_protection_ids": [], "activation_evidence_sigil": SIGIL, "clock": initial["payload"]["clock"]} + activation["quota_effects"] = [] + activation["event_sigil"] = content_sigil({key: value for key, value in activation.items() if key != "event_sigil"}) + uncertain = _next_event(activation) + uncertain["event_type"] = "storage.clock_uncertain" + uncertain["event_id"] = "SE-THREE" + uncertain["sequence"] = 3 + uncertain["recorded_at"] = "2026-08-06T00:00:02Z" + detected_clock = {**initial["payload"]["clock"], "utc": "2026-08-06T00:00:01Z"} + uncertain.update({ + "observed_at": detected_clock["utc"], + "entity_revisions": [{"entity_type": "STORE", "entity_id": "STORE", "previous_revision": 2, "next_revision": 3}], + "quota_effects": [], + "payload": {"previous_clock": initial["payload"]["clock"], "detected_clock": detected_clock, + "divergence_micros": 1, "affected_reservation_ids": [], + "reason": {"code": "CLOCK_UNCERTAIN", "evidence_sigils": []}}, + }) + uncertain["event_sigil"] = content_sigil({key: value for key, value in uncertain.items() if key != "event_sigil"}) + restored = _next_event(uncertain) + restored["event_type"] = "storage.clock_restored" + restored["event_id"] = "SE-FOUR" + restored["sequence"] = 4 + restored["recorded_at"] = "2026-08-06T00:00:03Z" + restored.update({ + "observed_at": "2026-08-06T00:00:02Z", + "entity_revisions": [{"entity_type": "STORE", "entity_id": "STORE", "previous_revision": 3, "next_revision": 4}], + "quota_effects": [], + "payload": {"previous_observation_sigil": detected_clock["observation_sigil"], + "new_clock": {**detected_clock, "utc": "2026-08-06T00:00:02Z"}, + "expired_entity_ids": [], "evidence_sigils": []}, + }) + restored["event_sigil"] = content_sigil({key: value for key, value in restored.items() if key != "event_sigil"}) + uncertain_state = replay_artifact_storage_journal_prefix_v1([initial, activation, uncertain]) + assert uncertain_state["clock_status"] == "UNCERTAIN" + state = replay_artifact_storage_journal_prefix_v1([initial, activation, uncertain, restored]) + assert state["clock_status"] == "TRUSTED" + assert state["clock_anchor"] == restored["payload"]["new_clock"] + head = _head(restored) + head.update({"event_count": 4, "last_sequence": 4, "current_epoch": 1, "state_sigil": state["state_sigil"]}) + replay_artifact_storage_journal_prefix_v1([initial, activation, uncertain, restored], head=head) + + wrong_anchor = deepcopy(uncertain) + wrong_anchor["payload"]["previous_clock"]["utc"] = "2026-08-06T00:00:01Z" + wrong_anchor["event_sigil"] = content_sigil({key: value for key, value in wrong_anchor.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="clock uncertainty"): + replay_artifact_storage_journal_prefix_v1([initial, activation, wrong_anchor]) + + +def test_storage_replay_advances_a_no_recovery_epoch() -> None: + initial = _initial_replay_event() + activation = _next_event(initial) + activation["event_type"] = "storage.activation_completed" + activation["entity_revisions"] = [{"entity_type": "STORE", "entity_id": "STORE", "previous_revision": 1, "next_revision": 2}] + activation["payload"] = {"legacy_protection_ids": [], "activation_evidence_sigil": SIGIL, "clock": initial["payload"]["clock"]} + activation["quota_effects"] = [] + activation["event_sigil"] = content_sigil({key: value for key, value in activation.items() if key != "event_sigil"}) + epoch = _next_event(activation) + epoch.update({ + "event_id": "SE-THREE", "sequence": 3, "event_type": "storage.epoch_started", "epoch": 2, + "recorded_at": "2026-08-06T00:00:02Z", "observed_at": "2026-08-06T00:00:01Z", + "entity_revisions": [{"entity_type": "STORE", "entity_id": "STORE", "previous_revision": 2, "next_revision": 3}], + "quota_effects": [], + "payload": {"previous_epoch": 1, "next_epoch": 2, "active_recovery_id": None, + "tail_recovery": None, "reason": {"code": "BACKEND_UNAVAILABLE", "evidence_sigils": []}, + "clock": {**initial["payload"]["clock"], "utc": "2026-08-06T00:00:01Z"}}, + }) + epoch["event_sigil"] = content_sigil({key: value for key, value in epoch.items() if key != "event_sigil"}) + state = replay_artifact_storage_journal_prefix_v1([initial, activation, epoch]) + assert state["current_epoch"] == 2 + assert state["clock_anchor"] == epoch["payload"]["clock"] + + wrong_epoch = deepcopy(epoch) + wrong_epoch["payload"]["next_epoch"] = 3 + wrong_epoch["event_sigil"] = content_sigil({key: value for key, value in wrong_epoch.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="epoch Event"): + replay_artifact_storage_journal_prefix_v1([initial, activation, wrong_epoch]) + + +def test_storage_replay_records_an_auditable_rejected_message() -> None: + initial = _initial_replay_event() + activation = _next_event(initial) + activation["event_type"] = "storage.activation_completed" + activation["entity_revisions"] = [{"entity_type": "STORE", "entity_id": "STORE", "previous_revision": 1, "next_revision": 2}] + activation["payload"] = {"legacy_protection_ids": [], "activation_evidence_sigil": SIGIL, "clock": initial["payload"]["clock"]} + activation["quota_effects"] = [] + activation["event_sigil"] = content_sigil({key: value for key, value in activation.items() if key != "event_sigil"}) + rejected = _next_event(activation) + rejected.update({ + "event_id": "SE-THREE", "sequence": 3, "event_type": "storage.message_rejected", + "recorded_at": "2026-08-06T00:00:02Z", "observed_at": None, "entity_revisions": [], "quota_effects": [], + "causation_event_id": None, "idempotency_key_sigil": None, + "payload": {"message_class": "untrusted", "message_sigil": None, + "reason": {"code": "INVALID_MESSAGE", "evidence_sigils": []}}, + }) + rejected["event_sigil"] = content_sigil({key: value for key, value in rejected.items() if key != "event_sigil"}) + state = replay_artifact_storage_journal_prefix_v1([initial, activation, rejected]) + assert state["applied_event_count"] == 3 + assert state["last_event_sigil"] == rejected["event_sigil"] + assert state["blobs"] == [] + + unexpected_effect = deepcopy(rejected) + unexpected_effect["quota_effects"] = [{"kind": "INITIALIZE", "snapshot": initial["payload"]["quota_snapshots"][0]}] + unexpected_effect["event_sigil"] = content_sigil({key: value for key, value in unexpected_effect.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="message rejection Event"): + replay_artifact_storage_journal_prefix_v1([initial, activation, unexpected_effect]) + + +def _reference_set() -> dict[str, object]: + reference_set: dict[str, object] = { + "schema_version": "artifact-storage-reference-set/1.0", "reference_set_id": "", + "source": {"kind": "CANONICAL_OBJECT", "identity": "SOURCE", + "schema_version": "artifact/1.0", "sigil": SIGIL}, + "extractor": {"extractor_id": "EXTRACTOR", "extractor_version": "1.0", + "extractor_sigil": SIGIL}, "edges": [], + "validation": {"validator_id": "VALIDATOR", "validator_version": "1.0", + "validator_sigil": SIGIL, "source_validation_sigil": SIGIL, + "evidence_sigils": [SIGIL]}, "registration_event_id": "", + "created_at": STAMP, "reference_set_sigil": "", + } + reference_set["reference_set_id"] = derive_artifact_storage_reference_set_id_v1(reference_set) + reference_set["registration_event_id"] = "SE-" + content_sigil([ + "artifact-storage-reference-set-registration-event-id/1.0", + reference_set["reference_set_id"], + ]).removeprefix("sha256:").upper() + reference_set["reference_set_sigil"] = content_sigil({ + key: member for key, member in reference_set.items() if key != "reference_set_sigil" + }) + return reference_set + + +def _legacy_protection() -> dict[str, object]: + protection: dict[str, object] = { + "schema_version": "artifact-storage-legacy-protection/1.0", "protection_id": "PROTECTION", + "artifact_id": "ARTIFACT", "program_id": "PROGRAM", "artifact_receipt_sigil": SIGIL, + "recorded_uri_sigil": SIGIL, "lexical_identity_sigil": SIGIL, + "resolved_file_identity_sigil": SIGIL, "anchor_observation_sigil": SIGIL, + "blob": {"blob_sigil": SIGIL, "size_bytes": 1}, "protected_replica_id": "SR-ONE", + "transfer": {"transfer_id": "ST-ONE", "transfer_attempt_id": "SA-ONE", + "request_record_sigil": SIGIL, "attempt_record_sigil": SIGIL, + "terminal_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", + "sequence": 1, "event_sigil": SIGIL}}, + "verification": {"method": "FULL_READBACK_SHA256", "evidence_sigil": SIGIL, + "verified_at": STAMP, "next_due_at": None}, + "exclusion": {"anchor_disposition": "PERMANENTLY_EXCLUDED", + "managed_copy_gc": "PERMANENTLY_PROTECTED", "policy_id": "SP-ONE", + "authorization_sigil": SIGIL}, "registered_at": STAMP, "record_sigil": "", + } + protection["record_sigil"] = content_sigil({ + key: member for key, member in protection.items() if key != "record_sigil" + }) + return protection + + +def _tail_evidence() -> dict[str, object]: + evidence: dict[str, object] = { + "schema_version": "artifact-storage-tail-evidence/1.0", "evidence_id": "EVIDENCE", + "recovery_id": "RECOVERY", "journal_id": "SJ-ONE", + "kind": "ORIGINAL_INTERRUPTED_APPEND", "frame_start": 1, "observed_size": 1, + "observed_bytes_sigil": SIGIL, "previous_evidence_record_sigil": None, + "created_at": STAMP, "record_sigil": "", + } + evidence["record_sigil"] = content_sigil({ + key: member for key, member in evidence.items() if key != "record_sigil" + }) + return evidence + + +def _disposition() -> dict[str, object]: + disposition: dict[str, object] = { + "schema_version": "artifact-storage-disposition/1.0", "disposition_id": "SD-ONE", + "target_kind": "STAGING", "target_id": "SA-ONE", "target_generation": "GENERATION", + "expected_blob_sigil": None, + "expected_size_or_bound": {"kind": "UPPER_BOUND", "max_size_bytes": 1}, + "reason_code": "POLICY_REJECTED", "actor_id": "ACTOR", "policy_sigil": SIGIL, + "approval_evidence_sigil": SIGIL, "authorization_sigil": SIGIL, + "authorized_at": STAMP, "expires_at": "2026-08-06T00:00:01Z", + "idempotency_key_sigil": SIGIL, "record_sigil": "", + } + disposition["record_sigil"] = content_sigil({ + key: member for key, member in disposition.items() if key != "record_sigil" + }) + return disposition + + +def _retention_policy() -> dict[str, object]: + policy: dict[str, object] = { + "schema_version": "artifact-retention-policy/1.0", "policy_id": "SP-ONE", + "scope": {"kind": "PROJECT", "project_id": "PROJECT"}, "minimum_replica_count": 0, + "required_backends": [], "required_failure_domains": [], + "maximum_integrity_age_seconds": None, "deletion_grace_seconds": 0, + "retain_until": None, "automatic_gc_allowed": True, "authorization_sigil": SIGIL, + "registered_at": STAMP, "record_sigil": "", + } + policy["record_sigil"] = content_sigil({ + key: member for key, member in policy.items() if key != "record_sigil" + }) + return policy + + +def _gc_plan() -> dict[str, object]: + bounds = { + "max_roots": 1, "max_nodes": 1, "max_edges": 1, "max_depth": 1, + "max_control_record_bytes": 1, "max_wall_millis": 1, + } + plan: dict[str, object] = { + "schema_version": "artifact-gc-plan/1.0", "gc_plan_id": "SG-ONE", "policy_id": "SP-ONE", + "root_snapshot": { + "chronicle_head": {"schema_version": "chronicle-head/1.1", "event_count": 0, + "terminal_receipt_sigil": None}, + "storage_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, + "execution_roots": {"execution_journal_id": "EXECUTION", "execution_event_count": 0, + "execution_last_event_sigil": None, "roots": [], "root_set_sigil": SIGIL}, + "hold_set_sigil": SIGIL, "legacy_protection_set_sigil": SIGIL, + "reference_intent_set_sigil": SIGIL, "reference_set_sigils": [], "policy_set_sigil": SIGIL, + }, "extractor_suite_sigil": SIGIL, "bounds": bounds, + "closure_proof": {"root_set_sigil": SIGIL, "extractor_suite_sigil": SIGIL, + "bounds": bounds, "visited_node_count": 0, "visited_edge_count": 0, + "cycle_summary_sigil": SIGIL, "reachable_blob_sigils": [], + "reachable_replica_ids": [], "proof_sigil": SIGIL}, + "targets": [], "created_at": STAMP, "grace_ends_at": "2026-08-06T00:00:01Z", + "record_sigil": "", + } + plan["record_sigil"] = content_sigil({ + key: member for key, member in plan.items() if key != "record_sigil" + }) + return plan + + +def _provenance() -> dict[str, object]: + backend = {"backend_id": "BACKEND", "backend_profile_version": "1.0", + "backend_profile_sigil": SIGIL} + object_ref = {"backend_id": "BACKEND", "object_identity_sigil": SIGIL, + "locator_sigil": SIGIL, "generation": "GENERATION", "size_bytes": 1, + "blob_sigil": SIGIL} + event = {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL} + provenance: dict[str, object] = { + "schema_version": "artifact-provenance/1.0", "provenance_id": "PROVENANCE", + "relation": "IMPORTED", "blob": {"blob_sigil": SIGIL, "size_bytes": 1}, + "source": {"kind": "EXTERNAL", "source_class": "SOURCE", + "sanitized_identity_sigil": SIGIL, "authorization_sigil": SIGIL}, + "destination": {"kind": "MANAGED_BACKEND", "backend": backend}, "actor_id": "ACTOR", + "authorization_sigil": SIGIL, "execution": {"kind": "NONE"}, "backend": backend, + "transfer": {"transfer_id": "ST-ONE", "transfer_attempt_id": "SA-ONE", + "request_record_sigil": SIGIL, "attempt_record_sigil": SIGIL, + "terminal_event": event}, + "provenance_policy": {"provenance_policy_id": "SPP-ONE", "provenance_policy_sigil": SIGIL}, + "verifications": [{"event": event, "replica_id": "SR-ONE", + "blob": {"blob_sigil": SIGIL, "size_bytes": 1}, "backend": backend, + "backend_object": object_ref, + "verification": {"method": "FULL_READBACK_SHA256", + "evidence_sigil": SIGIL, "verified_at": STAMP, + "next_due_at": None}}], + "transformation": {"kind": "NONE"}, + "times": {"observed_at": None, "started_at": STAMP, "committed_at": STAMP, + "verified_at": STAMP, "terminal_at": STAMP}, "terminal_reason": None, + "record_sigil": "", + } + provenance["record_sigil"] = content_sigil({ + key: member for key, member in provenance.items() if key != "record_sigil" + }) + return provenance + + +def _backend_profile() -> dict[str, object]: + reserve_classes = ( + "INITIALIZATION", "COORDINATOR_LIVENESS", "CLOCK_PRESSURE", + "CATALOG_ADMINISTRATION", "VERIFICATION_INCIDENT", "RETENTION_REFERENCE", + "GC_ADMINISTRATION", "RECOVERY", + ) + profile: dict[str, object] = { + "schema_version": "artifact-storage-backend/1.0", "backend_id": "BACKEND", + "adapter_id": "ADAPTER", "adapter_version": "1.0", "protocol_version": "1.0", + "adapter_sigil": SIGIL, "configuration_sigil": SIGIL, "namespace_sigil": SIGIL, + "isolation": {"scope": "SINGLE_PROJECT", "namespace_enforcement": "ADAPTER_SCOPED", + "worker_access": "NONE", "worker_credentials_exposed": False}, + "limits": {"max_object_bytes": 1, + "transfer_bounds": {"max_bytes": 1, "max_duration_millis": 1, + "max_file_count": None, "max_chunk_count": 1, "buffer_bytes": 1}, + "max_concurrent_streams": 1, "max_inventory_entries": 1, + "max_tail_recovery_retries": 1, + "system_reserve_limits": [{"reserve_class": item, "max_event_frame_count": 1, + "max_control_record_count": 0, + "max_recovery_evidence_count": 0, + "max_event_frame_bytes": 56, + "max_control_record_bytes": 1, + "max_recovery_evidence_bytes": 1} + for item in reserve_classes], + "system_journal_reserve_bytes": 1, "system_control_record_reserve_bytes": 1, + "system_recovery_reserve_bytes": 1}, + "consistency": {"read_after_write": "STRONG", "list_consistency": "STRONG", + "atomic_visibility": True, "immutable_generation": True, + "exact_generation_reads": True}, + "durability": {"commit_semantics": "FSYNC_FILE_AND_PARENT", "logical_readback": True, + "transparent_encryption": False, "transparent_compression": False}, + "verification_methods": ["CONFORMANCE_END_TO_END", "FULL_READBACK_SHA256"], + "range_resume": {"range_reads": False, "resumable_stage_writes": False, + "resume_binding": "UNSUPPORTED"}, + "conditional_operations": {"conditional_create": True, "no_overwrite_finalize": True, + "exact_generation_stat": True, "exact_generation_delete": True}, + "deletion_capabilities": {"exact_generation_delete": True, "wildcard_delete": False, + "retention_lock": "NONE", "verification": "POST_DELETE_STAT"}, + "credential_class": "COORDINATOR_HOST_LOCAL", + "fencing": {"mode": "COORDINATOR_PRECOMMIT", "attempt_staging_isolated": True, + "executor_epoch_checked": True, "job_fence_floor_checked": True, + "tombstone_checked": True}, + "conformance": {"profile_id": "LOCAL-PHASE3/1.0", "suite_version": "1.0", + "suite_sigil": SIGIL, "host_platform_sigil": SIGIL, "evidence_sigil": SIGIL}, + "record_sigil": "", + } + profile["record_sigil"] = content_sigil({ + key: member for key, member in profile.items() if key != "record_sigil" + }) + return profile + + +def _provenance_policy() -> dict[str, object]: + policy: dict[str, object] = { + "schema_version": "artifact-provenance-policy/1.0", "provenance_policy_id": "SPP-ONE", + "policy_version": "1.0", "scope": {"kind": "PROJECT", "project_id": "PROJECT"}, + "allowed_directions": ["INGEST"], "allowed_purposes": ["ARTIFACT_IMPORT"], + "allowed_source_kinds": ["EXTERNAL"], "allowed_destination_kinds": ["MANAGED_BACKEND"], + "allowed_relations": ["IMPORTED"], "execution_requirement": "OPTIONAL", + "allowed_verification_methods": ["FULL_READBACK_SHA256"], + "minimum_verification_evidence": 1, "transformation_mode": "NONE_ONLY", + "required_retention_policy_ids": [], "authorization_sigil": SIGIL, + "registered_at": STAMP, "record_sigil": "", + } + policy["record_sigil"] = content_sigil({ + key: member for key, member in policy.items() if key != "record_sigil" + }) + return policy + + +def _doctor_report() -> dict[str, object]: + check = {"check_id": "CHECK", "status": "INCOMPLETE", "subject_kind": "JOURNAL", + "subject_id": "SJ-ONE", "evidence_sigils": [], "reason": None} + report: dict[str, object] = { + "schema_version": "artifact-storage-doctor-report/1.0", "report_id": "REPORT", + "mode": "NORMAL", "project_id": "PROJECT", "storage_journal_id": None, + "journal_head_sigil": None, "chronicle_head_sigil": None, + "storage_format_version": None, "backend_profile_id": None, + "backend_profile_sigil": None, "conformance_profile_id": None, + "conformance_suite_sigil": None, "coordinator_epoch": None, + "journal_verification": check, "state_verification": check, + "backend_inventory": [], "replica_checks": [], "legacy_checks": [], + "quarantine_checks": [], "quota_checks": [], "reference_checks": [], + "open_intent_checks": [], + "bounds": {"max_inventory_entries": 0, "max_control_records": 0, + "max_rehash_bytes": 0, "max_wall_millis": 0, + "inventory_truncated": False, "rehash_truncated": False}, + "incomplete_reasons": [], "overall_status": "INCOMPLETE", + "started_at": STAMP, "completed_at": STAMP, "report_sigil": "", + } + report["report_sigil"] = content_sigil({ + key: member for key, member in report.items() if key != "report_sigil" + }) + return report + + +def _transfer() -> dict[str, object]: + backend = {"backend_id": "BACKEND", "backend_profile_version": "1.0", + "backend_profile_sigil": SIGIL} + execution = { + "kind": "LEASED", "execution_journal_id": "EXECUTION", "executor_epoch": 1, + "job_id": "JOB", "attempt_id": "ATTEMPT", "lease_id": "LEASE", "worker_id": "WORKER", + "worker_session_id": "SESSION", + "fence": {"execution_journal_id": "EXECUTION", "executor_epoch": 1, "job_id": "JOB", + "attempt_id": "ATTEMPT", "lease_id": "LEASE", "fencing_generation": 0, + "execution_event_sigil": SIGIL, "job_fence_floor": 0, "tombstone_present": False}, + } + transfer: dict[str, object] = { + "schema_version": "artifact-transfer/1.0", "transfer_id": "ST-ONE", "direction": "INGEST", + "purpose": "ATTEMPT_OUTPUT", + "source": {"kind": "ATTEMPT_OUTPUT", "execution": execution, "output_handle_id": "OUTPUT"}, + "destination": {"kind": "MANAGED_BACKEND", "backend": backend}, "expected_blob_sigil": SIGIL, + "bounds": {"max_bytes": 1, "max_duration_millis": 1, "max_file_count": None, + "max_chunk_count": 1, "buffer_bytes": 1}, "backend": backend, + "authorization_sigil": SIGIL, "idempotency_key_sigil": SIGIL, "execution": execution, + "verification_method": "FULL_READBACK_SHA256", + "provenance_policy": {"provenance_policy_id": "SPP-ONE", "provenance_policy_sigil": SIGIL}, + "retention_policy_ids": [], "created_at": STAMP, "record_sigil": "", + } + transfer["record_sigil"] = content_sigil({ + key: member for key, member in transfer.items() if key != "record_sigil" + }) + return transfer + + +def _transfer_attempt() -> dict[str, object]: + clock = {"utc": STAMP, "monotonic_anchor_id": "CLOCK", "monotonic_ticks": 0, + "monotonic_frequency_hz": 1, "uncertainty_micros": 0, + "observation_sigil": SIGIL} + attempt: dict[str, object] = { + "schema_version": "artifact-transfer-attempt/1.0", "transfer_attempt_id": "SA-ONE", + "transfer_id": "ST-ONE", "attempt_number": 1, "state": "PREPARED", + "staging_state": "NOT_CREATED", + "reservation": {"reservation_id": "RESERVATION", "claims": [], + "capacity_plan": {"allowed_event_types": [], "max_event_frame_count": 1, + "max_control_record_count": 0, + "max_recovery_evidence_count": 0, "max_event_frame_bytes": 1, + "max_control_record_bytes": 1, "max_recovery_evidence_bytes": 1}, + "expires_at": None, "created_clock": clock, + "remaining_micros_at_creation": None}, + "staging_object": None, "commit_intent": None, + "residual_staging_cleanup": {"state": "NOT_REQUIRED", "staging_object": None, + "evidence_sigil": None, "reason": None}, + "computed_blob_sigil": None, "computed_size_bytes": None, "selected_replica_id": None, + "quarantine_id": None, "terminal_reason": None, "started_at": STAMP, "terminal_at": None, + "revision": 1, "record_sigil": "", + } + attempt["record_sigil"] = content_sigil({ + key: member for key, member in attempt.items() if key != "record_sigil" + }) + return attempt + + +def _materialization() -> dict[str, object]: + clock = {"utc": STAMP, "monotonic_anchor_id": "CLOCK", "monotonic_ticks": 0, + "monotonic_frequency_hz": 1, "uncertainty_micros": 0, + "observation_sigil": SIGIL} + materialization: dict[str, object] = { + "schema_version": "artifact-materialization/1.0", "materialization_id": "SM-ONE", + "source_blob_sigil": SIGIL, "source_replica_id": "SR-ONE", + "source_verification_sigil": SIGIL, "destination_class": "SANCTUM_INPUT", + "destination_sigil": SIGIL, "task_id": None, "attempt_id": None, + "access_mode": "READ_ONLY", + "bounds": {"max_bytes": 0, "max_duration_millis": 1, "max_file_count": None, + "max_chunk_count": 1, "buffer_bytes": 1}, + "reservation": {"reservation_id": "RESERVATION", "claims": [], + "capacity_plan": {"allowed_event_types": [], "max_event_frame_count": 1, + "max_control_record_count": 0, + "max_recovery_evidence_count": 0, "max_event_frame_bytes": 1, + "max_control_record_bytes": 1, "max_recovery_evidence_bytes": 1}, + "expires_at": None, "created_clock": clock, + "remaining_micros_at_creation": None}, + "destination_staging_object": None, "commit_intent": None, + "residual_staging_cleanup": {"state": "NOT_REQUIRED", "staging_object": None, + "evidence_sigil": None, "reason": None}, + "state": "PREPARED", "verification": None, + "cleanup": {"state": "NOT_REQUIRED", "evidence_sigil": None, "reason": None}, + "created_at": STAMP, "terminal_at": None, "revision": 1, "record_sigil": "", + } + materialization["record_sigil"] = content_sigil({ + key: member for key, member in materialization.items() if key != "record_sigil" + }) + return materialization + + +def _recovery_marker() -> dict[str, object]: + marker: dict[str, object] = { + "schema_version": "artifact-storage-recovery-marker/1.0", "recovery_id": "RECOVERY", + "journal_id": "SJ-ONE", "prior_head_sigil": SIGIL, "old_committed_byte_length": 2, + "last_complete_byte_length": 1, "discarded_suffix_size": 1, + "discarded_suffix_sigil": SIGIL, "evidence_record_sigil": SIGIL, + "phase": "EVIDENCE_DURABLE", "recovery_event_id": None, "recovery_event_sigil": None, + "recovery_event_seed_record_sigil": None, "recovery_frame_start": None, + "recovery_frame_size": None, "recovery_frame_sigil": None, + "prepared_frame_evidence_record_sigil": None, "retry_count": 0, + "latest_retry_evidence_record_sigil": None, "created_at": STAMP, "updated_at": STAMP, + "record_sigil": "", + } + marker["record_sigil"] = content_sigil({ + key: member for key, member in marker.items() if key != "record_sigil" + }) + return marker + + +def test_storage_journal_event_checks_self_sigil_order_and_strict_loading() -> None: + event = _event() + validate_artifact_storage_journal_event_v1(event) + assert load_artifact_storage_journal_event_v1(json.dumps(event)) == event + + stale = deepcopy(event) + stale["payload"]["message_class"] = "changed" # type: ignore[index] + with pytest.raises(AthanorError, match="self-Sigil"): + validate_artifact_storage_journal_event_v1(stale) + + with pytest.raises(AthanorError, match="BOM"): + load_artifact_storage_journal_event_v1(b"\xef\xbb\xbf" + json.dumps(event).encode()) + duplicate = json.dumps(event).replace( + '"journal_id": "SJ-ONE",', + '"journal_id": "SJ-ONE", "journal_id": "SJ-TWO",', + 1, + ) + with pytest.raises(AthanorError, match="duplicate JSON key"): + load_artifact_storage_journal_event_v1(duplicate) + + +def test_reference_set_and_intent_close_ids_sigils_and_order() -> None: + reference_set = _reference_set() + validate_artifact_storage_reference_set_v1(reference_set) + assert load_artifact_storage_reference_set_v1(json.dumps(reference_set)) == reference_set + + stale_set = deepcopy(reference_set) + stale_set["reference_set_id"] = "RS-" + "A" * 64 + stale_set["reference_set_sigil"] = content_sigil({ + key: member for key, member in stale_set.items() if key != "reference_set_sigil" + }) + with pytest.raises(AthanorError, match="Reference Set ID mismatch"): + validate_artifact_storage_reference_set_v1(stale_set) + + execution_root_set = deepcopy(reference_set) + execution_root_set["source"] = { + "kind": "OPERATIONAL_CONTROL_RECORD", "identity": "ESM-ONE", + "schema_version": "execution-storage-root-manifest/1.0", "sigil": SIGIL, + } + execution_root_set["reference_set_id"] = derive_artifact_storage_reference_set_id_v1( + execution_root_set + ) + execution_root_set["registration_event_id"] = "SE-" + content_sigil([ + "artifact-storage-execution-root-reference-set-registration-event-id/1.0", "ESM-ONE", + ]).removeprefix("sha256:").upper() + execution_root_set["reference_set_sigil"] = content_sigil({ + key: member for key, member in execution_root_set.items() if key != "reference_set_sigil" + }) + validate_artifact_storage_reference_set_v1(execution_root_set) + + intent = { + "schema_version": "artifact-storage-reference-intent/1.0", "reference_intent_id": "", + "transition_request_id": "REQUEST", "transition_request_sigil": SIGIL, + "canonical_event_type": "patch.proposed", + "expected_chronicle_head": {"schema_version": "chronicle-head/1.1", "event_count": 0, + "terminal_receipt_sigil": None}, + "reference_sets": [{"reference_set_id": reference_set["reference_set_id"], + "reference_set_sigil": reference_set["reference_set_sigil"]}], + "blob_sigils": [SIGIL], "actor_id": "ACTOR", "authorization_sigil": SIGIL, + "idempotency_key_sigil": SIGIL, "requested_at": STAMP, "record_sigil": "", + } + intent["reference_intent_id"] = derive_artifact_storage_reference_intent_id_v1(intent) + intent["record_sigil"] = content_sigil({ + key: member for key, member in intent.items() if key != "record_sigil" + }) + validate_artifact_storage_reference_intent_v1(intent) + assert load_artifact_storage_reference_intent_v1(json.dumps(intent)) == intent + + stale_intent = deepcopy(intent) + stale_intent["reference_intent_id"] = "RI-" + "A" * 64 + stale_intent["record_sigil"] = content_sigil({ + key: member for key, member in stale_intent.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="Reference Intent ID mismatch"): + validate_artifact_storage_reference_intent_v1(stale_intent) + + state = _state() + state["reference_sets"] = [{ + "reference_set_id": reference_set["reference_set_id"], + "reference_set_sigil": reference_set["reference_set_sigil"], "source_identity": "SOURCE", + "revision": 1, "last_event_sigil": SIGIL, + }] + state["canonical_reference_intents"] = [{ + "reference_intent_id": intent["reference_intent_id"], "record_sigil": intent["record_sigil"], + "state": "OPEN", "chronicle_commit": None, "release_kind": None, + "release_authority_sigil": None, "release_reason": None, "revision": 1, + "last_event_sigil": SIGIL, + }] + state["open_intents"] = [{ + "intent_kind": "CANONICAL_REFERENCE", "intent_id": intent["reference_intent_id"], + "owner_id": intent["reference_intent_id"], + "source_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "intent_sigil": SIGIL, "revision": 1, + "last_event_sigil": SIGIL, "authorization_expires_at": None, + "expected_chronicle_head": intent["expected_chronicle_head"], + "blob_sigils": intent["blob_sigils"], "reference_set_sigils": [], + }] + state["state_sigil"] = content_sigil({ + key: member for key, member in state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_supplied_control_records_v1( + state, reference_sets=[reference_set], reference_intents=[intent] + ) + + missing_set = deepcopy(state) + with pytest.raises(AthanorError, match="Reference Set projection lacks"): + validate_artifact_storage_state_supplied_control_records_v1( + missing_set, reference_sets=[], reference_intents=[intent] + ) + wrong_source = deepcopy(state) + wrong_source["reference_sets"][0]["source_identity"] = "OTHER" # type: ignore[index] + wrong_source["state_sigil"] = content_sigil({ + key: member for key, member in wrong_source.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Reference Set projection lacks"): + validate_artifact_storage_state_supplied_control_records_v1( + wrong_source, reference_sets=[reference_set], reference_intents=[intent] + ) + with pytest.raises(AthanorError, match="Reference Intent projection lacks"): + validate_artifact_storage_state_supplied_control_records_v1( + state, reference_sets=[reference_set], reference_intents=[] + ) + + chronicle_event = { + "schema_version": "chronicle-event/1.1", "event_id": "CE-ONE", "sequence": 1, + "type": intent["canonical_event_type"], "object_id": "OBJECT", + "occurred_at": STAMP, "previous_receipt_sigil": None, + "actor": {"actor_id": "ACTOR", "actor_type": "agent", "host": "codex", + "authenticated_by": "AUTH"}, "payload": {}, "event_body_sigil": "", + "receipt": {}, + } + chronicle_event["event_body_sigil"] = content_sigil({ + key: value for key, value in chronicle_event.items() + if key not in {"event_body_sigil", "receipt"} + }) + receipt = { + "schema_version": "receipt/1.1", "receipt_id": "RC-ONE", "event_id": "CE-ONE", + "event_body_sigil": chronicle_event["event_body_sigil"], "previous_receipt_sigil": None, + "accepted_at": STAMP, "receipt_sigil": "", + } + receipt["receipt_sigil"] = content_sigil({ + key: value for key, value in receipt.items() if key != "receipt_sigil" + }) + chronicle_event["receipt"] = receipt + chronicle_commit = { + "event_id": chronicle_event["event_id"], + "event_body_sigil": chronicle_event["event_body_sigil"], + "receipt_id": receipt["receipt_id"], "receipt_sigil": receipt["receipt_sigil"], + "head": {"schema_version": "chronicle-head/1.1", "event_count": 1, + "terminal_receipt_sigil": receipt["receipt_sigil"]}, + } + validate_canonical_reference_commit_supplied_facts_v1( + intent, chronicle_event, chronicle_commit + ) + malformed_commit = deepcopy(chronicle_commit) + malformed_commit["head"]["event_count"] = 2 + with pytest.raises(AthanorError, match="supplied Chronicle commit"): + validate_canonical_reference_commit_supplied_facts_v1( + intent, chronicle_event, malformed_commit + ) + terminal_head = deepcopy(intent) + terminal_head["expected_chronicle_head"]["event_count"] = 9223372036854775807 + terminal_head["record_sigil"] = content_sigil({ + key: value for key, value in terminal_head.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="exceeds the U63"): + validate_canonical_reference_commit_supplied_facts_v1( + terminal_head, chronicle_event, chronicle_commit + ) + + abort_authority = { + "kind": "HEAD_SUPERSEDED_WITHOUT_BOUND_EVENT", + "reference_intent_id": intent["reference_intent_id"], + "reference_intent_record_sigil": intent["record_sigil"], + "transition_request_id": intent["transition_request_id"], + "transition_request_sigil": intent["transition_request_sigil"], + "expected_chronicle_head": intent["expected_chronicle_head"], + "verified_chronicle_head": {"schema_version": "chronicle-head/1.1", + "event_count": 1, "terminal_receipt_sigil": SIGIL}, + "absence_evidence_sigil": "", "authority_sigil": "", + } + abort_authority["absence_evidence_sigil"] = content_sigil([ + "artifact-storage-canonical-precommit-absence/1.0", + intent["reference_intent_id"], intent["record_sigil"], + intent["transition_request_id"], intent["transition_request_sigil"], + intent["expected_chronicle_head"], abort_authority["verified_chronicle_head"], + ]) + abort_authority["authority_sigil"] = content_sigil({ + key: value for key, value in abort_authority.items() if key != "authority_sigil" + }) + release_reason = { + "code": "CHRONICLE_REFERENCE_CHANGED", + "evidence_sigils": sorted([ + abort_authority["authority_sigil"], abort_authority["absence_evidence_sigil"], + intent["record_sigil"], intent["transition_request_sigil"], + ]), + } + validate_canonical_reference_release_supplied_facts_v1( + intent, abort_authority, release_reason + ) + malformed_release = deepcopy(release_reason) + malformed_release["evidence_sigils"] = [] + with pytest.raises(AthanorError, match="release facts"): + validate_canonical_reference_release_supplied_facts_v1( + intent, abort_authority, malformed_release + ) + malformed_authority = deepcopy(abort_authority) + malformed_authority["verified_chronicle_head"]["extra"] = True + malformed_authority["authority_sigil"] = content_sigil({ + key: value for key, value in malformed_authority.items() if key != "authority_sigil" + }) + with pytest.raises(AthanorError, match="invalid verified Chronicle Head"): + validate_canonical_reference_release_supplied_facts_v1( + intent, malformed_authority, release_reason + ) + malformed_reason = deepcopy(release_reason) + malformed_reason["extra"] = True + with pytest.raises(AthanorError, match="Reason has an invalid closed shape"): + validate_canonical_reference_release_supplied_facts_v1( + intent, abort_authority, malformed_reason + ) + + +def test_storage_replay_projects_exact_registered_reference_set() -> None: + initial = _initial_replay_event() + activation = _next_event(initial) + activation.update({ + "event_type": "storage.activation_completed", + "entity_revisions": [{ + "entity_type": "STORE", "entity_id": "STORE", + "previous_revision": 1, "next_revision": 2, + }], + "payload": { + "legacy_protection_ids": [], "activation_evidence_sigil": SIGIL, + "clock": initial["payload"]["clock"], + }, + "quota_effects": [], + }) + activation["event_sigil"] = content_sigil({ + key: value for key, value in activation.items() if key != "event_sigil" + }) + reference_set = _reference_set() + registered = _next_event(activation) + registered.update({ + "event_id": reference_set["registration_event_id"], + "sequence": 3, + "event_type": "reference_set.registered", + "recorded_at": "2026-08-06T00:00:01Z", + "observed_at": None, + "entity_revisions": [{ + "entity_type": "REFERENCE_SET", + "entity_id": reference_set["reference_set_id"], + "previous_revision": None, + "next_revision": 1, + }], + "causation_event_id": None, + "idempotency_key_sigil": None, + "quota_effects": [], + "payload": { + "reference_set_id": reference_set["reference_set_id"], + "reference_set_sigil": reference_set["reference_set_sigil"], + "source_identity": reference_set["source"]["identity"], + "source_sigil": reference_set["source"]["sigil"], + }, + }) + reference_set["created_at"] = registered["recorded_at"] + reference_set["reference_set_sigil"] = content_sigil({ + key: value for key, value in reference_set.items() + if key != "reference_set_sigil" + }) + registered["payload"]["reference_set_sigil"] = reference_set["reference_set_sigil"] + registered["event_sigil"] = content_sigil({ + key: value for key, value in registered.items() if key != "event_sigil" + }) + state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered], supplied_reference_sets=[reference_set] + ) + assert state["reference_sets"] == [{ + "reference_set_id": reference_set["reference_set_id"], + "reference_set_sigil": reference_set["reference_set_sigil"], + "source_identity": reference_set["source"]["identity"], + "revision": 1, + "last_event_sigil": registered["event_sigil"], + }] + + policy = _retention_policy() + policy["scope"] = { + "kind": "REFERENCE_SET", + "reference_set_id": reference_set["reference_set_id"], + "reference_set_sigil": reference_set["reference_set_sigil"], + } + retention_registered = _next_event(registered) + retention_registered.update({ + "event_id": "SE-RETENTION", "sequence": 4, + "event_type": "retention.policy_registered", + "entity_revisions": [{ + "entity_type": "RETENTION_POLICY", "entity_id": policy["policy_id"], + "previous_revision": None, "next_revision": 1, + }], + "quota_effects": [], + }) + policy["registered_at"] = retention_registered["recorded_at"] + policy["record_sigil"] = content_sigil({ + key: value for key, value in policy.items() if key != "record_sigil" + }) + retention_registered["payload"] = {"policy": { + "schema_version": policy["schema_version"], "record_id": policy["policy_id"], + "record_sigil": policy["record_sigil"], + }} + retention_registered["event_sigil"] = content_sigil({ + key: value for key, value in retention_registered.items() if key != "event_sigil" + }) + scoped_state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, retention_registered], + supplied_reference_sets=[reference_set], supplied_retention_policies=[policy], + ) + assert scoped_state["retention_policies"][0]["record_sigil"] == policy["record_sigil"] + + wrong_scope_policy = deepcopy(policy) + wrong_scope_policy["scope"]["reference_set_sigil"] = SIGIL_B + wrong_scope_policy["record_sigil"] = content_sigil({ + key: value for key, value in wrong_scope_policy.items() if key != "record_sigil" + }) + wrong_scope_event = deepcopy(retention_registered) + wrong_scope_event["payload"]["policy"]["record_sigil"] = wrong_scope_policy["record_sigil"] + wrong_scope_event["event_sigil"] = content_sigil({ + key: value for key, value in wrong_scope_event.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="scope is not locally closed"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, wrong_scope_event], + supplied_reference_sets=[reference_set], + supplied_retention_policies=[wrong_scope_policy], + ) + + extra_set = deepcopy(reference_set) + extra_set["extractor"]["extractor_sigil"] = SIGIL_B + extra_set["reference_set_id"] = derive_artifact_storage_reference_set_id_v1(extra_set) + extra_set["registration_event_id"] = "SE-" + content_sigil([ + "artifact-storage-reference-set-registration-event-id/1.0", + extra_set["reference_set_id"], + ]).removeprefix("sha256:").upper() + extra_set["reference_set_sigil"] = content_sigil({ + key: value for key, value in extra_set.items() if key != "reference_set_sigil" + }) + with pytest.raises(AthanorError, match="do not exactly match State projections"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, retention_registered], + supplied_reference_sets=[reference_set, extra_set], + supplied_retention_policies=[policy], + ) + + distinct_set = deepcopy(reference_set) + distinct_set["extractor"]["extractor_sigil"] = SIGIL_B + distinct_set["reference_set_id"] = derive_artifact_storage_reference_set_id_v1( + distinct_set + ) + distinct_set["registration_event_id"] = "SE-" + content_sigil([ + "artifact-storage-reference-set-registration-event-id/1.0", + distinct_set["reference_set_id"], + ]).removeprefix("sha256:").upper() + distinct_set["reference_set_sigil"] = content_sigil({ + key: value for key, value in distinct_set.items() + if key != "reference_set_sigil" + }) + second_registered = _next_event(registered) + second_registered.update({ + "event_id": distinct_set["registration_event_id"], + "sequence": 4, + "event_type": "reference_set.registered", + "recorded_at": "2026-08-06T00:00:02Z", + "entity_revisions": [{ + "entity_type": "REFERENCE_SET", + "entity_id": distinct_set["reference_set_id"], + "previous_revision": None, + "next_revision": 1, + }], + "payload": { + "reference_set_id": distinct_set["reference_set_id"], + "reference_set_sigil": distinct_set["reference_set_sigil"], + "source_identity": distinct_set["source"]["identity"], + "source_sigil": distinct_set["source"]["sigil"], + }, + }) + distinct_set["created_at"] = second_registered["recorded_at"] + distinct_set["reference_set_sigil"] = content_sigil({ + key: value for key, value in distinct_set.items() + if key != "reference_set_sigil" + }) + second_registered["payload"]["reference_set_sigil"] = distinct_set[ + "reference_set_sigil" + ] + second_registered["event_sigil"] = content_sigil({ + key: value for key, value in second_registered.items() if key != "event_sigil" + }) + second_state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, second_registered], + supplied_reference_sets=[reference_set, distinct_set], + ) + assert [item["reference_set_id"] for item in second_state["reference_sets"]] == sorted([ + reference_set["reference_set_id"], distinct_set["reference_set_id"] + ]) + + wrong_record = deepcopy(reference_set) + wrong_record["source"]["identity"] = "OTHER" + wrong_record["reference_set_id"] = derive_artifact_storage_reference_set_id_v1( + wrong_record + ) + wrong_record["reference_set_sigil"] = content_sigil({ + key: value for key, value in wrong_record.items() if key != "reference_set_sigil" + }) + with pytest.raises(AthanorError, match="requires exactly one supplied record"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered], supplied_reference_sets=[wrong_record] + ) + with pytest.raises(AthanorError, match="requires its supplied record"): + replay_artifact_storage_journal_prefix_v1([initial, activation, registered]) + + for member, wrong_value in ( + ("reference_set_sigil", SIGIL_B), + ("source_identity", "OTHER"), + ("source_sigil", SIGIL_B), + ): + malformed = deepcopy(registered) + malformed["payload"][member] = wrong_value + malformed["event_sigil"] = content_sigil({ + key: value for key, value in malformed.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="disagrees with record"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, malformed], + supplied_reference_sets=[reference_set], + ) + + wrong_timestamp = deepcopy(registered) + wrong_timestamp["recorded_at"] = "2026-08-06T00:00:02Z" + wrong_timestamp["event_sigil"] = content_sigil({ + key: value for key, value in wrong_timestamp.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="disagrees with record"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, wrong_timestamp], + supplied_reference_sets=[reference_set], + ) + + +def test_storage_replay_projects_canonical_reference_write_ahead_pin() -> None: + initial = _initial_replay_event() + for snapshot in initial["payload"]["quota_snapshots"]: # type: ignore[index] + if snapshot["quota_class"] in {"JOURNAL", "CONTROL_RECORD"}: + snapshot["limit"] = 10 + initial["quota_effects"] = [ # type: ignore[index] + {"kind": "INITIALIZE", "snapshot": snapshot} + for snapshot in initial["payload"]["quota_snapshots"] # type: ignore[index] + ] + initial["event_sigil"] = content_sigil({ + key: value for key, value in initial.items() if key != "event_sigil" + }) + activation = _next_event(initial) + activation.update({ + "event_type": "storage.activation_completed", + "entity_revisions": [{"entity_type": "STORE", "entity_id": "STORE", + "previous_revision": 1, "next_revision": 2}], + "payload": {"legacy_protection_ids": [], "activation_evidence_sigil": SIGIL, + "clock": initial["payload"]["clock"]}, # type: ignore[index] + "quota_effects": [], + }) + activation["event_sigil"] = content_sigil({ + key: value for key, value in activation.items() if key != "event_sigil" + }) + reference_set = _reference_set() + registered = _next_event(activation) + registered.update({ + "event_id": reference_set["registration_event_id"], "sequence": 3, + "event_type": "reference_set.registered", "recorded_at": "2026-08-06T00:00:02Z", + "observed_at": None, + "entity_revisions": [{"entity_type": "REFERENCE_SET", + "entity_id": reference_set["reference_set_id"], + "previous_revision": None, "next_revision": 1}], + "causation_event_id": None, "idempotency_key_sigil": None, "quota_effects": [], + "payload": {"reference_set_id": reference_set["reference_set_id"], + "reference_set_sigil": reference_set["reference_set_sigil"], + "source_identity": reference_set["source"]["identity"], + "source_sigil": reference_set["source"]["sigil"]}, + }) + reference_set["created_at"] = registered["recorded_at"] + reference_set["reference_set_sigil"] = content_sigil({ + key: value for key, value in reference_set.items() if key != "reference_set_sigil" + }) + registered["payload"]["reference_set_sigil"] = reference_set["reference_set_sigil"] # type: ignore[index] + registered["event_sigil"] = content_sigil({ + key: value for key, value in registered.items() if key != "event_sigil" + }) + reservation = { + "reservation_id": "RESERVATION", "claims": [ + {"quota_class": "CONTROL_RECORD", "byte_count": 0, "object_count": 0, + "inode_count": 0, "stream_count": 0, "journal_bytes": 0, + "control_record_bytes": 1}, + {"quota_class": "JOURNAL", "byte_count": 0, "object_count": 0, + "inode_count": 0, "stream_count": 0, "journal_bytes": 1, + "control_record_bytes": 0}, + ], + "capacity_plan": {"allowed_event_types": ["canonical_reference.committed", + "canonical_reference.released"], + "max_event_frame_count": 1, "max_control_record_count": 1, + "max_recovery_evidence_count": 0, "max_event_frame_bytes": 1, + "max_control_record_bytes": 1, + "max_recovery_evidence_bytes": 1}, + "expires_at": None, "created_clock": initial["payload"]["clock"], # type: ignore[index] + "remaining_micros_at_creation": None, + } + intent = { + "schema_version": "artifact-storage-reference-intent/1.0", "reference_intent_id": "", + "transition_request_id": "REQUEST", "transition_request_sigil": SIGIL, + "canonical_event_type": "patch.proposed", + "expected_chronicle_head": {"schema_version": "chronicle-head/1.1", "event_count": 0, + "terminal_receipt_sigil": None}, + "reference_sets": [{"reference_set_id": reference_set["reference_set_id"], + "reference_set_sigil": reference_set["reference_set_sigil"]}], + "blob_sigils": [], "actor_id": "ACTOR", "authorization_sigil": SIGIL, + "idempotency_key_sigil": SIGIL, "requested_at": "2026-08-06T00:00:03Z", + "record_sigil": "", + } + intent["reference_intent_id"] = derive_artifact_storage_reference_intent_id_v1(intent) + intent["record_sigil"] = content_sigil({ + key: value for key, value in intent.items() if key != "record_sigil" + }) + recorded = _next_event(registered) + recorded.update({ + "event_id": "SE-INTENT", "sequence": 4, + "event_type": "canonical_reference.intent_recorded", + "recorded_at": "2026-08-06T00:00:03Z", "observed_at": None, + "entity_revisions": [ + {"entity_type": "REFERENCE_INTENT", "entity_id": intent["reference_intent_id"], + "previous_revision": None, "next_revision": 1}, + {"entity_type": "QUOTA", "entity_id": reservation["reservation_id"], + "previous_revision": None, "next_revision": 1}, + ], "causation_event_id": None, "idempotency_key_sigil": SIGIL, + "quota_effects": [{"kind": "RESERVE", "reservation": reservation, + "owner_kind": "CANONICAL_REFERENCE", + "owner_id": intent["reference_intent_id"], + "purpose": "CANONICAL_PIN_LIFECYCLE"}], + "payload": {"reference_intent": { + "schema_version": "artifact-storage-reference-intent/1.0", + "record_id": intent["reference_intent_id"], "record_sigil": intent["record_sigil"], + }, "expected_chronicle_head": intent["expected_chronicle_head"], + "blob_sigils": [], "reference_set_sigils": [reference_set["reference_set_sigil"]], + "lifecycle_reservation": reservation}, + }) + recorded["event_sigil"] = content_sigil({ + key: value for key, value in recorded.items() if key != "event_sigil" + }) + state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, recorded], supplied_reference_sets=[reference_set], + supplied_reference_intents=[intent], + ) + assert state["canonical_reference_intents"][0]["state"] == "OPEN" + assert state["open_intents"][0]["intent_id"] == intent["reference_intent_id"] + assert [counter["reserved"] for counter in state["quota_counters"] if counter["quota_class"] + in {"JOURNAL", "CONTROL_RECORD"}] == [1, 1] + + abort_authority = {"kind": "HEAD_SUPERSEDED_WITHOUT_BOUND_EVENT", "reference_intent_id": intent["reference_intent_id"], "reference_intent_record_sigil": intent["record_sigil"], "transition_request_id": intent["transition_request_id"], "transition_request_sigil": intent["transition_request_sigil"], "expected_chronicle_head": intent["expected_chronicle_head"], "verified_chronicle_head": {"schema_version": "chronicle-head/1.1", "event_count": 1, "terminal_receipt_sigil": SIGIL}, "absence_evidence_sigil": "", "authority_sigil": ""} + abort_authority["absence_evidence_sigil"] = content_sigil(["artifact-storage-canonical-precommit-absence/1.0", intent["reference_intent_id"], intent["record_sigil"], intent["transition_request_id"], intent["transition_request_sigil"], intent["expected_chronicle_head"], abort_authority["verified_chronicle_head"]]) + abort_authority["authority_sigil"] = content_sigil({key: value for key, value in abort_authority.items() if key != "authority_sigil"}) + release_reason = {"code": "CHRONICLE_REFERENCE_CHANGED", "evidence_sigils": sorted([abort_authority["authority_sigil"], abort_authority["absence_evidence_sigil"], intent["record_sigil"], intent["transition_request_sigil"]])} + released = _next_event(recorded) + released.update({"event_id": "SE-RELEASE", "sequence": 5, "event_type": "canonical_reference.released", "recorded_at": "2026-08-06T00:00:04Z", "observed_at": None, "entity_revisions": [{"entity_type": "REFERENCE_INTENT", "entity_id": intent["reference_intent_id"], "previous_revision": 1, "next_revision": 2}, {"entity_type": "QUOTA", "entity_id": reservation["reservation_id"], "previous_revision": 1, "next_revision": 2}], "causation_event_id": "SE-INTENT", "idempotency_key_sigil": SIGIL, "quota_effects": [{"kind": "SETTLE", "reservation_id": reservation["reservation_id"], "state_after": "SETTLED", "consumed_claims": [deepcopy(reservation["claims"][1])], "released_claims": [deepcopy(reservation["claims"][0])], "remaining_claims": [], "usage_additions": [deepcopy(reservation["claims"][1])], "retained_for_event_types": []}], "payload": {"reference_intent_id": intent["reference_intent_id"], "release_kind": "ABORTED_BEFORE_CANONICAL_COMMIT", "chronicle_commit": None, "abort_authority": abort_authority, "reason": release_reason}}) + released["event_sigil"] = content_sigil({key: value for key, value in released.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="authoritative Chronicle absence proof"): + replay_artifact_storage_journal_prefix_v1([initial, activation, registered, recorded, released], supplied_reference_sets=[reference_set], supplied_reference_intents=[intent]) + + chronicle_event: dict[str, Any] = { + "schema_version": "chronicle-event/1.1", "event_id": "CE-ONE", "sequence": 1, + "type": "patch.proposed", "object_id": "PATCH-ONE", "occurred_at": "2026-08-06T00:00:04Z", + "previous_receipt_sigil": None, + "actor": {"actor_id": "ACTOR", "actor_type": "agent", "host": "codex", "authenticated_by": "MCP"}, + "payload": {"proposal": "bound-by-supplied-family-resolver"}, "event_body_sigil": "", + "receipt": {"schema_version": "receipt/1.1", "receipt_id": "RC-ONE", "event_id": "CE-ONE", "event_body_sigil": "", "previous_receipt_sigil": None, "accepted_at": "2026-08-06T00:00:04Z", "receipt_sigil": ""}, + } + chronicle_event["event_body_sigil"] = content_sigil({ + key: value for key, value in chronicle_event.items() if key not in {"event_body_sigil", "receipt"} + }) + chronicle_event["receipt"]["event_body_sigil"] = chronicle_event["event_body_sigil"] # type: ignore[index] + chronicle_event["receipt"]["receipt_sigil"] = content_sigil({ + key: value for key, value in chronicle_event["receipt"].items() if key != "receipt_sigil" + }) # type: ignore[index] + commit = { + "event_id": chronicle_event["event_id"], "event_body_sigil": chronicle_event["event_body_sigil"], + "receipt_id": chronicle_event["receipt"]["receipt_id"], "receipt_sigil": chronicle_event["receipt"]["receipt_sigil"], + "head": {"schema_version": "chronicle-head/1.1", "event_count": 1, "terminal_receipt_sigil": chronicle_event["receipt"]["receipt_sigil"]}, + } + committed = _next_event(recorded) + committed.update({ + "event_id": "SE-COMMIT", "sequence": 5, "event_type": "canonical_reference.committed", + "recorded_at": "2026-08-06T00:00:04Z", "observed_at": None, + "entity_revisions": [{"entity_type": "REFERENCE_INTENT", "entity_id": intent["reference_intent_id"], "previous_revision": 1, "next_revision": 2}, {"entity_type": "QUOTA", "entity_id": reservation["reservation_id"], "previous_revision": 1, "next_revision": 2}], + "causation_event_id": "SE-INTENT", "idempotency_key_sigil": SIGIL, + "quota_effects": [{"kind": "SETTLE", "reservation_id": reservation["reservation_id"], "state_after": "SETTLED", "consumed_claims": reservation["claims"], "released_claims": [], "remaining_claims": [], "usage_additions": reservation["claims"], "retained_for_event_types": []}], + "payload": {"reference_intent_id": intent["reference_intent_id"], "chronicle_commit": commit}, + }) + committed["event_sigil"] = content_sigil({key: value for key, value in committed.items() if key != "event_sigil"}) + committed_state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, recorded, committed], + supplied_reference_sets=[reference_set], supplied_reference_intents=[intent], + supplied_chronicle_events=[chronicle_event], + ) + assert committed_state["canonical_reference_intents"][0]["state"] == "COMMITTED" + assert committed_state["open_intents"] == [] + assert committed_state["quota_reservations"][0]["state"] == "SETTLED" + assert [counter["used"] for counter in committed_state["quota_counters"] if counter["quota_class"] in {"JOURNAL", "CONTROL_RECORD"}] == [1, 1] + partial = deepcopy(committed) + partial_claims = [deepcopy(reservation["claims"][1])] + partial["quota_effects"][0]["consumed_claims"] = partial_claims + partial["quota_effects"][0]["usage_additions"] = partial_claims + partial["quota_effects"][0]["released_claims"] = [deepcopy(reservation["claims"][0])] + partial["event_sigil"] = content_sigil({key: value for key, value in partial.items() if key != "event_sigil"}) + partial_state = replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, recorded, partial], + supplied_reference_sets=[reference_set], supplied_reference_intents=[intent], + supplied_chronicle_events=[chronicle_event], + ) + assert [counter["used"] for counter in partial_state["quota_counters"] if counter["quota_class"] in {"JOURNAL", "CONTROL_RECORD"}] == [1, 0] + no_journal = deepcopy(committed) + no_journal["quota_effects"][0]["consumed_claims"] = [deepcopy(reservation["claims"][0])] + no_journal["quota_effects"][0]["usage_additions"] = [deepcopy(reservation["claims"][0])] + no_journal["quota_effects"][0]["released_claims"] = [deepcopy(reservation["claims"][1])] + no_journal["event_sigil"] = content_sigil({key: value for key, value in no_journal.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="Journal frame usage"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, recorded, no_journal], + supplied_reference_sets=[reference_set], supplied_reference_intents=[intent], + supplied_chronicle_events=[chronicle_event], + ) + + malformed = deepcopy(recorded) + malformed["payload"]["blob_sigils"] = [SIGIL] + malformed["event_sigil"] = content_sigil({ + key: value for key, value in malformed.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="disagrees with immutable records"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, malformed], + supplied_reference_sets=[reference_set], supplied_reference_intents=[intent], + ) + closure_mismatch = deepcopy(intent) + closure_mismatch["blob_sigils"] = [SIGIL] + closure_mismatch["record_sigil"] = content_sigil({ + key: value for key, value in closure_mismatch.items() if key != "record_sigil" + }) + malformed = deepcopy(recorded) + malformed["payload"]["reference_intent"]["record_sigil"] = closure_mismatch["record_sigil"] + malformed["payload"]["blob_sigils"] = [SIGIL] + malformed["event_sigil"] = content_sigil({ + key: value for key, value in malformed.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="disagrees with immutable records"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, malformed], + supplied_reference_sets=[reference_set], supplied_reference_intents=[closure_mismatch], + ) + under_reserved = deepcopy(recorded) + under_reserved["payload"]["lifecycle_reservation"]["capacity_plan"]["max_event_frame_count"] = 2 + under_reserved["quota_effects"][0]["reservation"] = under_reserved["payload"]["lifecycle_reservation"] + under_reserved["event_sigil"] = content_sigil({ + key: value for key, value in under_reserved.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="lacks terminal capacity"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, under_reserved], + supplied_reference_sets=[reference_set], supplied_reference_intents=[intent], + ) + with pytest.raises(AthanorError, match="requires supplied control records"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, registered, recorded], supplied_reference_sets=[reference_set] + ) + + unknown_blob_set = deepcopy(reference_set) + unknown_blob_set["edges"] = [{ + "relationship": "CANONICAL_BINDS_BLOB", "target_kind": "BLOB", + "target_identity": SIGIL, "target_sigil": SIGIL, + }] + unknown_blob_set["reference_set_id"] = derive_artifact_storage_reference_set_id_v1( + unknown_blob_set + ) + unknown_blob_set["registration_event_id"] = "SE-" + content_sigil([ + "artifact-storage-reference-set-registration-event-id/1.0", + unknown_blob_set["reference_set_id"], + ]).removeprefix("sha256:").upper() + unknown_blob_set["reference_set_sigil"] = content_sigil({ + key: value for key, value in unknown_blob_set.items() + if key != "reference_set_sigil" + }) + unknown_registered = deepcopy(registered) + unknown_registered.update({ + "event_id": unknown_blob_set["registration_event_id"], + "entity_revisions": [{"entity_type": "REFERENCE_SET", + "entity_id": unknown_blob_set["reference_set_id"], + "previous_revision": None, "next_revision": 1}], + "payload": {"reference_set_id": unknown_blob_set["reference_set_id"], + "reference_set_sigil": unknown_blob_set["reference_set_sigil"], + "source_identity": unknown_blob_set["source"]["identity"], + "source_sigil": unknown_blob_set["source"]["sigil"]}, + }) + unknown_blob_set["created_at"] = unknown_registered["recorded_at"] + unknown_blob_set["reference_set_sigil"] = content_sigil({ + key: value for key, value in unknown_blob_set.items() + if key != "reference_set_sigil" + }) + unknown_registered["payload"]["reference_set_sigil"] = unknown_blob_set["reference_set_sigil"] # type: ignore[index] + unknown_registered["event_sigil"] = content_sigil({ + key: value for key, value in unknown_registered.items() if key != "event_sigil" + }) + unknown_blob_intent = deepcopy(intent) + unknown_blob_intent["reference_sets"] = [{ + "reference_set_id": unknown_blob_set["reference_set_id"], + "reference_set_sigil": unknown_blob_set["reference_set_sigil"], + }] + unknown_blob_intent["blob_sigils"] = [SIGIL] + unknown_blob_intent["reference_intent_id"] = derive_artifact_storage_reference_intent_id_v1( + unknown_blob_intent + ) + unknown_blob_intent["record_sigil"] = content_sigil({ + key: value for key, value in unknown_blob_intent.items() if key != "record_sigil" + }) + unknown_blob_event = deepcopy(recorded) + unknown_blob_event["previous_event_sigil"] = unknown_registered["event_sigil"] + unknown_blob_event["payload"]["reference_intent"] = { + "schema_version": "artifact-storage-reference-intent/1.0", + "record_id": unknown_blob_intent["reference_intent_id"], + "record_sigil": unknown_blob_intent["record_sigil"], + } + unknown_blob_event["payload"]["blob_sigils"] = [SIGIL] + unknown_blob_event["payload"]["reference_set_sigils"] = [unknown_blob_set["reference_set_sigil"]] + unknown_blob_event["entity_revisions"][0]["entity_id"] = unknown_blob_intent["reference_intent_id"] # type: ignore[index] + unknown_blob_event["quota_effects"][0]["owner_id"] = unknown_blob_intent["reference_intent_id"] # type: ignore[index] + unknown_blob_event["event_sigil"] = content_sigil({ + key: value for key, value in unknown_blob_event.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="Blob edge identity"): + replay_artifact_storage_journal_prefix_v1( + [initial, activation, unknown_registered, unknown_blob_event], + supplied_reference_sets=[unknown_blob_set], + supplied_reference_intents=[unknown_blob_intent], + ) + + +def test_legacy_protection_is_self_signed_and_matches_state_projection() -> None: + protection = _legacy_protection() + validate_artifact_storage_legacy_protection_v1(protection) + assert load_artifact_storage_legacy_protection_v1(json.dumps(protection)) == protection + + stale = deepcopy(protection) + stale["program_id"] = "OTHER" + with pytest.raises(AthanorError, match="Legacy Protection self-Sigil"): + validate_artifact_storage_legacy_protection_v1(stale) + + state = _state() + state["legacy_v1_protections"] = [{ + "protection_id": "PROTECTION", "artifact_id": "ARTIFACT", "state": "PROTECTED", + "record": protection, "receipt_sigil": SIGIL, "reason": None, "revision": 1, + "last_event_sigil": SIGIL, + }] + state["state_sigil"] = content_sigil({ + key: member for key, member in state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(state) + + mismatched = deepcopy(state) + mismatched["legacy_v1_protections"][0]["receipt_sigil"] = SIGIL_B # type: ignore[index] + mismatched["state_sigil"] = content_sigil({ + key: member for key, member in mismatched.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Legacy Protection disagrees"): + validate_artifact_storage_state_v1(mismatched) + + +def test_recovery_evidence_and_marker_phase_matrix() -> None: + evidence = _tail_evidence() + validate_artifact_storage_tail_evidence_v1(evidence) + assert load_artifact_storage_tail_evidence_v1(json.dumps(evidence)) == evidence + + marker = _recovery_marker() + validate_artifact_storage_recovery_marker_v1(marker) + assert load_artifact_storage_recovery_marker_v1(json.dumps(marker)) == marker + + id_durable = deepcopy(marker) + id_durable.update({ + "phase": "RECOVERY_EVENT_ID_DURABLE", "recovery_event_id": "SE-RECOVERY", + "recovery_event_sigil": SIGIL, "recovery_event_seed_record_sigil": evidence["record_sigil"], + }) + id_durable["record_sigil"] = content_sigil({ + key: member for key, member in id_durable.items() if key != "record_sigil" + }) + validate_artifact_storage_recovery_marker_v1(id_durable) + + malformed = deepcopy(id_durable) + malformed["recovery_frame_start"] = 1 + malformed["record_sigil"] = content_sigil({ + key: member for key, member in malformed.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="ID-durable phase"): + validate_artifact_storage_recovery_marker_v1(malformed) + + retried = deepcopy(id_durable) + retried.update({ + "phase": "RECOVERY_EVENT_RETRY_EVIDENCE_DURABLE", "recovery_frame_start": 1, + "recovery_frame_size": 1, "recovery_frame_sigil": SIGIL, + "prepared_frame_evidence_record_sigil": SIGIL, "retry_count": 1, + "latest_retry_evidence_record_sigil": SIGIL_B, + }) + retried["record_sigil"] = content_sigil({ + key: member for key, member in retried.items() if key != "record_sigil" + }) + validate_artifact_storage_recovery_marker_v1(retried) + + zero_retry = deepcopy(retried) + zero_retry["retry_count"] = 0 + zero_retry["record_sigil"] = content_sigil({ + key: member for key, member in zero_retry.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="zero retry"): + validate_artifact_storage_recovery_marker_v1(zero_retry) + + +def test_disposition_is_self_signed_and_has_a_positive_authorization_window() -> None: + disposition = _disposition() + validate_artifact_storage_disposition_v1(disposition) + assert load_artifact_storage_disposition_v1(json.dumps(disposition)) == disposition + + expired = deepcopy(disposition) + expired["expires_at"] = STAMP + expired["record_sigil"] = content_sigil({ + key: member for key, member in expired.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="expiry must follow"): + validate_artifact_storage_disposition_v1(expired) + + +def test_retention_policy_and_hold_projection_matrix() -> None: + policy = _retention_policy() + validate_artifact_retention_policy_v1(policy) + assert load_artifact_retention_policy_v1(json.dumps(policy)) == policy + + state = _state() + state["retention_policies"] = [{ + "policy_id": policy["policy_id"], "record_sigil": policy["record_sigil"], + "revision": 1, "last_event_sigil": SIGIL, + }] + state["holds"] = [{ + "hold_id": "SH-ONE", "target_kind": "BLOB", "target_id": SIGIL, + "policy_id": policy["policy_id"], "state": "ACTIVE", "set_authorization_sigil": SIGIL, + "release_authorization_sigil": None, "revision": 1, "last_event_sigil": SIGIL, + }] + state["state_sigil"] = content_sigil({ + key: member for key, member in state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_supplied_retention_policies_v1(state, policies=[policy]) + validate_artifact_storage_state_supplied_reference_sets_v1(state, reference_sets=[]) + + invalid_hold = deepcopy(state) + invalid_hold["holds"][0]["release_authorization_sigil"] = SIGIL_B # type: ignore[index] + invalid_hold["state_sigil"] = content_sigil({ + key: member for key, member in invalid_hold.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Hold release authorization"): + validate_artifact_storage_state_v1(invalid_hold) + + +def test_gc_plan_closes_local_proof_bindings_and_sorting() -> None: + plan = _gc_plan() + validate_artifact_gc_plan_v1(plan) + assert load_artifact_gc_plan_v1(json.dumps(plan)) == plan + + wrong_proof = deepcopy(plan) + wrong_proof["closure_proof"]["bounds"] = { # type: ignore[index] + **wrong_proof["bounds"], "max_depth": 2 # type: ignore[index] + } + wrong_proof["record_sigil"] = content_sigil({ + key: member for key, member in wrong_proof.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="Closure Proof disagrees"): + validate_artifact_gc_plan_v1(wrong_proof) + + +def test_provenance_is_self_signed_and_matches_state_projection() -> None: + provenance = _provenance() + validate_artifact_provenance_v1(provenance) + assert load_artifact_provenance_v1(json.dumps(provenance)) == provenance + + state = _state() + state["provenance"] = [{"provenance_id": provenance["provenance_id"], + "record_sigil": provenance["record_sigil"], "revision": 1, + "last_event_sigil": SIGIL}] + state["state_sigil"] = content_sigil({ + key: member for key, member in state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_supplied_provenance_v1(state, records=[provenance]) + + missing = deepcopy(state) + with pytest.raises(AthanorError, match="Provenance projection lacks"): + validate_artifact_storage_state_supplied_provenance_v1(missing, records=[]) + + +def test_backend_profile_is_self_signed_and_canonically_orders_methods() -> None: + profile = _backend_profile() + validate_artifact_storage_backend_v1(profile) + assert load_artifact_storage_backend_v1(json.dumps(profile)) == profile + + unordered = deepcopy(profile) + unordered["verification_methods"].reverse() # type: ignore[index] + unordered["record_sigil"] = content_sigil({ + key: member for key, member in unordered.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="verification methods are not sorted"): + validate_artifact_storage_backend_v1(unordered) + + +def test_provenance_policy_is_self_signed_and_matches_state_projection() -> None: + policy = _provenance_policy() + validate_artifact_provenance_policy_v1(policy) + assert load_artifact_provenance_policy_v1(json.dumps(policy)) == policy + + state = _state() + state["provenance_policies"] = [{ + "provenance_policy_id": policy["provenance_policy_id"], + "record_sigil": policy["record_sigil"], "revision": 1, "last_event_sigil": SIGIL, + }] + state["state_sigil"] = content_sigil({ + key: member for key, member in state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_supplied_provenance_policies_v1(state, policies=[policy]) + + missing = deepcopy(state) + with pytest.raises(AthanorError, match="Provenance Policy projection lacks"): + validate_artifact_storage_state_supplied_provenance_policies_v1(missing, policies=[]) + + +def test_doctor_report_is_self_signed_and_nonnegative_in_duration() -> None: + report = _doctor_report() + validate_artifact_storage_doctor_report_v1(report) + assert load_artifact_storage_doctor_report_v1(json.dumps(report)) == report + + reversed_times = deepcopy(report) + reversed_times["completed_at"] = "2026-08-05T23:59:59Z" + reversed_times["report_sigil"] = content_sigil({ + key: member for key, member in reversed_times.items() if key != "report_sigil" + }) + with pytest.raises(AthanorError, match="completes before"): + validate_artifact_storage_doctor_report_v1(reversed_times) + + +def test_attempt_output_transfer_is_self_signed_and_matches_state_projection() -> None: + transfer = _transfer() + validate_artifact_transfer_v1(transfer) + assert load_artifact_transfer_v1(json.dumps(transfer)) == transfer + + state = _state() + state["transfer_requests"] = [{ + "transfer_id": transfer["transfer_id"], "request_record_sigil": transfer["record_sigil"], + "state": "ACTIVE", "attempt_ids": [], "selected_attempt_id": None, + "revision": 1, "last_event_sigil": SIGIL, + }] + state["state_sigil"] = content_sigil({ + key: member for key, member in state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_supplied_transfers_v1(state, transfers=[transfer]) + + invalid = deepcopy(transfer) + invalid["destination"]["backend"] = deepcopy(invalid["destination"]["backend"]) # type: ignore[index] + invalid["destination"]["backend"]["backend_id"] = "OTHER" # type: ignore[index] + invalid["record_sigil"] = content_sigil({ + key: member for key, member in invalid.items() if key != "record_sigil" + }) + with pytest.raises(AthanorError, match="ATTEMPT_OUTPUT local bindings"): + validate_artifact_transfer_v1(invalid) + + +def test_transfer_attempt_state_record_matches_its_supplied_request() -> None: + transfer = _transfer() + attempt = _transfer_attempt() + state = _state() + state["transfer_requests"] = [{ + "transfer_id": transfer["transfer_id"], "request_record_sigil": transfer["record_sigil"], + "state": "ACTIVE", "attempt_ids": [attempt["transfer_attempt_id"]], + "selected_attempt_id": None, "revision": 1, "last_event_sigil": SIGIL, + }] + state["transfer_attempts"] = [{"record": attempt, "last_event_sigil": SIGIL}] + state["state_sigil"] = content_sigil({ + key: member for key, member in state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_supplied_transfer_attempts_v1(state, transfers=[transfer]) + + unlisted = deepcopy(state) + unlisted["transfer_requests"][0]["attempt_ids"] = [] # type: ignore[index] + unlisted["state_sigil"] = content_sigil({ + key: member for key, member in unlisted.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Request Attempts disagree"): + validate_artifact_storage_state_v1(unlisted) + with pytest.raises(AthanorError, match="Request Attempts disagree"): + validate_artifact_storage_state_supplied_transfer_attempts_v1(unlisted, transfers=[transfer]) + + wrong_request = deepcopy(state) + wrong_request["transfer_attempts"][0]["record"]["transfer_id"] = "ST-OTHER" # type: ignore[index] + wrong_request["transfer_attempts"][0]["record"]["record_sigil"] = content_sigil({ # type: ignore[index] + key: member for key, member in wrong_request["transfer_attempts"][0]["record"].items() # type: ignore[index] + if key != "record_sigil" + }) + wrong_request["state_sigil"] = content_sigil({ + key: member for key, member in wrong_request.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="lacks its request projection"): + validate_artifact_storage_state_v1(wrong_request) + + +def test_storage_journal_head_matrix_and_supplied_final_event() -> None: + event = _event() + head = _head(event) + validate_artifact_storage_journal_head_v1(head) + assert load_artifact_storage_journal_head_v1(json.dumps(head)) == head + validate_artifact_storage_journal_head_supplied_event_v1(head, event, SIGIL) + + bad_empty = deepcopy(head) + bad_empty.update({"event_count": 0, "last_sequence": 0}) + with pytest.raises(AthanorError, match="empty Journal Head"): + validate_artifact_storage_journal_head_v1(bad_empty) + + wrong_event = deepcopy(event) + wrong_event["journal_id"] = "SJ-TWO" + wrong_event["event_sigil"] = content_sigil({ + key: member for key, member in wrong_event.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="contradicts supplied"): + validate_artifact_storage_journal_head_supplied_event_v1(head, wrong_event, SIGIL) + + with pytest.raises(AthanorError, match="replay authority"): + require_artifact_storage_journal_replay_authority_v1() + with pytest.raises(AthanorError, match="runtime authority"): + require_artifact_storage_runtime_authority_v1() + + +def test_storage_journal_prefix_checks_chain_sequence_and_fixed_head() -> None: + first = _initial_event() + second = _next_event(first) + head = _head(second) + head.update({"event_count": 2, "last_sequence": 2}) + validate_artifact_storage_journal_prefix_v1([first, second]) + validate_artifact_storage_journal_head_supplied_prefix_v1(head, [first, second], SIGIL) + + broken_chain = deepcopy(second) + broken_chain["previous_event_sigil"] = SIGIL_B + broken_chain["event_sigil"] = content_sigil({ + key: member for key, member in broken_chain.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="chain Sigil"): + validate_artifact_storage_journal_prefix_v1([first, broken_chain]) + + gap = deepcopy(second) + gap["sequence"] = 3 + gap["event_sigil"] = content_sigil({ + key: member for key, member in gap.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="not contiguous"): + validate_artifact_storage_journal_prefix_v1([first, gap]) + + duplicate_identity = deepcopy(second) + duplicate_identity["event_id"] = first["event_id"] + duplicate_identity["event_sigil"] = content_sigil({ + key: member for key, member in duplicate_identity.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="duplicate Event identity"): + validate_artifact_storage_journal_prefix_v1([first, duplicate_identity]) + + not_initialized = _event() + with pytest.raises(AthanorError, match="does not start"): + validate_artifact_storage_journal_prefix_v1([not_initialized]) + + wrong_initial_epoch = deepcopy(first) + wrong_initial_epoch["epoch"] = 2 + wrong_initial_epoch["event_sigil"] = content_sigil({ + key: member for key, member in wrong_initial_epoch.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="must use epoch one"): + validate_artifact_storage_journal_prefix_v1([wrong_initial_epoch]) + + old_epoch = deepcopy(second) + old_epoch["epoch"] = 0 + old_epoch["event_sigil"] = content_sigil({ + key: member for key, member in old_epoch.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError): + validate_artifact_storage_journal_prefix_v1([first, old_epoch]) + + +def test_storage_state_checks_self_identity_order_and_head_binding() -> None: + state = _state() + validate_artifact_storage_state_v1(state) + assert load_artifact_storage_state_v1(json.dumps(state)) == state + head = _head(_event()) + head.update({ + "last_event_sigil": state["last_event_sigil"], + "state_sigil": state["state_sigil"], + }) + validate_artifact_storage_head_supplied_state_v1(head, state) + + stale = deepcopy(state) + stale["project_id"] = "CHANGED" + with pytest.raises(AthanorError, match="self-Sigil"): + validate_artifact_storage_state_v1(stale) + + wrong_head = deepcopy(head) + wrong_head["current_epoch"] = 2 + with pytest.raises(AthanorError, match="contradicts supplied State"): + validate_artifact_storage_head_supplied_state_v1(wrong_head, state) + + ordered = deepcopy(state) + ordered["transfer_requests"] = [ + {"transfer_id": "ST-ONE", "request_record_sigil": SIGIL, "state": "ACTIVE", + "attempt_ids": [], "selected_attempt_id": None, "revision": 1, + "last_event_sigil": SIGIL}, + {"transfer_id": "ST-TWO", "request_record_sigil": SIGIL, "state": "ACTIVE", + "attempt_ids": [], "selected_attempt_id": None, "revision": 1, + "last_event_sigil": SIGIL}, + ] + ordered["state_sigil"] = content_sigil({ + key: member for key, member in ordered.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(ordered) + + out_of_order = deepcopy(ordered) + out_of_order["transfer_requests"].reverse() + out_of_order["state_sigil"] = content_sigil({ + key: member for key, member in out_of_order.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="identity sorted"): + validate_artifact_storage_state_v1(out_of_order) + + duplicate_identity = deepcopy(ordered) + duplicate_identity["transfer_requests"][1]["transfer_id"] = "ST-ONE" + duplicate_identity["state_sigil"] = content_sigil({ + key: member for key, member in duplicate_identity.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="non-unique|identities must be unique"): + validate_artifact_storage_state_v1(duplicate_identity) + + object_ref = { + "backend_id": "BACKEND", "object_identity_sigil": SIGIL, "locator_sigil": SIGIL, + "generation": "GENERATION", "size_bytes": 0, "blob_sigil": None, + } + open_ids = deepcopy(state) + open_ids["open_intents"] = [ + {"intent_kind": "MATERIALIZATION_COMMIT", "intent_id": "INTENT", "owner_id": "SM-ONE", + "source_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "intent_sigil": SIGIL, "revision": 1, + "last_event_sigil": SIGIL, "authorization_expires_at": None, + "staging_object": object_ref, "target_object": object_ref}, + {"intent_kind": "TRANSFER_COMMIT", "intent_id": "INTENT", "owner_id": "SA-ONE", + "source_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "intent_sigil": SIGIL, "revision": 1, + "last_event_sigil": SIGIL, "authorization_expires_at": None, + "staging_object": object_ref, "target_object": object_ref}, + ] + open_ids["state_sigil"] = content_sigil({ + key: member for key, member in open_ids.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="globally unique"): + validate_artifact_storage_state_v1(open_ids) + + recovering = deepcopy(state) + recovering.update({ + "store_status": "RECOVERING", "active_recovery_id": "RECOVERY", + "recovery_origin_status": "INITIALIZING", "current_epoch": 2, + "recoveries": [{ + "recovery_id": "RECOVERY", "origin_status": "INITIALIZING", "state": "ACTIVE", + "started_event_sigil": SIGIL, "epoch_ids": [1, 2], + "tail_recovery_evidence_record_sigils": [], "completed_event_sigil": None, + "resume_status": None, + }], + }) + recovering["state_sigil"] = content_sigil({ + key: member for key, member in recovering.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(recovering) + + duplicate_active_recovery = deepcopy(recovering) + duplicate_active_recovery["recoveries"].append({ # type: ignore[index] + "recovery_id": "RECOVERY-TWO", "origin_status": "INITIALIZING", "state": "ACTIVE", + "started_event_sigil": SIGIL, "epoch_ids": [1, 2], + "tail_recovery_evidence_record_sigils": [], "completed_event_sigil": None, + "resume_status": None, + }) + duplicate_active_recovery["state_sigil"] = content_sigil({ + key: member for key, member in duplicate_active_recovery.items() + if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="active Recovery disagrees"): + validate_artifact_storage_state_v1(duplicate_active_recovery) + + stale_recovery = deepcopy(recovering) + stale_recovery["recoveries"][0]["epoch_ids"] = [1] # type: ignore[index] + stale_recovery["state_sigil"] = content_sigil({ + key: member for key, member in stale_recovery.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="active Recovery disagrees"): + validate_artifact_storage_state_v1(stale_recovery) + + unprojected_active_recovery = deepcopy(recovering) + unprojected_active_recovery.update({ + "store_status": "INITIALIZING", "active_recovery_id": None, + "recovery_origin_status": None, + }) + unprojected_active_recovery["state_sigil"] = content_sigil({ + key: member for key, member in unprojected_active_recovery.items() + if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="nonrecovering Store retains"): + validate_artifact_storage_state_v1(unprojected_active_recovery) + + over_limit_counter = deepcopy(state) + over_limit_counter["quota_counters"][0].update({ # type: ignore[index] + "limit": 1, "used": 1, "reserved": 1, + }) + over_limit_counter["state_sigil"] = content_sigil({ + key: member for key, member in over_limit_counter.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="quota counter exceeds"): + validate_artifact_storage_state_v1(over_limit_counter) + + wrong_open_sigil = deepcopy(open_ids) + wrong_open_sigil["open_intents"] = [wrong_open_sigil["open_intents"][0]] + wrong_open_sigil["open_intents"][0]["intent_sigil"] = SIGIL_B + wrong_open_sigil["state_sigil"] = content_sigil({ + key: member for key, member in wrong_open_sigil.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Open Intent disagrees"): + validate_artifact_storage_state_v1(wrong_open_sigil) + + wrong_open_journal = deepcopy(open_ids) + wrong_open_journal["open_intents"][0]["source_event"]["journal_id"] = "SJ-OTHER" + wrong_open_journal["state_sigil"] = content_sigil({ + key: member for key, member in wrong_open_journal.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Open Intent disagrees"): + validate_artifact_storage_state_v1(wrong_open_journal) + + future_open_intent = deepcopy(open_ids) + future_open_intent["open_intents"][0]["source_event"]["sequence"] = 2 + future_open_intent["state_sigil"] = content_sigil({ + key: member for key, member in future_open_intent.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Open Intent disagrees"): + validate_artifact_storage_state_v1(future_open_intent) + + quarantine_state = deepcopy(state) + quarantine = { + "quarantine_id": "SQ-ONE", "owner_kind": "TRANSFER_ATTEMPT", "owner_id": "SA-ONE", + "state": "INTENT_RECORDED", "source_object": object_ref, + "destination_object": object_ref, + "source_cleanup": {"state": "NOT_REQUIRED", "staging_object": None, + "evidence_sigil": None, "reason": None}, + "reservation": _transfer_attempt()["reservation"], + "reason": {"code": "BACKEND_UNAVAILABLE", "evidence_sigils": []}, + "revision": 1, "last_event_sigil": SIGIL, "record_sigil": "", + } + quarantine["record_sigil"] = content_sigil({ + key: member for key, member in quarantine.items() if key != "record_sigil" + }) + quarantine_state["quarantines"] = [quarantine] + quarantine_state["open_intents"] = [{ + "intent_kind": "QUARANTINE_MOVE", "intent_id": "SQ-ONE", "owner_id": "SA-ONE", + "source_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "intent_sigil": SIGIL, "revision": 1, + "last_event_sigil": SIGIL, "authorization_expires_at": None, + "source_object": object_ref, "target_object": object_ref, + }] + quarantine_state["state_sigil"] = content_sigil({ + key: member for key, member in quarantine_state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(quarantine_state) + + mismatched_quarantine_owner = deepcopy(quarantine_state) + mismatched_quarantine_owner["open_intents"][0]["owner_id"] = "SA-OTHER" + mismatched_quarantine_owner["state_sigil"] = content_sigil({ + key: member for key, member in mismatched_quarantine_owner.items() + if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Quarantine move Intent disagrees"): + validate_artifact_storage_state_v1(mismatched_quarantine_owner) + + missing_quarantine_intent = deepcopy(quarantine_state) + missing_quarantine_intent["open_intents"] = [] + missing_quarantine_intent["state_sigil"] = content_sigil({ + key: member for key, member in missing_quarantine_intent.items() + if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Quarantine move Intent disagrees"): + validate_artifact_storage_state_v1(missing_quarantine_intent) + + selected_unknown = deepcopy(ordered) + selected_unknown["transfer_requests"][0]["selected_attempt_id"] = "SA-UNKNOWN" + selected_unknown["state_sigil"] = content_sigil({ + key: member for key, member in selected_unknown.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="selects an unknown Attempt"): + validate_artifact_storage_state_v1(selected_unknown) + + replica_state = deepcopy(state) + replica = { + "schema_version": "artifact-replica/1.0", "replica_id": "SR-ONE", + "blob_sigil": SIGIL, "size_bytes": 0, + "backend": {"backend_id": "BACKEND", "backend_profile_version": "1.0", + "backend_profile_sigil": SIGIL}, + "object": {"backend_id": "BACKEND", "object_identity_sigil": SIGIL, + "locator_sigil": SIGIL, "generation": "GENERATION", "size_bytes": 0, + "blob_sigil": SIGIL}, "state": "COMMITTING", + "created_by_transfer_attempt_id": "SA-ONE", "verification": None, + "retention_policy_ids": [], "revision": 1, "record_sigil": "", + } + replica["record_sigil"] = content_sigil({ + key: member for key, member in replica.items() if key != "record_sigil" + }) + replica_state["replicas"] = [{"record": replica, "last_event_sigil": SIGIL}] + replica_state["state_sigil"] = content_sigil({ + key: member for key, member in replica_state.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="has no matching Blob projection"): + validate_artifact_storage_state_v1(replica_state) + + wrong_replica = deepcopy(replica_state) + wrong_replica["replicas"][0]["record"]["object"]["size_bytes"] = 1 + wrong_replica["replicas"][0]["record"]["record_sigil"] = content_sigil({ + key: member for key, member in wrong_replica["replicas"][0]["record"].items() + if key != "record_sigil" + }) + wrong_replica["state_sigil"] = content_sigil({ + key: member for key, member in wrong_replica.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Replica object disagrees"): + validate_artifact_storage_state_v1(wrong_replica) + + committed_state = deepcopy(state) + committed_attempt = _transfer_attempt() + target = { + "backend_id": "BACKEND", "object_identity_sigil": SIGIL, + "locator_sigil": SIGIL, "generation": "GENERATION", "size_bytes": 0, + "blob_sigil": SIGIL, + } + committed_attempt.update({ + "state": "COMMITTED", "staging_state": "MISSING", "staging_object": target, + "commit_intent": { + "intent_id": "INTENT", "provisional_replica_id": "SR-ONE", + "staging_object": target, "target_object": target, + "computed_blob": {"blob_sigil": SIGIL, "size_bytes": 0}, + "execution_fence": None, "reservation": committed_attempt["reservation"], + "recorded_clock": committed_attempt["reservation"]["created_clock"], + }, + "residual_staging_cleanup": {"state": "NOT_REQUIRED", "staging_object": None, + "evidence_sigil": None, "reason": None}, + "computed_blob_sigil": SIGIL, "computed_size_bytes": 0, + "selected_replica_id": "SR-ONE", "terminal_at": STAMP, + }) + committed_attempt["record_sigil"] = content_sigil({ + key: member for key, member in committed_attempt.items() if key != "record_sigil" + }) + selected_replica = deepcopy(replica) + selected_replica.update({ + "state": "AVAILABLE", "verification": { + "method": "FULL_READBACK_SHA256", "evidence_sigil": SIGIL, + "verified_at": STAMP, "next_due_at": None, + }, + }) + selected_replica["record_sigil"] = content_sigil({ + key: member for key, member in selected_replica.items() if key != "record_sigil" + }) + committed_state["replicas"] = [{"record": selected_replica, "last_event_sigil": SIGIL}] + committed_blob = { + "schema_version": "artifact-blob/1.0", "blob_sigil": SIGIL, "size_bytes": 0, + "first_verified_at": None, "availability": "AVAILABLE", + "availability_as_of": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "availability_basis_sigil": SIGIL, + "effective_policy_set_sigil": SIGIL, "next_verification_due_at": None, + "known_replica_ids": ["SR-ONE"], "eligible_replica_ids": [], + "integrity_event_sigils": [], "media_type_observations": [], + "filename_observations": [], "revision": 1, "record_sigil": "", + } + committed_blob["record_sigil"] = content_sigil({ + key: member for key, member in committed_blob.items() if key != "record_sigil" + }) + committed_state["blobs"] = [{"record": committed_blob, "last_event_sigil": SIGIL}] + committed_state["availability_counters"]["available_blobs"] = 1 + committed_state["transfer_attempts"] = [{ + "record": committed_attempt, "last_event_sigil": SIGIL, + }] + committed_state["transfer_requests"] = [{ + "transfer_id": committed_attempt["transfer_id"], "request_record_sigil": SIGIL, + "state": "ACTIVE", "attempt_ids": [committed_attempt["transfer_attempt_id"]], + "selected_attempt_id": None, "revision": 1, "last_event_sigil": SIGIL, + }] + committed_state["state_sigil"] = content_sigil({ + key: member for key, member in committed_state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(committed_state) + + missing_selected = deepcopy(committed_state) + missing_selected["replicas"] = [] + missing_selected["blobs"][0]["record"]["known_replica_ids"] = [] + missing_selected["blobs"][0]["record"]["record_sigil"] = content_sigil({ + key: member for key, member in missing_selected["blobs"][0]["record"].items() + if key != "record_sigil" + }) + missing_selected["state_sigil"] = content_sigil({ + key: member for key, member in missing_selected.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="lacks its selected Replica"): + validate_artifact_storage_state_v1(missing_selected) + + committing_state = deepcopy(state) + committing_attempt = _transfer_attempt() + committing_object = { + "backend_id": "BACKEND", "object_identity_sigil": SIGIL, + "locator_sigil": SIGIL, "generation": "GENERATION", "size_bytes": 0, + "blob_sigil": None, + } + committing_attempt.update({ + "state": "COMMITTING", "staging_state": "PRESENT", "staging_object": committing_object, + "commit_intent": { + "intent_id": "INTENT", "provisional_replica_id": "SR-ONE", + "staging_object": committing_object, "target_object": committing_object, + "computed_blob": {"blob_sigil": SIGIL, "size_bytes": 0}, + "execution_fence": None, "reservation": committing_attempt["reservation"], + "recorded_clock": committing_attempt["reservation"]["created_clock"], + }, + }) + committing_attempt["record_sigil"] = content_sigil({ + key: member for key, member in committing_attempt.items() if key != "record_sigil" + }) + committing_state["transfer_attempts"] = [{"record": committing_attempt, "last_event_sigil": SIGIL}] + committing_state["transfer_requests"] = [{ + "transfer_id": committing_attempt["transfer_id"], "request_record_sigil": SIGIL, + "state": "ACTIVE", "attempt_ids": [committing_attempt["transfer_attempt_id"]], + "selected_attempt_id": None, "revision": 1, "last_event_sigil": SIGIL, + }] + committing_state["open_intents"] = [{ + "intent_kind": "TRANSFER_COMMIT", "intent_id": "INTENT", + "owner_id": committing_attempt["transfer_attempt_id"], + "source_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "intent_sigil": SIGIL, "revision": 1, + "last_event_sigil": SIGIL, "authorization_expires_at": None, + "staging_object": committing_object, "target_object": committing_object, + }] + committing_state["state_sigil"] = content_sigil({ + key: member for key, member in committing_state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(committing_state) + + missing_intent = deepcopy(committing_state) + missing_intent["open_intents"] = [] + missing_intent["state_sigil"] = content_sigil({ + key: member for key, member in missing_intent.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="commit Intent disagrees with record state"): + validate_artifact_storage_state_v1(missing_intent) + + disposition_state = deepcopy(state) + disposition_state["dispositions"] = [{ + "disposition_id": "SD-ONE", "record_sigil": SIGIL, "state": "EXECUTING", + "execution_intent_id": "INTENT", "outcome_sigil": None, + "revision": 1, "last_event_sigil": SIGIL, + }] + disposition_state["open_intents"] = [{ + "intent_kind": "DISPOSITION", "intent_id": "INTENT", "owner_id": "SD-ONE", + "source_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "intent_sigil": SIGIL, "revision": 1, + "last_event_sigil": SIGIL, "authorization_expires_at": STAMP, + "target_kind": "STAGING", "target_object": committing_object, + }] + disposition_state["state_sigil"] = content_sigil({ + key: member for key, member in disposition_state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(disposition_state) + + missing_disposition_intent = deepcopy(disposition_state) + missing_disposition_intent["open_intents"] = [] + missing_disposition_intent["state_sigil"] = content_sigil({ + key: member for key, member in missing_disposition_intent.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="Disposition execution Intent disagrees"): + validate_artifact_storage_state_v1(missing_disposition_intent) + + canonical_state = deepcopy(state) + canonical_state["canonical_reference_intents"] = [{ + "reference_intent_id": "RI-ONE", "record_sigil": SIGIL, "state": "OPEN", + "chronicle_commit": None, "release_kind": None, "release_authority_sigil": None, + "release_reason": None, "revision": 1, "last_event_sigil": SIGIL, + }] + canonical_state["open_intents"] = [{ + "intent_kind": "CANONICAL_REFERENCE", "intent_id": "RI-ONE", "owner_id": "RI-ONE", + "source_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "intent_sigil": SIGIL, "revision": 1, + "last_event_sigil": SIGIL, "authorization_expires_at": None, + "expected_chronicle_head": {"schema_version": "chronicle-head/1.1", "event_count": 0, + "terminal_receipt_sigil": None}, + "blob_sigils": [], "reference_set_sigils": [], + }] + canonical_state["state_sigil"] = content_sigil({ + key: member for key, member in canonical_state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(canonical_state) + + missing_canonical_intent = deepcopy(canonical_state) + missing_canonical_intent["open_intents"] = [] + missing_canonical_intent["state_sigil"] = content_sigil({ + key: member for key, member in missing_canonical_intent.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="canonical-reference Intent disagrees"): + validate_artifact_storage_state_v1(missing_canonical_intent) + + wrong_canonical_owner = deepcopy(canonical_state) + wrong_canonical_owner["open_intents"][0]["owner_id"] = "RI-OTHER" # type: ignore[index] + wrong_canonical_owner["state_sigil"] = content_sigil({ + key: member for key, member in wrong_canonical_owner.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="canonical-reference Intent disagrees"): + validate_artifact_storage_state_v1(wrong_canonical_owner) + + mismatched_selected = deepcopy(committed_state) + mismatched_selected["replicas"][0]["record"]["object"]["generation"] = "OTHER" + mismatched_selected["replicas"][0]["record"]["record_sigil"] = content_sigil({ + key: member for key, member in mismatched_selected["replicas"][0]["record"].items() + if key != "record_sigil" + }) + mismatched_selected["state_sigil"] = content_sigil({ + key: member for key, member in mismatched_selected.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="disagrees with selected Replica"): + validate_artifact_storage_state_v1(mismatched_selected) + + materialization_state = deepcopy(replica_state) + source_blob = { + "schema_version": "artifact-blob/1.0", "blob_sigil": SIGIL, "size_bytes": 0, + "first_verified_at": None, "availability": "AVAILABLE", + "availability_as_of": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "availability_basis_sigil": SIGIL, + "effective_policy_set_sigil": SIGIL, "next_verification_due_at": None, + "known_replica_ids": ["SR-ONE"], "eligible_replica_ids": [], + "integrity_event_sigils": [], "media_type_observations": [], + "filename_observations": [], "revision": 1, "record_sigil": "", + } + source_blob["record_sigil"] = content_sigil({ + key: member for key, member in source_blob.items() if key != "record_sigil" + }) + materialization_state["blobs"] = [{"record": source_blob, "last_event_sigil": SIGIL}] + materialization_state["availability_counters"]["available_blobs"] = 1 + materialization_state["materializations"] = [{ + "record": _materialization(), "last_event_sigil": SIGIL, + }] + materialization_state["state_sigil"] = content_sigil({ + key: member for key, member in materialization_state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(materialization_state) + + missing_source = deepcopy(materialization_state) + missing_source["replicas"] = [] + missing_source["blobs"][0]["record"]["known_replica_ids"] = [] + missing_source["blobs"][0]["record"]["record_sigil"] = content_sigil({ + key: member for key, member in missing_source["blobs"][0]["record"].items() + if key != "record_sigil" + }) + missing_source["state_sigil"] = content_sigil({ + key: member for key, member in missing_source.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="lacks its source Replica"): + validate_artifact_storage_state_v1(missing_source) + + wrong_source_blob = deepcopy(materialization_state) + wrong_source_blob["materializations"][0]["record"]["source_blob_sigil"] = SIGIL_B + wrong_source_blob["materializations"][0]["record"]["record_sigil"] = content_sigil({ + key: member for key, member in wrong_source_blob["materializations"][0]["record"].items() + if key != "record_sigil" + }) + wrong_source_blob["state_sigil"] = content_sigil({ + key: member for key, member in wrong_source_blob.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="source Replica disagrees with Blob"): + validate_artifact_storage_state_v1(wrong_source_blob) + + blob_state = deepcopy(state) + blob = { + "schema_version": "artifact-blob/1.0", "blob_sigil": SIGIL, "size_bytes": 0, + "first_verified_at": None, "availability": "AVAILABLE", + "availability_as_of": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL}, "availability_basis_sigil": SIGIL, + "effective_policy_set_sigil": SIGIL, "next_verification_due_at": None, + "known_replica_ids": [], "eligible_replica_ids": [], "integrity_event_sigils": [], + "media_type_observations": [], "filename_observations": [], "revision": 1, + "record_sigil": "", + } + blob["record_sigil"] = content_sigil({ + key: member for key, member in blob.items() if key != "record_sigil" + }) + blob_state["blobs"] = [{"record": blob, "last_event_sigil": SIGIL}] + blob_state["availability_counters"]["available_blobs"] = 1 + blob_state["state_sigil"] = content_sigil({ + key: member for key, member in blob_state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(blob_state) + + linked_blob_state = deepcopy(blob_state) + linked_replica = deepcopy(replica) + linked_replica["state"] = "AVAILABLE" + linked_replica["verification"] = { + "method": "FULL_READBACK_SHA256", "evidence_sigil": SIGIL, + "verified_at": STAMP, "next_due_at": None, + } + linked_replica["record_sigil"] = content_sigil({ + key: member for key, member in linked_replica.items() if key != "record_sigil" + }) + linked_blob_state["replicas"] = [{"record": linked_replica, "last_event_sigil": SIGIL}] + linked_blob_state["blobs"][0]["record"]["known_replica_ids"] = ["SR-ONE"] + linked_blob_state["blobs"][0]["record"]["record_sigil"] = content_sigil({ + key: member for key, member in linked_blob_state["blobs"][0]["record"].items() + if key != "record_sigil" + }) + linked_blob_state["state_sigil"] = content_sigil({ + key: member for key, member in linked_blob_state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(linked_blob_state) + + missing_known = deepcopy(linked_blob_state) + missing_known["blobs"][0]["record"]["known_replica_ids"] = [] + missing_known["blobs"][0]["record"]["record_sigil"] = content_sigil({ + key: member for key, member in missing_known["blobs"][0]["record"].items() + if key != "record_sigil" + }) + missing_known["state_sigil"] = content_sigil({ + key: member for key, member in missing_known.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="known Replicas disagree"): + validate_artifact_storage_state_v1(missing_known) + + unknown_eligible = deepcopy(linked_blob_state) + unknown_eligible["blobs"][0]["record"]["eligible_replica_ids"] = ["SR-UNKNOWN"] + unknown_eligible["blobs"][0]["record"]["record_sigil"] = content_sigil({ + key: member for key, member in unknown_eligible["blobs"][0]["record"].items() + if key != "record_sigil" + }) + unknown_eligible["state_sigil"] = content_sigil({ + key: member for key, member in unknown_eligible.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="eligible Replicas are not known"): + validate_artifact_storage_state_v1(unknown_eligible) + + orphan_replica = deepcopy(replica_state) + with pytest.raises(AthanorError, match="has no matching Blob projection"): + validate_artifact_storage_state_v1(orphan_replica) + + bad_counters = deepcopy(blob_state) + bad_counters["availability_counters"]["available_blobs"] = 0 + bad_counters["state_sigil"] = content_sigil({ + key: member for key, member in bad_counters.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="availability counters disagree"): + validate_artifact_storage_state_v1(bad_counters) + + quota_state = deepcopy(state) + claim = { + "quota_class": "STAGING", "byte_count": 1, "object_count": 0, + "inode_count": 0, "stream_count": 0, "journal_bytes": 0, + "control_record_bytes": 0, + } + quota_state["quota_reservations"] = [{ + "reservation": { + "reservation_id": "RESERVATION", "claims": [claim], + "capacity_plan": { + "allowed_event_types": ["transfer.prepared"], "max_event_frame_count": 1, + "max_control_record_count": 0, "max_recovery_evidence_count": 0, + "max_event_frame_bytes": 1, "max_control_record_bytes": 1, + "max_recovery_evidence_bytes": 1, + }, "expires_at": None, "created_clock": state["clock_anchor"], + "remaining_micros_at_creation": None, + }, "owner_kind": "TRANSFER_ATTEMPT", "owner_id": "SA-ONE", + "purpose": "PAYLOAD_LIFECYCLE", "state": "ACTIVE", "consumed_claims": [], + "released_claims": [], "remaining_claims": [deepcopy(claim)], "retained_for_event_types": [], + "revision": 1, "last_event_sigil": SIGIL, + }] + quota_state["state_sigil"] = content_sigil({ + key: member for key, member in quota_state.items() if key != "state_sigil" + }) + validate_artifact_storage_state_v1(quota_state) + + bad_claim = deepcopy(quota_state) + bad_claim["quota_reservations"][0]["remaining_claims"][0]["journal_bytes"] = 1 + bad_claim["state_sigil"] = content_sigil({ + key: member for key, member in bad_claim.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="illegal quota dimension"): + validate_artifact_storage_state_v1(bad_claim) + + exceeds_claim = deepcopy(quota_state) + exceeds_claim["quota_reservations"][0]["remaining_claims"][0]["byte_count"] = 2 + exceeds_claim["state_sigil"] = content_sigil({ + key: member for key, member in exceeds_claim.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="exceeds its original claim"): + validate_artifact_storage_state_v1(exceeds_claim) + + unpartitioned = deepcopy(quota_state) + unpartitioned["quota_reservations"][0]["remaining_claims"] = [] + unpartitioned["state_sigil"] = content_sigil({ + key: member for key, member in unpartitioned.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="do not partition original claim"): + validate_artifact_storage_state_v1(unpartitioned) + + retained_without_events = deepcopy(quota_state) + retained_without_events["quota_reservations"][0]["state"] = "RETAINED" + retained_without_events["state_sigil"] = content_sigil({ + key: member for key, member in retained_without_events.items() if key != "state_sigil" + }) + with pytest.raises(AthanorError, match="retained Quota Reservation lacks"): + validate_artifact_storage_state_v1(retained_without_events) diff --git a/tests/test_cli_surface.py b/tests/test_cli_surface.py index 832f2bc..efcf729 100644 --- a/tests/test_cli_surface.py +++ b/tests/test_cli_surface.py @@ -223,7 +223,7 @@ def test_project_root_is_discovered_from_a_subdirectory(self) -> None: code, output = self._run("root") self.assertEqual(code, 0) - self.assertEqual(Path(output.strip()), self.root) + self.assertEqual(Path(output.strip()).resolve(), self.root.resolve()) self.assertEqual(self._run("status")[0], 0) def test_project_manifest_is_also_a_root_marker(self) -> None: @@ -234,7 +234,7 @@ def test_project_manifest_is_also_a_root_marker(self) -> None: code, output = self._run("root") self.assertEqual(code, 0) - self.assertEqual(Path(output.strip()), self.root) + self.assertEqual(Path(output.strip()).resolve(), self.root.resolve()) def test_active_program_is_explicit_and_used_by_direct_verbs(self) -> None: self._run("init") diff --git a/tests/test_execution.py b/tests/test_execution.py index 4e80827..1a96a27 100644 --- a/tests/test_execution.py +++ b/tests/test_execution.py @@ -1,7 +1,9 @@ +import json import tempfile import unittest from pathlib import Path from typing import cast +from unittest.mock import patch from benchwork.athanor import Athanor, AthanorError, content_sigil from benchwork.execution import ExecutionService, LocalBlobStore @@ -56,6 +58,11 @@ def test_storage_rejects_invalid_inputs_and_detects_tampering(self) -> None: with self.assertRaisesRegex(AthanorError, "integrity failure"): self.store.read_bytes(record["blob_sigil"]) + def test_storage_fails_closed_when_directory_sync_fails(self) -> None: + with patch("benchwork.execution._fsync_directory", side_effect=AthanorError("directory sync failed")): + with self.assertRaisesRegex(AthanorError, "directory sync failed"): + self.store.initialize() + def test_storage_rejects_incompatible_format(self) -> None: self.store.initialize() format_path = Path(self.directory.name) / ".benchwork" / "storage" / "format.json" @@ -63,6 +70,79 @@ def test_storage_rejects_incompatible_format(self) -> None: with self.assertRaisesRegex(AthanorError, "format is incompatible"): self.store.initialize() + def test_storage_rejects_colliding_managed_paths(self) -> None: + storage = Path(self.directory.name) / ".benchwork" / "storage" + storage.mkdir(parents=True) + (storage / "blobs").write_text("not a directory", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "path is not a directory: blobs"): + self.store.initialize() + + def test_storage_rejects_colliding_root_and_lock_paths(self) -> None: + storage = Path(self.directory.name) / ".benchwork" / "storage" + storage.parent.mkdir(parents=True) + storage.write_text("not a directory", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "managed storage path is not a directory"): + self.store.initialize() + + storage.unlink() + storage.mkdir() + (storage / "locks").write_text("not a directory", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "managed storage lock path is not a directory"): + self.store.initialize() + + def test_storage_rejects_symlinked_managed_root(self) -> None: + storage = Path(self.directory.name) / ".benchwork" / "storage" + target = Path(self.directory.name) / "outside-storage" + target.mkdir() + storage.parent.mkdir(parents=True) + storage.symlink_to(target, target_is_directory=True) + with self.assertRaisesRegex(AthanorError, "managed storage path is not a directory"): + self.store.initialize() + + def test_deduplication_rejects_resealed_or_conflicting_blob_metadata(self) -> None: + first = self.store.import_bytes(b"phase-three", media_type="text/plain") + record_path = ( + Path(self.directory.name) / ".benchwork" / "storage" / "records" + / f"blob-{first['blob_sigil'].removeprefix('sha256:')}.json" + ) + record = json.loads(record_path.read_text(encoding="utf-8")) + record["media_type"] = "application/json" + record["record_sigil"] = content_sigil({ + key: value for key, value in record.items() if key != "record_sigil" + }) + record_path.write_text(json.dumps(record), encoding="utf-8") + + with self.assertRaisesRegex(AthanorError, "record conflict or integrity failure"): + self.store.import_bytes(b"phase-three", media_type="text/plain") + + def test_readback_requires_a_matching_immutable_blob_record(self) -> None: + record = self.store.import_bytes(b"phase-three", media_type="text/plain") + record_path = ( + Path(self.directory.name) / ".benchwork" / "storage" / "records" + / f"blob-{record['blob_sigil'].removeprefix('sha256:')}.json" + ) + record_path.unlink() + with self.assertRaisesRegex(AthanorError, "record is unavailable or invalid"): + self.store.read_bytes(record["blob_sigil"]) + + record = self.store.import_bytes(b"phase-three", media_type="text/plain") + record_path.write_text("{}", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "Blob record is invalid"): + self.store.read_bytes(record["blob_sigil"]) + + def test_readback_rejects_a_symlinked_blob_path(self) -> None: + record = self.store.import_bytes(b"phase-three", media_type="text/plain") + blob_path = ( + Path(self.directory.name) / ".benchwork" / "storage" / "blobs" + / record["blob_sigil"].removeprefix("sha256:") + ) + target = Path(self.directory.name) / "outside-blob" + target.write_bytes(b"phase-three") + blob_path.unlink() + blob_path.symlink_to(target) + with self.assertRaisesRegex(AthanorError, "Blob is unavailable"): + self.store.read_bytes(record["blob_sigil"]) + class ExecutionServiceTest(unittest.TestCase): def setUp(self) -> None: @@ -89,6 +169,34 @@ def test_start_is_idempotent_and_cancel_preserves_negative_outcome(self) -> None self.assertEqual(outcome["terminal_state"], "CANCELLED") self.assertFalse(outcome["eligible_for_acceptance"]) + def test_restart_recovers_idempotency_cancellation_and_terminal_outcome(self) -> None: + first = self.service.start(_specification(), "start-001") + job = first["job"] + + restarted = ExecutionService(Path(self.directory.name)) + replayed_start = restarted.start(_specification(), "start-001") + self.assertEqual(replayed_start["job"], job) + self.assertEqual(restarted.observe(job["job_id"])["job"], job) + + cancelled = restarted.cancel( + job["job_id"], job["job_binding_sigil"], job["revision"], + "cancel-001", "operator requested cancellation", + ) + final_job = cancelled["job"] + self.assertEqual(final_job["state"], "CANCELLED") + + recovered = ExecutionService(Path(self.directory.name)) + outcome = recovered.get_outcome(job["job_id"]) + self.assertEqual(outcome["terminal_state"], "CANCELLED") + self.assertEqual(outcome["terminal_event_sigil"], final_job["terminal_event_sigil"]) + self.assertEqual( + recovered.cancel( + job["job_id"], job["job_binding_sigil"], final_job["revision"], + "cancel-001", "operator requested cancellation", + )["job"], + final_job, + ) + def test_changed_request_under_same_task_key_is_a_conflict(self) -> None: self.service.start(_specification(), "start-001") with self.assertRaisesRegex(AthanorError, "idempotency conflict"): @@ -134,6 +242,56 @@ def test_terminal_cancellation_is_idempotent_and_cancelled_jobs_reject_success(s with self.assertRaisesRegex(AthanorError, "not terminalizable|cancelled"): self.service.record_terminal(job["job_id"], "SUCCEEDED", "late worker result") + def test_changed_cancellation_under_same_key_is_a_conflict(self) -> None: + job = self.service.start(_specification(), "start-001")["job"] + self.service.cancel( + job["job_id"], job["job_binding_sigil"], job["revision"], + "cancel-001", "operator requested cancellation", + ) + terminal = self.service.observe(job["job_id"])["job"] + with self.assertRaisesRegex(AthanorError, "cancellation idempotency conflict"): + self.service.cancel( + job["job_id"], job["job_binding_sigil"], terminal["revision"], + "cancel-001", "different cancellation reason", + ) + + def test_expired_local_job_retains_negative_outcome_and_rejects_late_delivery(self) -> None: + job = self.service.start(_specification(), "start-001")["job"] + self.service.queue(job["job_id"]) + expired = self.service.record_terminal( + job["job_id"], "LEASE_EXPIRED", "local lease deadline elapsed", + ) + self.assertEqual(expired["job"]["state"], "LEASE_EXPIRED") + outcome = self.service.get_outcome(job["job_id"]) + self.assertEqual(outcome["terminal_state"], "LEASE_EXPIRED") + self.assertFalse(outcome["eligible_for_acceptance"]) + with self.assertRaisesRegex(AthanorError, "not terminalizable"): + self.service.record_terminal(job["job_id"], "SUCCEEDED", "late worker result") + + def test_duplicate_terminal_delivery_is_rejected_without_rewriting_history(self) -> None: + job = self.service.start(_specification(), "start-001")["job"] + self.service.queue(job["job_id"]) + terminal = self.service.record_terminal(job["job_id"], "FAILED", "worker failed") + event_count = len(self.service.observe(job["job_id"])["events"]) + + with self.assertRaisesRegex(AthanorError, "not terminalizable"): + self.service.record_terminal(job["job_id"], "FAILED", "worker failed") + + observation = self.service.observe(job["job_id"]) + self.assertEqual(observation["job"], terminal["job"]) + self.assertEqual(len(observation["events"]), event_count) + + def test_worker_terminal_requires_durable_queue_and_survives_restart(self) -> None: + job = self.service.start(_specification(), "start-001")["job"] + with self.assertRaisesRegex(AthanorError, "must be queued"): + self.service.record_terminal(job["job_id"], "SUCCEEDED", "worker completed") + + queued = self.service.queue(job["job_id"])["job"] + restarted = ExecutionService(Path(self.directory.name)) + self.assertEqual(restarted.observe(job["job_id"])["job"], queued) + terminal = restarted.record_terminal(job["job_id"], "SUCCEEDED", "worker completed") + self.assertEqual(terminal["job"]["state"], "SUCCEEDED") + def test_tampered_journal_fails_closed(self) -> None: observation = self.service.start(_specification(), "start-001") journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" @@ -141,6 +299,232 @@ def test_tampered_journal_fails_closed(self) -> None: with self.assertRaisesRegex(AthanorError, "Sigil|journal"): self.service.observe(observation["job"]["job_id"]) + def test_resealed_wrong_journal_identity_and_duplicate_epoch_fail_closed(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + + events[1]["journal_id"] = "EJ-OTHER" + events[1]["event_sigil"] = content_sigil({ + key: value for key, value in events[1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "identity is invalid"): + self.service.observe(observation["job"]["job_id"]) + + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + events[1]["journal_id"] = events[0]["journal_id"] + events[1]["event_type"] = "executor.epoch-started" + events[1]["payload"] = events[0]["payload"] + events[1]["event_sigil"] = content_sigil({ + key: value for key, value in events[1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "duplicate executor epoch"): + self.service.observe(observation["job"]["job_id"]) + + def test_resealed_unknown_or_duplicate_event_identity_fails_in_loader(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + + events[1]["event_type"] = "job.unknown" + events[1]["event_sigil"] = content_sigil({ + key: value for key, value in events[1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "Event type is invalid"): + self.service.observe(observation["job"]["job_id"]) + + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + events[1]["event_type"] = "job.submitted" + events[1]["event_id"] = events[0]["event_id"] + events[1]["event_sigil"] = content_sigil({ + key: value for key, value in events[1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "duplicate Event identity"): + self.service.observe(observation["job"]["job_id"]) + + def test_resealed_noncanonical_event_scalars_fail_in_loader(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + events[1]["sequence"] = True + events[1]["event_sigil"] = content_sigil({ + key: value for key, value in events[1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "scalar fields are invalid"): + self.service.observe(observation["job"]["job_id"]) + + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + events[1]["sequence"] = 2 + events[1]["recorded_at"] = "2026-08-06T00:00:00+00:00" + events[1]["event_sigil"] = content_sigil({ + key: value for key, value in events[1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "recorded_at is invalid"): + self.service.observe(observation["job"]["job_id"]) + + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + events[1]["recorded_at"] = events[0]["recorded_at"] + events[1]["event_id"] = "JE-NOT-CANONICAL" + events[1]["event_sigil"] = content_sigil({ + key: value for key, value in events[1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "scalar fields are invalid"): + self.service.observe(observation["job"]["job_id"]) + + def test_resealed_decreasing_event_time_fails_in_loader(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + events[1]["recorded_at"] = "1970-01-01T00:00:00Z" + events[1]["event_sigil"] = content_sigil({ + key: value for key, value in events[1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "time is decreasing"): + self.service.observe(observation["job"]["job_id"]) + + def test_resealed_event_payloads_cannot_break_local_replay_bindings(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + + events[1]["payload"]["job_binding_sigil"] = "sha256:" + "2" * 64 + events[1]["event_sigil"] = content_sigil({ + key: value for key, value in events[1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "submission binding"): + self.service.observe(observation["job"]["job_id"]) + + journal.unlink() + observation = self.service.start(_specification(), "start-002") + job = observation["job"] + self.service.cancel( + job["job_id"], job["job_binding_sigil"], job["revision"], + "cancel-001", "operator requested cancellation", + ) + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + events[2]["payload"]["expected_job_revision"] = 99 + for index in range(2, len(events)): + if index > 2: + events[index]["previous_event_sigil"] = events[index - 1]["event_sigil"] + events[index]["event_sigil"] = content_sigil({ + key: value for key, value in events[index].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "invalid execution Job cancellation"): + self.service.observe(job["job_id"]) + + def test_resealed_local_payload_scalars_reject_bool_and_unhashable_values(self) -> None: + observation = self.service.start(_specification(), "start-001") + job = observation["job"] + self.service.cancel( + job["job_id"], job["job_binding_sigil"], job["revision"], + "cancel-001", "operator requested cancellation", + ) + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + events[2]["payload"]["expected_job_revision"] = True + for index in range(2, len(events)): + if index > 2: + events[index]["previous_event_sigil"] = events[index - 1]["event_sigil"] + events[index]["event_sigil"] = content_sigil({ + key: value for key, value in events[index].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "cancellation payload is invalid"): + self.service.observe(job["job_id"]) + + journal.unlink() + observation = self.service.start(_specification(), "start-002") + job = observation["job"] + self.service.queue(job["job_id"]) + self.service.record_terminal(job["job_id"], "FAILED", "worker failed") + events = [json.loads(line) for line in journal.read_text(encoding="utf-8").splitlines()] + events[-1]["payload"]["state"] = [] + events[-1]["event_sigil"] = content_sigil({ + key: value for key, value in events[-1].items() if key != "event_sigil" + }) + journal.write_text("\n".join(json.dumps(event) for event in events) + "\n", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "terminal payload is invalid"): + self.service.observe(job["job_id"]) + + def test_local_persistence_rejects_duplicate_keys_and_nonfinite_numbers(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + raw = journal.read_text(encoding="utf-8") + duplicated = raw.replace( + '"task_id":"TK-001"', '"task_id":"TK-001","task_id":"TK-TWO"', 1, + ) + journal.write_text(duplicated, encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "duplicate JSON key: task_id"): + self.service.observe(observation["job"]["job_id"]) + + journal.write_text(raw.replace('"payload":{', '"payload":{"ignored":NaN,', 1), encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "non-finite JSON number"): + self.service.observe(observation["job"]["job_id"]) + + def test_local_journal_rejects_invalid_utf8_on_recovery(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + journal.write_bytes(b"\xff\xfe") + with self.assertRaisesRegex(AthanorError, "journal is unreadable"): + self.service.observe(observation["job"]["job_id"]) + + def test_local_journal_rejects_a_directory_at_its_file_path(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + journal.unlink() + journal.mkdir() + with self.assertRaisesRegex(AthanorError, "journal is unreadable"): + self.service.observe(observation["job"]["job_id"]) + + def test_local_journal_rejects_a_symlink_at_its_file_path(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + target = Path(self.directory.name) / "outside-journal.jsonl" + target.write_bytes(journal.read_bytes()) + journal.unlink() + journal.symlink_to(target) + with self.assertRaisesRegex(AthanorError, "journal is unreadable"): + self.service.observe(observation["job"]["job_id"]) + + def test_execution_initialize_rejects_malformed_managed_paths(self) -> None: + execution = Path(self.directory.name) / ".benchwork" / "execution" + execution.parent.mkdir(parents=True) + execution.write_text("not a directory", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "execution storage path is not a directory"): + self.service.start(_specification(), "start-001") + + execution.unlink() + execution.mkdir() + (execution / "locks").write_text("not a directory", encoding="utf-8") + with self.assertRaisesRegex(AthanorError, "execution lock path is not a directory"): + self.service.start(_specification(), "start-001") + + def test_execution_initialize_rejects_symlinked_managed_root(self) -> None: + execution = Path(self.directory.name) / ".benchwork" / "execution" + target = Path(self.directory.name) / "outside-execution" + target.mkdir() + execution.parent.mkdir(parents=True) + execution.symlink_to(target, target_is_directory=True) + with self.assertRaisesRegex(AthanorError, "execution storage path is not a directory"): + self.service.start(_specification(), "start-001") + + def test_local_journal_rejects_an_unterminated_tail_on_recovery(self) -> None: + observation = self.service.start(_specification(), "start-001") + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + journal.write_bytes(journal.read_bytes().rstrip(b"\n")) + with self.assertRaisesRegex(AthanorError, "incomplete tail"): + self.service.observe(observation["job"]["job_id"]) + def test_read_of_unknown_job_does_not_initialize_execution_state(self) -> None: with self.assertRaisesRegex(AthanorError, "unknown execution Job"): self.service.observe("JB-" + "A" * 64) @@ -166,10 +550,20 @@ def test_specification_and_start_key_validation_fail_closed(self) -> None: with self.assertRaisesRegex(AthanorError, "idempotency key"): self.service.start(_specification(), "\x00") + extra = _specification() + extra["backend_configuration"] = {"command": "must-not-be-accepted"} + extra["specification_sigil"] = content_sigil( + {key: value for key, value in extra.items() if key != "specification_sigil"} + ) + with self.assertRaisesRegex(AthanorError, "specification is incomplete"): + self.service.start(extra, "start-001") + def test_observation_and_cancel_validation_fail_closed(self) -> None: job = self.service.start(_specification(), "start-001")["job"] with self.assertRaisesRegex(AthanorError, "observation limit"): self.service.observe(job["job_id"], limit=0) + with self.assertRaisesRegex(AthanorError, "observation limit"): + self.service.observe(job["job_id"], limit=True) with self.assertRaisesRegex(AthanorError, "cursor is invalid"): self.service.observe(job["job_id"], cursor={}) with self.assertRaisesRegex(AthanorError, "Job ID is invalid"): @@ -180,9 +574,18 @@ def test_observation_and_cancel_validation_fail_closed(self) -> None: self.service.cancel( job["job_id"], job["job_binding_sigil"], job["revision"] + 1, "cancel-001", "reason" ) + with self.assertRaisesRegex(AthanorError, "cancellation revision"): + self.service.cancel( + job["job_id"], job["job_binding_sigil"], True, "cancel-001", "reason" + ) + with self.assertRaisesRegex(AthanorError, "cancellation idempotency key"): + self.service.cancel( + job["job_id"], job["job_binding_sigil"], job["revision"], "\x00", "reason" + ) def test_completed_job_records_terminal_cancellation_observation(self) -> None: job = self.service.start(_specification(), "start-001")["job"] + self.service.queue(job["job_id"]) completed = self.service.record_terminal(job["job_id"], "SUCCEEDED", "worker completed") terminal = completed["job"] observed = self.service.cancel( @@ -197,9 +600,9 @@ def test_completed_job_records_terminal_cancellation_observation(self) -> None: def test_queued_job_can_terminalize_and_invalid_journal_json_is_rejected(self) -> None: job = self.service.start(_specification(), "start-001")["job"] - self.service._append_unlocked("job.queued", {"job_id": job["job_id"]}) - queued = self.service.observe(job["job_id"])["job"] + queued = self.service.queue(job["job_id"])["job"] self.assertEqual(queued["state"], "QUEUED") + self.assertEqual(self.service.queue(job["job_id"])["job"], queued) failed = self.service.record_terminal(job["job_id"], "FAILED", "worker failed") self.assertEqual(failed["job"]["state"], "FAILED") @@ -208,6 +611,15 @@ def test_queued_job_can_terminalize_and_invalid_journal_json_is_rejected(self) - with self.assertRaisesRegex(AthanorError, "invalid JSON"): self.service.observe(job["job_id"]) + def test_invalid_internal_transition_is_rejected_before_journal_publication(self) -> None: + job = self.service.start(_specification(), "start-001")["job"] + journal = Path(self.directory.name) / ".benchwork" / "execution" / "journal.jsonl" + before = journal.read_bytes() + with self.assertRaisesRegex(AthanorError, "queue transition"): + self.service._append_unlocked("job.queued", {"job_id": "JB-" + "A" * 64}) + self.assertEqual(journal.read_bytes(), before) + self.assertEqual(self.service.observe(job["job_id"])["job"], job) + def test_host_neutral_runtime_returns_stable_execution_errors(self) -> None: Athanor(Path(self.directory.name)).initialize() tools = BenchworkTools(Path(self.directory.name)) @@ -219,6 +631,21 @@ def test_host_neutral_runtime_returns_stable_execution_errors(self) -> None: not_ready = tools.benchwork_get_job_result(started["data"]["job"]["job_id"]) self.assertFalse(not_ready["ok"]) self.assertEqual(not_ready["error"]["code"], "EXECUTION_NOT_READY") + service = ExecutionService(Path(self.directory.name)) + job = started["data"]["job"] + service.queue(job["job_id"]) + service.record_terminal(job["job_id"], "FAILED", "worker failed") + stale_revision = tools.benchwork_cancel_job( + job["job_id"], + job["job_binding_sigil"], + job["revision"], + "cancel-after-terminal", + "late cancellation", + ) + self.assertFalse(stale_revision["ok"]) + self.assertEqual(stale_revision["error"]["code"], "EXECUTION_CONFLICT") + + started = tools.benchwork_start_job(_specification(specification_id="ES-002"), "start-002") cancelled = tools.benchwork_cancel_job( started["data"]["job"]["job_id"], started["data"]["job"]["job_binding_sigil"], diff --git a/tests/test_execution_job_outcome_v1_contract.py b/tests/test_execution_job_outcome_v1_contract.py new file mode 100644 index 0000000..d1479af --- /dev/null +++ b/tests/test_execution_job_outcome_v1_contract.py @@ -0,0 +1,560 @@ +import json +from copy import deepcopy +from pathlib import Path +from typing import Any + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.execution_contracts import derive_execution_output_storage_observation_set_id_v1 +from benchwork.execution_job_outcome import ( + derive_execution_job_outcome_derivation_profile_v1, + derive_execution_job_outcome_id_v1, + derive_execution_job_outcome_sigil_v1, + execution_job_outcome_algorithm_sigil_v1, + execution_job_outcome_imported_schema_set_v1, + load_execution_job_outcome_v1, + require_execution_job_outcome_acceptance_eligibility_authority_v1, + require_execution_job_outcome_journal_derivation_v1, + require_execution_job_outcome_runtime_authority_v1, + validate_execution_job_outcome_fixed_retry_v1, + validate_execution_job_outcome_replayed_facts_v1, + validate_execution_job_outcome_v1, +) +from benchwork.schema_validation import validate_instance + + +ROOT = Path(__file__).parents[1] +SCHEMA_PATH = ROOT / "schemas" / "execution-job-outcome-1.0.json" +FIXTURE = ( + ROOT + / "tests" + / "fixtures" + / "phase3" + / "rfc0015" + / "execution-job-outcome-v1" + / "valid-no-attempt.json" +) +OS_FIXTURE = ( + ROOT + / "tests" + / "fixtures" + / "phase3" + / "rfc0012" + / "execution-output-storage-observation-set-v1" + / "valid-minimal.json" +) +DERIVED_MEMBERS = { + "schema_version", + "outcome_id", + "acceptance_eligible", + "ineligibility_reasons", + "derivation_profile", + "outcome_sigil", +} + + +def _load() -> dict[str, Any]: + return json.loads(FIXTURE.read_text(encoding="utf-8")) + + +def _seal(outcome: dict[str, Any]) -> dict[str, Any]: + outcome["outcome_id"] = derive_execution_job_outcome_id_v1( + outcome["job_id"], outcome["job_terminal"]["event_sigil"] + ) + outcome["derivation_profile"] = derive_execution_job_outcome_derivation_profile_v1() + outcome["outcome_sigil"] = derive_execution_job_outcome_sigil_v1(outcome) + return outcome + + +def _facts(outcome: dict[str, Any]) -> dict[str, Any]: + facts = { + key: deepcopy(value) + for key, value in outcome.items() + if key not in DERIVED_MEMBERS + } + facts["expected_ineligibility_reasons"] = deepcopy( + outcome["ineligibility_reasons"] + ) + facts["output_storage_observation_set"] = None + return facts + + +def _selected() -> tuple[dict[str, Any], dict[str, Any]]: + """Build a contract-only selected-Attempt Outcome from frozen fixtures.""" + outcome = _load() + observation = json.loads(OS_FIXTURE.read_text(encoding="utf-8")) + sigil = "sha256:" + "d" * 64 + attempt_id = observation["attempt_id"] + attempt_sigil = observation["attempt_binding_sigil"] + worker = {"kind": "NONE"} + authorization = {"kind": "NONE"} + storage_binding = { + "kind": "FROZEN", + "storage_journal_id": observation["storage_event"]["journal_id"], + "through_sequence": observation["storage_event"]["sequence"], + "through_event_sigil": observation["storage_event"]["event_sigil"], + "output_storage_observation_set_id": observation["observation_set_id"], + "output_storage_observation_set_sigil": observation["observation_set_sigil"], + } + first_stop = { + "kind": "PRESENT", "event_id": "JE-STOP", "event_type": "attempt.failed", + "event_sigil": "sha256:" + "8" * 64, "effective_sequence": 8, + } + summary = { + "attempt_id": attempt_id, "attempt_binding_sigil": attempt_sigil, + "retry_ordinal": 1, "terminal_state": "FAILED", + "terminal_event_id": "JE-ATTEMPTFAILED", "terminal_event_sigil": "sha256:" + "9" * 64, + "worker_session_binding": worker, + "attempt_authorization_requirement": {"kind": "NONE", "effects": []}, + "attempt_authorization_state": authorization, + "budget_settlement_event_sigil": "sha256:" + "a" * 64, + "assurance_evaluation_event_sigil": "sha256:" + "b" * 64, + } + selected = { + "kind": "SELECTED", "attempt_id": attempt_id, "attempt_binding_sigil": attempt_sigil, + "attempt_terminal_event_id": summary["terminal_event_id"], + "attempt_terminal_event_sigil": summary["terminal_event_sigil"], + "attempt_authorization_state": authorization, "worker_session_binding": worker, + "result_binding": observation["result_binding"], + "completion_anchor_binding": {"kind": "NOT_ESTABLISHED"}, + "first_stop_or_fence_binding": first_stop, + "storage_observation_binding": storage_binding, + } + outcome["job_terminal"] = { + **outcome["job_terminal"], "job_revision": 12, "event_id": "JE-JOBFAILED", + "event_sequence": 12, "event_sigil": "sha256:" + "f" * 64, + } + outcome["attempt_summaries"] = [summary] + outcome["selected_attempt_binding"] = selected + outcome["result_binding"] = selected["result_binding"] + outcome["completion_anchor_binding"] = selected["completion_anchor_binding"] + outcome["first_stop_or_fence_binding"] = first_stop + outcome["lease_terminal_binding"] = {"kind": "NONE"} + outcome["authority_binding"] = { + "kind": "ASSIGNED_NO_LEASE", "allocation_executor_instance_id": "XI-ONE", + "allocation_executor_epoch": 1, "allocation_executor_build_sigil": sigil, + "job_id": outcome["job_id"], "attempt_id": attempt_id, "fencing_generation": 1, + } + outcome["final_fence_binding"] = { + "kind": "ASSIGNED_NO_LEASE", "final_fence_floor": 1, "attempt_id": attempt_id, + "attempt_terminal_event_sigil": summary["terminal_event_sigil"], + } + outcome["runtime_outcome"] = { + "kind": "ATTEMPT", "computation_status": "FAILED", "worker_status": "FAILED", + "process_termination_status": "EXITED", "handle_revocation_status": "NOT_APPLICABLE", + "cleanup_status": "VERIFIED", "mutable_resource_isolation_status": "VERIFIED_ISOLATED", + "output_publication_status": "FAILED", "quarantine_status": "NOT_REQUIRED", + "termination_evidence_sigil": sigil, "handle_disposition_evidence_sigil": sigil, + "cleanup_summary_sigil": sigil, "quarantine_evidence_sigil": sigil, + "log_closure_sigil": observation["log_closure_sigil"], + "output_closure_sigil": observation["output_closure_sigil"], + "accounting_capture_event_id": "JE-ACCOUNTING", "accounting_capture_event_sigil": sigil, + } + outcome["terminal_source_binding"] = observation["terminal_source_binding"] + outcome["terminal_source_observation"] = observation["members"][-1] + outcome["assurance_context_binding"] = { + **{key: value for key, value in outcome["assurance_context_binding"].items() if key != "kind"}, + "kind": "ATTEMPT", "backend_identity": "local-backend", + "backend_configuration_sigil": sigil, "host_identity_sigil": sigil, + } + outcome["attempt_assurance_binding"] = { + "kind": "UNMET", "evaluation_event_id": "JE-ATTEMPTASSURANCE", + "evaluation_event_sigil": summary["assurance_evaluation_event_sigil"], + "evaluation_sequence": 10, "reason_codes": ["ASSURANCE_UNMET"], "evidence_set_sigil": sigil, + } + outcome["job_assurance_binding"] = { + "kind": "UNMET", "evaluation_event_id": "JE-JOBASSURANCE", + "evaluation_event_sigil": "sha256:" + "c" * 64, "evaluation_sequence": 11, + "attempt_id": attempt_id, + "attempt_assurance_event_sigil": summary["assurance_evaluation_event_sigil"], + "reason_codes": ["ASSURANCE_UNMET"], "evidence_set_sigil": sigil, + } + for member in ( + "control_evidence_set_binding", "quarantine_binding_set_binding", + "terminalization_storage_manifest_binding", "output_root_protection", + ): + outcome[member] = observation[member] + outcome["budget_binding"]["selected_attempt_settlement"] = { + "kind": "SETTLED", "event_id": "JE-BUDGETSETTLED", + "event_sigil": summary["budget_settlement_event_sigil"], + "accounting_capture_event_id": "JE-ACCOUNTING", "accounting_capture_event_sigil": sigil, + "usage_status": "MEASURED", + } + outcome["outputs"] = observation["members"][:1] + outcome["logs"] = observation["members"][1:4] + outcome["resource_evidence"] = observation["members"][4:5] + outcome["storage_observation_binding"] = storage_binding + outcome["ineligibility_reasons"] = [ + "JOB_NOT_SUCCEEDED", "ATTEMPT_NOT_SUCCEEDED", "COMPLETION_NOT_ESTABLISHED", + "OUTPUT_INVALID", "ASSURANCE_UNMET", "STORAGE_OBSERVATION_INVALID", + ] + outcome["terminal_recorded_at"] = "2026-08-06T00:00:12Z" + return _seal(outcome), observation + + +def test_valid_no_attempt_fixture_and_strict_loader() -> None: + outcome = _load() + validate_execution_job_outcome_v1(outcome) + assert load_execution_job_outcome_v1(FIXTURE.read_bytes()) == outcome + validate_instance("execution-job-outcome-1.0.json", outcome) + + +def test_budget_ledger_requires_exact_arithmetic_status_and_self_sigil() -> None: + outcome = _load() + ledger = outcome["budget_binding"]["job_budget_ledger"] + assert ledger["budget_ledger_sigil"] == content_sigil( + {key: value for key, value in ledger.items() if key != "budget_ledger_sigil"} + ) + + wrong_status = deepcopy(outcome) + wrong_status["budget_binding"]["job_budget_ledger"]["attempts"]["exhaustion_status"] = "EXHAUSTED" + _seal(wrong_status) + with pytest.raises(Exception, match="budget ledger self-Sigil"): + validate_execution_job_outcome_v1(wrong_status) + + arithmetic_mismatch = deepcopy(outcome) + arithmetic_mismatch["budget_binding"]["job_budget_ledger"]["attempts"]["exhaustion_status"] = "EXHAUSTED" + ledger = arithmetic_mismatch["budget_binding"]["job_budget_ledger"] + ledger["budget_ledger_sigil"] = content_sigil( + {key: value for key, value in ledger.items() if key != "budget_ledger_sigil"} + ) + _seal(arithmetic_mismatch) + with pytest.raises(Exception, match="incorrect exhaustion status"): + validate_execution_job_outcome_v1(arithmetic_mismatch) + + +def test_schema_has_exact_closed_root_and_public_rfc0014_defs() -> None: + schema = json.loads(SCHEMA_PATH.read_text(encoding="utf-8")) + assert schema["$id"] == "https://benchwork.dev/schemas/execution-job-outcome/1.0" + assert schema["additionalProperties"] is False + assert len(schema["required"]) == len(schema["properties"]) == 40 + assert set(schema["required"]) == set(schema["properties"]) + for public_definition in ( + "authority_binding", + "assurance_context_binding", + "worker_session_binding", + ): + assert public_definition in schema["$defs"] + + +def test_schema_imports_owner_defs_without_unpublished_result_schema() -> None: + source = SCHEMA_PATH.read_text(encoding="utf-8") + assert "execution-result/1.0" not in source + for reference in ( + "execution-state/1.0#/$defs/public_fence_tuple", + "execution-journal-event/1.0#/$defs/attempt_summary", + "execution-journal-event/1.0#/$defs/result_binding", + "execution-output-storage-observation-set/1.0#/$defs/attempt_output_member", + "execution-output-storage-observation-set/1.0#/$defs/log_stream_member", + "execution-output-storage-observation-set/1.0#/$defs/resource_evidence_member", + "execution-output-storage-observation-set/1.0#/$defs/terminal_source_member", + ): + assert reference in source + + +def test_id_sigil_and_derivation_profile_known_answers() -> None: + outcome = _load() + assert outcome["outcome_id"] == ( + "OJ-D7AFDAE5DDE0D4F74D68AA4ACDBA07FB14FAAD4C9B96C3DB5536992BB62B3015" + ) + assert outcome["outcome_sigil"] == derive_execution_job_outcome_sigil_v1(outcome) + assert execution_job_outcome_algorithm_sigil_v1() == ( + "sha256:2bec4db5be71e36d9b5019b30e1d58a4990d2cc3ae6a8f0c124311195aca964f" + ) + assert outcome["derivation_profile"] == ( + derive_execution_job_outcome_derivation_profile_v1() + ) + + +def test_imported_schema_set_is_complete_sorted_and_unique() -> None: + imported = execution_job_outcome_imported_schema_set_v1() + ids = [entry["schema_id"] for entry in imported] + assert ids == sorted(ids, key=lambda item: item.encode("utf-8")) + assert len(ids) == len(set(ids)) == 25 + assert all(set(entry) == {"schema_id", "schema_sigil"} for entry in imported) + assert "https://benchwork.dev/schemas/execution-job-outcome/1.0" not in ids + assert "https://benchwork.dev/schemas/execution-journal-event/1.0" in ids + assert "https://benchwork.dev/schemas/execution-output-storage-observation-set/1.0" in ids + + +def test_no_attempt_matrix_and_directly_decidable_reasons_are_enforced() -> None: + outcome = _load() + assert outcome["attempt_summaries"] == [] + assert outcome["selected_attempt_binding"] == {"kind": "NONE"} + assert outcome["authority_binding"] == {"kind": "NO_ATTEMPT"} + assert outcome["final_fence_binding"] == { + "kind": "NO_ATTEMPT", + "final_fence_floor": 0, + } + assert outcome["runtime_outcome"]["kind"] == "NO_ATTEMPT" + assert outcome["outputs"] == outcome["logs"] == outcome["resource_evidence"] == [] + assert outcome["ineligibility_reasons"] == [ + "JOB_NOT_SUCCEEDED", + "ATTEMPT_ABSENT", + ] + + missing_reason = deepcopy(outcome) + missing_reason["ineligibility_reasons"] = ["ATTEMPT_ABSENT"] + _seal(missing_reason) + with pytest.raises(AthanorError, match="JOB_NOT_SUCCEEDED"): + validate_execution_job_outcome_v1(missing_reason) + + wrong_runtime = deepcopy(outcome) + wrong_runtime["runtime_outcome"]["worker_status"] = "FAILED" + _seal(wrong_runtime) + with pytest.raises(AthanorError): + validate_execution_job_outcome_v1(wrong_runtime) + + +def test_selected_attempt_direct_copies_and_observation_reconstruction() -> None: + outcome, observation = _selected() + validate_execution_job_outcome_v1(outcome) + facts = _facts(outcome) + facts["output_storage_observation_set"] = observation + validate_execution_job_outcome_replayed_facts_v1(outcome, facts) + assert [member["stream"] for member in outcome["logs"]] == [ + "STDOUT", "STDERR", "STRUCTURED", + ] + assert [ + *outcome["outputs"], *outcome["logs"], *outcome["resource_evidence"], + outcome["terminal_source_observation"], + ] == observation["members"] + + +def test_selected_outcome_cannot_omit_locally_evident_authority_loss() -> None: + outcome, _ = _selected() + completion = { + "kind": "NO_RESULT", "event_id": "JE-DRAINING", + "event_sigil": "sha256:" + "7" * 64, "sequence": 8, + "process_exit_observation_sigil": "sha256:" + "6" * 64, + } + outcome["completion_anchor_binding"] = completion + outcome["selected_attempt_binding"]["completion_anchor_binding"] = completion + outcome["ineligibility_reasons"] = [ + "JOB_NOT_SUCCEEDED", "ATTEMPT_NOT_SUCCEEDED", + "AUTHORITY_LOST_BEFORE_COMPLETION", "OUTPUT_INVALID", "ASSURANCE_UNMET", + "STORAGE_OBSERVATION_INVALID", + ] + _seal(outcome) + validate_execution_job_outcome_v1(outcome) + + missing_reason = deepcopy(outcome) + missing_reason["ineligibility_reasons"].remove("AUTHORITY_LOST_BEFORE_COMPLETION") + _seal(missing_reason) + with pytest.raises(AthanorError, match="AUTHORITY_LOST_BEFORE_COMPLETION"): + validate_execution_job_outcome_v1(missing_reason) + + +def test_selected_outcome_cannot_omit_invalid_attempt_authorization_matrix_reason() -> None: + outcome, _ = _selected() + outcome["attempt_summaries"][0]["attempt_authorization_requirement"] = { + "kind": "NONE", "effects": [], + } + outcome["attempt_summaries"][0]["attempt_authorization_state"] = {"kind": "PENDING"} + outcome["selected_attempt_binding"]["attempt_authorization_state"] = {"kind": "PENDING"} + _seal(outcome) + with pytest.raises(AthanorError, match="ATTEMPT_AUTHORIZATION_INVALID"): + validate_execution_job_outcome_v1(outcome) + + outcome["ineligibility_reasons"] = [ + "JOB_NOT_SUCCEEDED", "ATTEMPT_NOT_SUCCEEDED", "COMPLETION_NOT_ESTABLISHED", + "ATTEMPT_AUTHORIZATION_INVALID", "OUTPUT_INVALID", "ASSURANCE_UNMET", + "STORAGE_OBSERVATION_INVALID", + ] + _seal(outcome) + validate_execution_job_outcome_v1(outcome) + + +def test_selected_outcome_rejects_nonpositive_attempt_retry_ordinal() -> None: + outcome, _ = _selected() + outcome["attempt_summaries"][0]["retry_ordinal"] = 0 + _seal(outcome) + with pytest.raises(AthanorError, match="retry ordinal"): + validate_execution_job_outcome_v1(outcome) + + +@pytest.mark.parametrize( + ("mutation", "message"), + [ + ("selected_copy", "direct result_binding"), + ("authority_job", "authority bindings disagree"), + ("final_fence", "authority bindings disagree"), + ("manifest_copy", "frozen manifest"), + ("terminal_source", "terminal-source observation"), + ], +) +def test_selected_cross_object_equalities_fail_closed(mutation: str, message: str) -> None: + outcome, _ = _selected() + if mutation == "selected_copy": + outcome["result_binding"] = { + "kind": "REJECTED", "message_sigil": "sha256:" + "1" * 64, + "disposition_event_id": "JE-REJECTED", "disposition_event_sigil": "sha256:" + "2" * 64, + "disposition_sequence": 6, "reason_codes": ["RESULT_CONFLICT"], + } + elif mutation == "authority_job": + outcome["authority_binding"]["job_id"] = "JB-" + "B" * 64 + elif mutation == "final_fence": + outcome["final_fence_binding"]["final_fence_floor"] = 2 + elif mutation == "manifest_copy": + outcome["output_root_protection"]["terminalization_storage_manifest_binding"][ + "storage_root_manifest_sigil" + ] = "sha256:" + "0" * 64 + else: + outcome["terminal_source_observation"] = { + "kind": "TERMINAL_SOURCE_NONE", "reason_codes": ["SOURCE_ABSENT"], + } + _seal(outcome) + with pytest.raises(AthanorError, match=message): + validate_execution_job_outcome_v1(outcome) + + +@pytest.mark.parametrize( + "reason", + ("COMPLETION_NOT_ESTABLISHED", "OUTPUT_INVALID", "ASSURANCE_UNMET", "STORAGE_OBSERVATION_INVALID"), +) +def test_selected_outcome_cannot_omit_a_locally_required_reason(reason: str) -> None: + outcome, _ = _selected() + outcome["ineligibility_reasons"].remove(reason) + _seal(outcome) + with pytest.raises(AthanorError, match=reason): + validate_execution_job_outcome_v1(outcome) + + +def test_supplied_observation_set_must_match_outcome_owner_and_closure() -> None: + outcome, observation = _selected() + observation["job_id"] = "JB-" + "B" * 64 + observation["observation_set_id"] = derive_execution_output_storage_observation_set_id_v1(observation) + observation["observation_set_sigil"] = content_sigil({ + key: value for key, value in observation.items() if key != "observation_set_sigil" + }) + for binding in ( + outcome["storage_observation_binding"], + outcome["selected_attempt_binding"]["storage_observation_binding"], + ): + binding["output_storage_observation_set_id"] = observation["observation_set_id"] + binding["output_storage_observation_set_sigil"] = observation["observation_set_sigil"] + _seal(outcome) + facts = _facts(outcome) + facts["output_storage_observation_set"] = observation + with pytest.raises(AthanorError, match="observation-set job_id"): + validate_execution_job_outcome_replayed_facts_v1(outcome, facts) + + +def test_selected_leased_authority_tuple_is_closed_and_cross_bound() -> None: + outcome, _ = _selected() + sigil = "sha256:" + "e" * 64 + worker = { + "kind": "BOUND", "worker_id": "WK-ONE", "worker_binding_sigil": sigil, + "worker_session_id": "WS-01ARZ3NDEKTSV4RRFFQ69G5FAV", + "worker_session_binding_sigil": sigil, + } + lease_id = "LS-01ARZ3NDEKTSV4RRFFQ69G5FAV" + outcome["attempt_summaries"][0]["worker_session_binding"] = worker + outcome["selected_attempt_binding"]["worker_session_binding"] = worker + outcome["authority_binding"] = { + "kind": "LEASED", "executor_instance_id": "XI-ONE", "executor_epoch": 1, + "executor_build_sigil": sigil, + "public_fence_tuple": { + "journal_id": "EJ-MAIN", "executor_epoch": 1, "job_id": outcome["job_id"], + "attempt_id": outcome["selected_attempt_binding"]["attempt_id"], "lease_id": lease_id, + "fencing_generation": 1, + }, + } + outcome["lease_terminal_binding"] = { + "kind": "TERMINAL", "lease_id": lease_id, "lease_state": "FENCED", + "terminal_event_id": "JE-LEASEFENCED", "terminal_event_sigil": sigil, + "final_fence_floor": 1, "tombstone_event_sigil": "sha256:" + "f" * 64, + } + outcome["final_fence_binding"] = { + "kind": "TOMBSTONE", "final_fence_floor": 1, "lease_id": lease_id, + "lease_terminal_event_sigil": sigil, "tombstone_event_sigil": "sha256:" + "f" * 64, + } + _seal(outcome) + validate_execution_job_outcome_v1(outcome) + + wrong_epoch = deepcopy(outcome) + wrong_epoch["authority_binding"]["executor_epoch"] = 2 + _seal(wrong_epoch) + with pytest.raises(AthanorError, match="leased authority"): + validate_execution_job_outcome_v1(wrong_epoch) + + +def test_reason_order_and_eligibility_equivalence_are_enforced() -> None: + outcome = _load() + reversed_reasons = deepcopy(outcome) + reversed_reasons["ineligibility_reasons"].reverse() + _seal(reversed_reasons) + with pytest.raises(AthanorError, match="canonical order"): + validate_execution_job_outcome_v1(reversed_reasons) + + wrong_eligibility = deepcopy(outcome) + wrong_eligibility["acceptance_eligible"] = True + _seal(wrong_eligibility) + with pytest.raises(AthanorError): + validate_execution_job_outcome_v1(wrong_eligibility) + + +def test_supplied_facts_compare_every_nonderived_field_but_grant_no_authority() -> None: + outcome = _load() + facts = _facts(outcome) + validate_execution_job_outcome_replayed_facts_v1(outcome, facts) + + wrong = deepcopy(facts) + wrong["terminal_recorded_at"] = "2026-08-06T00:00:04Z" + with pytest.raises(AthanorError, match="terminal_recorded_at"): + validate_execution_job_outcome_replayed_facts_v1(outcome, wrong) + + extra = deepcopy(facts) + extra["journal_is_current"] = True + with pytest.raises(AthanorError, match="exact closed field set"): + validate_execution_job_outcome_replayed_facts_v1(outcome, extra) + + +def test_retry_requires_same_id_and_identical_canonical_record() -> None: + outcome = _load() + validate_execution_job_outcome_fixed_retry_v1(outcome, deepcopy(outcome)) + + changed = deepcopy(outcome) + changed["terminal_recorded_at"] = "2026-08-06T00:00:04Z" + _seal(changed) + with pytest.raises(AthanorError, match="byte-for-byte"): + validate_execution_job_outcome_fixed_retry_v1(outcome, changed) + + different = deepcopy(outcome) + different["job_terminal"]["event_sigil"] = "sha256:" + "0" * 64 + _seal(different) + with pytest.raises(AthanorError, match="identity"): + validate_execution_job_outcome_fixed_retry_v1(outcome, different) + + +@pytest.mark.parametrize( + "raw", + [ + b'\xff\xfe{\x00}\x00', + b'\xef\xbb\xbf{}', + b'{"schema_version":"execution-job-outcome/1.0","schema_version":"x"}', + b'{"outer":{"member":1,"member":2}}', + b'[]', + b'{} trailing', + b'{"x":NaN}', + b'{"x":1.0}', + b'{"x":"e\xcc\x81"}', + ], +) +def test_strict_loader_rejects_noncanonical_json_inputs(raw: bytes) -> None: + with pytest.raises(AthanorError): + load_execution_job_outcome_v1(raw) + + +@pytest.mark.parametrize( + "guard", + [ + require_execution_job_outcome_journal_derivation_v1, + require_execution_job_outcome_acceptance_eligibility_authority_v1, + require_execution_job_outcome_runtime_authority_v1, + ], +) +def test_contract_only_authority_surfaces_fail_closed(guard: Any) -> None: + with pytest.raises(AthanorError): + guard() diff --git a/tests/test_execution_job_submission_replay_v1.py b/tests/test_execution_job_submission_replay_v1.py new file mode 100644 index 0000000..c6e1062 --- /dev/null +++ b/tests/test_execution_job_submission_replay_v1.py @@ -0,0 +1,1689 @@ +from __future__ import annotations + +import hashlib +import json +from copy import deepcopy +from pathlib import Path +from typing import Any + +import pytest + +from benchwork.athanor import AthanorError, canonical_json, content_sigil +from benchwork.execution_contracts import ( + build_execution_state_v1, + build_execution_journal_event_v1, + derive_observation_evidence_id_v1, + derive_observation_evidence_subject_sigil_v1, + derive_result_ingress_receipt_id_v1, + replay_execution_journal_prefix_v1, + replay_execution_journal_supplied_facts_v1, + replay_execution_supplied_state_suffix_v1, + load_agent_result_acceptance_authorization_v1, + load_sanctum_assurance_claim_v1, + validate_agent_result_acceptance_authorization_v1, + validate_sanctum_assurance_claim_v1, + validate_execution_job_v1, + validate_sanctum_assurance_claim_supplied_attempt_facts_v1, +) + + +ROOT = Path(__file__).parents[1] +INITIAL = json.loads( + ( + ROOT / "tests/fixtures/phase3/rfc0012/execution-journal-event-v1/valid-initial.json" + ).read_text() +) +SIGIL = "sha256:" + "a" * 64 +SIGIL_B = "sha256:" + "b" * 64 +JOB_ID = "JB-" + "A" * 64 + + +def _job() -> dict[str, Any]: + evidence = { + "profile": "PHASE3_CHRONICLE_HEAD_ADMISSION_V1", + "job_id": JOB_ID, + "start_request_sigil": SIGIL, + "observed_chronicle_head": { + "schema_version": "chronicle-head/1.1", + "event_count": 0, + "terminal_receipt_sigil": None, + }, + "observed_at": "2026-08-06T00:00:00Z", + "validator_build_sigil": SIGIL, + "evidence_sigil": "", + } + evidence["evidence_sigil"] = content_sigil( + {key: value for key, value in evidence.items() if key != "evidence_sigil"} + ) + job: dict[str, Any] = { + "schema_version": "execution-job/1.0", + "job_id": JOB_ID, + "submitted_at": "2026-08-06T00:00:00Z", + "submission_idempotency_key_sigil": SIGIL, + "start_request_sigil": SIGIL, + "task_id": "TK-ONE", + "task_capsule_sigil": SIGIL, + "specification_id": "ES-ONE", + "specification_sigil": SIGIL, + "admission_chronicle_head": evidence["observed_chronicle_head"], + "admission_chronicle_head_evidence": evidence, + "assurance_requirement": { + "requested_level": "SANCTUM-A0", + "profile_version": "1.0", + "profile_sigil": SIGIL, + "conformance_suite_id": "CS-ONE", + "conformance_suite_sigil": SIGIL, + }, + "deadline_due_at": "2026-08-06T00:01:00Z", + "job_budget": { + "attempts": 1, + "cpu_time_seconds": 1, + "storage_bytes_written": 1, + "output_bytes": 1, + "log_bytes": 1, + "process_starts": 1, + "network_egress_bytes": 1, + "network_requests": 1, + }, + "job_storage_roots": [], + "job_binding_sigil": "", + } + job["job_binding_sigil"] = content_sigil( + {key: value for key, value in job.items() if key != "job_binding_sigil"} + ) + return job + + +def _submitted_event(job: dict[str, Any]) -> dict[str, Any]: + event = { + "schema_version": "execution-journal-event/1.0", + "journal_id": INITIAL["journal_id"], + "event_id": "JE-TWO", + "sequence": 2, + "event_type": "job.submitted", + "executor_instance_id": INITIAL["executor_instance_id"], + "executor_epoch": INITIAL["executor_epoch"], + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": job["submitted_at"], + "observed_at": None, + "entity_revisions": [ + { + "entity_kind": "JOB", + "entity_id": job["job_id"], + "preceding_revision": None, + "next_revision": 0, + } + ], + "causation_event_id": None, + "idempotency_key_sigil": job["submission_idempotency_key_sigil"], + "recovery_action_binding": None, + "payload": { + key: job[key] + for key in ( + "job_binding_sigil", + "start_request_sigil", + "submission_idempotency_key_sigil", + "admission_chronicle_head", + "admission_chronicle_head_evidence", + "deadline_due_at", + "job_budget", + "job_storage_roots", + ) + }, + "previous_event_sigil": INITIAL["event_sigil"], + } + return build_execution_journal_event_v1(event) + + +def _queued_event(submitted: dict[str, Any]) -> dict[str, Any]: + return build_execution_journal_event_v1( + { + "schema_version": "execution-journal-event/1.0", + "journal_id": submitted["journal_id"], + "event_id": "JE-THREE", + "sequence": 3, + "event_type": "job.queued", + "executor_instance_id": submitted["executor_instance_id"], + "executor_epoch": submitted["executor_epoch"], + "executor_build_sigil": submitted["executor_build_sigil"], + "recorded_at": "2026-08-06T00:00:01Z", + "observed_at": None, + "entity_revisions": [ + { + "entity_kind": "JOB", + "entity_id": JOB_ID, + "preceding_revision": 0, + "next_revision": 1, + } + ], + "causation_event_id": submitted["event_id"], + "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": { + "admission_evidence_sigil": SIGIL, + "queue_key": {"ready_sequence": 3, "job_id": JOB_ID}, + }, + "previous_event_sigil": submitted["event_sigil"], + } + ) + + +def _attempt() -> dict[str, Any]: + attempt: dict[str, Any] = { + "schema_version": "execution-attempt/1.0", + "attempt_id": "AT-ONE", + "job_id": JOB_ID, + "job_binding_sigil": _job()["job_binding_sigil"], + "retry_ordinal": 1, + "fencing_generation": 1, + "assurance_requirement": { + "requested_level": "SANCTUM-A0", + "profile_version": "1.0", + "profile_sigil": SIGIL, + "conformance_suite_id": "CS-ONE", + "conformance_suite_sigil": SIGIL, + }, + "backend_identity": "LOCAL", + "backend_version": "1.0", + "backend_implementation_sigil": SIGIL, + "backend_configuration_sigil": SIGIL, + "base_identity": None, + "base_sigil": None, + "input_identities": [], + "resume_mode": "FRESH", + "crucible_id": "CU-ONE", + "output_namespace_id": "ON-ONE", + "log_stream_ids": {"STDOUT": "LG-ONE", "STDERR": "LG-TWO", "STRUCTURED": "LG-THREE"}, + "budget_reservation": { + "attempts": 1, + "cpu_time_seconds": 1, + "storage_bytes_written": 1, + "output_bytes": 1, + "log_bytes": 1, + "process_starts": 1, + "network_egress_bytes": 1, + "network_requests": 1, + }, + "attempt_authorization_requirement": {"kind": "NONE", "effects": []}, + "created_at": "2026-08-06T00:00:02Z", + "deadline_due_at": "2026-08-06T00:00:30Z", + "attempt_binding_sigil": "", + } + attempt["attempt_binding_sigil"] = content_sigil( + {key: value for key, value in attempt.items() if key != "attempt_binding_sigil"} + ) + return attempt + + +def _reseal_attempt(attempt: dict[str, Any]) -> dict[str, Any]: + attempt["attempt_binding_sigil"] = content_sigil( + {key: value for key, value in attempt.items() if key != "attempt_binding_sigil"} + ) + return attempt + + +def _assurance_claim() -> dict[str, Any]: + claim: dict[str, Any] = { + "schema_version": "sanctum-assurance-claim/1.0", + "assurance_claim_id": "AC-0" + "0" * 25, + "job_id": JOB_ID, "attempt_id": "AT-ONE", "attempt_binding_sigil": SIGIL, + "attempt_terminal_event": {"journal_id": INITIAL["journal_id"], "sequence": 1, + "event_id": "JE-ONE", "event_sigil": SIGIL}, + "requested_assurance": "SANCTUM-A0", "realized_level": "SANCTUM-A0", + "satisfies_request": True, + "assurance_profile_binding": {"profile_version": "1.0", "profile_sigil": SIGIL, + "conformance_suite_id": "CS-ONE", "conformance_suite_sigil": SIGIL}, + "backend_identity": "LOCAL", "backend_configuration_sigil": SIGIL, + "host_binding": {"kind": "NONE"}, "policy_set_sigil": SIGIL, + "result_binding": {"kind": "NONE"}, + "control_evidence_set_binding": {"kind": "FROZEN", "control_evidence_set_id": "CES-" + "A" * 64, + "control_evidence_set_sigil": SIGIL}, + "terminal_status": {"attempt_state": "FAILED", "process_termination_status": "EXITED", + "handle_revocation_status": "REVOKED", "cleanup_status": "VERIFIED", + "quarantine_status": "NOT_REQUIRED"}, + "evidence_cut": { + "journal_prefix": {"journal_id": INITIAL["journal_id"], "ending_sequence": 1, + "ending_event_id": "JE-ONE", "ending_event_sigil": SIGIL}, + "state_sigil": SIGIL, + "accounting_capture_event": {"journal_id": INITIAL["journal_id"], "sequence": 1, + "event_id": "JE-ONE", "event_sigil": SIGIL}, + "budget_settlement_event": {"journal_id": INITIAL["journal_id"], "sequence": 1, + "event_id": "JE-ONE", "event_sigil": SIGIL}, + "control_evidence_allocation_commit_sigil": SIGIL, + "control_evidence_inventory_sigil": SIGIL, + "control_evidence_set_binding": {"kind": "FROZEN", "control_evidence_set_id": "CES-" + "A" * 64, + "control_evidence_set_sigil": SIGIL}, + "predicate_result_set_binding": {"schema_version": "sanctum-assurance-predicate-result-set/1.0", + "predicate_result_set_id": "PRS-" + "A" * 64, "predicate_result_set_sigil": SIGIL}, + "verification_bundle_binding": {"schema_version": "sanctum-assurance-verification-bundle/1.0", + "verification_bundle_id": "AVB-" + "A" * 64, "verification_bundle_sigil": SIGIL}, + "verification_started_at": "2026-08-06T00:00:00Z", + "verification_completed_at": "2026-08-06T00:00:01Z", + }, + "verifier_binding": { + "verifier_identity": {"verifier_id": "VERIFIER", "verifier_build_sigil": SIGIL, + "verifier_profile_id": "PROFILE", "verifier_profile_sigil": SIGIL}, + "registry_authority_binding": {"schema_version": "sanctum-verifier-registry-authority-binding/1.0", + "authority_policy_id": "VAP-" + "A" * 64, "authority_policy_sigil": SIGIL, + "installed_head_id": "VRH-" + "A" * 64, "installed_head_sigil": SIGIL, + "active_transition_id": "VAT-" + "A" * 64, "active_transition_sigil": SIGIL}, + "registry_snapshot_binding": {"schema_version": "sanctum-trusted-verifier-registry-snapshot/1.0", + "registry_snapshot_id": "VRS-0" + "0" * 25, "registry_snapshot_sigil": SIGIL}, + "authorization_binding": {"schema_version": "sanctum-verifier-authorization/1.0", + "authorization_record_id": "VAU-" + "A" * 64, "authorization_record_sigil": SIGIL}, + "authentication_binding": {"schema_version": "sanctum-verifier-authentication-evidence/1.0", + "authentication_evidence_id": "VAE-" + "A" * 64, "authentication_evidence_sigil": SIGIL}, + }, + "issued_at": "2026-08-06T00:00:02Z", "assurance_claim_sigil": "", + } + claim["assurance_claim_sigil"] = content_sigil( + {key: value for key, value in claim.items() if key != "assurance_claim_sigil"} + ) + return claim + + +def test_assurance_claim_loader_checks_local_integrity_only() -> None: + claim = _assurance_claim() + validate_sanctum_assurance_claim_v1(claim) + assert load_sanctum_assurance_claim_v1(json.dumps(claim)) == claim + stale = deepcopy(claim) + stale["issued_at"] = "2026-08-06T00:00:03Z" + with pytest.raises(AthanorError, match="self-Sigil"): + validate_sanctum_assurance_claim_v1(stale) + impossible = deepcopy(claim) + impossible["requested_assurance"] = "SANCTUM-A2" + impossible["assurance_claim_sigil"] = content_sigil({ + key: value for key, value in impossible.items() if key != "assurance_claim_sigil" + }) + with pytest.raises(AthanorError, match="below its request"): + validate_sanctum_assurance_claim_v1(impossible) + + +def _acceptance_authorization() -> dict[str, Any]: + blobs = ["sha256:" + "a" * 64, "sha256:" + "b" * 64] + policy: dict[str, Any] = { + "schema_version": "agent-result-acceptance-policy/1.0", + "policy_id": "agent-result-acceptance", "policy_version": "1.0", + "canonical_event_type": "agent-result.accepted", + "transition_request_schema": "agent-result-acceptance-transition-request/1.0", + "authorization_schema": "agent-result-acceptance-authorization/1.0", + "agent_result_schema": "agent-result/2.0", "job_outcome_schema": "execution-job-outcome/1.0", + "reference_intent_schema": "artifact-storage-reference-intent/1.0", + "chronicle_event_schema": "chronicle-event/1.1", "receipt_schema": "receipt/1.1", + "ward_evaluator_profile": "sanctum-authority-intersection/1.0", + "actor_authentication_profile": "mcp-authenticated-invocation/1.0", + "predicate_profile": "agent-result-acceptance-predicates/1.0", + "predicates": [ + "EXPECTED_HEAD_ADMISSIBLE", "AUTHENTICATED_INVOCATION_MATCH", + "TASK_AUTHORITY_CHAIN_VALID", "CURRENT_WARD_PASS", "APPROVAL_CHAIN_VALID", + "OUTCOME_REDERIVATION_MATCH", "TERMINAL_SUCCESS_ELIGIBLE", + "EXECUTION_EVIDENCE_VALID", "BUDGET_SETTLED", "ASSURANCE_EVIDENCE_VALID", + "STORAGE_OBSERVATION_VALID", "TERMINAL_SOURCE_VALID", "EVIDENCE_SELECTION_FINAL", + "AGENT_RESULT_DERIVATION_MATCH", "REFERENCE_SET_CLOSURE_VALID", + "ACCEPTANCE_STORAGE_PREFIX_VALID", + ], + "policy_sigil": "", + } + policy["policy_sigil"] = content_sigil({key: value for key, value in policy.items() if key != "policy_sigil"}) + head = {"schema_version": "chronicle-head/1.1", "event_count": 1, "terminal_receipt_sigil": SIGIL} + evidence = [ + {"blob_sigil": blob, "size_bytes": 1, "replica_id": f"SR-{index}", "backend_id": "BACKEND", + "backend_generation": "1", "availability_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, "event_sigil": SIGIL}, + "integrity_evidence_sigil": SIGIL, "quarantine_status": "CLEAR"} + for index, blob in enumerate(blobs) + ] + authorization: dict[str, Any] = { + "schema_version": "agent-result-acceptance-authorization/1.0", + "transition_request_id": "", "event_type": "agent-result.accepted", + "expected_chronicle_head": head, + "authority_subject": { + "registry_binding": {"registry_id": "CR-ONE", "registry_revision": 1, "registry_sigil": SIGIL}, + "task_binding": {"task_id": "TK-ONE", "task_capsule_sigil": SIGIL}, "program_id": "RP-ONE", + "capability_binding": {"capability_id": "bench.work.exec", "contract_version": "2.0", "capability_contract_sigil": SIGIL}, + "snapshot_binding": {"snapshot_id": "SS-ONE", "snapshot_sigil": SIGIL}, + "circle_binding": {"circle_id": "CI-ONE", "circle_sigil": SIGIL}, + "execution_specification_binding": {"specification_id": "ES-" + "0" * 26, "specification_sigil": SIGIL}, + "job_binding": {"job_id": JOB_ID, "job_binding_sigil": SIGIL}, + "job_outcome_binding": {"outcome_id": "OJ-" + "A" * 64, "outcome_sigil": SIGIL}, + "agent_result_sigil": SIGIL, + }, + "ward_pass": {"status": "PASS", "ward_decision_id": "WD-ONE", "ward_decision_sigil": SIGIL, + "resolved_permission_set_sigil": SIGIL, "evaluated_chronicle_head": head, + "evaluated_at": "2026-08-06T00:00:00Z"}, + "approval": {"kind": "NOT_REQUIRED", "ward_decision_id": "WD-ONE", "ward_decision_sigil": SIGIL}, + "acceptance_policy": policy, "acceptance_request_sigil": SIGIL, "idempotency_key_sigil": SIGIL, + "reference_sets": [{"reference_set_id": "RS-ONE", "reference_set_sigil": SIGIL}], + "managed_blob_sigils": blobs, + "acceptance_storage_binding": {"storage_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, "event_sigil": SIGIL}, + "storage_state_sigil": SIGIL, "validated_blob_sigils": blobs, + "validation_evidence": evidence, "validation_evidence_set_sigil": content_sigil(evidence)}, + "actor": {"kind": "AGENT", "actor_id": "ACTOR", "authentication_context_sigil": SIGIL, "actor_sigil": ""}, + "host_invocation": {"host_identity_sigil": SIGIL, "invocation_id": "INVOCATION", "authentication_context_sigil": SIGIL, "invocation_sigil": ""}, + "chronicle_actor": {"actor_id": "ACTOR", "actor_type": "agent", "host": "codex", "authenticated_by": "MCP"}, + "requested_at": "2026-08-06T00:00:00Z", "authorization_sigil": "", + } + authorization["transition_request_id"] = "ATR-" + content_sigil([ + "agent-result-acceptance-transition-id/1.0", "TK-ONE", SIGIL, + ]).removeprefix("sha256:").upper() + authorization["actor"]["actor_sigil"] = content_sigil({ + key: value for key, value in authorization["actor"].items() if key != "actor_sigil" + }) + authorization["host_invocation"]["invocation_sigil"] = content_sigil({ + key: value for key, value in authorization["host_invocation"].items() + if key != "invocation_sigil" + }) + authorization["authorization_sigil"] = content_sigil({key: value for key, value in authorization.items() if key != "authorization_sigil"}) + return authorization + + +def test_agent_result_acceptance_authorization_checks_local_closure_only() -> None: + authorization = _acceptance_authorization() + validate_agent_result_acceptance_authorization_v1(authorization) + assert load_agent_result_acceptance_authorization_v1(json.dumps(authorization)) == authorization + unsorted = deepcopy(authorization) + unsorted["managed_blob_sigils"] = list(reversed(unsorted["managed_blob_sigils"])) + unsorted["acceptance_storage_binding"]["validated_blob_sigils"] = list( + reversed(unsorted["acceptance_storage_binding"]["validated_blob_sigils"]) + ) + unsorted["acceptance_storage_binding"]["validation_evidence"] = list( + reversed(unsorted["acceptance_storage_binding"]["validation_evidence"]) + ) + unsorted["acceptance_storage_binding"]["validation_evidence_set_sigil"] = content_sigil(unsorted["acceptance_storage_binding"]["validation_evidence"]) + unsorted["authorization_sigil"] = content_sigil({key: value for key, value in unsorted.items() if key != "authorization_sigil"}) + with pytest.raises(AthanorError, match="ASCII-sorted"): + validate_agent_result_acceptance_authorization_v1(unsorted) + mismatched = deepcopy(authorization) + mismatched["acceptance_storage_binding"]["validation_evidence_set_sigil"] = SIGIL + mismatched["authorization_sigil"] = content_sigil({key: value for key, value in mismatched.items() if key != "authorization_sigil"}) + with pytest.raises(AthanorError, match="evidence-set Sigil"): + validate_agent_result_acceptance_authorization_v1(mismatched) + wrong_id = deepcopy(authorization) + wrong_id["transition_request_id"] = "ATR-" + "A" * 64 + wrong_id["authorization_sigil"] = content_sigil({key: value for key, value in wrong_id.items() if key != "authorization_sigil"}) + with pytest.raises(AthanorError, match="request ID"): + validate_agent_result_acceptance_authorization_v1(wrong_id) + wrong_actor = deepcopy(authorization) + wrong_actor["chronicle_actor"]["actor_type"] = "human" + wrong_actor["authorization_sigil"] = content_sigil({key: value for key, value in wrong_actor.items() if key != "authorization_sigil"}) + with pytest.raises(AthanorError, match="Actor type"): + validate_agent_result_acceptance_authorization_v1(wrong_actor) + wrong_context = deepcopy(authorization) + wrong_context["host_invocation"]["authentication_context_sigil"] = "sha256:" + "c" * 64 + wrong_context["host_invocation"]["invocation_sigil"] = content_sigil({ + key: value for key, value in wrong_context["host_invocation"].items() + if key != "invocation_sigil" + }) + wrong_context["authorization_sigil"] = content_sigil({key: value for key, value in wrong_context.items() if key != "authorization_sigil"}) + with pytest.raises(AthanorError, match="authentication contexts"): + validate_agent_result_acceptance_authorization_v1(wrong_context) + outside_prefix = deepcopy(authorization) + outside_prefix["acceptance_storage_binding"]["validation_evidence"][0]["availability_event"]["sequence"] = 2 + outside_prefix["acceptance_storage_binding"]["validation_evidence_set_sigil"] = content_sigil( + outside_prefix["acceptance_storage_binding"]["validation_evidence"] + ) + outside_prefix["authorization_sigil"] = content_sigil({ + key: value for key, value in outside_prefix.items() if key != "authorization_sigil" + }) + with pytest.raises(AthanorError, match="frozen Storage prefix"): + validate_agent_result_acceptance_authorization_v1(outside_prefix) + + +def _allocated_event(queued: dict[str, Any], attempt: dict[str, Any]) -> dict[str, Any]: + ledger = { + name: {"limit": value, "reserved": value, "consumed": 0, "exhaustion_status": "EXHAUSTED"} + for name, value in attempt["budget_reservation"].items() + } + ledger["budget_ledger_sigil"] = content_sigil(ledger) + return build_execution_journal_event_v1( + { + "schema_version": "execution-journal-event/1.0", + "journal_id": queued["journal_id"], + "event_id": "JE-FOUR", + "sequence": 4, + "event_type": "job.attempt_allocated", + "executor_instance_id": queued["executor_instance_id"], + "executor_epoch": queued["executor_epoch"], + "executor_build_sigil": queued["executor_build_sigil"], + "recorded_at": attempt["created_at"], + "observed_at": None, + "entity_revisions": [ + { + "entity_kind": "JOB", + "entity_id": JOB_ID, + "preceding_revision": 1, + "next_revision": 2, + }, + { + "entity_kind": "ATTEMPT", + "entity_id": "AT-ONE", + "preceding_revision": None, + "next_revision": 0, + }, + *sorted( + ( + { + "entity_kind": "LOG_STREAM", + "entity_id": attempt["log_stream_ids"][stream], + "preceding_revision": None, + "next_revision": 0, + } + for stream in ("STDOUT", "STDERR", "STRUCTURED") + ), + key=lambda item: item["entity_id"], + ), + ], + "causation_event_id": queued["event_id"], + "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": { + "attempt_binding_sigil": attempt["attempt_binding_sigil"], + "retry_ordinal": 1, + "fencing_generation": 1, + "prior_fencing_counter": 0, + "resulting_fence_floor": 1, + "budget_reservation": attempt["budget_reservation"], + "resulting_budget_ledger_sigil": ledger["budget_ledger_sigil"], + }, + "previous_event_sigil": queued["event_sigil"], + } + ) + + +def _preflight_event(allocated: dict[str, Any]) -> dict[str, Any]: + return build_execution_journal_event_v1( + { + "schema_version": "execution-journal-event/1.0", "journal_id": allocated["journal_id"], + "event_id": "JE-FIVE", "sequence": 5, "event_type": "attempt.preflight_started", + "executor_instance_id": allocated["executor_instance_id"], "executor_epoch": allocated["executor_epoch"], + "executor_build_sigil": allocated["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:03Z", + "observed_at": None, + "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 0, "next_revision": 1}], + "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, + "payload": {"preflight_plan_sigil": SIGIL, "freshness_evidence_sigil": SIGIL}, + "previous_event_sigil": allocated["event_sigil"], + } + ) + + +def _preflight_passed_event(preflight: dict[str, Any]) -> dict[str, Any]: + return build_execution_journal_event_v1( + { + "schema_version": "execution-journal-event/1.0", "journal_id": preflight["journal_id"], + "event_id": "JE-SIX", "sequence": 6, "event_type": "attempt.preflight_passed", + "executor_instance_id": preflight["executor_instance_id"], "executor_epoch": preflight["executor_epoch"], + "executor_build_sigil": preflight["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:04Z", + "observed_at": None, + "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 1, "next_revision": 2}], + "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, + "payload": {"materialization_identity": "MATERIALIZATION", "materialization_sigil": SIGIL, + "preflight_evidence_set_sigil": SIGIL, "input_storage_roots": []}, + "previous_event_sigil": preflight["event_sigil"], + } + ) + + +def test_job_submission_replay_requires_exact_supplied_job() -> None: + job = _job() + validate_execution_job_v1(job) + event = _submitted_event(job) + state = replay_execution_journal_prefix_v1([INITIAL, event], supplied_jobs=[job]) + assert state["jobs"][0]["state"] == "SUBMITTED" + assert state["jobs"][0]["budget_ledger"]["attempts"]["limit"] == 1 + assert state["deadlines"][0]["deadline_kind"] == "JOB_DEADLINE" + assert state["idempotency_records"][0]["scope_id"] == "TK-ONE" + + queued = _queued_event(event) + queued_state = replay_execution_journal_prefix_v1([INITIAL, event, queued], supplied_jobs=[job]) + assert queued_state["jobs"][0]["state"] == "QUEUED" + assert queued_state["jobs"][0]["queue_key"] == {"ready_sequence": 3, "job_id": JOB_ID} + + attempt = _attempt() + allocated = _allocated_event(queued, attempt) + allocated_state = replay_execution_journal_prefix_v1( + [INITIAL, event, queued, allocated], supplied_jobs=[job], supplied_attempts=[attempt] + ) + assert allocated_state["jobs"][0]["state"] == "ACTIVE" + assert allocated_state["attempts"][0]["state"] == "CREATED" + assert [stream["stream"] for stream in allocated_state["log_streams"]] == [ + "STDOUT", + "STDERR", + "STRUCTURED", + ] + future_attempt = _reseal_attempt({ + **deepcopy(attempt), + "attempt_id": "AT-TWO", + "retry_ordinal": 2, + "fencing_generation": 2, + "crucible_id": "CU-TWO", + "output_namespace_id": "ON-TWO", + "log_stream_ids": { + "STDOUT": "LG-FOUR", + "STDERR": "LG-FIVE", + "STRUCTURED": "LG-SIX", + }, + "created_at": "2026-08-06T00:00:04Z", + }) + assert replay_execution_journal_supplied_facts_v1( + [INITIAL, event, queued, allocated], + supplied_jobs=[job], + supplied_attempts=[attempt, future_attempt], + ) == allocated_state + unrelated_allocation = deepcopy(allocated) + unrelated_allocation["causation_event_id"] = event["event_id"] + unrelated_allocation = build_execution_journal_event_v1({ + key: value for key, value in unrelated_allocation.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="queued Job projection"): + replay_execution_journal_supplied_facts_v1( + [INITIAL, event, queued, unrelated_allocation], + supplied_jobs=[job], + supplied_attempts=[attempt], + ) + preflight = _preflight_event(allocated) + preflight_state = replay_execution_journal_prefix_v1( + [INITIAL, event, queued, allocated, preflight], + supplied_jobs=[job], supplied_attempts=[attempt], + ) + assert preflight_state["attempts"][0]["state"] == "PREFLIGHTING" + preflight_progress = build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], + "event_id": "JE-PREFLIGHTPROGRESS", "sequence": 6, + "event_type": "attempt.preflight_progressed", + "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": "2026-08-06T00:00:03Z", "observed_at": None, + "entity_revisions": [{ + "entity_kind": "ATTEMPT", "entity_id": "AT-ONE", + "preceding_revision": 1, "next_revision": 2, + }], + "causation_event_id": preflight["event_id"], "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": {"step": "TASK_BINDINGS_VERIFIED", "progress_evidence_sigil": SIGIL}, + "previous_event_sigil": preflight["event_sigil"], + }) + progressed_state = replay_execution_supplied_state_suffix_v1( + preflight_state, [preflight_progress] + ) + assert progressed_state["attempts"][0]["revision"] == 2 + invalid_progress = deepcopy(preflight_progress) + invalid_progress["payload"]["step"] = "NOT_A_PREFLIGHT_STEP" + invalid_progress = build_execution_journal_event_v1({ + key: value for key, value in invalid_progress.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="Preflight progress Event disagrees"): + replay_execution_supplied_state_suffix_v1(preflight_state, [invalid_progress]) + preflight_passed = _preflight_passed_event(preflight) + ready_state = replay_execution_journal_prefix_v1( + [INITIAL, event, queued, allocated, preflight, preflight_passed], + supplied_jobs=[job], supplied_attempts=[attempt], + ) + assert ready_state["attempts"][0]["state"] == "READY" + assert replay_execution_journal_supplied_facts_v1( + [INITIAL, event, queued, allocated, preflight, preflight_passed], + supplied_jobs=[job], supplied_attempts=[attempt], + ) == ready_state + + wrong_supplied = deepcopy(attempt) + wrong_supplied["attempt_binding_sigil"] = SIGIL + with pytest.raises(AthanorError, match="self-Sigil mismatch"): + replay_execution_journal_supplied_facts_v1( + [INITIAL, event, queued, allocated, preflight, preflight_passed], + supplied_jobs=[job], supplied_attempts=[wrong_supplied], + ) + + required_attempt = _attempt() + required_attempt["attempt_authorization_requirement"] = { + "kind": "REQUIRED", "effects": [{"side_effect_id": "SE-ONE", "authority_sigil": SIGIL}], + } + required_attempt["attempt_binding_sigil"] = content_sigil({ + key: value for key, value in required_attempt.items() if key != "attempt_binding_sigil" + }) + required_allocated = _allocated_event(queued, required_attempt) + required_state = replay_execution_journal_supplied_facts_v1( + [INITIAL, event, queued, required_allocated], + supplied_jobs=[job], supplied_attempts=[required_attempt], + ) + effects = required_attempt["attempt_authorization_requirement"]["effects"] + subject: dict[str, Any] = { + "schema_version": "attempt-authorization-subject/1.0", "authorization_subject_id": "", + "job_id": JOB_ID, "job_binding_sigil": job["job_binding_sigil"], + "attempt_id": required_attempt["attempt_id"], + "attempt_binding_sigil": required_attempt["attempt_binding_sigil"], + "retry_ordinal": 1, "specification_id": job["specification_id"], + "specification_sigil": job["specification_sigil"], "effects": effects, + "authorization_subject_sigil": "", + } + subject["authorization_subject_id"] = "AA-" + hashlib.sha256(canonical_json([ + "attempt-authorization-subject-id/1.0", subject["job_id"], subject["job_binding_sigil"], + subject["attempt_id"], subject["attempt_binding_sigil"], subject["retry_ordinal"], + subject["specification_id"], subject["specification_sigil"], subject["effects"], + ]).encode()).hexdigest().upper() + subject["authorization_subject_sigil"] = content_sigil({ + key: value for key, value in subject.items() if key != "authorization_subject_sigil" + }) + binding = { + "authorization_subject_id": subject["authorization_subject_id"], + "authorization_subject_sigil": subject["authorization_subject_sigil"], + "authorization_transition_request_id": "AAT-" + "A" * 64, + "authorization_transition_request_sigil": SIGIL, + "authorization_event_id": "AUTH-EVENT", "authorization_event_body_sigil": SIGIL, + "authorization_receipt_id": "RC-ONE", "authorization_receipt_sigil": SIGIL, + } + binding["authorization_binding_sigil"] = content_sigil(binding) + bound = build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], + "event_id": "JE-AUTH", "sequence": 5, "event_type": "attempt.authorization_bound", + "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, + "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:03Z", + "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 0, "next_revision": 1}], + "causation_event_id": required_allocated["event_id"], "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": {"authorization_subject": subject, "attempt_authorization_binding": binding}, + "previous_event_sigil": required_allocated["event_sigil"], + }) + bound_state = replay_execution_supplied_state_suffix_v1( + required_state, [bound], supplied_jobs=[job], supplied_attempts=[required_attempt], + ) + assert bound_state["attempts"][0]["attempt_authorization_state"]["kind"] == "BOUND" + assert replay_execution_journal_supplied_facts_v1( + [INITIAL, event, queued, required_allocated, bound], + supplied_jobs=[job], supplied_attempts=[required_attempt], + ) == bound_state + + wrong_binding = deepcopy(bound) + wrong_binding["payload"]["authorization_subject"]["specification_id"] = "ES-TWO" + wrong_binding = build_execution_journal_event_v1({ + key: value for key, value in wrong_binding.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="Subject identity"): + replay_execution_supplied_state_suffix_v1( + required_state, [wrong_binding], supplied_jobs=[job], supplied_attempts=[required_attempt], + ) + + duplicate_effect = deepcopy(bound) + duplicate_subject = duplicate_effect["payload"]["authorization_subject"] + duplicate_subject["effects"] = [ + *effects, + {"side_effect_id": "SE-ONE", "authority_sigil": "sha256:" + "b" * 64}, + ] + duplicate_subject["authorization_subject_id"] = "AA-" + hashlib.sha256( + canonical_json([ + "attempt-authorization-subject-id/1.0", duplicate_subject["job_id"], + duplicate_subject["job_binding_sigil"], duplicate_subject["attempt_id"], + duplicate_subject["attempt_binding_sigil"], duplicate_subject["retry_ordinal"], + duplicate_subject["specification_id"], duplicate_subject["specification_sigil"], + duplicate_subject["effects"], + ]).encode() + ).hexdigest().upper() + duplicate_subject["authorization_subject_sigil"] = content_sigil({ + key: value for key, value in duplicate_subject.items() + if key != "authorization_subject_sigil" + }) + duplicate_binding = duplicate_effect["payload"]["attempt_authorization_binding"] + duplicate_binding["authorization_subject_id"] = duplicate_subject["authorization_subject_id"] + duplicate_binding["authorization_subject_sigil"] = duplicate_subject["authorization_subject_sigil"] + duplicate_binding["authorization_binding_sigil"] = content_sigil({ + key: value for key, value in duplicate_binding.items() + if key != "authorization_binding_sigil" + }) + duplicate_effect = build_execution_journal_event_v1({ + key: value for key, value in duplicate_effect.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="effects are not uniquely sorted"): + replay_execution_supplied_state_suffix_v1( + required_state, [duplicate_effect], supplied_jobs=[job], supplied_attempts=[required_attempt], + ) + + rejected_cancel = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-JOBREJECT", "sequence": 7, "event_type": "job.message_rejected", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:05Z", "observed_at": None, "entity_revisions": [{"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 2, "next_revision": 3}], "causation_event_id": allocated["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"message_kind": "CANCEL_REQUEST", "message_sigil": SIGIL, "reason_codes": ["CONTROL_CHANNEL_LOST"], "historical_disposition_event_id": None}, "previous_event_sigil": preflight_passed["event_sigil"]}) + rejected_cancel_state = replay_execution_supplied_state_suffix_v1(ready_state, [rejected_cancel]) + assert rejected_cancel_state["jobs"][0]["state"] == "ACTIVE" + assert rejected_cancel_state["jobs"][0]["revision"] == 3 + + wrong_cancel = deepcopy(rejected_cancel) + wrong_cancel["payload"]["message_kind"] = "LEASE_RELEASE" + wrong_cancel = build_execution_journal_event_v1({key: value for key, value in wrong_cancel.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(ready_state, [wrong_cancel]) + + combined = deepcopy(ready_state) + session_id = "WS-00000000000000000000000000" + combined["workers"] = [{"worker_id": "WK-ONE", "revision": 1, "state": "ENABLED", "worker_binding_sigil": SIGIL, "definition_revision": 0, "worker_session_ids": [session_id], "last_event_id": "JE-SIX", "last_event_sigil": preflight_passed["event_sigil"]}] + combined["worker_sessions"] = [{"worker_session_id": session_id, "revision": 1, "state": "READY", "worker_id": "WK-ONE", "worker_binding_sigil": SIGIL, "worker_session_binding_sigil": SIGIL, "executor_epoch": 1, "worker_session_heartbeat_policy_id": "WSHP-" + "A" * 64, "worker_session_heartbeat_policy_sigil": SIGIL, "capacity": 1, "capacity_in_use": 0, "last_heartbeat_sequence": None, "last_heartbeat_message_sigil": None, "last_resource_sample_sigil": None, "resource_counter_floors": {"cpu_time_seconds": None, "storage_bytes_written": None, "network_egress_bytes": None}, "next_heartbeat_due_at": "2026-08-06T00:00:30Z", "lease_ids": [], "last_event_id": "JE-SIX", "last_event_sigil": preflight_passed["event_sigil"]}] + combined["deadlines"].append({"deadline_kind": "HEARTBEAT_TIMEOUT", "due_at": "2026-08-06T00:00:30Z", "fixed_priority": 30, "entity_id": session_id, "source_event_id": "JE-SIX", "source_event_sigil": preflight_passed["event_sigil"]}) + combined["deadlines"].sort(key=lambda item: (item["due_at"], item["fixed_priority"], item["entity_id"])) + combined["state_sigil"] = content_sigil({key: value for key, value in combined.items() if key != "state_sigil"}) + session_heartbeat = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-SESSIONHEARTBEAT", "sequence": 7, "event_type": "worker_session.heartbeat_accepted", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:05Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 1, "next_revision": 2}], "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"heartbeat_message_sigil": SIGIL, "sequence": 0, "prior_accepted_sequence": None, "received_at": "2026-08-06T00:00:05Z", "next_heartbeat_due_at": "2026-08-06T00:00:06Z", "worker_session_heartbeat_policy_id": "WSHP-" + "A" * 64, "worker_session_heartbeat_policy_sigil": SIGIL, "resource_sample_sigil": SIGIL, "resource_counter_floors_after": {"cpu_time_seconds": 0, "storage_bytes_written": 0, "network_egress_bytes": 0}}, "previous_event_sigil": preflight_passed["event_sigil"]}) + session_heartbeat_state = replay_execution_supplied_state_suffix_v1(combined, [session_heartbeat]) + assert session_heartbeat_state["worker_sessions"][0]["last_heartbeat_sequence"] == 0 + assert session_heartbeat_state["worker_sessions"][0]["next_heartbeat_due_at"] == "2026-08-06T00:00:06Z" + + wrong_session_heartbeat = deepcopy(session_heartbeat) + wrong_session_heartbeat["payload"]["sequence"] = 1 + wrong_session_heartbeat = build_execution_journal_event_v1({key: value for key, value in wrong_session_heartbeat.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(combined, [wrong_session_heartbeat]) + + rejected_session_message = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-SESSIONREJECT", "sequence": 7, "event_type": "worker_session.message_rejected", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:05Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 1, "next_revision": 2}], "causation_event_id": "JE-SIX", "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"message_kind": "WORKER_SESSION_HEARTBEAT", "message_sigil": SIGIL, "identity_binding": {"kind": "NONE"}, "reason_codes": ["CONTROL_CHANNEL_LOST"], "historical_disposition_event_id": None}, "previous_event_sigil": preflight_passed["event_sigil"]}) + rejected_session_state = replay_execution_supplied_state_suffix_v1(combined, [rejected_session_message]) + assert rejected_session_state["worker_sessions"][0]["state"] == "READY" + assert rejected_session_state["worker_sessions"][0]["revision"] == 2 + + wrong_session_message = deepcopy(rejected_session_message) + wrong_session_message["payload"]["message_kind"] = "LEASE_HEARTBEAT" + wrong_session_message = build_execution_journal_event_v1({key: value for key, value in wrong_session_message.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(combined, [wrong_session_message]) + + worker_draining = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-WORKERDRAIN", "sequence": 7, "event_type": "worker.draining", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:05Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER", "entity_id": "WK-ONE", "preceding_revision": 1, "next_revision": 2}], "causation_event_id": "JE-SIX", "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"reason_code": "ADMIN_DRAIN", "affected_worker_session_ids": [session_id]}, "previous_event_sigil": preflight_passed["event_sigil"]}) + worker_draining_state = replay_execution_supplied_state_suffix_v1(combined, [worker_draining]) + assert worker_draining_state["workers"][0]["state"] == "DRAINING" + + worker_quarantined = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-WORKERQUAR", "sequence": 8, "event_type": "worker.quarantined", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:05Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER", "entity_id": "WK-ONE", "preceding_revision": 2, "next_revision": 3}], "causation_event_id": worker_draining["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"reason_codes": ["VERIFICATION_FAILED"], "evidence_set_sigil": SIGIL, "affected_worker_session_ids": [session_id]}, "previous_event_sigil": worker_draining["event_sigil"]}) + worker_quarantined_state = replay_execution_supplied_state_suffix_v1(worker_draining_state, [worker_quarantined]) + assert worker_quarantined_state["workers"][0]["state"] == "QUARANTINED" + + wrong_worker_drain = deepcopy(worker_draining) + wrong_worker_drain["payload"]["affected_worker_session_ids"] = [] + wrong_worker_drain = build_execution_journal_event_v1({key: value for key, value in wrong_worker_drain.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(combined, [wrong_worker_drain]) + + retired_input = deepcopy(worker_quarantined_state) + retired_input["worker_sessions"][0].update({"revision": 2, "state": "CLOSED", "capacity_in_use": 0, "next_heartbeat_due_at": None, "last_event_id": worker_quarantined["event_id"], "last_event_sigil": worker_quarantined["event_sigil"]}) + retired_input["state_sigil"] = content_sigil({key: value for key, value in retired_input.items() if key != "state_sigil"}) + worker_retired = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-WORKERRETIRED", "sequence": 9, "event_type": "worker.retired", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:05Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER", "entity_id": "WK-ONE", "preceding_revision": 3, "next_revision": 4}], "causation_event_id": worker_quarantined["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"reason_code": "ADMIN_RETIRE", "closed_worker_session_ids": [session_id]}, "previous_event_sigil": worker_quarantined["event_sigil"]}) + worker_retired_state = replay_execution_supplied_state_suffix_v1(retired_input, [worker_retired]) + assert worker_retired_state["workers"][0]["state"] == "RETIRED" + + wrong_worker_retired = deepcopy(worker_retired) + wrong_worker_retired["payload"]["closed_worker_session_ids"] = [] + wrong_worker_retired = build_execution_journal_event_v1({key: value for key, value in wrong_worker_retired.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(retired_input, [wrong_worker_retired]) + + session_draining = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-SESSIONDRAIN", "sequence": 7, "event_type": "worker_session.draining", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:05Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 1, "next_revision": 2}], "causation_event_id": "JE-SIX", "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"reason_code": "ADMIN_DRAIN", "active_lease_ids": []}, "previous_event_sigil": preflight_passed["event_sigil"]}) + session_draining_state = replay_execution_supplied_state_suffix_v1(combined, [session_draining]) + assert session_draining_state["worker_sessions"][0]["state"] == "DRAINING" + + session_offline = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-SESSIONOFFLINE", "sequence": 8, "event_type": "worker_session.offline", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:05Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 2, "next_revision": 3}], "causation_event_id": session_draining["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"transition_cause": {"code": "SESSION_CHANNEL_LOST", "trigger_kind": "PRIOR_EVENT", "trigger_event_id": session_draining["event_id"], "effective_sequence": session_draining["sequence"], "evidence_sigil": SIGIL}, "last_heartbeat_sequence": None, "active_lease_ids": []}, "previous_event_sigil": session_draining["event_sigil"]}) + session_offline_state = replay_execution_supplied_state_suffix_v1(session_draining_state, [session_offline]) + assert session_offline_state["worker_sessions"][0]["next_heartbeat_due_at"] is None + + wrong_session_offline = deepcopy(session_offline) + wrong_session_offline["payload"]["active_lease_ids"] = ["LS-ONE"] + wrong_session_offline = build_execution_journal_event_v1({key: value for key, value in wrong_session_offline.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(session_draining_state, [wrong_session_offline]) + + lease: dict[str, Any] = {"schema_version": "execution-lease/1.0", "lease_id": "LS-00000000000000000000000000", "job_id": JOB_ID, "attempt_id": "AT-ONE", "worker_id": "WK-ONE", "worker_binding_sigil": SIGIL, "worker_session_id": session_id, "worker_session_binding_sigil": SIGIL, "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "fencing_generation": 1, "offered_at": "2026-08-06T00:00:05Z", "claim_due_at": "2026-08-06T00:00:06Z", "initial_expiry_due_at": "2026-08-06T00:00:07Z", "maximum_expiry_due_at": "2026-08-06T00:00:08Z", "heartbeat_policy": {"heartbeat_interval_seconds": 1, "heartbeat_timeout_seconds": 1}, "lease_credential_digest": SIGIL, "lease_binding_sigil": ""} + lease["lease_binding_sigil"] = content_sigil({key: value for key, value in lease.items() if key != "lease_binding_sigil"}) + offered = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-SEVEN", "sequence": 7, "event_type": "lease.offered", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": lease["offered_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 1, "next_revision": 2}, {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 2, "next_revision": 3}, {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": None, "next_revision": 0}], "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"lease_binding_sigil": lease["lease_binding_sigil"], "credential_digest": SIGIL, "claim_due_at": lease["claim_due_at"], "initial_expiry_due_at": lease["initial_expiry_due_at"], "maximum_expiry_due_at": lease["maximum_expiry_due_at"]}, "previous_event_sigil": preflight_passed["event_sigil"]}) + offered_state = replay_execution_supplied_state_suffix_v1(combined, [offered], supplied_leases=[lease]) + assert offered_state["leases"][0]["state"] == "OFFERED" + assert offered_state["attempts"][0]["lease_id"] == lease["lease_id"] + + claim_expired = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-CLAIMEXPIRED", "sequence": 8, "event_type": "lease.expired", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": lease["claim_due_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 2, "next_revision": 3}, {"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 2, "next_revision": 3}, {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 3, "next_revision": 4}, {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 0, "next_revision": 1}], "causation_event_id": offered["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"deadline_kind": "LEASE_CLAIM_DEADLINE", "due_at": lease["claim_due_at"], "prior_fence_floor": 1, "tombstone_generation": 2, "tombstone_publication_sigil": SIGIL, "session_capacity_after": 0}, "previous_event_sigil": offered["event_sigil"]}) + claim_expired_state = replay_execution_supplied_state_suffix_v1(offered_state, [claim_expired]) + assert claim_expired_state["leases"][0]["state"] == "EXPIRED" + assert claim_expired_state["attempts"][0]["state"] == "READY" + assert claim_expired_state["worker_sessions"][0]["next_heartbeat_due_at"] == "2026-08-06T00:00:30Z" + + claim_stop = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-CLAIMSTOP", "sequence": 9, "event_type": "attempt.stop_latched", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": lease["claim_due_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 3, "next_revision": 3}, {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 4, "next_revision": 5}], "causation_event_id": claim_expired["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"transition_cause": {"code": "LEASE_CLAIM_EXPIRED", "trigger_kind": "PRIOR_EVENT", "trigger_event_id": claim_expired["event_id"], "effective_sequence": claim_expired["sequence"], "evidence_sigil": SIGIL}, "grace_due_at": "2026-08-06T00:00:07Z"}, "previous_event_sigil": claim_expired["event_sigil"]}) + claim_stopped_state = replay_execution_supplied_state_suffix_v1(claim_expired_state, [claim_stop]) + assert claim_stopped_state["attempts"][0]["state"] == "STOPPING" + assert claim_stopped_state["attempts"][0]["first_stop_or_fence_binding"]["event_id"] == claim_expired["event_id"] + + claimed = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-EIGHT", "sequence": 8, "event_type": "lease.claimed", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:06Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 2, "next_revision": 3}, {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 3, "next_revision": 4}, {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 0, "next_revision": 1}], "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"credential_proof_sigil": SIGIL, "claimed_at": "2026-08-06T00:00:06Z", "next_heartbeat_due_at": "2026-08-06T00:00:09Z", "session_capacity_after": 1}, "previous_event_sigil": offered["event_sigil"]}) + claimed_state = replay_execution_supplied_state_suffix_v1(offered_state, [claimed]) + assert claimed_state["leases"][0]["state"] == "ACTIVE" + assert claimed_state["attempts"][0]["state"] == "LEASED" + assert claimed_state["worker_sessions"][0]["capacity_in_use"] == 1 + + fenced = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-FENCED", "sequence": 9, "event_type": "lease.fenced", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:07Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 3, "next_revision": 4}, {"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 2, "next_revision": 3}, {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 4, "next_revision": 5}, {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 1, "next_revision": 2}], "causation_event_id": claimed["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"transition_cause": {"code": "RECOVERY_FENCE", "trigger_kind": "PRIOR_EVENT", "trigger_event_id": claimed["event_id"], "effective_sequence": claimed["sequence"], "evidence_sigil": SIGIL}, "prior_fence_floor": 1, "tombstone_generation": 2, "tombstone_publication_sigil": SIGIL, "session_capacity_after": 0}, "previous_event_sigil": claimed["event_sigil"]}) + fenced_state = replay_execution_supplied_state_suffix_v1(claimed_state, [fenced]) + assert fenced_state["leases"][0]["state"] == "FENCED" + assert fenced_state["attempts"][0]["lease_terminal_binding"]["lease_state"] == "FENCED" + assert fenced_state["worker_sessions"][0]["capacity_in_use"] == 0 + + wrong_fence = deepcopy(fenced) + wrong_fence["payload"]["transition_cause"]["code"] = "CANCEL_REQUESTED" + wrong_fence = build_execution_journal_event_v1({ + key: value for key, value in wrong_fence.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="Lease fencing Event disagrees"): + replay_execution_supplied_state_suffix_v1(claimed_state, [wrong_fence]) + + nonadvancing_fence = deepcopy(claimed_state) + nonadvancing_fence["jobs"][0]["fence_floor"] = 2 + nonadvancing_fence["state_sigil"] = content_sigil( + {key: value for key, value in nonadvancing_fence.items() if key != "state_sigil"} + ) + with pytest.raises(AthanorError, match="Lease fencing Event disagrees"): + replay_execution_supplied_state_suffix_v1(nonadvancing_fence, [fenced]) + + revocation_input = deepcopy(claimed_state) + first_stop = {"kind": "PRESENT", "event_id": claimed["event_id"], "event_type": "lease.claimed", "event_sigil": claimed["event_sigil"], "effective_sequence": claimed["sequence"]} + revocation_input["jobs"][0].update({"revision": 3, "state": "STOPPING", "first_stop_or_fence_binding": first_stop, "last_event_id": "JE-STOPLATCHED", "last_event_sigil": SIGIL}) + revocation_input["attempts"][0].update({"revision": 5, "state": "STOPPING", "first_stop_or_fence_binding": first_stop, "grace_due_at": "2026-08-06T00:00:08Z", "last_event_id": "JE-STOPLATCHED", "last_event_sigil": SIGIL}) + revocation_input["state_sigil"] = content_sigil({key: value for key, value in revocation_input.items() if key != "state_sigil"}) + revoked = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-REVOKED", "sequence": 9, "event_type": "lease.revoked", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:07Z", "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 3, "next_revision": 4}, {"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 3, "next_revision": 4}, {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 5, "next_revision": 6}, {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 1, "next_revision": 2}], "causation_event_id": "JE-STOPLATCHED", "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"transition_cause": {"code": "CANCEL_REQUESTED", "trigger_kind": "PRIOR_EVENT", "trigger_event_id": claimed["event_id"], "effective_sequence": claimed["sequence"], "evidence_sigil": SIGIL}, "prior_fence_floor": 1, "tombstone_generation": 2, "tombstone_publication_sigil": SIGIL, "session_capacity_after": 0}, "previous_event_sigil": claimed["event_sigil"]}) + revoked_state = replay_execution_supplied_state_suffix_v1(revocation_input, [revoked]) + assert revoked_state["leases"][0]["state"] == "REVOKED" + assert revoked_state["attempts"][0]["lease_terminal_binding"]["lease_state"] == "REVOKED" + assert revoked_state["worker_sessions"][0]["capacity_in_use"] == 0 + + republished = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-REPUBLISHED", "sequence": 10, "event_type": "lease.tombstone_republished", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:07Z", "observed_at": None, "entity_revisions": [{"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 2, "next_revision": 3}], "causation_event_id": revoked["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"tombstone_generation": 2, "original_terminal_event_sigil": revoked["event_sigil"], "sink_ids": ["SINK"], "publication_evidence_sigil": SIGIL}, "previous_event_sigil": revoked["event_sigil"]}) + republished_state = replay_execution_supplied_state_suffix_v1(revoked_state, [republished]) + assert republished_state["leases"][0]["revision"] == 3 + assert republished_state["leases"][0]["state"] == "REVOKED" + + rejected_lease_message = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-LEASEREJECT", "sequence": 11, "event_type": "lease.message_rejected", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:07Z", "observed_at": None, "entity_revisions": [{"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 3, "next_revision": 4}], "causation_event_id": republished["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"message_kind": "LEASE_HEARTBEAT", "message_sigil": SIGIL, "identity_binding": {"kind": "NONE"}, "reason_codes": ["LEASE_TERMINAL"], "historical_disposition_event_id": None}, "previous_event_sigil": republished["event_sigil"]}) + lease_message_state = replay_execution_supplied_state_suffix_v1(republished_state, [rejected_lease_message]) + assert lease_message_state["leases"][0]["state"] == "REVOKED" + assert lease_message_state["leases"][0]["revision"] == 4 + + wrong_lease_message = deepcopy(rejected_lease_message) + wrong_lease_message["payload"]["message_kind"] = "CANCEL_REQUEST" + wrong_lease_message = build_execution_journal_event_v1({key: value for key, value in wrong_lease_message.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(republished_state, [wrong_lease_message]) + + wrong_republish = deepcopy(republished) + wrong_republish["payload"]["tombstone_generation"] = 3 + wrong_republish = build_execution_journal_event_v1({key: value for key, value in wrong_republish.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(revoked_state, [wrong_republish]) + + unlatched = deepcopy(claimed_state) + unlatched["state_sigil"] = content_sigil({key: value for key, value in unlatched.items() if key != "state_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(unlatched, [revoked]) + + expired = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-EXPIRED", "sequence": 9, "event_type": "lease.expired", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": lease["initial_expiry_due_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 3, "next_revision": 4}, {"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 2, "next_revision": 3}, {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 4, "next_revision": 5}, {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 1, "next_revision": 2}], "causation_event_id": claimed["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"deadline_kind": "LEASE_EXPIRY", "due_at": lease["initial_expiry_due_at"], "prior_fence_floor": 1, "tombstone_generation": 2, "tombstone_publication_sigil": SIGIL, "session_capacity_after": 0}, "previous_event_sigil": claimed["event_sigil"]}) + expired_state = replay_execution_supplied_state_suffix_v1(claimed_state, [expired]) + assert expired_state["leases"][0]["state"] == "EXPIRED" + assert expired_state["attempts"][0]["state"] == "LEASED" + assert expired_state["attempts"][0]["lease_terminal_binding"]["lease_state"] == "EXPIRED" + assert expired_state["jobs"][0]["fence_floor"] == 2 + assert expired_state["worker_sessions"][0]["capacity_in_use"] == 0 + + stop = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-STOP", "sequence": 10, "event_type": "attempt.stop_latched", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:07Z", "observed_at": None, "entity_revisions": [{"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 3, "next_revision": 3}, {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 5, "next_revision": 6}], "causation_event_id": expired["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"transition_cause": {"code": "LEASE_ACTIVE_EXPIRED", "trigger_kind": "PRIOR_EVENT", "trigger_event_id": expired["event_id"], "effective_sequence": expired["sequence"], "evidence_sigil": SIGIL}, "grace_due_at": "2026-08-06T00:00:08Z"}, "previous_event_sigil": expired["event_sigil"]}) + stopped_state = replay_execution_supplied_state_suffix_v1(expired_state, [stop]) + assert stopped_state["attempts"][0]["state"] == "STOPPING" + assert stopped_state["jobs"][0]["state"] == "ACTIVE" + assert stopped_state["jobs"][0]["revision"] == expired_state["jobs"][0]["revision"] + assert stopped_state["attempts"][0]["first_stop_or_fence_binding"]["event_type"] == "lease.expired" + assert any(item["deadline_kind"] == "CANCELLATION_GRACE" for item in stopped_state["deadlines"]) + + wrong_stop = deepcopy(stop) + wrong_stop["payload"]["transition_cause"]["code"] = "CANCEL_REQUESTED" + wrong_stop = build_execution_journal_event_v1({key: value for key, value in wrong_stop.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(expired_state, [wrong_stop]) + + stop_progress = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-STOPPROGRESS", "sequence": 11, "event_type": "attempt.stop_progressed", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:07Z", "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 6, "next_revision": 7}], "causation_event_id": stop["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"step": "PROCESS_TREE_TERMINATED", "termination_evidence_sigil": SIGIL, "remaining_handle_ids": []}, "previous_event_sigil": stop["event_sigil"]}) + progressed_state = replay_execution_supplied_state_suffix_v1(stopped_state, [stop_progress]) + assert progressed_state["attempts"][0]["state"] == "STOPPING" + + stopping_cleaning = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-STOPCLEAN", "sequence": 12, "event_type": "attempt.cleaning", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:07Z", "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 7, "next_revision": 8}], "causation_event_id": stop_progress["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"log_closure_sigil": SIGIL, "output_closure_sigil": SIGIL, "termination_evidence_sigil": SIGIL, "quarantine_plan_sigil": SIGIL, "terminal_source_binding": {"kind": "NOT_APPLICABLE"}}, "previous_event_sigil": stop_progress["event_sigil"]}) + stopping_clean_state = replay_execution_supplied_state_suffix_v1(progressed_state, [stopping_cleaning]) + assert stopping_clean_state["attempts"][0]["state"] == "CLEANING" + + wrong_expiry = deepcopy(expired) + wrong_expiry["payload"]["due_at"] = "2026-08-06T00:00:08Z" + wrong_expiry = build_execution_journal_event_v1({key: value for key, value in wrong_expiry.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(claimed_state, [wrong_expiry]) + + starting = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-NINE", "sequence": 9, "event_type": "attempt.starting", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:07Z", "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 4, "next_revision": 5}], "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"backend_start_handle_sigil": SIGIL, "start_request_sigil": SIGIL}, "previous_event_sigil": claimed["event_sigil"]}) + running = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-TEN", "sequence": 10, "event_type": "attempt.running", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:08Z", "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 5, "next_revision": 6}], "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"process_tree_identity": "PROCESS", "process_tree_evidence_sigil": SIGIL, "side_effect_handle_set_sigil": SIGIL}, "previous_event_sigil": starting["event_sigil"]}) + running_state = replay_execution_supplied_state_suffix_v1(claimed_state, [starting, running]) + assert running_state["attempts"][0]["state"] == "RUNNING" + + stdout_stream = next(stream for stream in running_state["log_streams"] if stream["stream"] == "STDOUT") + chunk = {"schema_version": "execution-log-chunk/1.0", "chunk_id": "LC-ONE", "log_stream_id": stdout_stream["log_stream_id"], "job_id": JOB_ID, "attempt_id": "AT-ONE", "lease_id": lease["lease_id"], "worker_id": "WK-ONE", "worker_session_id": session_id, "executor_epoch": 1, "attempt_binding_sigil": attempt["attempt_binding_sigil"], "lease_binding_sigil": lease["lease_binding_sigil"], "worker_session_binding_sigil": SIGIL, "fence_tuple": running_state["attempts"][0]["public_fence_tuple"], "stream": "STDOUT", "sequence": 0, "byte_length": 1, "media_type": "application/octet-stream", "encoding": "BINARY", "blob_sigil": SIGIL, "staging_reference": {"kind": "EXECUTION_LOG_SPOOL_RECORD", "staging_record_id": "LSR-" + "A" * 64, "staging_record_sigil": SIGIL}, "observed_at": "2026-08-06T00:00:08Z", "received_at": "2026-08-06T00:00:08Z", "split_utf8_boundary": False, "split_line": False, "chunk_record_sigil": SIGIL} + chunk_committed = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-LOGCOMMIT", "sequence": 11, "event_type": "log.chunk_committed", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:08Z", "observed_at": None, "entity_revisions": [{"entity_kind": "LOG_STREAM", "entity_id": stdout_stream["log_stream_id"], "preceding_revision": 0, "next_revision": 1}], "causation_event_id": None, "idempotency_key_sigil": SIGIL, "recovery_action_binding": None, "payload": {"intake_kind": "RAW_CHUNK", "intake_id": "LCI-ONE", "intake_record_sigil": SIGIL, "disposition_intent_id": "LDI-ONE", "log_stream_id": stdout_stream["log_stream_id"], "chunk_record_sigil": SIGIL, "stream": "STDOUT", "sequence": 0, "blob_sigil": SIGIL, "captured_bytes_after": 1}, "previous_event_sigil": running["event_sigil"]}) + chunked_state = replay_execution_supplied_state_suffix_v1(running_state, [chunk_committed], supplied_log_chunks=[chunk]) + assert next(stream for stream in chunked_state["log_streams"] if stream["stream"] == "STDOUT")["captured_bytes"] == 1 + + wrong_chunk = deepcopy(chunk) + wrong_chunk["sequence"] = 1 + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(running_state, [chunk_committed], supplied_log_chunks=[wrong_chunk]) + + duplicate_chunk = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-LOGDUP", "sequence": 12, "event_type": "log.chunk_duplicate_observed", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:08Z", "observed_at": None, "entity_revisions": [{"entity_kind": "LOG_STREAM", "entity_id": stdout_stream["log_stream_id"], "preceding_revision": 1, "next_revision": 2}], "causation_event_id": None, "idempotency_key_sigil": SIGIL, "recovery_action_binding": None, "payload": {"intake_kind": "RAW_CHUNK", "intake_id": "LCI-TWO", "intake_record_sigil": SIGIL, "disposition_intent_id": "LDI-TWO", "log_stream_id": stdout_stream["log_stream_id"], "stream": "STDOUT", "sequence": 0, "original_chunk_id": chunk["chunk_id"], "original_chunk_record_sigil": SIGIL, "original_disposition_event": {"event_id": chunk_committed["event_id"], "event_sigil": chunk_committed["event_sigil"]}}, "previous_event_sigil": chunk_committed["event_sigil"]}) + duplicate_chunk_state = replay_execution_supplied_state_suffix_v1(chunked_state, [duplicate_chunk]) + duplicate_stream = next(stream for stream in duplicate_chunk_state["log_streams"] if stream["stream"] == "STDOUT") + assert (duplicate_stream["next_sequence"], duplicate_stream["captured_bytes"]) == (1, 1) + + wrong_duplicate = deepcopy(duplicate_chunk) + wrong_duplicate["payload"]["sequence"] = 1 + wrong_duplicate = build_execution_journal_event_v1({key: value for key, value in wrong_duplicate.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(chunked_state, [wrong_duplicate]) + + heartbeat = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-HEARTBEAT", "sequence": 11, "event_type": "lease.heartbeat_accepted", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:08Z", "observed_at": None, "entity_revisions": [{"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 1, "next_revision": 2}], "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"heartbeat_message_sigil": SIGIL, "sequence": 1, "prior_accepted_sequence": None, "received_at": "2026-08-06T00:00:06Z", "next_heartbeat_due_at": "2026-08-06T00:00:09Z", "resource_sample_sigil": SIGIL, "resource_counter_floors_after": {"cpu_time_seconds": 0, "storage_bytes_written": 0, "network_egress_bytes": 0}}, "previous_event_sigil": running["event_sigil"]}) + heartbeat_state = replay_execution_supplied_state_suffix_v1(running_state, [heartbeat]) + assert heartbeat_state["leases"][0]["last_heartbeat_sequence"] == 1 + renewal = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-RENEWAL", "sequence": 12, "event_type": "lease.renewed", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:08Z", "observed_at": None, "entity_revisions": [{"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 2, "next_revision": 3}], "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"renewal_request_sigil": SIGIL, "prior_expiry_due_at": lease["initial_expiry_due_at"], "new_expiry_due_at": lease["maximum_expiry_due_at"], "renewal_counter": 1}, "previous_event_sigil": heartbeat["event_sigil"]}) + renewed_state = replay_execution_supplied_state_suffix_v1(heartbeat_state, [renewal]) + assert renewed_state["leases"][0]["renewal_counter"] == 1 + + owner = { + "job_id": JOB_ID, "job_binding_sigil": job["job_binding_sigil"], "attempt_id": "AT-ONE", + "attempt_binding_sigil": attempt["attempt_binding_sigil"], "lease_id": lease["lease_id"], + "lease_binding_sigil": lease["lease_binding_sigil"], "worker_id": "WK-ONE", + "worker_binding_sigil": SIGIL, "worker_session_id": session_id, + "worker_session_binding_sigil": SIGIL, "executor_epoch": 1, + "fence_tuple": running_state["attempts"][0]["public_fence_tuple"], + } + observation = { + "runtime_observation": {"started_at": "2026-08-06T00:00:07Z", "ended_at": "2026-08-06T00:00:08Z", "cpu_time_seconds": 0, "peak_memory_bytes": 0, "process_count": 0}, + "termination_observation": {"kind": "EXITED", "exit_code": 0, "observed_at": "2026-08-06T00:00:08Z", "observation_source": "WORKER"}, + "observation_evidence_subject_sigil": "", + } + observation["observation_evidence_subject_sigil"] = derive_observation_evidence_subject_sigil_v1(owner, observation) + receipt: dict[str, Any] = { + "schema_version": "execution-result-ingress-receipt/1.0", "ingress_receipt_id": "", "owner_binding": owner, + "result_sigil": SIGIL, "result_observation_binding": observation, "received_at": "2026-08-06T00:00:08Z", + "control_channel_identity_sigil": SIGIL, + "credential_verification": {"kind": "VERIFIED", "lease_credential_digest": SIGIL, "verification_profile_sigil": SIGIL, "verified_at": "2026-08-06T00:00:08Z", "verification_sigil": ""}, + "receiver_identity": {"executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "implementation_sigil": SIGIL}, + "created_at": "2026-08-06T00:00:08Z", "ingress_receipt_sigil": "", + } + receipt["ingress_receipt_id"] = derive_result_ingress_receipt_id_v1(receipt) + verification = receipt["credential_verification"] + verification["verification_sigil"] = content_sigil(["execution-result-ingress-credential-verification/1.0", owner, SIGIL, receipt["received_at"], SIGIL, SIGIL, SIGIL, verification["verified_at"]]) + receipt["ingress_receipt_sigil"] = content_sigil({key: value for key, value in receipt.items() if key != "ingress_receipt_sigil"}) + ingress = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-ELEVEN", "sequence": 11, "event_type": "attempt.result_ingress_received", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 6, "next_revision": 7}], "causation_event_id": running["event_id"], "idempotency_key_sigil": content_sigil(["execution-result-ingress-key/1.0", "AT-ONE", SIGIL]), "recovery_action_binding": None, "payload": {"ingress_receipt_id": receipt["ingress_receipt_id"], "ingress_receipt_sigil": receipt["ingress_receipt_sigil"], "result_sigil": SIGIL, "observation_evidence_subject_sigil": observation["observation_evidence_subject_sigil"], "received_at": receipt["received_at"]}, "previous_event_sigil": running["event_sigil"]}) + intent: dict[str, Any] = {"schema_version": "execution-result-ingress-event-intent/1.0", "ingress_event_intent_id": "OII-" + "A" * 64, "result_ingress_receipt_binding": {"ingress_receipt_id": receipt["ingress_receipt_id"], "ingress_receipt_sigil": receipt["ingress_receipt_sigil"]}, "event_candidate": ingress, "created_at": receipt["received_at"], "intent_sigil": ""} + intent["intent_sigil"] = content_sigil({key: value for key, value in intent.items() if key != "intent_sigil"}) + ingress_state = replay_execution_supplied_state_suffix_v1(running_state, [ingress], supplied_result_ingress_receipts=[receipt], supplied_result_ingress_intents=[intent]) + assert ingress_state["attempts"][0]["result_intake"]["kind"] == "RECEIVED" + + source = {"source_kind": "WORKER", "source_identity_id": "SOURCE", "source_identity_sigil": SIGIL, "source_identity_profile_sigil": SIGIL, "source_channel_sigil": SIGIL, "source_channel_profile_sigil": SIGIL, "source_registry_id": "REGISTRY", "source_registry_version": "1.0", "source_registry_snapshot_sigil": SIGIL} + evidence: dict[str, Any] = {"schema_version": "execution-observation-evidence/1.0", "observation_evidence_id": "", **owner, "result_observation_binding": observation, "result_ingress_receipt_binding": intent["result_ingress_receipt_binding"], "producer_evidence_binding": {"raw_evidence_id": "ORE-" + "A" * 64, "raw_evidence_record_sigil": SIGIL}, "verifier_evidence_binding": {"raw_evidence_id": "ORE-" + "B" * 64, "raw_evidence_record_sigil": SIGIL}, "evidence_profile_binding": {"evidence_profile_id": "PROFILE", "evidence_profile_version": "1.0", "evidence_profile_sigil": SIGIL}, "assessment": {"kind": "MATCHED", "verified_runtime_observation": observation["runtime_observation"], "verified_termination_observation": observation["termination_observation"], "verified_source_binding": source, "reason_bindings": []}, "created_at": receipt["received_at"], "observation_evidence_sigil": ""} + evidence["observation_evidence_id"] = derive_observation_evidence_id_v1(evidence) + evidence["observation_evidence_sigil"] = content_sigil({key: value for key, value in evidence.items() if key != "observation_evidence_sigil"}) + disposition = {"result_ingress_receipt_binding": intent["result_ingress_receipt_binding"], "observation_evidence_subject_sigil": observation["observation_evidence_subject_sigil"], "observation_evidence_id": evidence["observation_evidence_id"], "observation_evidence_sigil": evidence["observation_evidence_sigil"]} + + mismatched = deepcopy(evidence) + mismatched["assessment"]["kind"] = "MISMATCHED" + mismatched["assessment"]["reason_bindings"] = [{"field": "TERMINATION_KIND", "reason_code": "MISMATCH", "detail_sigil": SIGIL}] + mismatched["observation_evidence_id"] = derive_observation_evidence_id_v1(mismatched) + mismatched["observation_evidence_sigil"] = content_sigil({key: value for key, value in mismatched.items() if key != "observation_evidence_sigil"}) + rejection_disposition = {"result_ingress_receipt_binding": intent["result_ingress_receipt_binding"], "observation_evidence_subject_sigil": observation["observation_evidence_subject_sigil"], "observation_evidence_id": mismatched["observation_evidence_id"], "observation_evidence_sigil": mismatched["observation_evidence_sigil"]} + rejected = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-REJECTED", "sequence": 12, "event_type": "attempt.result_rejected", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 7, "next_revision": 8}], "causation_event_id": ingress["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"disposition_kind": "FIRST_DISPOSITION_REJECTION", "message_sigil": SIGIL, "claimed_result_sigil": SIGIL, "received_at": receipt["received_at"], "reason_codes": ["OBSERVATION_MISMATCH"], "historical_disposition_event_id": None, "observation_evidence_disposition_binding": rejection_disposition}, "previous_event_sigil": ingress["event_sigil"]}) + rejected_state = replay_execution_supplied_state_suffix_v1(ingress_state, [rejected], supplied_result_ingress_receipts=[receipt], supplied_observation_evidence=[mismatched]) + assert rejected_state["attempts"][0]["result_binding"]["kind"] == "REJECTED" + + accepted = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-TWELVE", "sequence": 12, "event_type": "attempt.result_accepted", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 7, "next_revision": 8}], "causation_event_id": ingress["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"result_sigil": SIGIL, "lease_revision": 1, "fence_tuple": owner["fence_tuple"], "received_at": receipt["received_at"], "validation_evidence_sigil": evidence["observation_evidence_sigil"], "observation_evidence_disposition_binding": disposition}, "previous_event_sigil": ingress["event_sigil"]}) + accepted_state = replay_execution_supplied_state_suffix_v1(ingress_state, [accepted], supplied_result_ingress_receipts=[receipt], supplied_observation_evidence=[evidence]) + assert accepted_state["attempts"][0]["result_binding"]["kind"] == "ACCEPTED" + assert accepted_state["attempts"][0]["result_intake"]["outcome"] == "ACCEPTED" + + draining = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-THIRTEEN", "sequence": 13, "event_type": "attempt.draining", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 8, "next_revision": 9}], "causation_event_id": accepted["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"result_binding": accepted_state["attempts"][0]["result_binding"], "process_exit_observation_sigil": SIGIL}, "previous_event_sigil": accepted["event_sigil"]}) + draining_state = replay_execution_supplied_state_suffix_v1(accepted_state, [draining]) + assert draining_state["attempts"][0]["state"] == "DRAINING" + assert draining_state["attempts"][0]["completion_anchor_binding"] == {"kind": "RESULT_ACCEPTED", "event_id": accepted["event_id"], "event_sigil": accepted["event_sigil"], "sequence": accepted["sequence"], "result_sigil": SIGIL} + + wrong_draining = deepcopy(draining) + wrong_draining["payload"]["result_binding"] = {"kind": "NONE"} + wrong_draining = build_execution_journal_event_v1({key: value for key, value in wrong_draining.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(accepted_state, [wrong_draining]) + + cleaning = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-FOURTEEN", "sequence": 14, "event_type": "attempt.cleaning", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 9, "next_revision": 10}], "causation_event_id": draining["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"log_closure_sigil": SIGIL, "output_closure_sigil": SIGIL, "termination_evidence_sigil": SIGIL, "quarantine_plan_sigil": SIGIL, "terminal_source_binding": {"kind": "NOT_APPLICABLE"}}, "previous_event_sigil": draining["event_sigil"]}) + cleaning_state = replay_execution_supplied_state_suffix_v1(draining_state, [cleaning]) + assert cleaning_state["attempts"][0]["state"] == "CLEANING" + assert cleaning_state["attempts"][0]["terminal_source_binding"] == {"kind": "NOT_APPLICABLE"} + + closed = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-FIFTEEN", "sequence": 15, "event_type": "attempt.cleanup_progressed", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 10, "next_revision": 11}], "causation_event_id": cleaning["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"step": "LOGS_CLOSED", "cleanup_evidence_sigil": SIGIL, "remaining_resource_ids": [], "finalization_bindings": {"kind": "NONE"}}, "previous_event_sigil": cleaning["event_sigil"]}) + closed_state = replay_execution_supplied_state_suffix_v1(cleaning_state, [closed]) + assert closed_state["attempts"][0]["revision"] == 11 + + capture_finalization = { + "kind": "FROZEN", + "control_evidence_set_binding": { + "kind": "FROZEN", "control_evidence_set_id": "CES-" + "A" * 64, + "control_evidence_set_sigil": SIGIL, + }, + "quarantine_binding_set_binding": { + "kind": "FROZEN", "quarantine_binding_set_id": "QBS-" + "A" * 64, + "quarantine_binding_set_sigil": SIGIL, + }, + "terminalization_storage_manifest_binding": { + "kind": "FROZEN", "storage_root_manifest_id": "ESM-" + "A" * 64, + "storage_root_manifest_sigil": SIGIL, + }, + "output_root_protection": { + "kind": "NO_HOLD", "terminalization_storage_manifest_binding": { + "kind": "FROZEN", "storage_root_manifest_id": "ESM-" + "A" * 64, + "storage_root_manifest_sigil": SIGIL, + }, + }, + } + accounting_capture = build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], + "event_id": "JE-ACCOUNTING", "sequence": 16, "event_type": "attempt.cleanup_progressed", + "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": receipt["received_at"], "observed_at": None, + "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", + "preceding_revision": 11, "next_revision": 12}], + "causation_event_id": closed["event_id"], "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": {"step": "ACCOUNTING_CAPTURED", "cleanup_evidence_sigil": SIGIL, + "remaining_resource_ids": [], "finalization_bindings": capture_finalization}, + "previous_event_sigil": closed["event_sigil"], + }) + captured_state = replay_execution_supplied_state_suffix_v1(closed_state, [accounting_capture]) + assert captured_state["attempts"][0]["accounting_capture_binding"]["event_id"] == accounting_capture["event_id"] + + terminal_attempt = captured_state["attempts"][0] + terminal_evidence = { + "transition_cause": { + "code": "COMPLETION_ESTABLISHED", "trigger_kind": "PRIOR_EVENT", + "trigger_event_id": accepted["event_id"], "effective_sequence": accepted["sequence"], + "evidence_sigil": SIGIL, + }, + "computation_status": "COMPLETED", "worker_status": "COMPLETED", + "process_termination_status": "EXITED", "handle_revocation_status": "NOT_APPLICABLE", + "cleanup_status": "VERIFIED", "mutable_resource_isolation_status": "NOT_APPLICABLE", + "output_publication_status": "VERIFIED", "quarantine_status": "NOT_REQUIRED", + "termination_evidence_sigil": SIGIL, "handle_disposition_evidence_sigil": SIGIL, + "cleanup_summary_sigil": SIGIL, "quarantine_evidence_sigil": SIGIL, + "log_closure_sigil": SIGIL, "output_closure_sigil": SIGIL, + "result_binding": terminal_attempt["result_binding"], + "attempt_authorization_state": terminal_attempt["attempt_authorization_state"], + "completion_anchor_binding": terminal_attempt["completion_anchor_binding"], + "worker_session_binding": terminal_attempt["worker_session_binding"], + "lease_terminal_binding": terminal_attempt["lease_terminal_binding"] or {"kind": "NONE"}, + "first_stop_or_fence_binding": terminal_attempt["first_stop_or_fence_binding"], + "storage_observation_binding": { + "kind": "FROZEN", "storage_journal_id": "SJ-ONE", "through_sequence": 1, + "through_event_sigil": SIGIL, "output_storage_observation_set_id": "OS-ONE", + "output_storage_observation_set_sigil": SIGIL, + }, + "accounting_capture_event_id": accounting_capture["event_id"], + "accounting_capture_event_sigil": accounting_capture["event_sigil"], + "control_evidence_set_binding": capture_finalization["control_evidence_set_binding"], + "quarantine_binding_set_binding": capture_finalization["quarantine_binding_set_binding"], + "terminalization_storage_manifest_binding": capture_finalization["terminalization_storage_manifest_binding"], + "output_root_protection": capture_finalization["output_root_protection"], + "assurance_input_set_sigil": SIGIL, + "terminal_source_binding": terminal_attempt["terminal_source_binding"], + } + terminal = build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], + "event_id": "JE-TERMINAL", "sequence": 17, "event_type": "attempt.succeeded", + "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": receipt["received_at"], "observed_at": None, + "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", + "preceding_revision": 12, "next_revision": 13}], + "causation_event_id": accounting_capture["event_id"], "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": {"attempt_terminal_evidence": terminal_evidence, + "fencing_generation": 1, "final_fence_floor": 1, + "output_storage_roots": []}, + "previous_event_sigil": accounting_capture["event_sigil"], + }) + terminal_state = replay_execution_supplied_state_suffix_v1(captured_state, [terminal]) + assert terminal_state["attempts"][0]["state"] == "SUCCEEDED" + assert terminal_state["attempts"][0]["terminal_event_binding"]["terminal_event_sigil"] == terminal["event_sigil"] + + reservation = attempt["budget_reservation"] + settled_ledger = { + name: { + "limit": value, "reserved": 0, "consumed": value, + "exhaustion_status": "EXHAUSTED", + } + for name, value in reservation.items() + } + settled_ledger["budget_ledger_sigil"] = content_sigil(settled_ledger) + settled = build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], + "event_id": "JE-SETTLED", "sequence": 18, "event_type": "job.budget_settled", + "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": receipt["received_at"], "observed_at": None, + "entity_revisions": [ + {"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 2, "next_revision": 3}, + {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 13, "next_revision": 14}, + ], + "causation_event_id": terminal["event_id"], "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": { + "attempt_id": "AT-ONE", "reservation": reservation, + "accounting_capture_event_id": accounting_capture["event_id"], + "accounting_capture_event_sigil": accounting_capture["event_sigil"], "usage_status": "UNAVAILABLE", + "measured": reservation, "charged": reservation, + "accounting_started_at": receipt["received_at"], + "accounting_ended_at": receipt["received_at"], + "supervisor_identity": {"kind": "EXECUTOR", "identity_sigil": SIGIL}, + "accounting_evidence_set_sigil": accounting_capture["payload"]["cleanup_evidence_sigil"], + "resulting_budget_ledger_sigil": settled_ledger["budget_ledger_sigil"], + }, + "previous_event_sigil": terminal["event_sigil"], + }) + settled_state = replay_execution_supplied_state_suffix_v1( + terminal_state, [settled], supplied_attempts=[attempt] + ) + assert settled_state["jobs"][0]["budget_ledger"] == settled_ledger + assert settled_state["attempts"][0]["budget_settlement_binding"]["kind"] == "SETTLED" + + supplied_claim = _assurance_claim() + supplied_claim.update({ + "attempt_binding_sigil": attempt["attempt_binding_sigil"], + "attempt_terminal_event": { + "journal_id": INITIAL["journal_id"], + "sequence": terminal["sequence"], + "event_id": terminal["event_id"], + "event_sigil": terminal["event_sigil"], + }, + "assurance_profile_binding": { + key: value for key, value in job["assurance_requirement"].items() + if key != "requested_level" + }, + "result_binding": { + "kind": "ACCEPTED", + "result_sigil": SIGIL, + "disposition_event": { + "journal_id": INITIAL["journal_id"], + "sequence": accepted["sequence"], + "event_id": accepted["event_id"], + "event_sigil": accepted["event_sigil"], + }, + }, + "control_evidence_set_binding": capture_finalization[ + "control_evidence_set_binding" + ], + "terminal_status": { + "attempt_state": "SUCCEEDED", + "process_termination_status": "EXITED", + "handle_revocation_status": "NOT_APPLICABLE", + "cleanup_status": "VERIFIED", + "quarantine_status": "NOT_REQUIRED", + }, + }) + supplied_claim["evidence_cut"].update({ + "journal_prefix": { + "journal_id": INITIAL["journal_id"], + "ending_sequence": settled["sequence"], + "ending_event_id": settled["event_id"], + "ending_event_sigil": settled["event_sigil"], + }, + "state_sigil": settled_state["state_sigil"], + "accounting_capture_event": { + "journal_id": INITIAL["journal_id"], + "sequence": accounting_capture["sequence"], + "event_id": accounting_capture["event_id"], + "event_sigil": accounting_capture["event_sigil"], + }, + "budget_settlement_event": { + "journal_id": INITIAL["journal_id"], + "sequence": settled["sequence"], + "event_id": settled["event_id"], + "event_sigil": settled["event_sigil"], + }, + "control_evidence_set_binding": capture_finalization[ + "control_evidence_set_binding" + ], + }) + supplied_claim["assurance_claim_sigil"] = content_sigil({ + key: value for key, value in supplied_claim.items() + if key != "assurance_claim_sigil" + }) + validate_sanctum_assurance_claim_supplied_attempt_facts_v1( + supplied_claim, + job, + settled_state, + "AT-ONE", + accounting_capture, + settled, + ) + forged_claim = deepcopy(supplied_claim) + forged_claim["evidence_cut"]["state_sigil"] = SIGIL_B + forged_claim["assurance_claim_sigil"] = content_sigil({ + key: value for key, value in forged_claim.items() + if key != "assurance_claim_sigil" + }) + with pytest.raises(AthanorError, match="terminal Attempt facts"): + validate_sanctum_assurance_claim_supplied_attempt_facts_v1( + forged_claim, + job, + settled_state, + "AT-ONE", + accounting_capture, + settled, + ) + + forged_claim = deepcopy(supplied_claim) + forged_claim["evidence_cut"]["control_evidence_set_binding"]["control_evidence_set_sigil"] = SIGIL_B + forged_claim["assurance_claim_sigil"] = content_sigil({ + key: value for key, value in forged_claim.items() + if key != "assurance_claim_sigil" + }) + with pytest.raises(AthanorError, match="terminal Attempt facts"): + validate_sanctum_assurance_claim_supplied_attempt_facts_v1( + forged_claim, + job, + settled_state, + "AT-ONE", + accounting_capture, + settled, + ) + + forged_claim = deepcopy(supplied_claim) + forged_claim["evidence_cut"]["accounting_capture_event"]["sequence"] = 15 + forged_claim["assurance_claim_sigil"] = content_sigil({ + key: value for key, value in forged_claim.items() + if key != "assurance_claim_sigil" + }) + with pytest.raises(AthanorError, match="terminal Attempt facts"): + validate_sanctum_assurance_claim_supplied_attempt_facts_v1( + forged_claim, + job, + settled_state, + "AT-ONE", + accounting_capture, + settled, + ) + + partial_undercharge = deepcopy(settled) + partial_undercharge["payload"].update({ + "usage_status": "PARTIAL", + "measured": {name: 0 for name in reservation}, + "charged": {name: 0 for name in reservation}, + }) + partial_undercharge = build_execution_journal_event_v1({ + key: value for key, value in partial_undercharge.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="Partial budget settlement must charge"): + replay_execution_supplied_state_suffix_v1( + terminal_state, [partial_undercharge], supplied_attempts=[attempt] + ) + + attempt_assurance = build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], + "event_id": "JE-ATTEMPTASSURANCE", "sequence": 19, + "event_type": "attempt.assurance_evaluated", + "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": receipt["received_at"], "observed_at": None, + "entity_revisions": [ + {"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 3, "next_revision": 4}, + {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 14, "next_revision": 15}, + ], + "causation_event_id": settled["event_id"], "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": {"evaluation": "CLAIMED", "assurance_claim_sigil": supplied_claim["assurance_claim_sigil"], + "reason_codes": [], "evidence_set_sigil": SIGIL}, + "previous_event_sigil": settled["event_sigil"], + }) + assured_state = replay_execution_supplied_state_suffix_v1( + settled_state, + [attempt_assurance], + supplied_jobs=[job], + supplied_assurance_claims=[supplied_claim], + supplied_accounting_capture_events=[accounting_capture], + supplied_budget_settlement_events=[settled], + ) + assert assured_state["jobs"][0]["current_attempt_id"] is None + assert assured_state["attempts"][0]["attempt_assurance_binding"]["kind"] == "CLAIMED" + assert assured_state["jobs"][0]["attempt_summaries"][0]["attempt_id"] == "AT-ONE" + + with pytest.raises(AthanorError, match="Claimed Attempt assurance"): + replay_execution_supplied_state_suffix_v1(settled_state, [attempt_assurance]) + + unsatisfied_claim = deepcopy(supplied_claim) + unsatisfied_claim["satisfies_request"] = False + unsatisfied_claim["assurance_claim_sigil"] = content_sigil( + {key: value for key, value in unsatisfied_claim.items() if key != "assurance_claim_sigil"} + ) + unsatisfied_assurance = deepcopy(attempt_assurance) + unsatisfied_assurance["payload"]["assurance_claim_sigil"] = unsatisfied_claim[ + "assurance_claim_sigil" + ] + unsatisfied_assurance = build_execution_journal_event_v1( + {key: value for key, value in unsatisfied_assurance.items() if key != "event_sigil"} + ) + with pytest.raises(AthanorError, match="satisfies its request"): + replay_execution_supplied_state_suffix_v1( + settled_state, + [unsatisfied_assurance], + supplied_jobs=[job], + supplied_assurance_claims=[unsatisfied_claim], + supplied_accounting_capture_events=[accounting_capture], + supplied_budget_settlement_events=[settled], + ) + + unmet_attempt_assurance = deepcopy(attempt_assurance) + unmet_attempt_assurance["payload"].update({ + "evaluation": "UNMET", "assurance_claim_sigil": None, + "reason_codes": ["ASSURANCE_UNMET"], + }) + unmet_attempt_assurance = build_execution_journal_event_v1({ + key: value for key, value in unmet_attempt_assurance.items() if key != "event_sigil" + }) + unmet_state = replay_execution_supplied_state_suffix_v1(settled_state, [unmet_attempt_assurance]) + assert unmet_state["attempts"][0]["attempt_assurance_binding"]["kind"] == "UNMET" + assert unmet_state["jobs"][0]["attempt_summaries"][0]["assurance_evaluation_event_sigil"] == unmet_attempt_assurance["event_sigil"] + + retry_state_unsigned = deepcopy(assured_state) + retry_state_unsigned.pop("state_sigil") + retry_job = retry_state_unsigned["jobs"][0] + retry_job.update({ + "state": "QUEUED", + "queue_key": {"ready_sequence": 20, "job_id": JOB_ID}, + }) + retry_ledger = { + name: { + "limit": 2, + "reserved": 0, + "consumed": 1, + "exhaustion_status": "AVAILABLE", + } + for name in reservation + } + retry_ledger["budget_ledger_sigil"] = content_sigil(retry_ledger) + retry_job["budget_ledger"] = retry_ledger + retry_state = build_execution_state_v1(retry_state_unsigned) + + retry_attempt = _reseal_attempt({ + **deepcopy(attempt), + "attempt_id": "AT-TWO", + "retry_ordinal": 2, + "fencing_generation": 2, + "crucible_id": "CU-TWO", + "output_namespace_id": "ON-TWO", + "log_stream_ids": { + "STDOUT": "LG-FOUR", + "STDERR": "LG-FIVE", + "STRUCTURED": "LG-SIX", + }, + "created_at": "2026-08-06T00:00:04Z", + }) + + def retry_allocation_event(candidate: dict[str, Any]) -> dict[str, Any]: + resulting_ledger = { + name: { + "limit": 2, + "reserved": 1, + "consumed": 1, + "exhaustion_status": "EXHAUSTED", + } + for name in reservation + } + resulting_ledger["budget_ledger_sigil"] = content_sigil(resulting_ledger) + return build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", + "journal_id": INITIAL["journal_id"], + "event_id": "JE-RETRYALLOCATED", + "sequence": 20, + "event_type": "job.attempt_allocated", + "executor_instance_id": INITIAL["executor_instance_id"], + "executor_epoch": 1, + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": candidate["created_at"], + "observed_at": None, + "entity_revisions": [ + {"entity_kind": "JOB", "entity_id": JOB_ID, + "preceding_revision": 4, "next_revision": 5}, + {"entity_kind": "ATTEMPT", "entity_id": candidate["attempt_id"], + "preceding_revision": None, "next_revision": 0}, + *[ + {"entity_kind": "LOG_STREAM", "entity_id": stream_id, + "preceding_revision": None, "next_revision": 0} + for stream_id in sorted(candidate["log_stream_ids"].values()) + ], + ], + "causation_event_id": retry_state["jobs"][0]["last_event_id"], + "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": { + "attempt_binding_sigil": candidate["attempt_binding_sigil"], + "retry_ordinal": 2, + "fencing_generation": 2, + "prior_fencing_counter": 1, + "resulting_fence_floor": 2, + "budget_reservation": candidate["budget_reservation"], + "resulting_budget_ledger_sigil": resulting_ledger["budget_ledger_sigil"], + }, + "previous_event_sigil": retry_state["journal_binding"]["through_event_sigil"], + }) + + allocated_retry_state = replay_execution_supplied_state_suffix_v1( + retry_state, + [retry_allocation_event(retry_attempt)], + supplied_attempts=[attempt, retry_attempt], + ) + assert [item["attempt_id"] for item in allocated_retry_state["attempts"]] == [ + "AT-ONE", "AT-TWO" + ] + + for field, old_value in ( + ("crucible_id", attempt["crucible_id"]), + ("output_namespace_id", attempt["output_namespace_id"]), + ("log_stream_ids", attempt["log_stream_ids"]), + ): + reused = _reseal_attempt({**deepcopy(retry_attempt), field: old_value}) + with pytest.raises(AthanorError, match="queued Job projection"): + replay_execution_supplied_state_suffix_v1( + retry_state, + [retry_allocation_event(reused)], + supplied_attempts=[attempt, reused], + ) + + job_assurance = build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], + "event_id": "JE-JOBASSURANCE", "sequence": 20, "event_type": "job.assurance_evaluated", + "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": receipt["received_at"], "observed_at": None, + "entity_revisions": [{"entity_kind": "JOB", "entity_id": JOB_ID, + "preceding_revision": 4, "next_revision": 5}], + "causation_event_id": attempt_assurance["event_id"], "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": {"evaluation": "CLAIMED", "attempt_id": "AT-ONE", + "attempt_assurance_event_sigil": attempt_assurance["event_sigil"], + "assurance_claim_sigil": supplied_claim["assurance_claim_sigil"], "reason_codes": [], + "evidence_set_sigil": SIGIL}, + "previous_event_sigil": attempt_assurance["event_sigil"], + }) + job_assured_state = replay_execution_supplied_state_suffix_v1(assured_state, [job_assurance]) + assert job_assured_state["jobs"][0]["job_assurance_binding"]["kind"] == "CLAIMED" + + selected_attempt = job_assured_state["attempts"][0] + selected_binding = { + "kind": "SELECTED", "attempt_id": "AT-ONE", + "attempt_binding_sigil": attempt["attempt_binding_sigil"], + "attempt_terminal_event_id": terminal["event_id"], + "attempt_terminal_event_sigil": terminal["event_sigil"], + "attempt_authorization_state": selected_attempt["attempt_authorization_state"], + "worker_session_binding": selected_attempt["worker_session_binding"], + "result_binding": selected_attempt["result_binding"], + "completion_anchor_binding": selected_attempt["completion_anchor_binding"], + "first_stop_or_fence_binding": selected_attempt["first_stop_or_fence_binding"], + "storage_observation_binding": selected_attempt["storage_observation_binding"], + } + job_terminal = build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], + "event_id": "JE-JOBSUCCEEDED", "sequence": 21, "event_type": "job.succeeded", + "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": receipt["received_at"], "observed_at": None, + "entity_revisions": [{"entity_kind": "JOB", "entity_id": JOB_ID, + "preceding_revision": 5, "next_revision": 6}], + "causation_event_id": job_assurance["event_id"], "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": { + "transition_cause": {"code": "COMPLETION_ESTABLISHED", "trigger_kind": "PRIOR_EVENT", + "trigger_event_id": job_assurance["event_id"], "effective_sequence": 20, + "evidence_sigil": SIGIL}, + "attempt_summaries": job_assured_state["jobs"][0]["attempt_summaries"], + "selected_attempt_binding": selected_binding, + "completion_anchor_binding": selected_attempt["completion_anchor_binding"], + "first_stop_or_fence_binding": selected_attempt["first_stop_or_fence_binding"], + "job_assurance_event_sigil": job_assurance["event_sigil"], + "budget_ledger_sigil": settled_ledger["budget_ledger_sigil"], + "final_fence_binding": {"kind": "ASSIGNED_NO_LEASE", "final_fence_floor": 1, + "attempt_id": "AT-ONE", "attempt_terminal_event_sigil": terminal["event_sigil"]}, + "cleanup_summary_sigil": SIGIL, + "storage_observation_binding": selected_attempt["storage_observation_binding"], + "terminal_source_binding": selected_attempt["terminal_source_binding"], + "output_hold_release_schedules": [], + }, + "previous_event_sigil": job_assurance["event_sigil"], + }) + terminal_job_state = replay_execution_supplied_state_suffix_v1(job_assured_state, [job_terminal]) + assert terminal_job_state["jobs"][0]["state"] == "SUCCEEDED" + + duplicate_settlement = deepcopy(settled) + duplicate_settlement["event_id"] = "JE-SETTLEDTWO" + duplicate_settlement["sequence"] = 19 + duplicate_settlement["entity_revisions"][0].update({"preceding_revision": 3, "next_revision": 4}) + duplicate_settlement["entity_revisions"][1].update({"preceding_revision": 14, "next_revision": 15}) + duplicate_settlement["previous_event_sigil"] = settled["event_sigil"] + duplicate_settlement = build_execution_journal_event_v1({ + key: value for key, value in duplicate_settlement.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1( + settled_state, [duplicate_settlement], supplied_attempts=[attempt] + ) + + forged_terminal = deepcopy(terminal) + forged_terminal["payload"]["attempt_terminal_evidence"]["result_binding"] = {"kind": "NONE"} + forged_terminal = build_execution_journal_event_v1({ + key: value for key, value in forged_terminal.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(captured_state, [forged_terminal]) + + late_rejection = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-LATEREJECT", "sequence": 16, "event_type": "attempt.result_rejected", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 11, "next_revision": 12}], "causation_event_id": closed["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"disposition_kind": "LATE_OR_CONFLICTING_REJECTION", "message_sigil": SIGIL, "claimed_result_sigil": SIGIL, "received_at": receipt["received_at"], "reason_codes": ["LEASE_TERMINAL"], "historical_disposition_event_id": accepted["event_id"]}, "previous_event_sigil": closed["event_sigil"]}) + late_rejected_state = replay_execution_supplied_state_suffix_v1(closed_state, [late_rejection]) + assert late_rejected_state["attempts"][0]["result_binding"] == accepted_state["attempts"][0]["result_binding"] + assert late_rejected_state["attempts"][0]["revision"] == 12 + + stdout_stream = next(stream for stream in closed_state["log_streams"] if stream["stream"] == "STDOUT") + log_closed = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-LOGCLOSED", "sequence": 16, "event_type": "log.closed", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "LOG_STREAM", "entity_id": stdout_stream["log_stream_id"], "preceding_revision": 0, "next_revision": 1}], "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"log_stream_id": stdout_stream["log_stream_id"], "stream": "STDOUT", "final_sequence": None, "captured_bytes": 0, "dropped_bytes": 0, "stream_set_sigil": SIGIL, "freeze_binding": {"kind": "NONE"}, "closure_intent_id": "LCI-ONE"}, "previous_event_sigil": closed["event_sigil"]}) + log_closed_state = replay_execution_supplied_state_suffix_v1(closed_state, [log_closed]) + assert next(stream for stream in log_closed_state["log_streams"] if stream["stream"] == "STDOUT")["state"] == "CLOSED" + + wrong_log_close = deepcopy(log_closed) + wrong_log_close["payload"]["captured_bytes"] = 1 + wrong_log_close = build_execution_journal_event_v1({key: value for key, value in wrong_log_close.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(closed_state, [wrong_log_close]) + + log_rejected = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-LOGREJECT", "sequence": 16, "event_type": "log.chunk_rejected", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "LOG_STREAM", "entity_id": stdout_stream["log_stream_id"], "preceding_revision": 0, "next_revision": 1}], "causation_event_id": None, "idempotency_key_sigil": SIGIL, "recovery_action_binding": None, "payload": {"intake_kind": "RAW_CHUNK", "intake_id": "LCI-ONE", "intake_record_sigil": SIGIL, "disposition_intent_id": "LDI-ONE", "log_stream_id": stdout_stream["log_stream_id"], "stream": "STDOUT", "sequence": 0, "message_sigil": SIGIL, "reason_codes": ["LEASE_TERMINAL"], "historical_disposition_event_id": None}, "previous_event_sigil": closed["event_sigil"]}) + log_rejected_state = replay_execution_supplied_state_suffix_v1(closed_state, [log_rejected]) + rejected_stream = next(stream for stream in log_rejected_state["log_streams"] if stream["stream"] == "STDOUT") + assert (rejected_stream["captured_bytes"], rejected_stream["next_sequence"]) == (0, 0) + + wrong_log_rejection = deepcopy(log_rejected) + wrong_log_rejection["payload"]["stream"] = "STDERR" + wrong_log_rejection = build_execution_journal_event_v1({key: value for key, value in wrong_log_rejection.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(closed_state, [wrong_log_rejection]) + + log_truncated = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-LOGTRUNCATED", "sequence": 16, "event_type": "log.truncated", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "LOG_STREAM", "entity_id": stdout_stream["log_stream_id"], "preceding_revision": 0, "next_revision": 1}], "causation_event_id": None, "idempotency_key_sigil": SIGIL, "recovery_action_binding": None, "payload": {"intake_kind": "RAW_CHUNK", "intake_id": "LCI-ONE", "intake_record_sigil": SIGIL, "disposition_intent_id": "LDI-ONE", "log_stream_id": stdout_stream["log_stream_id"], "stream": "STDOUT", "limit_kind": "PER_STREAM", "limit_bytes": 0, "captured_bytes": 0, "dropped_bytes": 1, "overflow_behavior": "TRUNCATE", "structured_truncation_status": "NOT_APPLICABLE", "accepted_prefix_length": 0, "capture_cutoff_ordinal": 0}, "previous_event_sigil": closed["event_sigil"]}) + log_truncated_state = replay_execution_supplied_state_suffix_v1(closed_state, [log_truncated]) + truncated_stream = next(stream for stream in log_truncated_state["log_streams"] if stream["stream"] == "STDOUT") + assert (truncated_stream["truncated"], truncated_stream["dropped_bytes"]) == (True, 1) + + duplicate_truncation = deepcopy(log_truncated) + duplicate_truncation["event_id"] = "JE-LOGTRUNCATED2" + duplicate_truncation["sequence"] = 17 + duplicate_truncation["entity_revisions"][0].update({"preceding_revision": 1, "next_revision": 2}) + duplicate_truncation["previous_event_sigil"] = log_truncated["event_sigil"] + duplicate_truncation = build_execution_journal_event_v1({key: value for key, value in duplicate_truncation.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(log_truncated_state, [duplicate_truncation]) + + wrong_late_rejection = deepcopy(late_rejection) + wrong_late_rejection["payload"]["historical_disposition_event_id"] = None + wrong_late_rejection = build_execution_journal_event_v1({key: value for key, value in wrong_late_rejection.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(closed_state, [wrong_late_rejection]) + + premature_capture = deepcopy(closed) + premature_capture["payload"]["step"] = "ACCOUNTING_CAPTURED" + premature_capture = build_execution_journal_event_v1({key: value for key, value in premature_capture.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(cleaning_state, [premature_capture]) + + released = build_execution_journal_event_v1({"schema_version": "execution-journal-event/1.0", "journal_id": INITIAL["journal_id"], "event_id": "JE-SIXTEEN", "sequence": 16, "event_type": "lease.released", "executor_instance_id": INITIAL["executor_instance_id"], "executor_epoch": 1, "executor_build_sigil": INITIAL["executor_build_sigil"], "recorded_at": receipt["received_at"], "observed_at": None, "entity_revisions": [{"entity_kind": "WORKER_SESSION", "entity_id": session_id, "preceding_revision": 3, "next_revision": 4}, {"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 2, "next_revision": 3}, {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 11, "next_revision": 12}, {"entity_kind": "LEASE", "entity_id": lease["lease_id"], "preceding_revision": 1, "next_revision": 2}], "causation_event_id": closed["event_id"], "idempotency_key_sigil": None, "recovery_action_binding": None, "payload": {"release_evidence_sigil": SIGIL, "prior_fence_floor": 1, "tombstone_generation": 2, "tombstone_publication_sigil": SIGIL, "session_capacity_after": 0}, "previous_event_sigil": closed["event_sigil"]}) + released_state = replay_execution_supplied_state_suffix_v1(closed_state, [released]) + assert released_state["leases"][0]["state"] == "RELEASED" + assert released_state["attempts"][0]["lease_terminal_binding"]["lease_state"] == "RELEASED" + assert released_state["jobs"][0]["fence_floor"] == 2 + + malformed = deepcopy(ingress) + malformed["payload"]["result_sigil"] = "sha256:" + "b" * 64 + malformed = build_execution_journal_event_v1({key: value for key, value in malformed.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_supplied_state_suffix_v1(running_state, [malformed], supplied_result_ingress_receipts=[receipt], supplied_result_ingress_intents=[intent]) + + wrong_attempt = deepcopy(attempt) + wrong_attempt["retry_ordinal"] = 2 + wrong_attempt["attempt_binding_sigil"] = content_sigil( + {key: value for key, value in wrong_attempt.items() if key != "attempt_binding_sigil"} + ) + with pytest.raises(AthanorError, match="disagrees"): + replay_execution_journal_prefix_v1( + [INITIAL, event, queued, allocated], + supplied_jobs=[job], + supplied_attempts=[wrong_attempt], + ) + + duplicate_attempt = deepcopy(attempt) + duplicate_attempt.update({ + "attempt_id": "AT-TWO", + "retry_ordinal": 2, + "fencing_generation": 2, + "created_at": "2026-08-06T00:00:04Z", + }) + duplicate_attempt["attempt_binding_sigil"] = content_sigil({ + key: value for key, value in duplicate_attempt.items() if key != "attempt_binding_sigil" + }) + retry_allocation = deepcopy(allocated) + retry_allocation.update({ + "event_id": "JE-ALLOCATEDTWO", "sequence": 4, + "recorded_at": duplicate_attempt["created_at"], + "previous_event_sigil": queued["event_sigil"], + "entity_revisions": [ + {"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 1, "next_revision": 2}, + {"entity_kind": "ATTEMPT", "entity_id": "AT-TWO", "preceding_revision": None, "next_revision": 0}, + *[ + {"entity_kind": "LOG_STREAM", "entity_id": stream_id, "preceding_revision": None, "next_revision": 0} + for stream_id in sorted(duplicate_attempt["log_stream_ids"].values()) + ], + ], + "payload": { + "attempt_binding_sigil": duplicate_attempt["attempt_binding_sigil"], + "retry_ordinal": 2, "fencing_generation": 2, "prior_fencing_counter": 1, + "resulting_fence_floor": 2, "budget_reservation": duplicate_attempt["budget_reservation"], + "resulting_budget_ledger_sigil": SIGIL, + }, + }) + retry_allocation["event_sigil"] = content_sigil({ + key: value for key, value in retry_allocation.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="queued Job projection"): + replay_execution_journal_prefix_v1( + [INITIAL, event, queued, retry_allocation], + supplied_jobs=[job], supplied_attempts=[attempt, duplicate_attempt], + ) + + altered = deepcopy(job) + altered["deadline_due_at"] = "2026-08-06T00:02:00Z" + altered["job_binding_sigil"] = content_sigil( + {key: value for key, value in altered.items() if key != "job_binding_sigil"} + ) + with pytest.raises(AthanorError, match="does not exactly copy"): + replay_execution_journal_prefix_v1([INITIAL, event], supplied_jobs=[altered]) + with pytest.raises(AthanorError, match="requires exactly one supplied immutable record"): + replay_execution_journal_prefix_v1([INITIAL, event]) diff --git a/tests/test_execution_state_journal_event_v1_contract.py b/tests/test_execution_state_journal_event_v1_contract.py new file mode 100644 index 0000000..11ce98b --- /dev/null +++ b/tests/test_execution_state_journal_event_v1_contract.py @@ -0,0 +1,2431 @@ +import json +from copy import deepcopy +from pathlib import Path +from typing import Any + +import pytest + +from benchwork.athanor import content_sigil +from benchwork.execution_contracts import ( + EXECUTION_EVENT_TYPES_V1, + IDEMPOTENCY_OPERATION_KINDS_V1, + build_execution_journal_event_v1, + derive_observation_evidence_id_v1, + derive_observation_evidence_subject_sigil_v1, + derive_execution_observation_cursor_sigil_v1, + derive_execution_storage_root_manifest_id_v1, + derive_execution_root_hold_release_authorization_id_v1, + derive_execution_control_evidence_set_id_v1, + derive_execution_quarantine_binding_set_id_v1, + derive_execution_output_storage_observation_set_id_v1, + derive_result_ingress_receipt_id_v1, + expected_event_causation_v1, + expected_event_idempotency_v1, + load_execution_journal_event_v1, + load_execution_journal_head_v1, + load_execution_observation_evidence_v1, + load_execution_request_v1, + load_execution_result_ingress_receipt_v1, + load_execution_result_ingress_index_v1, + load_execution_recovery_action_set_v1, + load_execution_state_v1, + load_execution_storage_root_manifest_v1, + load_execution_root_hold_release_authorization_v1, + load_execution_control_evidence_set_v1, + load_execution_quarantine_binding_set_v1, + load_execution_output_storage_observation_set_v1, + replay_execution_initial_prefix_v1, + replay_execution_journal_prefix_v1, + replay_execution_journal_supplied_facts_v1, + replay_execution_supplied_state_suffix_v1, + replay_execution_empty_recovery_phase_prefix_v1, + _reduce_recovery_completed_v1, + validate_execution_journal_prefix_wire_v1, + validate_execution_observation_evidence_v1, + validate_execution_observation_evidence_supplied_receipt_v1, + validate_execution_journal_head_v1, + validate_execution_initial_state_supplied_facts_v1, + validate_execution_request_v1, + validate_execution_result_ingress_receipt_v1, + validate_execution_result_ingress_index_v1, + validate_execution_recovery_action_set_v1, + validate_execution_recovery_action_set_supplied_prefix_v1, + validate_execution_recovery_start_supplied_action_set_v1, + validate_execution_recovery_phase_advance_supplied_action_sets_v1, + validate_execution_recovery_rebase_supplied_action_sets_v1, + validate_execution_recovery_completion_supplied_action_set_v1, + validate_execution_state_supplied_recovery_action_set_v1, + validate_execution_recovery_action_supplied_event_v1, + validate_execution_storage_root_manifest_v1, + validate_execution_root_hold_release_authorization_v1, + validate_execution_control_evidence_set_v1, + validate_execution_quarantine_binding_set_v1, + validate_execution_output_storage_observation_set_v1, + validate_execution_terminalization_supplied_records_v1, +) +ROOT = Path(__file__).parents[1] +SCHEMAS = ROOT / "schemas" +FIXTURES = ROOT / "tests" / "fixtures" / "phase3" / "rfc0012" +SIGIL = "sha256:" + "a" * 64 +SIGIL_B = "sha256:" + "b" * 64 +STAMP = "2026-08-06T00:00:00Z" +JOB_ID = "JB-" + "A" * 64 +SESSION_ID = "WS-" + "0" * 26 +LEASE_ID = "LS-" + "0" * 26 + + +def _reseal_state(state: dict[str, Any]) -> None: + state["state_sigil"] = content_sigil( + {key: member for key, member in state.items() if key != "state_sigil"} + ) + + +def _state_with_session_and_lease() -> dict[str, Any]: + state = json.loads((FIXTURES / "execution-state-v1" / "valid-initial.json").read_text()) + state["workers"] = [{ + "worker_id": "WK-ONE", "revision": 0, "state": "ENABLED", + "worker_binding_sigil": SIGIL, "definition_revision": 0, + "worker_session_ids": [SESSION_ID], "last_event_id": "JE-ONE", "last_event_sigil": SIGIL, + }] + state["worker_sessions"] = [{ + "worker_session_id": SESSION_ID, "revision": 0, "state": "READY", "worker_id": "WK-ONE", + "worker_binding_sigil": SIGIL, "worker_session_binding_sigil": SIGIL, "executor_epoch": 1, + "worker_session_heartbeat_policy_id": "WSHP-" + "A" * 64, + "worker_session_heartbeat_policy_sigil": SIGIL, "capacity": 1, "capacity_in_use": 1, + "last_heartbeat_sequence": 1, "last_heartbeat_message_sigil": SIGIL, + "last_resource_sample_sigil": SIGIL, + "resource_counter_floors": {"cpu_time_seconds": None, "storage_bytes_written": None, "network_egress_bytes": None}, + "next_heartbeat_due_at": STAMP, "lease_ids": [LEASE_ID], "last_event_id": "JE-ONE", "last_event_sigil": SIGIL, + }] + state["leases"] = [{ + "lease_id": LEASE_ID, "revision": 0, "state": "ACTIVE", "lease_binding_sigil": SIGIL, + "job_id": JOB_ID, "attempt_id": "AT-ONE", "worker_id": "WK-ONE", "worker_session_id": SESSION_ID, + "executor_epoch": 1, "fencing_generation": 0, "claim_due_at": STAMP, "expiry_due_at": STAMP, + "maximum_expiry_due_at": STAMP, "last_heartbeat_sequence": 1, + "last_heartbeat_message_sigil": SIGIL, "last_resource_sample_sigil": SIGIL, + "resource_counter_floors": {"cpu_time_seconds": None, "storage_bytes_written": None, "network_egress_bytes": None}, + "next_heartbeat_due_at": STAMP, "renewal_counter": 0, "terminal_event_binding": {"kind": "NONE"}, + "tombstone_generation": None, "tombstone_event_sigil": None, "last_event_id": "JE-ONE", "last_event_sigil": SIGIL, + }] + _reseal_state(state) + return state + + +def _event_unsigned() -> dict[str, Any]: + return { + "schema_version": "execution-journal-event/1.0", + "journal_id": "EJ-ONE", + "event_id": "JE-TWO", + "sequence": 2, + "event_type": "log.chunk_committed", + "executor_instance_id": "XI-ONE", + "executor_epoch": 1, + "executor_build_sigil": SIGIL, + "recorded_at": STAMP, + "observed_at": None, + "entity_revisions": [ + { + "entity_kind": "LOG_STREAM", + "entity_id": "LG-ONE", + "preceding_revision": 0, + "next_revision": 1, + } + ], + "causation_event_id": None, + "idempotency_key_sigil": SIGIL, + "recovery_action_binding": None, + "payload": { + "intake_kind": "CHUNK", + "intake_id": "LCI-ONE", + "intake_record_sigil": SIGIL, + "disposition_intent_id": "LDI-ONE", + "log_stream_id": "LG-ONE", + "chunk_record_sigil": SIGIL, + "stream": "STDOUT", + "sequence": 0, + "blob_sigil": SIGIL, + "captured_bytes_after": 1, + }, + "previous_event_sigil": SIGIL_B, + } + + +def _clock_uncertain_event(initial: dict[str, Any]) -> dict[str, Any]: + event = { + "schema_version": "execution-journal-event/1.0", "journal_id": initial["journal_id"], + "event_id": "JE-TWO", "sequence": 2, "event_type": "executor.clock_uncertain", + "executor_instance_id": initial["executor_instance_id"], + "executor_epoch": initial["executor_epoch"], + "executor_build_sigil": initial["executor_build_sigil"], + "recorded_at": "2026-08-06T00:00:01Z", "observed_at": None, + "entity_revisions": [{ + "entity_kind": "EXECUTOR", "entity_id": initial["executor_instance_id"], + "preceding_revision": 0, "next_revision": 1, + }], + "causation_event_id": None, "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": { + "last_trusted_utc": initial["recorded_at"], + "detected_utc": "2026-08-06T00:00:01Z", "monotonic_status": "RESET", + "divergence_seconds": 0, "affected_lease_ids": [], + }, + "previous_event_sigil": initial["event_sigil"], + } + event["event_sigil"] = content_sigil(event) + return event + + +def _recovery_started_event(clock_uncertain: dict[str, Any]) -> dict[str, Any]: + event = { + "schema_version": "execution-journal-event/1.0", "journal_id": clock_uncertain["journal_id"], + "event_id": "JE-THREE", "sequence": 3, "event_type": "recovery.started", + "executor_instance_id": clock_uncertain["executor_instance_id"], + "executor_epoch": clock_uncertain["executor_epoch"], + "executor_build_sigil": clock_uncertain["executor_build_sigil"], + "recorded_at": "2026-08-06T00:00:02Z", "observed_at": None, + "entity_revisions": [ + {"entity_kind": "EXECUTOR", "entity_id": clock_uncertain["executor_instance_id"], + "preceding_revision": 1, "next_revision": 2}, + {"entity_kind": "RECOVERY", "entity_id": "RY-ONE", + "preceding_revision": None, "next_revision": 0}, + ], + "causation_event_id": None, "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": { + "recovery_id": "RY-ONE", "prior_recovery_id": None, + "replay_through_sequence": 2, + "replay_through_event_sigil": clock_uncertain["event_sigil"], + "old_epoch": clock_uncertain["executor_epoch"], + "new_epoch": clock_uncertain["executor_epoch"], + "nonterminal_job_ids": [], "nonterminal_attempt_ids": [], + "nonterminal_lease_ids": [], "nonterminal_worker_session_ids": [], + "initial_action_set_sigil": SIGIL, + }, + "previous_event_sigil": clock_uncertain["event_sigil"], + } + event["event_sigil"] = content_sigil(event) + return event + + +def _recovery_action_set() -> dict[str, Any]: + action_set = { + "schema_version": "execution-recovery-action-set/1.0", "recovery_id": "RY-ONE", + "phase": "STARTED", "derived_from_journal_id": "EJ-ONE", + "derived_through_sequence": 2, "derived_through_event_sigil": SIGIL, + "supersedes_action_set_sigil": None, + "actions": [{ + "ordinal": 0, "action_kind": "COMMIT_DUE_EVENT", "entity_kind": "JOB", + "entity_id": "JB-ONE", "expected_revision": 0, "target_event_id": "JE-FOUR", + "target_sequence": 4, "target_event_type": "job.stop_latched", + "prerequisite_event_ids": ["JE-ONE", "JE-TWO"], + "parameters": {"deadline_kind": "JOB_DEADLINE", "due_at": STAMP, "deadline_entity_id": "JB-ONE"}, + }], + } + action_set["action_set_sigil"] = content_sigil(action_set) + return action_set + + +def _empty_recovery_action_set( + phase: str, prefix: list[dict[str, Any]], +) -> dict[str, Any]: + action_set = { + "schema_version": "execution-recovery-action-set/1.0", "recovery_id": "RY-ONE", + "phase": phase, "derived_from_journal_id": prefix[-1]["journal_id"], + "derived_through_sequence": prefix[-1]["sequence"], + "derived_through_event_sigil": prefix[-1]["event_sigil"], + "supersedes_action_set_sigil": None, "actions": [], "action_set_sigil": "", + } + action_set["action_set_sigil"] = content_sigil({ + key: member for key, member in action_set.items() if key != "action_set_sigil" + }) + return action_set + + +def _recovery_phase_event( + prior_event: dict[str, Any], completed_set: dict[str, Any], next_set: dict[str, Any], + event_id: str, +) -> dict[str, Any]: + event = { + "schema_version": "execution-journal-event/1.0", "journal_id": prior_event["journal_id"], + "event_id": event_id, "sequence": prior_event["sequence"] + 1, + "event_type": "recovery.phase_advanced", + "executor_instance_id": prior_event["executor_instance_id"], + "executor_epoch": prior_event["executor_epoch"], + "executor_build_sigil": prior_event["executor_build_sigil"], + "recorded_at": f"2026-08-06T00:00:0{prior_event['sequence']}Z", "observed_at": None, + "entity_revisions": [{"entity_kind": "RECOVERY", "entity_id": "RY-ONE", + "preceding_revision": prior_event["sequence"] - 3, + "next_revision": prior_event["sequence"] - 2}], + "causation_event_id": None, "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": {"recovery_id": "RY-ONE", "from_phase": completed_set["phase"], + "to_phase": next_set["phase"], + "completed_action_set_sigil": completed_set["action_set_sigil"], + "next_action_set_sigil": next_set["action_set_sigil"], + "completed_entity_ids": [], "quarantined_entity_ids": []}, + "previous_event_sigil": prior_event["event_sigil"], + } + event["event_sigil"] = content_sigil(event) + return event + + +def _recovery_action_event(action_set: dict[str, Any]) -> dict[str, Any]: + action = action_set["actions"][0] + event = { + "schema_version": "execution-journal-event/1.0", "journal_id": "EJ-ONE", + "event_id": action["target_event_id"], "sequence": action["target_sequence"], + "event_type": action["target_event_type"], "executor_instance_id": "XI-ONE", + "executor_epoch": 1, "executor_build_sigil": SIGIL, + "recorded_at": "2026-08-06T00:00:02Z", "observed_at": None, + "entity_revisions": [{"entity_kind": action["entity_kind"], "entity_id": action["entity_id"], + "preceding_revision": action["expected_revision"], + "next_revision": action["expected_revision"] + 1}], + "causation_event_id": "JE-TWO", "idempotency_key_sigil": None, + "recovery_action_binding": {"recovery_id": action_set["recovery_id"], + "phase": action_set["phase"], + "action_set_sigil": action_set["action_set_sigil"], + "action_ordinal": action["ordinal"]}, + "payload": {"transition_cause": {"code": "JOB_DEADLINE", + "trigger_kind": "RECOVERY_DERIVATION", + "trigger_event_id": action["target_event_id"], + "effective_sequence": action["target_sequence"], + "evidence_sigil": SIGIL}, "request_binding": None}, + "previous_event_sigil": SIGIL_B, + } + event["event_sigil"] = content_sigil(event) + return event + + +def _owner() -> dict[str, Any]: + return { + "job_id": JOB_ID, + "job_binding_sigil": SIGIL, + "attempt_id": "AT-ONE", + "attempt_binding_sigil": SIGIL, + "lease_id": LEASE_ID, + "lease_binding_sigil": SIGIL, + "worker_id": "WK-ONE", + "worker_binding_sigil": SIGIL, + "worker_session_id": SESSION_ID, + "worker_session_binding_sigil": SIGIL, + "executor_epoch": 1, + "fence_tuple": { + "journal_id": "EJ-ONE", + "executor_epoch": 1, + "job_id": JOB_ID, + "attempt_id": "AT-ONE", + "lease_id": LEASE_ID, + "fencing_generation": 1, + }, + } + + +def _result_observation(owner: dict[str, Any]) -> dict[str, Any]: + binding = { + "runtime_observation": { + "started_at": STAMP, + "ended_at": STAMP, + "cpu_time_seconds": 0, + "peak_memory_bytes": 0, + "process_count": 0, + }, + "termination_observation": { + "kind": "EXITED", + "exit_code": 0, + "observed_at": STAMP, + "observation_source": "WORKER", + }, + "observation_evidence_subject_sigil": "", + } + binding["observation_evidence_subject_sigil"] = derive_observation_evidence_subject_sigil_v1(owner, binding) + return binding + + +def _receipt() -> dict[str, Any]: + owner = _owner() + value: dict[str, Any] = { + "schema_version": "execution-result-ingress-receipt/1.0", + "ingress_receipt_id": "", + "owner_binding": owner, + "result_sigil": SIGIL_B, + "result_observation_binding": _result_observation(owner), + "received_at": STAMP, + "control_channel_identity_sigil": SIGIL, + "credential_verification": { + "kind": "VERIFIED", + "lease_credential_digest": SIGIL, + "verification_profile_sigil": SIGIL, + "verified_at": STAMP, + "verification_sigil": "", + }, + "receiver_identity": { + "executor_instance_id": "XI-ONE", + "executor_epoch": 1, + "implementation_sigil": SIGIL, + }, + "created_at": STAMP, + "ingress_receipt_sigil": "", + } + value["ingress_receipt_id"] = derive_result_ingress_receipt_id_v1(value) + verification = value["credential_verification"] + verification["verification_sigil"] = content_sigil( + [ + "execution-result-ingress-credential-verification/1.0", + owner, + value["result_sigil"], + value["received_at"], + value["control_channel_identity_sigil"], + verification["lease_credential_digest"], + verification["verification_profile_sigil"], + verification["verified_at"], + ] + ) + value["ingress_receipt_sigil"] = content_sigil( + {key: member for key, member in value.items() if key != "ingress_receipt_sigil"} + ) + return value + + +def _result_ingress_index() -> dict[str, Any]: + receipt = _receipt() + candidate = _event_unsigned() + candidate.update({ + "event_type": "attempt.result_ingress_received", "event_id": "JE-THREE", + "sequence": 3, "previous_event_sigil": SIGIL, + "entity_revisions": [{ + "entity_kind": "ATTEMPT", "entity_id": receipt["owner_binding"]["attempt_id"], + "preceding_revision": 4, "next_revision": 5, + }], + "idempotency_key_sigil": content_sigil([ + "execution-result-ingress-key/1.0", receipt["owner_binding"]["attempt_id"], receipt["result_sigil"], + ]), + "payload": { + "ingress_receipt_id": receipt["ingress_receipt_id"], + "ingress_receipt_sigil": receipt["ingress_receipt_sigil"], + "result_sigil": receipt["result_sigil"], + "observation_evidence_subject_sigil": receipt["result_observation_binding"]["observation_evidence_subject_sigil"], + "received_at": receipt["received_at"], + }, + }) + candidate["event_sigil"] = content_sigil(candidate) + intent = { + "schema_version": "execution-result-ingress-event-intent/1.0", + "ingress_event_intent_id": "OII-" + "A" * 64, + "result_ingress_receipt_binding": { + "ingress_receipt_id": receipt["ingress_receipt_id"], + "ingress_receipt_sigil": receipt["ingress_receipt_sigil"], + }, + "event_candidate": candidate, "created_at": STAMP, "intent_sigil": "", + } + intent["intent_sigil"] = content_sigil( + {key: member for key, member in intent.items() if key != "intent_sigil"} + ) + head = { + "schema_version": "execution-journal-head/1.0", "limit_profile": "EXECUTION_JOURNAL_V1_FIXED_LIMITS", + "journal_id": candidate["journal_id"], "last_sequence": 2, "last_event_id": "JE-TWO", + "last_event_sigil": candidate["previous_event_sigil"], "updated_at": STAMP, "head_sigil": "", + } + head["head_sigil"] = content_sigil({key: member for key, member in head.items() if key != "head_sigil"}) + index = { + "schema_version": "execution-result-ingress-index/1.0", "ingress_index_id": "OIX-" + "A" * 64, + "attempt_id": receipt["owner_binding"]["attempt_id"], "result_sigil": receipt["result_sigil"], + "idempotency_key_sigil": candidate["idempotency_key_sigil"], "event_id": candidate["event_id"], + "result_ingress_receipt": receipt, "ingress_event_intent": intent, + "status": {"kind": "PENDING_EVENT", "expected_prior_index_sigil": None, + "expected_journal_head": head, "installed_at": STAMP}, + "created_at": STAMP, "index_sigil": "", + } + index["index_sigil"] = content_sigil({key: member for key, member in index.items() if key != "index_sigil"}) + return index + + +def _storage_root_manifest() -> dict[str, Any]: + subject = { + "kind": "JOB_INPUT", "input_ordinal": 0, + "input_identity": {"logical_name": "input", "object_id": "RP-ONE", "object_type": "research-program", + "object_sigil": SIGIL, "media_type": "application/json", "maximum_bytes": 1, + "mount_path": "input.json"}, + "input_sigil": SIGIL, + } + entry = { + "storage_subject_id": content_sigil([ + "execution-storage-subject-id/1.0", "JOB_INPUT", JOB_ID, None, subject, + ]), + "subject": subject, "claimed_blob": None, + "storage_origin": {"kind": "NOT_STORED", "transfer": None, + "terminal_reason": {"code": "BACKEND_UNAVAILABLE", "evidence_sigils": []}, + "evidence_sigil": SIGIL}, + "entry_sigil": "", + } + entry["entry_sigil"] = content_sigil({key: member for key, member in entry.items() if key != "entry_sigil"}) + manifest = { + "schema_version": "execution-storage-root-manifest/1.0", "manifest_id": "", + "root_kind": "JOB_INPUT", "job_id": JOB_ID, "attempt_id": None, + "owner_binding": {"kind": "JOB_INPUT", "start_request_sigil": SIGIL, "task_id": "TK-ONE", + "task_capsule_sigil": SIGIL, "specification_id": "ES-0" + "0" * 25, + "specification_sigil": SIGIL, "input_set_sigil": SIGIL}, + "entries": [entry], "blob_refs": [], "protection_plan": {"kind": "NONE"}, + "created_at": STAMP, "manifest_sigil": "", + } + manifest["manifest_id"] = derive_execution_storage_root_manifest_id_v1(manifest) + manifest["manifest_sigil"] = content_sigil({key: member for key, member in manifest.items() if key != "manifest_sigil"}) + return manifest + + +def _root_hold_release_authorization() -> dict[str, Any]: + root = { + "root_kind": "JOB_INPUT", "job_id": JOB_ID, "attempt_id": None, + "storage_root_manifest_id": "ESM-" + "A" * 64, "storage_root_manifest_sigil": SIGIL, + "reference_set_id": "RS-ONE", "reference_set_sigil": SIGIL, "hold_id": "SH-ONE", + "hold_set_event": {"journal_id": "EJ-ONE", "event_id": "JE-ONE", "sequence": 1, "event_sigil": SIGIL}, + } + head = { + "schema_version": "execution-journal-head/1.0", "limit_profile": "EXECUTION_JOURNAL_V1_FIXED_LIMITS", + "journal_id": "EJ-ONE", "last_sequence": 3, "last_event_id": "JE-THREE", + "last_event_sigil": SIGIL, "updated_at": STAMP, "head_sigil": "", + } + head["head_sigil"] = content_sigil({key: member for key, member in head.items() if key != "head_sigil"}) + authorization = { + "schema_version": "execution-root-hold-release-authorization/1.0", "release_authorization_id": "", + "execution_journal_id": "EJ-ONE", "storage_root": root, + "policy": {"policy_id": "SP-EXECUTION-ROOT-HOLD-V1", "policy_sigil": SIGIL}, + "hold_set_authorization_sigil": SIGIL, + "basis": {"kind": "OWNER_TERMINAL", "activation_event_id": "JE-ONE", "activation_event_sequence": 1, + "activation_event_sigil": SIGIL, "terminal_event_id": "JE-TWO", "terminal_event_sequence": 2, + "terminal_event_sigil": SIGIL_B, "terminal_event_type": "job.succeeded", + "verification_head": head, "verification_state_sigil": SIGIL}, + "release_authorization_sigil": "", + } + authorization["release_authorization_id"] = derive_execution_root_hold_release_authorization_id_v1(authorization) + authorization["release_authorization_sigil"] = content_sigil({ + key: member for key, member in authorization.items() if key != "release_authorization_sigil" + }) + return authorization + + +def _control_evidence_set() -> dict[str, Any]: + dimensions = [ + "IDENTITY_AUTHORIZATION", "FILESYSTEM", "NETWORK", "PROCESS_EXECUTABLE", "RESOURCE", + "ENVIRONMENT_CREDENTIAL", "LOG_OUTPUT_CAPTURE", "RUNTIME_INPUT_OUTPUT_IDENTITY", + "CANCELLATION_FENCING", "TERMINATION_CLEANUP", + ] + evidence_set = { + "schema_version": "execution-control-evidence-set/1.0", "control_evidence_set_id": "", + "job_id": JOB_ID, "attempt_id": "AT-ONE", "attempt_binding_sigil": SIGIL, + "control_evidence_refs": [ + {"control_dimension": dimension, "control_evidence_id": "CVE-0" + "0" * 25, + "control_evidence_sigil": SIGIL if index == 0 else SIGIL_B} + for index, dimension in enumerate(dimensions) + ], + "control_evidence_set_sigil": "", + } + for index, reference in enumerate(evidence_set["control_evidence_refs"]): + reference["control_evidence_id"] = f"CVE-0{index:025d}"[-30:] + evidence_set["control_evidence_set_id"] = derive_execution_control_evidence_set_id_v1(evidence_set) + evidence_set["control_evidence_set_sigil"] = content_sigil({ + key: member for key, member in evidence_set.items() if key != "control_evidence_set_sigil" + }) + return evidence_set + + +def _quarantine_binding_set() -> dict[str, Any]: + binding_set = { + "schema_version": "execution-quarantine-binding-set/1.0", "quarantine_binding_set_id": "", + "job_id": JOB_ID, "attempt_id": "AT-ONE", "attempt_binding_sigil": SIGIL, + "quarantine_plan_sigil": SIGIL, + "terminalization_storage_manifest_binding": { + "kind": "FROZEN", "storage_root_manifest_id": "ESM-" + "A" * 64, + "storage_root_manifest_sigil": SIGIL, + }, + "storage_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, "event_sigil": SIGIL}, + "storage_state_sigil": SIGIL, "bindings": [], "quarantine_binding_set_sigil": "", + } + binding_set["quarantine_binding_set_id"] = derive_execution_quarantine_binding_set_id_v1(binding_set) + binding_set["quarantine_binding_set_sigil"] = content_sigil({ + key: member for key, member in binding_set.items() if key != "quarantine_binding_set_sigil" + }) + return binding_set + + +def _output_storage_observation_set() -> dict[str, Any]: + storage_event = { + "journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, + "event_sigil": SIGIL, + } + blob_storage = { + "kind": "BLOB", "terminal_storage_status": "AVAILABLE", "blob_sigil": SIGIL, + "size_bytes": 0, "blob_record_sigil": SIGIL_B, "availability": "AVAILABLE", + "availability_as_of": storage_event, "availability_basis_sigil": SIGIL, + "integrity_event_sigils": [], "quarantine": {"kind": "NONE"}, + "replica": {"kind": "NONE"}, + } + origin = { + "kind": "COMMITTED_BLOB", "transfer": { + "transfer_id": "ST-ONE", "transfer_attempt_id": "SA-ONE", + "request_record_sigil": SIGIL, "attempt_record_sigil": SIGIL_B, + "terminal_event": storage_event, + }, "provenance_id": "PROVENANCE", "provenance_sigil": SIGIL, + "blob_record_sigil": SIGIL_B, "terminal_event": storage_event, + } + members = [{"kind": "ATTEMPT_OUTPUTS_NONE", "reason": "NO_RESULT"}] + for stream in ("STDOUT", "STDERR", "STRUCTURED"): + members.append({ + "kind": "LOG_STREAM", "storage_subject_id": SIGIL, + "manifest_entry_sigil": SIGIL_B, "stream": stream, + "log_stream_id": f"LG-{stream}", "final_sequence": None, + "captured_bytes": 0, "dropped_bytes": 0, "truncated": False, + "stream_set_sigil": SIGIL, "closure_event_id": "JE-ONE", + "closure_event_sigil": SIGIL_B, "storage_origin": origin, + "content": {"kind": "EMPTY", "blob_sigil": SIGIL, "storage": blob_storage}, + }) + members.extend([ + {"kind": "RESOURCE_EVIDENCE_NONE"}, + {"kind": "TERMINAL_SOURCE_NOT_APPLICABLE"}, + ]) + manifest = { + "kind": "FROZEN", "storage_root_manifest_id": "ESM-" + "A" * 64, + "storage_root_manifest_sigil": SIGIL, + } + observation_set = { + "schema_version": "execution-output-storage-observation-set/1.0", + "observation_set_id": "", "job_id": JOB_ID, "attempt_id": "AT-ONE", + "attempt_binding_sigil": SIGIL, "result_binding": {"kind": "NONE"}, + "log_closure_sigil": SIGIL, "output_closure_sigil": SIGIL_B, + "control_evidence_set_binding": { + "kind": "FROZEN", "control_evidence_set_id": "CES-" + "A" * 64, + "control_evidence_set_sigil": SIGIL, + }, "quarantine_binding_set_binding": { + "kind": "FROZEN", "quarantine_binding_set_id": "QBS-" + "A" * 64, + "quarantine_binding_set_sigil": SIGIL, + }, "terminalization_storage_manifest_binding": manifest, + "output_root_protection": { + "kind": "NO_HOLD", "terminalization_storage_manifest_binding": manifest, + }, "terminal_source_binding": {"kind": "NOT_APPLICABLE"}, + "storage_event": storage_event, "storage_state_sigil": SIGIL, + "members": members, "blob_sigils": [SIGIL], "observation_set_sigil": "", + } + observation_set["observation_set_id"] = derive_execution_output_storage_observation_set_id_v1(observation_set) + observation_set["observation_set_sigil"] = content_sigil({ + key: member for key, member in observation_set.items() if key != "observation_set_sigil" + }) + return observation_set + + +def _evidence(receipt: dict[str, Any]) -> dict[str, Any]: + owner = _owner() + runtime = receipt["result_observation_binding"]["runtime_observation"] + termination = receipt["result_observation_binding"]["termination_observation"] + source = { + "source_kind": "WORKER", + "source_identity_id": "SOURCE", + "source_identity_sigil": SIGIL, + "source_identity_profile_sigil": SIGIL, + "source_channel_sigil": SIGIL, + "source_channel_profile_sigil": SIGIL, + "source_registry_id": "REGISTRY", + "source_registry_version": "1.0", + "source_registry_snapshot_sigil": SIGIL, + } + value = { + "schema_version": "execution-observation-evidence/1.0", + "observation_evidence_id": "", + **owner, + "result_observation_binding": receipt["result_observation_binding"], + "result_ingress_receipt_binding": { + "ingress_receipt_id": receipt["ingress_receipt_id"], + "ingress_receipt_sigil": receipt["ingress_receipt_sigil"], + }, + "producer_evidence_binding": { + "raw_evidence_id": "ORE-" + "A" * 64, + "raw_evidence_record_sigil": SIGIL, + }, + "verifier_evidence_binding": { + "raw_evidence_id": "ORE-" + "B" * 64, + "raw_evidence_record_sigil": SIGIL_B, + }, + "evidence_profile_binding": { + "evidence_profile_id": "PROFILE", + "evidence_profile_version": "1.0", + "evidence_profile_sigil": SIGIL, + }, + "assessment": { + "kind": "MATCHED", + "verified_runtime_observation": runtime, + "verified_termination_observation": termination, + "verified_source_binding": source, + "reason_bindings": [], + }, + "created_at": STAMP, + "observation_evidence_sigil": "", + } + value["observation_evidence_id"] = derive_observation_evidence_id_v1(value) + value["observation_evidence_sigil"] = content_sigil( + {key: member for key, member in value.items() if key != "observation_evidence_sigil"} + ) + return value + + +def _reseal_receipt(receipt: dict[str, Any]) -> None: + receipt["ingress_receipt_id"] = derive_result_ingress_receipt_id_v1(receipt) + verification = receipt["credential_verification"] + verification["verification_sigil"] = content_sigil( + [ + "execution-result-ingress-credential-verification/1.0", + receipt["owner_binding"], + receipt["result_sigil"], + receipt["received_at"], + receipt["control_channel_identity_sigil"], + verification["lease_credential_digest"], + verification["verification_profile_sigil"], + verification["verified_at"], + ] + ) + receipt["ingress_receipt_sigil"] = content_sigil( + {key: member for key, member in receipt.items() if key != "ingress_receipt_sigil"} + ) + + +def _reseal_evidence(evidence: dict[str, Any]) -> None: + owner = { + member: evidence[member] + for member in ( + "job_id", "job_binding_sigil", "attempt_id", "attempt_binding_sigil", + "lease_id", "lease_binding_sigil", "worker_id", "worker_binding_sigil", + "worker_session_id", "worker_session_binding_sigil", "executor_epoch", "fence_tuple", + ) + } + binding = evidence["result_observation_binding"] + binding["observation_evidence_subject_sigil"] = derive_observation_evidence_subject_sigil_v1(owner, binding) + evidence["observation_evidence_id"] = derive_observation_evidence_id_v1(evidence) + evidence["observation_evidence_sigil"] = content_sigil( + {key: member for key, member in evidence.items() if key != "observation_evidence_sigil"} + ) + + +def test_state_closes_19_24_projection_members_and_all_11_ranks() -> None: + schema = json.loads((SCHEMAS / "execution-state-1.0.json").read_text()) + assert len(schema["$defs"]["worker_session_projection"]["required"]) == 19 + assert len(schema["$defs"]["lease_projection"]["required"]) == 24 + assert "anyOf" in schema["$defs"]["terminal_event_binding"]["oneOf"][1]["properties"]["terminal_state"] + assert schema["$defs"]["idempotency_operation_kind"]["enum"] == list( + IDEMPOTENCY_OPERATION_KINDS_V1 + ) + raw = (FIXTURES / "execution-state-v1" / "invalid-duplicate-key.json").read_text() + with pytest.raises(Exception, match="duplicate JSON key"): + load_execution_state_v1(raw) + + +def test_recovery_action_set_is_strictly_sealed_and_ordered() -> None: + action_set = _recovery_action_set() + assert load_execution_recovery_action_set_v1(json.dumps(action_set)) == action_set + + bad_ordinal = deepcopy(action_set) + bad_ordinal["actions"][0]["ordinal"] = 1 + bad_ordinal["action_set_sigil"] = content_sigil( + {key: member for key, member in bad_ordinal.items() if key != "action_set_sigil"} + ) + with pytest.raises(Exception, match="ordinals must be contiguous"): + validate_execution_recovery_action_set_v1(bad_ordinal) + + bad_target = deepcopy(action_set) + bad_target["actions"][0]["target_sequence"] = 5 + bad_target["action_set_sigil"] = content_sigil( + {key: member for key, member in bad_target.items() if key != "action_set_sigil"} + ) + with pytest.raises(Exception, match="target sequence"): + validate_execution_recovery_action_set_v1(bad_target) + + stale_sigil = deepcopy(action_set) + stale_sigil["actions"][0]["expected_revision"] = 1 + with pytest.raises(Exception, match="self-Sigil"): + validate_execution_recovery_action_set_v1(stale_sigil) + + unordered_prerequisites = deepcopy(action_set) + unordered_prerequisites["actions"][0]["prerequisite_event_ids"].reverse() + unordered_prerequisites["action_set_sigil"] = content_sigil( + {key: member for key, member in unordered_prerequisites.items() if key != "action_set_sigil"} + ) + with pytest.raises(Exception, match="prerequisite Event IDs"): + validate_execution_recovery_action_set_v1(unordered_prerequisites) + + two_actions = deepcopy(action_set) + second = deepcopy(two_actions["actions"][0]) + second.update({ + "ordinal": 1, "target_event_id": "JE-FIVE", "target_sequence": 5, + "parameters": { + "deadline_kind": "ATTEMPT_DEADLINE", "due_at": "2026-08-06T00:00:01Z", + "deadline_entity_id": "JB-ONE", + }, + }) + two_actions["actions"].append(second) + two_actions["action_set_sigil"] = content_sigil( + {key: member for key, member in two_actions.items() if key != "action_set_sigil"} + ) + validate_execution_recovery_action_set_v1(two_actions) + + wrong_phase = deepcopy(action_set) + wrong_phase["phase"] = "FENCING" + wrong_phase["action_set_sigil"] = content_sigil( + {key: member for key, member in wrong_phase.items() if key != "action_set_sigil"} + ) + with pytest.raises(Exception, match="not allowed in its phase"): + validate_execution_recovery_action_set_v1(wrong_phase) + + unordered_actions = deepcopy(two_actions) + unordered_actions["actions"].reverse() + for ordinal, action in enumerate(unordered_actions["actions"]): + action["ordinal"] = ordinal + action["target_sequence"] = unordered_actions["derived_through_sequence"] + 2 + ordinal + unordered_actions["action_set_sigil"] = content_sigil( + {key: member for key, member in unordered_actions.items() if key != "action_set_sigil"} + ) + with pytest.raises(Exception, match="canonical order"): + validate_execution_recovery_action_set_v1(unordered_actions) + + duplicate = deepcopy(two_actions) + duplicate["actions"][1]["parameters"] = deepcopy(duplicate["actions"][0]["parameters"]) + duplicate["action_set_sigil"] = content_sigil( + {key: member for key, member in duplicate.items() if key != "action_set_sigil"} + ) + with pytest.raises(Exception, match="duplicate logical actions"): + validate_execution_recovery_action_set_v1(duplicate) + + self_referential = deepcopy(action_set) + self_referential["phase"] = "FENCING" + self_referential["actions"][0].update({ + "action_kind": "ADVANCE_ATTEMPT", "entity_kind": "ATTEMPT", "entity_id": "AT-ONE", + "target_event_type": "attempt.stop_latched", + "parameters": {"attempt_id": "AT-ONE", "from_state": "RUNNING", "transition_cause": { + "code": "RECOVERY_FENCE", "trigger_kind": "RECOVERY_DERIVATION", + "trigger_event_id": "JE-FOUR", "effective_sequence": 4, "evidence_sigil": SIGIL, + }}, + }) + self_referential_second = deepcopy(self_referential["actions"][0]) + self_referential_second.update({"ordinal": 1, "target_event_id": "JE-FIVE", "target_sequence": 5}) + self_referential_second["parameters"]["transition_cause"].update({ + "trigger_event_id": "JE-FIVE", "effective_sequence": 5, + }) + self_referential["actions"].append(self_referential_second) + self_referential["action_set_sigil"] = content_sigil( + {key: member for key, member in self_referential.items() if key != "action_set_sigil"} + ) + with pytest.raises(Exception, match="duplicate logical actions"): + validate_execution_recovery_action_set_v1(self_referential) + + +def test_active_recovery_projection_matches_one_supplied_action_set() -> None: + action_set = _recovery_action_set() + state = json.loads((FIXTURES / "execution-state-v1" / "valid-initial.json").read_text()) + state["recoveries"] = [{ + "recovery_id": action_set["recovery_id"], "revision": 0, "state": "STARTED", + "prior_recovery_id": None, "started_event_sigil": SIGIL, + "current_action_set_sigil": action_set["action_set_sigil"], + "last_event_id": "JE-ONE", "last_event_sigil": SIGIL, + }] + state["executor"]["active_recovery_id"] = action_set["recovery_id"] + state["executor"]["authority_gates"] = ["RECOVERY_ACTIVE"] + _reseal_state(state) + validate_execution_state_supplied_recovery_action_set_v1(state, action_set) + + wrong_set = deepcopy(action_set) + wrong_set["recovery_id"] = "RY-TWO" + wrong_set["action_set_sigil"] = content_sigil({ + key: member for key, member in wrong_set.items() if key != "action_set_sigil" + }) + with pytest.raises(Exception, match="disagrees with supplied"): + validate_execution_state_supplied_recovery_action_set_v1(state, wrong_set) + + +def test_recovery_action_set_anchors_to_its_supplied_prefix() -> None: + initial = json.loads( + (FIXTURES / "execution-journal-event-v1" / "valid-initial.json").read_text() + ) + clock_uncertain = _clock_uncertain_event(initial) + action_set = _recovery_action_set() + action_set["derived_through_event_sigil"] = clock_uncertain["event_sigil"] + action_set["action_set_sigil"] = content_sigil({ + key: member for key, member in action_set.items() if key != "action_set_sigil" + }) + validate_execution_recovery_action_set_supplied_prefix_v1( + action_set, [initial, clock_uncertain], + ) + + stale_anchor = deepcopy(action_set) + stale_anchor["derived_through_sequence"] = 1 + stale_anchor["actions"][0]["target_sequence"] = 3 + stale_anchor["action_set_sigil"] = content_sigil({ + key: member for key, member in stale_anchor.items() if key != "action_set_sigil" + }) + with pytest.raises(Exception, match="disagrees with supplied prefix"): + validate_execution_recovery_action_set_supplied_prefix_v1( + stale_anchor, [initial, clock_uncertain], + ) + + broken_prefix = deepcopy(clock_uncertain) + broken_prefix["previous_event_sigil"] = None + broken_prefix["event_sigil"] = content_sigil({ + key: member for key, member in broken_prefix.items() if key != "event_sigil" + }) + with pytest.raises(Exception, match="previous_event_sigil"): + validate_execution_recovery_action_set_supplied_prefix_v1( + action_set, [initial, broken_prefix], + ) + + later = _event_unsigned() + later.update({ + "event_id": "JE-FOUR", "sequence": 4, "event_type": "log.chunk_committed", + "executor_instance_id": initial["executor_instance_id"], + "executor_epoch": initial["executor_epoch"], + "executor_build_sigil": initial["executor_build_sigil"], + "recorded_at": "2026-08-06T00:00:03Z", + "previous_event_sigil": _recovery_started_event(clock_uncertain)["event_sigil"], + }) + later["event_sigil"] = content_sigil({ + key: member for key, member in later.items() if key != "event_sigil" + }) + recovery_started = _recovery_started_event(clock_uncertain) + later["previous_event_sigil"] = recovery_started["event_sigil"] + later["event_sigil"] = content_sigil({ + key: member for key, member in later.items() if key != "event_sigil" + }) + later_action_set = deepcopy(action_set) + later_action_set["derived_through_sequence"] = 4 + later_action_set["derived_through_event_sigil"] = later["event_sigil"] + later_action_set["actions"][0]["target_sequence"] = 6 + later_action_set["action_set_sigil"] = content_sigil({ + key: member for key, member in later_action_set.items() if key != "action_set_sigil" + }) + validate_execution_journal_prefix_wire_v1([initial, clock_uncertain, recovery_started, later]) + validate_execution_recovery_action_set_supplied_prefix_v1( + later_action_set, [initial, clock_uncertain, recovery_started, later], + ) + with pytest.raises(Exception, match="requires supplied immutable records"): + replay_execution_journal_prefix_v1([initial, clock_uncertain, recovery_started, later]) + + +def test_recovery_start_binds_its_started_action_set_and_prefix() -> None: + initial = json.loads( + (FIXTURES / "execution-journal-event-v1" / "valid-initial.json").read_text() + ) + clock_uncertain = _clock_uncertain_event(initial) + action_set = _recovery_action_set() + action_set["derived_through_event_sigil"] = clock_uncertain["event_sigil"] + action_set["action_set_sigil"] = content_sigil({ + key: member for key, member in action_set.items() if key != "action_set_sigil" + }) + recovery_started = _recovery_started_event(clock_uncertain) + recovery_started["payload"]["initial_action_set_sigil"] = action_set["action_set_sigil"] + recovery_started["event_sigil"] = content_sigil({ + key: member for key, member in recovery_started.items() if key != "event_sigil" + }) + validate_execution_recovery_start_supplied_action_set_v1( + recovery_started, action_set, [initial, clock_uncertain], + ) + + wrong_set = deepcopy(action_set) + wrong_set["supersedes_action_set_sigil"] = SIGIL + wrong_set["action_set_sigil"] = content_sigil({ + key: member for key, member in wrong_set.items() if key != "action_set_sigil" + }) + with pytest.raises(Exception, match="start disagrees"): + validate_execution_recovery_start_supplied_action_set_v1( + recovery_started, wrong_set, [initial, clock_uncertain], + ) + + +def test_execution_journal_prefix_rejects_resealed_duplicate_event_identity() -> None: + initial = json.loads( + (FIXTURES / "execution-journal-event-v1" / "valid-initial.json").read_text() + ) + clock_uncertain = _clock_uncertain_event(initial) + clock_uncertain["event_id"] = initial["event_id"] + clock_uncertain["event_sigil"] = content_sigil({ + key: member for key, member in clock_uncertain.items() if key != "event_sigil" + }) + with pytest.raises(Exception, match="duplicate Event identity"): + validate_execution_journal_prefix_wire_v1([initial, clock_uncertain]) + + +def test_recovery_phase_advance_binds_state_and_sealed_action_sets() -> None: + initial = json.loads( + (FIXTURES / "execution-journal-event-v1" / "valid-initial.json").read_text() + ) + clock_uncertain = _clock_uncertain_event(initial) + recovery_started = _recovery_started_event(clock_uncertain) + completed_set = _recovery_action_set() + completed_set["derived_through_event_sigil"] = clock_uncertain["event_sigil"] + completed_set["action_set_sigil"] = content_sigil({ + key: member for key, member in completed_set.items() if key != "action_set_sigil" + }) + next_set = deepcopy(completed_set) + next_set.update({ + "phase": "FENCING", "derived_through_sequence": 3, + "derived_through_event_sigil": recovery_started["event_sigil"], "actions": [], + }) + next_set["action_set_sigil"] = content_sigil({ + key: member for key, member in next_set.items() if key != "action_set_sigil" + }) + state = json.loads((FIXTURES / "execution-state-v1" / "valid-initial.json").read_text()) + state["journal_binding"] = { + "journal_id": recovery_started["journal_id"], "through_sequence": 3, + "through_event_id": recovery_started["event_id"], + "through_event_sigil": recovery_started["event_sigil"], + } + state["executor"].update({ + "revision": 2, "clock_state": "UNCERTAIN", "clock_uncertain_event_id": "JE-TWO", + "active_recovery_id": "RY-ONE", "authority_gates": ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"], + "last_event_id": recovery_started["event_id"], "last_event_sigil": recovery_started["event_sigil"], + }) + state["recoveries"] = [{ + "recovery_id": "RY-ONE", "revision": 0, "state": "STARTED", + "prior_recovery_id": None, "started_event_sigil": recovery_started["event_sigil"], + "current_action_set_sigil": completed_set["action_set_sigil"], + "last_event_id": recovery_started["event_id"], "last_event_sigil": recovery_started["event_sigil"], + }] + _reseal_state(state) + event = { + "schema_version": "execution-journal-event/1.0", "journal_id": "EJ-ONE", + "event_id": "JE-FOUR", "sequence": 4, "event_type": "recovery.phase_advanced", + "executor_instance_id": initial["executor_instance_id"], "executor_epoch": initial["executor_epoch"], + "executor_build_sigil": initial["executor_build_sigil"], "recorded_at": "2026-08-06T00:00:03Z", + "observed_at": None, + "entity_revisions": [{"entity_kind": "RECOVERY", "entity_id": "RY-ONE", + "preceding_revision": 0, "next_revision": 1}], + "causation_event_id": None, "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": {"recovery_id": "RY-ONE", "from_phase": "STARTED", "to_phase": "FENCING", + "completed_action_set_sigil": completed_set["action_set_sigil"], + "next_action_set_sigil": next_set["action_set_sigil"], + "completed_entity_ids": [], "quarantined_entity_ids": []}, + "previous_event_sigil": recovery_started["event_sigil"], + } + event["event_sigil"] = content_sigil({key: member for key, member in event.items() if key != "event_sigil"}) + validate_execution_recovery_phase_advance_supplied_action_sets_v1( + state, event, completed_set, next_set, + ) + + wrong_next = deepcopy(next_set) + wrong_next["recovery_id"] = "RY-TWO" + wrong_next["action_set_sigil"] = content_sigil({ + key: member for key, member in wrong_next.items() if key != "action_set_sigil" + }) + with pytest.raises(Exception, match="phase advance disagrees"): + validate_execution_recovery_phase_advance_supplied_action_sets_v1( + state, event, completed_set, wrong_next, + ) + + +def test_empty_recovery_phase_replay_projects_each_control_phase() -> None: + initial = json.loads( + (FIXTURES / "execution-journal-event-v1" / "valid-initial.json").read_text() + ) + clock_uncertain = _clock_uncertain_event(initial) + started_set = _empty_recovery_action_set("STARTED", [initial, clock_uncertain]) + recovery_started = _recovery_started_event(clock_uncertain) + recovery_started["payload"]["initial_action_set_sigil"] = started_set["action_set_sigil"] + recovery_started["event_sigil"] = content_sigil({ + key: member for key, member in recovery_started.items() if key != "event_sigil" + }) + fencing_set = _empty_recovery_action_set("FENCING", [initial, clock_uncertain, recovery_started]) + fencing = _recovery_phase_event(recovery_started, started_set, fencing_set, "JE-FOUR") + reconciling_set = _empty_recovery_action_set( + "RECONCILING", [initial, clock_uncertain, recovery_started, fencing], + ) + reconciling = _recovery_phase_event(fencing, fencing_set, reconciling_set, "JE-FIVE") + finalizing_set = _empty_recovery_action_set( + "FINALIZING", [initial, clock_uncertain, recovery_started, fencing, reconciling], + ) + finalizing = _recovery_phase_event(reconciling, reconciling_set, finalizing_set, "JE-SIX") + + state = replay_execution_empty_recovery_phase_prefix_v1( + [initial, clock_uncertain, recovery_started, fencing, reconciling, finalizing], + [started_set, fencing_set, reconciling_set, finalizing_set], + ) + assert replay_execution_journal_prefix_v1( + [initial, clock_uncertain, recovery_started, fencing, reconciling, finalizing], + recovery_action_sets=[started_set, fencing_set, reconciling_set, finalizing_set], + ) == state + assert replay_execution_journal_supplied_facts_v1( + [initial, clock_uncertain, recovery_started, fencing, reconciling, finalizing], + supplied_recovery_action_sets=[started_set, fencing_set, reconciling_set, finalizing_set], + ) == state + + assert state["journal_binding"]["through_sequence"] == 6 + assert state["recoveries"] == [{ + "recovery_id": "RY-ONE", "revision": 3, "state": "FINALIZING", + "prior_recovery_id": None, "started_event_sigil": recovery_started["event_sigil"], + "current_action_set_sigil": finalizing_set["action_set_sigil"], + "last_event_id": finalizing["event_id"], "last_event_sigil": finalizing["event_sigil"], + }] + assert state["executor"]["authority_gates"] == ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"] + + completed = { + "schema_version": "execution-journal-event/1.0", + "journal_id": "EJ-ONE", + "event_id": "JE-SEVEN", + "sequence": 7, + "event_type": "recovery.completed", + "executor_instance_id": "XI-ONE", + "executor_epoch": 1, + "executor_build_sigil": state["executor"]["executor_build_binding"]["executor_build_sigil"], + "recorded_at": "2026-08-06T00:00:06Z", + "observed_at": None, + "entity_revisions": [ + {"entity_kind": "EXECUTOR", "entity_id": "XI-ONE", "preceding_revision": 2, "next_revision": 3}, + {"entity_kind": "RECOVERY", "entity_id": "RY-ONE", "preceding_revision": 3, "next_revision": 4}, + ], + "causation_event_id": None, + "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": { + "recovery_id": "RY-ONE", + "completed_action_set_sigil": finalizing_set["action_set_sigil"], + "finalizing_state_sigil": state["state_sigil"], + "fence_tombstone_event_ids": [], + "quarantined_entity_ids": [], + "resumable_job_ids": [], + }, + "previous_event_sigil": finalizing["event_sigil"], + } + completed["event_sigil"] = content_sigil({ + key: member for key, member in completed.items() if key != "event_sigil" + }) + fully_completed = replay_execution_empty_recovery_phase_prefix_v1( + [initial, clock_uncertain, recovery_started, fencing, reconciling, finalizing, completed], + [started_set, fencing_set, reconciling_set, finalizing_set], + ) + assert replay_execution_journal_prefix_v1( + [initial, clock_uncertain, recovery_started, fencing, reconciling, finalizing, completed], + recovery_action_sets=[started_set, fencing_set, reconciling_set, finalizing_set], + ) == fully_completed + assert fully_completed["recoveries"][0]["state"] == "COMPLETED" + assert fully_completed["executor"]["authority_gates"] == ["CLOCK_UNCERTAIN"] + + one_step = replay_execution_supplied_state_suffix_v1( + replay_execution_journal_prefix_v1([initial, clock_uncertain, recovery_started]), + [fencing], + supplied_recovery_action_sets=[started_set, fencing_set], + ) + assert one_step["recoveries"][0]["state"] == "FENCING" + assert one_step["recoveries"][0]["current_action_set_sigil"] == fencing_set["action_set_sigil"] + assert one_step["executor"]["authority_gates"] == ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"] + + with pytest.raises(Exception, match="requires exactly one"): + replay_execution_supplied_state_suffix_v1( + replay_execution_journal_prefix_v1([initial, clock_uncertain, recovery_started]), + [fencing], supplied_recovery_action_sets=[started_set], + ) + + malformed = deepcopy(fencing_set) + malformed["actions"] = _recovery_action_set()["actions"] + malformed["action_set_sigil"] = content_sigil({ + key: member for key, member in malformed.items() if key != "action_set_sigil" + }) + with pytest.raises(Exception, match="action kind is not allowed|initial empty action sets"): + replay_execution_empty_recovery_phase_prefix_v1( + [initial, clock_uncertain, recovery_started, fencing, reconciling, finalizing], + [started_set, malformed, reconciling_set, finalizing_set], + ) + + +def test_recovery_rebase_binds_state_and_sealed_action_sets() -> None: + prior_set = _recovery_action_set() + state = json.loads((FIXTURES / "execution-state-v1" / "valid-initial.json").read_text()) + state["journal_binding"] = { + "journal_id": "EJ-ONE", "through_sequence": 3, "through_event_id": "JE-THREE", + "through_event_sigil": SIGIL_B, + } + state["executor"].update({ + "revision": 2, "clock_state": "UNCERTAIN", "clock_uncertain_event_id": "JE-TWO", + "active_recovery_id": "RY-ONE", "authority_gates": ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"], + "last_event_id": "JE-THREE", "last_event_sigil": SIGIL_B, + }) + state["recoveries"] = [{ + "recovery_id": "RY-ONE", "revision": 0, "state": "STARTED", + "prior_recovery_id": None, "started_event_sigil": SIGIL, + "current_action_set_sigil": prior_set["action_set_sigil"], + "last_event_id": "JE-THREE", "last_event_sigil": SIGIL_B, + }] + _reseal_state(state) + replacement_set = deepcopy(prior_set) + replacement_set["supersedes_action_set_sigil"] = prior_set["action_set_sigil"] + replacement_set["action_set_sigil"] = content_sigil({ + key: member for key, member in replacement_set.items() if key != "action_set_sigil" + }) + event = { + "schema_version": "execution-journal-event/1.0", "journal_id": "EJ-ONE", + "event_id": "JE-FOUR", "sequence": 4, "event_type": "recovery.action_set_rebased", + "executor_instance_id": "XI-ONE", "executor_epoch": 1, "executor_build_sigil": SIGIL, + "recorded_at": "2026-08-06T00:00:03Z", "observed_at": None, + "entity_revisions": [{"entity_kind": "RECOVERY", "entity_id": "RY-ONE", + "preceding_revision": 0, "next_revision": 1}], + "causation_event_id": None, "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": {"recovery_id": "RY-ONE", "phase": "STARTED", + "prior_action_set_sigil": prior_set["action_set_sigil"], + "replacement_action_set_sigil": replacement_set["action_set_sigil"], + "reason_event_id": "JE-TWO", "new_epoch": 1, + "carried_completion_event_ids": []}, + "previous_event_sigil": SIGIL_B, + } + event["event_sigil"] = content_sigil({key: member for key, member in event.items() if key != "event_sigil"}) + validate_execution_recovery_rebase_supplied_action_sets_v1( + state, event, prior_set, replacement_set, + ) + + wrong_replacement = deepcopy(replacement_set) + wrong_replacement["supersedes_action_set_sigil"] = SIGIL + wrong_replacement["action_set_sigil"] = content_sigil({ + key: member for key, member in wrong_replacement.items() if key != "action_set_sigil" + }) + with pytest.raises(Exception, match="rebase disagrees"): + validate_execution_recovery_rebase_supplied_action_sets_v1( + state, event, prior_set, wrong_replacement, + ) + + reduced = replay_execution_supplied_state_suffix_v1( + state, [event], supplied_recovery_action_sets=[prior_set, replacement_set], + ) + assert reduced["recoveries"][0]["revision"] == 1 + assert reduced["recoveries"][0]["current_action_set_sigil"] == replacement_set["action_set_sigil"] + assert reduced["executor"]["authority_gates"] == ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"] + + with pytest.raises(Exception, match="requires exactly one"): + replay_execution_supplied_state_suffix_v1( + state, [event], supplied_recovery_action_sets=[prior_set], + ) + + +def test_recovery_completion_binds_finalizing_state_and_action_set() -> None: + action_set = _recovery_action_set() + action_set.update({"phase": "FINALIZING", "actions": []}) + action_set["action_set_sigil"] = content_sigil({ + key: member for key, member in action_set.items() if key != "action_set_sigil" + }) + state = json.loads((FIXTURES / "execution-state-v1" / "valid-initial.json").read_text()) + state["journal_binding"] = {"journal_id": "EJ-ONE", "through_sequence": 3, + "through_event_id": "JE-THREE", "through_event_sigil": SIGIL_B} + state["executor"].update({"revision": 2, "clock_state": "UNCERTAIN", + "clock_uncertain_event_id": "JE-TWO", "active_recovery_id": "RY-ONE", + "authority_gates": ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"], + "last_event_id": "JE-THREE", "last_event_sigil": SIGIL_B}) + state["recoveries"] = [{"recovery_id": "RY-ONE", "revision": 3, "state": "FINALIZING", + "prior_recovery_id": None, "started_event_sigil": SIGIL, + "current_action_set_sigil": action_set["action_set_sigil"], + "last_event_id": "JE-THREE", "last_event_sigil": SIGIL_B}] + _reseal_state(state) + executor_build_sigil = state["executor"]["executor_build_binding"]["executor_build_sigil"] + event = {"schema_version": "execution-journal-event/1.0", "journal_id": "EJ-ONE", + "event_id": "JE-FOUR", "sequence": 4, "event_type": "recovery.completed", + "executor_instance_id": "XI-ONE", "executor_epoch": 1, + "executor_build_sigil": executor_build_sigil, + "recorded_at": "2026-08-06T00:00:03Z", "observed_at": None, + "entity_revisions": [ + {"entity_kind": "EXECUTOR", "entity_id": "XI-ONE", "preceding_revision": 2, "next_revision": 3}, + {"entity_kind": "RECOVERY", "entity_id": "RY-ONE", "preceding_revision": 3, "next_revision": 4}, + ], "causation_event_id": None, "idempotency_key_sigil": None, "recovery_action_binding": None, + "payload": {"recovery_id": "RY-ONE", "completed_action_set_sigil": action_set["action_set_sigil"], + "finalizing_state_sigil": state["state_sigil"], "fence_tombstone_event_ids": [], + "quarantined_entity_ids": [], "resumable_job_ids": []}, + "previous_event_sigil": SIGIL_B} + event["event_sigil"] = content_sigil({key: member for key, member in event.items() if key != "event_sigil"}) + validate_execution_recovery_completion_supplied_action_set_v1(state, event, action_set) + completed = _reduce_recovery_completed_v1(state, event, action_set) + assert completed["executor"]["active_recovery_id"] is None + assert completed["executor"]["authority_gates"] == ["CLOCK_UNCERTAIN"] + assert completed["recoveries"][0]["state"] == "COMPLETED" + assert completed["journal_binding"]["through_event_sigil"] == event["event_sigil"] + + wrong_state = deepcopy(event) + wrong_state["payload"]["finalizing_state_sigil"] = SIGIL + wrong_state["event_sigil"] = content_sigil({ + key: member for key, member in wrong_state.items() if key != "event_sigil" + }) + with pytest.raises(Exception, match="completion disagrees"): + validate_execution_recovery_completion_supplied_action_set_v1( + state, wrong_state, action_set + ) + + wrong_set = deepcopy(action_set) + wrong_set["phase"] = "RECONCILING" + wrong_set["action_set_sigil"] = content_sigil({ + key: member for key, member in wrong_set.items() if key != "action_set_sigil" + }) + with pytest.raises(Exception, match="completion disagrees"): + validate_execution_recovery_completion_supplied_action_set_v1(state, event, wrong_set) + + wrong_epoch = deepcopy(event) + wrong_epoch["executor_epoch"] = 2 + wrong_epoch["event_sigil"] = content_sigil({ + key: member for key, member in wrong_epoch.items() if key != "event_sigil" + }) + with pytest.raises(Exception, match="completion disagrees"): + validate_execution_recovery_completion_supplied_action_set_v1( + state, wrong_epoch, action_set, + ) + + +def test_clock_restoration_keeps_recovery_authority_gate_closed() -> None: + state = json.loads((FIXTURES / "execution-state-v1" / "valid-initial.json").read_text()) + state["journal_binding"] = { + "journal_id": "EJ-ONE", "through_sequence": 3, + "through_event_id": "JE-THREE", "through_event_sigil": SIGIL_B, + } + action_set = { + "schema_version": "execution-recovery-action-set/1.0", "recovery_id": "RY-ONE", + "phase": "FINALIZING", "derived_from_journal_id": "EJ-ONE", + "derived_through_sequence": 2, "derived_through_event_sigil": SIGIL, + "supersedes_action_set_sigil": None, + "actions": [{ + "ordinal": 0, "action_kind": "RESTORE_CLOCK", "entity_kind": "EXECUTOR", + "entity_id": "XI-ONE", "expected_revision": 2, "target_event_id": "JE-FOUR", + "target_sequence": 4, "target_event_type": "executor.clock_restored", + "prerequisite_event_ids": ["JE-ONE", "JE-TWO"], + "parameters": {"clock_uncertain_event_id": "JE-TWO", "trusted_time_source_sigil": SIGIL, + "clock_uncertainty_tolerance_seconds": 0}, + }], "action_set_sigil": "", + } + action_set["action_set_sigil"] = content_sigil({ + key: member for key, member in action_set.items() if key != "action_set_sigil" + }) + state["executor"].update({ + "revision": 2, "clock_state": "UNCERTAIN", "clock_uncertain_event_id": "JE-TWO", + "active_recovery_id": "RY-ONE", "authority_gates": ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"], + "last_event_id": "JE-THREE", "last_event_sigil": SIGIL_B, + }) + state["recoveries"] = [{ + "recovery_id": "RY-ONE", "revision": 3, "state": "FINALIZING", + "prior_recovery_id": None, "started_event_sigil": SIGIL, + "current_action_set_sigil": action_set["action_set_sigil"], + "last_event_id": "JE-THREE", "last_event_sigil": SIGIL_B, + }] + _reseal_state(state) + event = build_execution_journal_event_v1({ + "schema_version": "execution-journal-event/1.0", "journal_id": "EJ-ONE", + "event_id": "JE-FOUR", "sequence": 4, "event_type": "executor.clock_restored", + "executor_instance_id": "XI-ONE", "executor_epoch": 1, + "executor_build_sigil": state["executor"]["executor_build_binding"]["executor_build_sigil"], + "recorded_at": "2026-08-06T00:00:03Z", "observed_at": None, + "entity_revisions": [{"entity_kind": "EXECUTOR", "entity_id": "XI-ONE", + "preceding_revision": 2, "next_revision": 3}], + "causation_event_id": "JE-THREE", "idempotency_key_sigil": None, + "recovery_action_binding": {"recovery_id": "RY-ONE", "phase": "FINALIZING", + "action_set_sigil": action_set["action_set_sigil"], "action_ordinal": 0}, + "payload": {"trusted_time_source_sigil": SIGIL, "restored_utc": "2026-08-06T00:00:03Z", + "fenced_lease_ids": [], "new_anchor_evidence_sigil": SIGIL}, + "previous_event_sigil": SIGIL_B, + }) + restored = replay_execution_supplied_state_suffix_v1( + state, [event], supplied_recovery_action_sets=[action_set], + ) + assert restored["executor"]["clock_state"] == "TRUSTED" + assert restored["executor"]["authority_gates"] == ["RECOVERY_ACTIVE"] + assert restored["executor"]["active_recovery_id"] == "RY-ONE" + + wrong = deepcopy(event) + wrong["payload"]["fenced_lease_ids"] = ["LS-" + "0" * 26] + wrong = build_execution_journal_event_v1({key: value for key, value in wrong.items() if key != "event_sigil"}) + with pytest.raises(Exception, match="Clock restoration"): + replay_execution_supplied_state_suffix_v1( + state, [wrong], supplied_recovery_action_sets=[action_set], + ) + + +def test_recovery_action_event_matches_its_supplied_frozen_envelope() -> None: + action_set = _recovery_action_set() + event = _recovery_action_event(action_set) + validate_execution_recovery_action_supplied_event_v1(action_set, event) + + multi_owner = deepcopy(event) + multi_owner["entity_revisions"] = [ + {"entity_kind": "EXECUTOR", "entity_id": "XI-ONE", "preceding_revision": 1, + "next_revision": 2}, + *event["entity_revisions"], + ] + multi_owner["event_sigil"] = content_sigil({ + key: member for key, member in multi_owner.items() if key != "event_sigil" + }) + validate_execution_recovery_action_supplied_event_v1(action_set, multi_owner) + + wrong_envelope = deepcopy(event) + wrong_envelope["event_id"] = "JE-WRONG" + wrong_envelope["event_sigil"] = content_sigil({ + key: member for key, member in wrong_envelope.items() if key != "event_sigil" + }) + with pytest.raises(Exception, match="envelope disagrees"): + validate_execution_recovery_action_supplied_event_v1(action_set, wrong_envelope) + + +def test_state_locally_binds_session_and_lease_heartbeat_projections() -> None: + state = _state_with_session_and_lease() + assert load_execution_state_v1(json.dumps(state)) == state + + bad_session = deepcopy(state) + bad_session["worker_sessions"][0]["last_heartbeat_message_sigil"] = None + _reseal_state(bad_session) + with pytest.raises(Exception, match="Worker-Session heartbeat fields"): + load_execution_state_v1(json.dumps(bad_session)) + + bad_session_due = deepcopy(state) + bad_session_due["worker_sessions"][0]["state"] = "OFFLINE" + _reseal_state(bad_session_due) + with pytest.raises(Exception, match="Worker-Session terminal or unready"): + load_execution_state_v1(json.dumps(bad_session_due)) + + missing_capacity = deepcopy(state) + missing_capacity["worker_sessions"][0].update({ + "capacity": None, "capacity_in_use": 0, + "worker_session_heartbeat_policy_id": None, + "worker_session_heartbeat_policy_sigil": None, + }) + _reseal_state(missing_capacity) + with pytest.raises(Exception, match="capacity nullability"): + load_execution_state_v1(json.dumps(missing_capacity)) + + bad_lease = deepcopy(state) + bad_lease["leases"][0]["last_resource_sample_sigil"] = None + _reseal_state(bad_lease) + with pytest.raises(Exception, match="Lease heartbeat fields"): + load_execution_state_v1(json.dumps(bad_lease)) + + bad_lease_due = deepcopy(state) + bad_lease_due["leases"][0]["next_heartbeat_due_at"] = None + _reseal_state(bad_lease_due) + with pytest.raises(Exception, match="Lease heartbeat due time"): + load_execution_state_v1(json.dumps(bad_lease_due)) + + bad_tombstone = deepcopy(state) + bad_tombstone["leases"][0]["tombstone_generation"] = 0 + bad_tombstone["leases"][0]["tombstone_event_sigil"] = SIGIL + _reseal_state(bad_tombstone) + with pytest.raises(Exception, match="Lease tombstone fields"): + load_execution_state_v1(json.dumps(bad_tombstone)) + + terminal_lease = deepcopy(state) + terminal_lease["leases"][0].update({ + "state": "RELEASED", "next_heartbeat_due_at": None, + "tombstone_generation": 0, "tombstone_event_sigil": SIGIL, + "terminal_event_binding": { + "kind": "PRESENT", "terminal_state": "RELEASED", "terminal_event_id": "JE-TWO", + "terminal_event_sigil": SIGIL, "terminal_sequence": 2, "terminal_recorded_at": STAMP, + }, + }) + _reseal_state(terminal_lease) + assert load_execution_state_v1(json.dumps(terminal_lease)) == terminal_lease + + missing_worker = deepcopy(state) + missing_worker["workers"] = [] + _reseal_state(missing_worker) + with pytest.raises(Exception, match="no matching Worker"): + load_execution_state_v1(json.dumps(missing_worker)) + + missing_session = deepcopy(state) + missing_session["worker_sessions"] = [] + _reseal_state(missing_session) + with pytest.raises(Exception, match="session IDs do not exactly match|no matching Worker-Session"): + load_execution_state_v1(json.dumps(missing_session)) + + mismatched_lease_worker = deepcopy(state) + mismatched_lease_worker["leases"][0]["worker_id"] = "WK-TWO" + _reseal_state(mismatched_lease_worker) + with pytest.raises(Exception, match="Lease Worker does not match"): + load_execution_state_v1(json.dumps(mismatched_lease_worker)) + + mismatched_worker_binding = deepcopy(state) + mismatched_worker_binding["worker_sessions"][0]["worker_binding_sigil"] = SIGIL_B + _reseal_state(mismatched_worker_binding) + with pytest.raises(Exception, match="binding Sigil does not match"): + load_execution_state_v1(json.dumps(mismatched_worker_binding)) + + excess_lease_expiry = deepcopy(state) + excess_lease_expiry["leases"][0]["expiry_due_at"] = "2026-08-06T00:00:01Z" + _reseal_state(excess_lease_expiry) + with pytest.raises(Exception, match="exceeds its maximum expiry"): + load_execution_state_v1(json.dumps(excess_lease_expiry)) + + orphan_session = deepcopy(state) + orphan_session["workers"][0]["worker_session_ids"].append("WS-" + "1" * 26) + _reseal_state(orphan_session) + with pytest.raises(Exception, match="session IDs do not exactly match"): + load_execution_state_v1(json.dumps(orphan_session)) + + orphan_lease = deepcopy(state) + orphan_lease["worker_sessions"][0]["lease_ids"].append("LS-" + "1" * 26) + _reseal_state(orphan_lease) + with pytest.raises(Exception, match="lease IDs do not exactly match"): + load_execution_state_v1(json.dumps(orphan_lease)) + + +def test_state_locally_binds_log_stream_closure_projections() -> None: + state = _state_with_session_and_lease() + log_stream = { + "log_stream_id": "LG-ONE", "revision": 0, "state": "OPEN", "attempt_id": "AT-ONE", + "stream": "STDOUT", "next_sequence": 0, "captured_bytes": 0, "dropped_bytes": 0, + "truncated": False, "final_sequence": None, "stream_set_sigil": None, + "last_event_id": "JE-ONE", "last_event_sigil": SIGIL, + } + state["log_streams"] = [log_stream] + _reseal_state(state) + assert load_execution_state_v1(json.dumps(state)) == state + + open_with_terminal_fields = deepcopy(state) + open_with_terminal_fields["log_streams"][0]["stream_set_sigil"] = SIGIL + _reseal_state(open_with_terminal_fields) + with pytest.raises(Exception, match="Open Log stream"): + load_execution_state_v1(json.dumps(open_with_terminal_fields)) + + closed_without_sigil = deepcopy(state) + closed_without_sigil["log_streams"][0]["state"] = "CLOSED" + _reseal_state(closed_without_sigil) + with pytest.raises(Exception, match="Closed Log stream must have"): + load_execution_state_v1(json.dumps(closed_without_sigil)) + + closed_empty = deepcopy(state) + closed_empty["log_streams"][0].update({"state": "CLOSED", "stream_set_sigil": SIGIL}) + _reseal_state(closed_empty) + assert load_execution_state_v1(json.dumps(closed_empty)) == closed_empty + + closed_past_next = deepcopy(closed_empty) + closed_past_next["log_streams"][0]["final_sequence"] = 0 + _reseal_state(closed_past_next) + with pytest.raises(Exception, match="final sequence must precede"): + load_execution_state_v1(json.dumps(closed_past_next)) + + +def test_state_locally_binds_deadline_priority_and_order() -> None: + state = _state_with_session_and_lease() + state["deadlines"] = [ + {"deadline_kind": "JOB_DEADLINE", "due_at": STAMP, "fixed_priority": 10, + "entity_id": JOB_ID, "source_event_id": "JE-ONE", "source_event_sigil": SIGIL}, + {"deadline_kind": "LEASE_EXPIRY", "due_at": STAMP, "fixed_priority": 40, + "entity_id": LEASE_ID, "source_event_id": "JE-ONE", "source_event_sigil": SIGIL}, + ] + _reseal_state(state) + assert load_execution_state_v1(json.dumps(state)) == state + + wrong_priority = deepcopy(state) + wrong_priority["deadlines"][0]["fixed_priority"] = 20 + _reseal_state(wrong_priority) + with pytest.raises(Exception, match="fixed priority"): + load_execution_state_v1(json.dumps(wrong_priority)) + + wrong_order = deepcopy(state) + wrong_order["deadlines"].reverse() + _reseal_state(wrong_order) + with pytest.raises(Exception, match="canonical deadline key"): + load_execution_state_v1(json.dumps(wrong_order)) + + duplicate_key = deepcopy(state) + duplicate_key["deadlines"].append(deepcopy(duplicate_key["deadlines"][1])) + _reseal_state(duplicate_key) + with pytest.raises(Exception, match="duplicate Deadline"): + load_execution_state_v1(json.dumps(duplicate_key)) + + +def test_isr3_initial_event_state_head_triplet_is_closed_and_cross_bound() -> None: + event = json.loads( + (FIXTURES / "execution-journal-event-v1" / "valid-initial.json").read_text() + ) + state = json.loads( + (FIXTURES / "execution-state-v1" / "valid-initial.json").read_text() + ) + head = json.loads( + (FIXTURES / "execution-journal-head-v1" / "valid-initial.json").read_text() + ) + assert load_execution_journal_event_v1(json.dumps(event)) == event + assert load_execution_state_v1(json.dumps(state)) == state + validate_execution_journal_head_v1(head) + assert load_execution_journal_head_v1(json.dumps(head)) == head + validate_execution_initial_state_supplied_facts_v1(event, state, head) + assert replay_execution_initial_prefix_v1([event], head=head) == state + assert replay_execution_journal_prefix_v1([event], head=head) == state + with pytest.raises(Exception, match="nonempty prefix"): + replay_execution_journal_prefix_v1([]) + with pytest.raises(Exception, match="nonobject Event"): + replay_execution_journal_prefix_v1([event, None]) # type: ignore[list-item] + + wrong_first_kind = deepcopy(event) + wrong_first_kind["event_type"] = "executor.clock_uncertain" + wrong_first_kind["event_sigil"] = content_sigil( + {key: member for key, member in wrong_first_kind.items() if key != "event_sigil"} + ) + with pytest.raises(Exception, match="must begin with executor epoch start"): + replay_execution_journal_prefix_v1([wrong_first_kind]) + with pytest.raises(Exception, match="only the initial one-Event prefix"): + replay_execution_initial_prefix_v1([event, event]) + with pytest.raises(Exception, match="duplicate Event identity|sequence gap"): + replay_execution_journal_prefix_v1([event, event]) + + wrong_head = deepcopy(head) + wrong_head["last_event_id"] = "JE-TWO" + wrong_head["head_sigil"] = content_sigil( + {key: member for key, member in wrong_head.items() if key != "head_sigil"} + ) + with pytest.raises(Exception, match="Head disagrees"): + replay_execution_journal_prefix_v1([event], head=wrong_head) + + wrong_initial_event = deepcopy(event) + wrong_initial_event["event_type"] = "executor.clock_uncertain" + wrong_initial_event["event_sigil"] = content_sigil( + {key: member for key, member in wrong_initial_event.items() if key != "event_sigil"} + ) + with pytest.raises(Exception, match="execution-journal-event"): + replay_execution_initial_prefix_v1([wrong_initial_event]) + + clock_uncertain = _clock_uncertain_event(event) + reduced = replay_execution_journal_prefix_v1([event, clock_uncertain]) + assert reduced["executor"]["clock_state"] == "UNCERTAIN" + assert reduced["executor"]["authority_gates"] == ["CLOCK_UNCERTAIN"] + assert reduced["executor"]["clock_uncertain_event_id"] == "JE-TWO" + assert reduced["journal_binding"]["through_event_sigil"] == clock_uncertain["event_sigil"] + + recovery_started = _recovery_started_event(clock_uncertain) + recovered = replay_execution_journal_prefix_v1([event, clock_uncertain, recovery_started]) + assert recovered["executor"]["active_recovery_id"] == "RY-ONE" + assert recovered["executor"]["authority_gates"] == ["CLOCK_UNCERTAIN", "RECOVERY_ACTIVE"] + assert recovered["recoveries"] == [{ + "recovery_id": "RY-ONE", "revision": 0, "state": "STARTED", + "prior_recovery_id": None, "started_event_sigil": recovery_started["event_sigil"], + "current_action_set_sigil": SIGIL, "last_event_id": "JE-THREE", + "last_event_sigil": recovery_started["event_sigil"], + }] + + mismatched_prefix = deepcopy(recovery_started) + mismatched_prefix["payload"]["replay_through_sequence"] = 1 + mismatched_prefix["event_sigil"] = content_sigil({ + key: member for key, member in mismatched_prefix.items() if key != "event_sigil" + }) + with pytest.raises(Exception, match="payload disagrees"): + replay_execution_journal_prefix_v1([event, clock_uncertain, mismatched_prefix]) + + changed_anchor = deepcopy(clock_uncertain) + changed_anchor["payload"]["last_trusted_utc"] = "2026-08-06T00:00:01Z" + changed_anchor["event_sigil"] = content_sigil( + {key: member for key, member in changed_anchor.items() if key != "event_sigil"} + ) + with pytest.raises(Exception, match="trusted-time anchor"): + replay_execution_journal_prefix_v1([event, changed_anchor]) + + decreasing_time = deepcopy(clock_uncertain) + decreasing_time["recorded_at"] = "2026-08-05T23:59:59Z" + decreasing_time["event_sigil"] = content_sigil( + {key: member for key, member in decreasing_time.items() if key != "event_sigil"} + ) + with pytest.raises(Exception, match="decreasing recorded_at"): + replay_execution_journal_prefix_v1([event, decreasing_time]) + + conflicting_build = deepcopy(clock_uncertain) + conflicting_build["executor_build_sigil"] = SIGIL + conflicting_build["event_sigil"] = content_sigil( + {key: member for key, member in conflicting_build.items() if key != "event_sigil"} + ) + with pytest.raises(Exception, match="conflicting Executor build"): + replay_execution_journal_prefix_v1([event, conflicting_build]) + assert head["head_sigil"] == content_sigil( + {key: member for key, member in head.items() if key != "head_sigil"} + ) + for record in (state["journal_binding"], head): + assert record["journal_id"] == event["journal_id"] + assert record["through_sequence" if record is state["journal_binding"] else "last_sequence"] == event["sequence"] + assert record["through_event_id" if record is state["journal_binding"] else "last_event_id"] == event["event_id"] + assert record["through_event_sigil" if record is state["journal_binding"] else "last_event_sigil"] == event["event_sigil"] + assert state["executor"]["executor_build_binding"] == event["payload"]["executor_build_binding"] + assert state["executor"]["last_event_sigil"] == event["event_sigil"] + for member in ( + "recoveries", "workers", "worker_sessions", "jobs", "attempts", + "leases", "log_streams", "deadlines", "idempotency_records", + ): + assert state[member] == [] + + tampered = deepcopy(state) + tampered["executor"]["executor_build_binding"]["implementation_version"] = "V2" + tampered["state_sigil"] = content_sigil( + {key: member for key, member in tampered.items() if key != "state_sigil"} + ) + with pytest.raises(Exception, match="executor build self-Sigil"): + load_execution_state_v1(json.dumps(tampered)) + + wrong_gate = deepcopy(state) + wrong_gate["executor"]["authority_gates"] = ["CLOCK_UNCERTAIN"] + wrong_gate["state_sigil"] = content_sigil( + {key: member for key, member in wrong_gate.items() if key != "state_sigil"} + ) + with pytest.raises(Exception, match="clock uncertainty gate"): + load_execution_state_v1(json.dumps(wrong_gate)) + + wrong_order = deepcopy(state) + wrong_order["executor"]["authority_gates"] = ["RECOVERY_ACTIVE", "INTEGRITY_FAILURE"] + wrong_order["state_sigil"] = content_sigil( + {key: member for key, member in wrong_order.items() if key != "state_sigil"} + ) + with pytest.raises(Exception, match="canonical order"): + load_execution_state_v1(json.dumps(wrong_order)) + + recovery = deepcopy(state) + recovery_id = "RY-" + "A" * 64 + recovery["recoveries"] = [{ + "recovery_id": recovery_id, "revision": 0, "state": "STARTED", + "prior_recovery_id": None, "started_event_sigil": SIGIL, + "current_action_set_sigil": None, "last_event_id": "JE-ONE", "last_event_sigil": SIGIL, + }] + recovery["executor"]["active_recovery_id"] = recovery_id + recovery["executor"]["authority_gates"] = ["RECOVERY_ACTIVE"] + _reseal_state(recovery) + assert load_execution_state_v1(json.dumps(recovery)) == recovery + + missing_recovery = deepcopy(recovery) + missing_recovery["recoveries"] = [] + _reseal_state(missing_recovery) + with pytest.raises(Exception, match="active Recovery does not match"): + load_execution_state_v1(json.dumps(missing_recovery)) + + unprojected_recovery = deepcopy(recovery) + unprojected_recovery["executor"]["active_recovery_id"] = None + unprojected_recovery["executor"]["authority_gates"] = [] + _reseal_state(unprojected_recovery) + with pytest.raises(Exception, match="active Recovery is missing"): + load_execution_state_v1(json.dumps(unprojected_recovery)) + + invalid_first_recovery = deepcopy(recovery) + invalid_first_recovery["recoveries"][0]["prior_recovery_id"] = "RY-" + "B" * 64 + _reseal_state(invalid_first_recovery) + with pytest.raises(Exception, match="first Recovery projection"): + load_execution_state_v1(json.dumps(invalid_first_recovery)) + + invalid_later_recovery = deepcopy(recovery) + invalid_later_recovery["recoveries"].append({ + "recovery_id": "RY-" + "B" * 64, "revision": 0, "state": "COMPLETED", + "prior_recovery_id": None, "started_event_sigil": SIGIL, + "current_action_set_sigil": None, "last_event_id": "JE-TWO", "last_event_sigil": SIGIL, + }) + _reseal_state(invalid_later_recovery) + with pytest.raises(Exception, match="immediately prior Recovery"): + load_execution_state_v1(json.dumps(invalid_later_recovery)) + + mismatched_prior_recovery = deepcopy(recovery) + mismatched_prior_recovery["recoveries"][0]["state"] = "COMPLETED" + mismatched_prior_recovery["recoveries"].append({ + "recovery_id": "RY-" + "B" * 64, "revision": 0, "state": "STARTED", + "prior_recovery_id": "RY-" + "C" * 64, "started_event_sigil": SIGIL, + "current_action_set_sigil": SIGIL, "last_event_id": "JE-TWO", "last_event_sigil": SIGIL, + }) + mismatched_prior_recovery["executor"]["active_recovery_id"] = "RY-" + "B" * 64 + _reseal_state(mismatched_prior_recovery) + with pytest.raises(Exception, match="immediately prior Recovery"): + load_execution_state_v1(json.dumps(mismatched_prior_recovery)) + + incomplete_prior_recovery = deepcopy(mismatched_prior_recovery) + incomplete_prior_recovery["recoveries"][1]["prior_recovery_id"] = recovery_id + incomplete_prior_recovery["recoveries"][0]["state"] = "FINALIZING" + _reseal_state(incomplete_prior_recovery) + with pytest.raises(Exception, match="follows a Recovery that is not completed"): + load_execution_state_v1(json.dumps(incomplete_prior_recovery)) + + changed_executor = deepcopy(state) + changed_executor["executor"]["revision"] = 1 + changed_executor["state_sigil"] = content_sigil( + {key: member for key, member in changed_executor.items() if key != "state_sigil"} + ) + with pytest.raises(Exception, match="executor projection"): + validate_execution_initial_state_supplied_facts_v1(event, changed_executor, head) + + changed_head = deepcopy(head) + changed_head["updated_at"] = "2026-08-06T00:00:01Z" + changed_head["head_sigil"] = content_sigil( + {key: member for key, member in changed_head.items() if key != "head_sigil"} + ) + validate_execution_initial_state_supplied_facts_v1(event, state, changed_head) + + invalid_head = deepcopy(head) + invalid_head["last_sequence"] = 2 + with pytest.raises(Exception, match="Head self-Sigil"): + load_execution_journal_head_v1(json.dumps(invalid_head)) + with pytest.raises(Exception, match="duplicate JSON key"): + load_execution_journal_head_v1( + b'{"schema_version":"execution-journal-head/1.0","schema_version":"x"}' + ) + + +def test_rfc0015_request_loaders_are_strict_and_cursor_bound_to_fixed_prefix() -> None: + cursor: dict[str, Any] = { + "job_id": JOB_ID, + "last_returned_sequence": 2, + "through_journal_sequence": 3, + "through_event_sigil": SIGIL, + } + cursor["cursor_sigil"] = derive_execution_observation_cursor_sigil_v1(cursor) + observe: dict[str, Any] = { + "schema_version": "execution-observe-request/1.0", + "job_id": JOB_ID, + "limit": 2, + "cursor": cursor, + } + validate_execution_request_v1("observe", observe) + assert load_execution_request_v1("observe", json.dumps(observe)) == observe + for raw in ( + b'\xef\xbb\xbf{}', + "{}".encode("utf-16"), + "{}".encode("utf-32"), + b'{"schema_version":"execution-observe-request/1.0","limit":1,"limit":2}', + ): + with pytest.raises(Exception): + load_execution_request_v1("observe", raw) + for invalid_limit in (1.0, True): + noncanonical = {**observe, "limit": invalid_limit} + with pytest.raises(Exception): + validate_execution_request_v1("observe", noncanonical) + wrong_job = deepcopy(observe) + wrong_job["cursor"]["job_id"] = "JB-" + "B" * 64 + wrong_job["cursor"]["cursor_sigil"] = derive_execution_observation_cursor_sigil_v1(wrong_job["cursor"]) + with pytest.raises(Exception, match="does not match"): + validate_execution_request_v1("observe", wrong_job) + bad_range = deepcopy(observe) + bad_range["cursor"]["last_returned_sequence"] = 4 + bad_range["cursor"]["cursor_sigil"] = derive_execution_observation_cursor_sigil_v1(bad_range["cursor"]) + with pytest.raises(Exception, match="sequence range"): + validate_execution_request_v1("observe", bad_range) + with pytest.raises(Exception, match="unknown Execution API"): + validate_execution_request_v1("dispatch", observe) + + get_result = {"schema_version": "execution-get-result-request/1.0", "job_id": JOB_ID} + validate_execution_request_v1("get_result", get_result) + get_result["job_id"] = "JB-" + "Z" * 64 + with pytest.raises(Exception): + validate_execution_request_v1("get_result", get_result) + + +def test_rfc0015_cancel_and_accept_requests_close_nested_and_scalar_fields() -> None: + cancel: dict[str, Any] = { + "schema_version": "execution-cancel-request/1.0", + "cancellation_request_id": "cancel-001", + "idempotency_key": "cancel-key", + "job_id": JOB_ID, + "job_binding_sigil": SIGIL, + "expected_job_revision": 1, + "reason": "operator-requested", + "actor": { + "kind": "USER", + "actor_id": "user-001", + "authentication_context_sigil": SIGIL, + "actor_sigil": SIGIL, + }, + "host_invocation": { + "host_identity_sigil": SIGIL, + "invocation_id": "invoke-001", + "authentication_context_sigil": SIGIL, + "invocation_sigil": SIGIL, + }, + "caller_observed_at": STAMP, + } + validate_execution_request_v1("cancel", cancel) + assert load_execution_request_v1("cancel", json.dumps(cancel)) == cancel + nested_extra = deepcopy(cancel) + nested_extra["actor"]["authority"] = "ambient" + with pytest.raises(Exception): + validate_execution_request_v1("cancel", nested_extra) + with pytest.raises(Exception): + validate_execution_request_v1("cancel", {**cancel, "expected_job_revision": True}) + + accept: dict[str, Any] = { + "schema_version": "execution-accept-result-request/1.0", + "job_id": JOB_ID, + "execution_job_outcome_sigil": SIGIL, + "idempotency_key": "accept-key", + } + validate_execution_request_v1("accept_result", accept) + assert load_execution_request_v1("accept_result", json.dumps(accept)) == accept + with pytest.raises(Exception): + validate_execution_request_v1("accept_result", {**accept, "idempotency_key": "\x00"}) + + +def test_state_rejects_split_policy_legacy_shapes_unknowns_and_duplicate_bytes() -> None: + raw = (FIXTURES / "execution-state-v1" / "invalid-duplicate-key.json").read_text() + with pytest.raises(Exception, match="duplicate JSON key"): + load_execution_state_v1(raw) + with pytest.raises(Exception, match="BOM"): + load_execution_state_v1(b"\xef\xbb\xbf{}") + for encoding in ("utf-16", "utf-32"): + with pytest.raises(Exception, match="non-UTF-8"): + load_execution_state_v1("{}".encode(encoding)) + + +def test_event_schema_exposes_81_ordered_closed_payload_branches_and_l12_closure() -> None: + schema = json.loads((SCHEMAS / "execution-journal-event-1.0.json").read_text()) + assert schema["$defs"]["event_type"]["enum"] == list(EXECUTION_EVENT_TYPES_V1) + assert len(schema["allOf"]) == 81 + for rank, branch in enumerate(schema["allOf"]): + assert branch["if"]["properties"]["event_type"]["const"] == EXECUTION_EVENT_TYPES_V1[rank] + payload = branch["then"]["properties"]["payload"] + candidates = payload.get("oneOf", [payload]) + assert all(candidate["additionalProperties"] is False for candidate in candidates) + log_members = schema["allOf"][72]["then"]["properties"]["payload"]["required"] + assert log_members[:4] == ["intake_kind", "intake_id", "intake_record_sigil", "disposition_intent_id"] + assert "intake_kind" not in schema["allOf"][76]["then"]["properties"]["payload"]["required"] + assert schema["allOf"][48]["then"]["properties"]["payload"]["required"] == ["transition_cause", "grace_due_at"] + + +def test_event_round_trip_unknown_duplicate_and_jew_matrix_helpers() -> None: + context = { + "ordinary_l12_suffix": True, + "ordinary_l12_anchor": True, + "l12_idempotency_key_sigil": SIGIL, + } + event = build_execution_journal_event_v1(_event_unsigned(), context=context) + assert load_execution_journal_event_v1(json.dumps(event), context=context) == event + extra = deepcopy(event) + extra["payload"]["intent_sigil"] = SIGIL + extra["event_sigil"] = content_sigil({key: value for key, value in extra.items() if key != "event_sigil"}) + with pytest.raises(Exception): + load_execution_journal_event_v1(json.dumps(extra), context=context) + for preceding, following, expected in ((None, 1, "null then zero"), (1, 3, "exactly one")): + invalid_revision = _event_unsigned() + invalid_revision["entity_revisions"][0]["preceding_revision"] = preceding + invalid_revision["entity_revisions"][0]["next_revision"] = following + invalid_revision["event_sigil"] = content_sigil( + {key: value for key, value in invalid_revision.items() if key != "event_sigil"} + ) + with pytest.raises(Exception, match=expected): + load_execution_journal_event_v1(json.dumps(invalid_revision), context=context) + raw = (FIXTURES / "execution-journal-event-v1" / "invalid-duplicate-key.json").read_text() + with pytest.raises(Exception, match="duplicate JSON key"): + load_execution_journal_event_v1(raw) + non_scalar = _event_unsigned() + non_scalar["payload"]["intake_id"] = "\ud800" + non_scalar["event_sigil"] = content_sigil( + {key: value for key, value in non_scalar.items() if key != "event_sigil"} + ) + with pytest.raises(Exception, match="non-Unicode-scalar"): + load_execution_journal_event_v1(json.dumps(non_scalar, ensure_ascii=True)) + + non_ascii_identity = _event_unsigned() + non_ascii_identity["entity_revisions"][0]["entity_id"] = "LG-\u00e9" + non_ascii_identity["event_sigil"] = content_sigil( + {key: value for key, value in non_ascii_identity.items() if key != "event_sigil"} + ) + with pytest.raises(Exception, match="unsigned ASCII"): + load_execution_journal_event_v1(json.dumps(non_ascii_identity), context=context) + + reversed_kinds = _event_unsigned() + reversed_kinds["entity_revisions"] = [ + {"entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 0, "next_revision": 1}, + {"entity_kind": "JOB", "entity_id": JOB_ID, "preceding_revision": 0, "next_revision": 1}, + ] + reversed_kinds["event_sigil"] = content_sigil( + {key: value for key, value in reversed_kinds.items() if key != "event_sigil"} + ) + with pytest.raises(Exception, match="strictly sorted"): + load_execution_journal_event_v1(json.dumps(reversed_kinds), context=context) + + output = { + "event_type": "attempt.output_staging_preallocated", + "payload": {"job_id": JOB_ID, "attempt_id": "AT-ONE", "output_handle_id": "OUT"}, + "recovery_action_binding": None, + "event_id": "JE-TWO", + "sequence": 2, + } + assert expected_event_causation_v1(output, {"attempt_running_event_id": "JE-ONE"}) == "JE-ONE" + assert expected_event_idempotency_v1(output, {}) == content_sigil( + ["execution-output-staging-preallocation-key/1.0", JOB_ID, "AT-ONE", "OUT"] + ) + prior = { + "event_type": "attempt.stop_latched", + "payload": {"transition_cause": {"trigger_kind": "PRIOR_EVENT", "trigger_event_id": "JE-ONE"}}, + "recovery_action_binding": None, + "event_id": "JE-TWO", + "sequence": 2, + } + assert expected_event_causation_v1(prior, {}) == "JE-ONE" + contradictory = deepcopy(prior) + with pytest.raises(Exception, match="contradictory"): + expected_event_causation_v1( + contradictory, + {"ordinary_l12_suffix": True, "ordinary_l12_anchor": False, "l12_preceding_event_id": "JE-OTHER"}, + ) + + +def test_jew4_owners_are_resolvable_direct_refs_and_validate_complete_roots() -> None: + event_schema = json.loads((SCHEMAS / "execution-journal-event-1.0.json").read_text()) + result_payload = event_schema["allOf"][45]["then"]["properties"]["payload"] + assert result_payload["properties"]["observation_evidence_disposition_binding"]["$ref"] == ( + "https://benchwork.dev/schemas/execution-observation-evidence/1.0#/$defs/observation_evidence_disposition_binding" + ) + owner_schema = json.loads((SCHEMAS / "execution-observation-evidence-1.0.json").read_text()) + receipt_ref = owner_schema["$defs"]["observation_evidence_disposition_binding"]["properties"]["result_ingress_receipt_binding"]["$ref"] + assert receipt_ref == "https://benchwork.dev/schemas/execution-result-ingress-receipt/1.0#/$defs/result_ingress_receipt_binding" + + receipt = _receipt() + validate_execution_result_ingress_receipt_v1(receipt) + assert load_execution_result_ingress_receipt_v1(json.dumps(receipt)) == receipt + evidence = _evidence(receipt) + validate_execution_observation_evidence_v1(evidence) + assert load_execution_observation_evidence_v1(json.dumps(evidence)) == evidence + validate_execution_observation_evidence_supplied_receipt_v1(evidence, receipt) + + +def test_result_ingress_index_seals_receipt_candidate_and_status_bindings() -> None: + index = _result_ingress_index() + validate_execution_result_ingress_index_v1(index) + assert load_execution_result_ingress_index_v1(json.dumps(index)) == index + + bad_payload = deepcopy(index) + bad_payload["ingress_event_intent"]["event_candidate"]["payload"]["result_sigil"] = SIGIL + bad_payload["ingress_event_intent"]["event_candidate"]["event_sigil"] = content_sigil( + {key: member for key, member in bad_payload["ingress_event_intent"]["event_candidate"].items() if key != "event_sigil"} + ) + bad_payload["ingress_event_intent"]["intent_sigil"] = content_sigil( + {key: member for key, member in bad_payload["ingress_event_intent"].items() if key != "intent_sigil"} + ) + bad_payload["index_sigil"] = content_sigil( + {key: member for key, member in bad_payload.items() if key != "index_sigil"} + ) + with pytest.raises(Exception, match="candidate payload"): + validate_execution_result_ingress_index_v1(bad_payload) + + bad_pending = deepcopy(index) + bad_pending["status"]["expected_journal_head"]["last_sequence"] = 1 + bad_pending["status"]["expected_journal_head"]["head_sigil"] = content_sigil({ + key: member for key, member in bad_pending["status"]["expected_journal_head"].items() if key != "head_sigil" + }) + bad_pending["index_sigil"] = content_sigil( + {key: member for key, member in bad_pending.items() if key != "index_sigil"} + ) + with pytest.raises(Exception, match="pending Index Head"): + validate_execution_result_ingress_index_v1(bad_pending) + + bad_owner = deepcopy(index) + bad_owner["ingress_event_intent"]["event_candidate"]["executor_epoch"] = 2 + bad_owner["ingress_event_intent"]["event_candidate"]["event_sigil"] = content_sigil( + {key: member for key, member in bad_owner["ingress_event_intent"]["event_candidate"].items() if key != "event_sigil"} + ) + bad_owner["ingress_event_intent"]["intent_sigil"] = content_sigil( + {key: member for key, member in bad_owner["ingress_event_intent"].items() if key != "intent_sigil"} + ) + bad_owner["index_sigil"] = content_sigil( + {key: member for key, member in bad_owner.items() if key != "index_sigil"} + ) + with pytest.raises(Exception, match="candidate Event disagrees with Receipt owner"): + validate_execution_result_ingress_index_v1(bad_owner) + + committed = deepcopy(index) + candidate = committed["ingress_event_intent"]["event_candidate"] + committed["status"] = {"kind": "COMMITTED", "expected_prior_index_sigil": SIGIL, + "actual_event_ref": {"journal_id": candidate["journal_id"], "event_id": candidate["event_id"], + "sequence": candidate["sequence"], "event_sigil": candidate["event_sigil"]}, + "committed_at": STAMP} + committed["index_sigil"] = content_sigil( + {key: member for key, member in committed.items() if key != "index_sigil"} + ) + validate_execution_result_ingress_index_v1(committed) + + +def test_storage_root_manifest_closes_local_owner_and_blob_integrity() -> None: + manifest = _storage_root_manifest() + validate_execution_storage_root_manifest_v1(manifest) + assert load_execution_storage_root_manifest_v1(json.dumps(manifest)) == manifest + + bad_subject_id = deepcopy(manifest) + bad_subject_id["entries"][0]["storage_subject_id"] = SIGIL + bad_subject_id["entries"][0]["entry_sigil"] = content_sigil({ + key: member for key, member in bad_subject_id["entries"][0].items() if key != "entry_sigil" + }) + bad_subject_id["manifest_sigil"] = content_sigil({ + key: member for key, member in bad_subject_id.items() if key != "manifest_sigil" + }) + with pytest.raises(Exception, match="storage subject ID mismatch"): + validate_execution_storage_root_manifest_v1(bad_subject_id) + + bad_protection = deepcopy(manifest) + bad_protection["protection_plan"] = { + "kind": "PLANNED", "reference_set_registration_event_id": "SE-ONE", "hold_id": "SH-ONE", + "hold_set_event_id": "SE-TWO", "policy_id": "SP-EXECUTION-ROOT-HOLD-V1", "policy_sigil": SIGIL, + "hold_lifetime": {"kind": "OWNER_TERMINAL"}, + } + bad_protection["manifest_sigil"] = content_sigil({ + key: member for key, member in bad_protection.items() if key != "manifest_sigil" + }) + with pytest.raises(Exception, match="protection plan"): + validate_execution_storage_root_manifest_v1(bad_protection) + + committed_blob = deepcopy(manifest) + blob = {"blob_sigil": SIGIL_B, "size_bytes": 1} + committed_blob["entries"][0]["claimed_blob"] = blob + committed_blob["entries"][0]["storage_origin"] = { + "kind": "COMMITTED_BLOB", + "transfer": {"transfer_id": "ST-ONE", "transfer_attempt_id": "SA-ONE", + "request_record_sigil": SIGIL, "attempt_record_sigil": SIGIL, "terminal_event": { + "journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, "event_sigil": SIGIL, + }}, + "provenance_id": "SP-ONE", "provenance_sigil": SIGIL, "blob_record_sigil": SIGIL, + "terminal_event": {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, "event_sigil": SIGIL}, + } + committed_blob["entries"][0]["entry_sigil"] = content_sigil({ + key: member for key, member in committed_blob["entries"][0].items() if key != "entry_sigil" + }) + committed_blob["blob_refs"] = [blob] + committed_blob["protection_plan"] = { + "kind": "PLANNED", "reference_set_registration_event_id": "SE-ONE", "hold_id": "SH-ONE", + "hold_set_event_id": "SE-TWO", "policy_id": "SP-EXECUTION-ROOT-HOLD-V1", "policy_sigil": SIGIL, + "hold_lifetime": {"kind": "OWNER_TERMINAL"}, + } + committed_blob["manifest_sigil"] = content_sigil({ + key: member for key, member in committed_blob.items() if key != "manifest_sigil" + }) + validate_execution_storage_root_manifest_v1(committed_blob) + + missing_blob = deepcopy(committed_blob) + missing_blob["blob_refs"] = [] + missing_blob["manifest_sigil"] = content_sigil({ + key: member for key, member in missing_blob.items() if key != "manifest_sigil" + }) + with pytest.raises(Exception, match="Blob refs"): + validate_execution_storage_root_manifest_v1(missing_blob) + + output_manifest = deepcopy(manifest) + output_manifest.update({ + "root_kind": "ATTEMPT_OUTPUT", "attempt_id": "AT-ONE", + "owner_binding": { + "kind": "ATTEMPT_OUTPUT", "job_binding_sigil": SIGIL, "attempt_binding_sigil": SIGIL, + "result_binding": {"kind": "NONE"}, "log_set_sigil": SIGIL, "output_set_sigil": SIGIL, + "control_evidence_set_binding": {"kind": "PENDING"}, + "terminal_source_binding": {"kind": "NOT_APPLICABLE"}, "quarantine_plan_sigil": SIGIL, + }, + }) + output_subject = { + "kind": "ATTEMPT_OUTPUT", "logical_name": "output", "schema_id": "result/1.0", + "schema_sigil": SIGIL, "staging_reference_sigil": SIGIL, "byte_size": 1, "blob_sigil": SIGIL_B, + } + output_entry = deepcopy(committed_blob["entries"][0]) + output_entry["storage_subject_id"] = SIGIL + output_entry["subject"] = output_subject + output_entry["claimed_blob"] = {"blob_sigil": SIGIL_B, "size_bytes": 1} + output_entry["entry_sigil"] = content_sigil({ + key: member for key, member in output_entry.items() if key != "entry_sigil" + }) + output_manifest["entries"] = [output_entry] + output_manifest["blob_refs"] = [output_entry["claimed_blob"]] + output_manifest["protection_plan"] = { + **committed_blob["protection_plan"], + "hold_lifetime": {"kind": "OUTPUT_RETENTION", "maximum_duration_seconds": 0}, + } + output_manifest["manifest_id"] = derive_execution_storage_root_manifest_id_v1(output_manifest) + output_manifest["manifest_sigil"] = content_sigil({ + key: member for key, member in output_manifest.items() if key != "manifest_sigil" + }) + validate_execution_storage_root_manifest_v1(output_manifest) + + mismatched_output_blob = deepcopy(output_manifest) + mismatched_output_blob["entries"][0]["claimed_blob"] = {"blob_sigil": SIGIL, "size_bytes": 2} + mismatched_output_blob["entries"][0]["entry_sigil"] = content_sigil({ + key: member for key, member in mismatched_output_blob["entries"][0].items() if key != "entry_sigil" + }) + mismatched_output_blob["blob_refs"] = [mismatched_output_blob["entries"][0]["claimed_blob"]] + mismatched_output_blob["manifest_sigil"] = content_sigil({ + key: member for key, member in mismatched_output_blob.items() if key != "manifest_sigil" + }) + with pytest.raises(Exception, match="claimed Blob disagrees with subject"): + validate_execution_storage_root_manifest_v1(mismatched_output_blob) + + +def test_root_hold_release_authorization_closes_id_sigil_and_prefix_bounds() -> None: + authorization = _root_hold_release_authorization() + validate_execution_root_hold_release_authorization_v1(authorization) + assert load_execution_root_hold_release_authorization_v1(json.dumps(authorization)) == authorization + + stale_id = deepcopy(authorization) + stale_id["release_authorization_id"] = "EHR-" + "A" * 64 + stale_id["release_authorization_sigil"] = content_sigil({ + key: member for key, member in stale_id.items() if key != "release_authorization_sigil" + }) + with pytest.raises(Exception, match="Authorization ID mismatch"): + validate_execution_root_hold_release_authorization_v1(stale_id) + + reversed_events = deepcopy(authorization) + reversed_events["basis"]["terminal_event_sequence"] = 1 + reversed_events["release_authorization_sigil"] = content_sigil({ + key: member for key, member in reversed_events.items() if key != "release_authorization_sigil" + }) + with pytest.raises(Exception, match="event order"): + validate_execution_root_hold_release_authorization_v1(reversed_events) + + short_head = deepcopy(authorization) + short_head["basis"]["verification_head"]["last_sequence"] = 1 + short_head["basis"]["verification_head"]["head_sigil"] = content_sigil({ + key: member for key, member in short_head["basis"]["verification_head"].items() if key != "head_sigil" + }) + short_head["release_authorization_sigil"] = content_sigil({ + key: member for key, member in short_head.items() if key != "release_authorization_sigil" + }) + with pytest.raises(Exception, match="Head predates"): + validate_execution_root_hold_release_authorization_v1(short_head) + + +def test_control_evidence_set_closes_owner_id_and_ten_dimension_matrix() -> None: + evidence_set = _control_evidence_set() + validate_execution_control_evidence_set_v1(evidence_set) + assert load_execution_control_evidence_set_v1(json.dumps(evidence_set)) == evidence_set + + wrong_order = deepcopy(evidence_set) + wrong_order["control_evidence_refs"][0], wrong_order["control_evidence_refs"][1] = ( + wrong_order["control_evidence_refs"][1], wrong_order["control_evidence_refs"][0] + ) + wrong_order["control_evidence_set_sigil"] = content_sigil({ + key: member for key, member in wrong_order.items() if key != "control_evidence_set_sigil" + }) + with pytest.raises(Exception, match="matrix order"): + validate_execution_control_evidence_set_v1(wrong_order) + + duplicate_id = deepcopy(evidence_set) + duplicate_id["control_evidence_refs"][1]["control_evidence_id"] = ( + duplicate_id["control_evidence_refs"][0]["control_evidence_id"] + ) + duplicate_id["control_evidence_set_sigil"] = content_sigil({ + key: member for key, member in duplicate_id.items() if key != "control_evidence_set_sigil" + }) + with pytest.raises(Exception, match="evidence IDs"): + validate_execution_control_evidence_set_v1(duplicate_id) + + +def test_quarantine_binding_set_closes_frozen_owner_and_self_identity() -> None: + binding_set = _quarantine_binding_set() + validate_execution_quarantine_binding_set_v1(binding_set) + assert load_execution_quarantine_binding_set_v1(json.dumps(binding_set)) == binding_set + + stale_id = deepcopy(binding_set) + stale_id["quarantine_binding_set_id"] = "QBS-" + "A" * 64 + stale_id["quarantine_binding_set_sigil"] = content_sigil({ + key: member for key, member in stale_id.items() if key != "quarantine_binding_set_sigil" + }) + with pytest.raises(Exception, match="Binding Set ID mismatch"): + validate_execution_quarantine_binding_set_v1(stale_id) + + populated = deepcopy(binding_set) + event = {"journal_id": "SJ-ONE", "event_id": "SE-ONE", "sequence": 1, "event_sigil": SIGIL} + backend_object = { + "backend_id": "BACKEND", "object_identity_sigil": SIGIL, "locator_sigil": SIGIL, + "generation": "GENERATION", "size_bytes": 1, "blob_sigil": SIGIL_B, + } + subject = { + "kind": "ATTEMPT_OUTPUT", "logical_name": "output", "schema_id": "result/1.0", + "schema_sigil": SIGIL, "staging_reference_sigil": SIGIL, "byte_size": 1, "blob_sigil": SIGIL_B, + } + binding = { + "storage_subject_id": SIGIL, "manifest_entry_sigil": SIGIL, "subject": subject, + "storage_origin": {"kind": "QUARANTINE", "transfer": { + "transfer_id": "ST-ONE", "transfer_attempt_id": "SA-ONE", "request_record_sigil": SIGIL, + "attempt_record_sigil": SIGIL, "terminal_event": event, + }, "provenance_id": "PROVENANCE", "provenance_sigil": SIGIL, "quarantine_id": "SQ-ONE", + "quarantine_origin_event": event}, + "quarantine_ref": {"quarantine_id": "SQ-ONE", "owner_kind": "TRANSFER_ATTEMPT", "owner_id": "SA-ONE", + "quarantine_record_sigil": SIGIL, "origin_event": event, + "observation_event": {**event, "event_id": "SE-TWO", "sequence": 2, "event_sigil": SIGIL_B}, + "state": "HELD", "source_object": backend_object, "destination_object": backend_object, + "source_cleanup": {"state": "NOT_REQUIRED", "staging_object": None, "evidence_sigil": None, "reason": None}, + "reason": {"code": "BACKEND_UNAVAILABLE", "evidence_sigils": []}}, + "disposition": "RETAINED", "quarantine_binding_sigil": "", + } + binding["quarantine_binding_sigil"] = content_sigil({ + key: member for key, member in binding.items() if key != "quarantine_binding_sigil" + }) + populated["bindings"] = [binding] + populated["quarantine_binding_set_sigil"] = content_sigil({ + key: member for key, member in populated.items() if key != "quarantine_binding_set_sigil" + }) + validate_execution_quarantine_binding_set_v1(populated) + + mismatched_owner = deepcopy(populated) + mismatched_owner["bindings"][0]["quarantine_ref"]["owner_id"] = "SA-TWO" + mismatched_owner["bindings"][0]["quarantine_binding_sigil"] = content_sigil({ + key: member for key, member in mismatched_owner["bindings"][0].items() if key != "quarantine_binding_sigil" + }) + mismatched_owner["quarantine_binding_set_sigil"] = content_sigil({ + key: member for key, member in mismatched_owner.items() if key != "quarantine_binding_set_sigil" + }) + with pytest.raises(Exception, match="origin disagrees with Quarantine owner"): + validate_execution_quarantine_binding_set_v1(mismatched_owner) + + +def test_output_storage_observation_set_closes_id_members_and_blob_union() -> None: + observation_set = _output_storage_observation_set() + validate_execution_output_storage_observation_set_v1(observation_set) + assert load_execution_output_storage_observation_set_v1(json.dumps(observation_set)) == observation_set + + stale_id = deepcopy(observation_set) + stale_id["observation_set_id"] = "OS-" + "A" * 64 + stale_id["observation_set_sigil"] = content_sigil({ + key: member for key, member in stale_id.items() if key != "observation_set_sigil" + }) + with pytest.raises(Exception, match="Observation Set ID mismatch"): + validate_execution_output_storage_observation_set_v1(stale_id) + + wrong_log_order = deepcopy(observation_set) + wrong_log_order["members"][1], wrong_log_order["members"][2] = ( + wrong_log_order["members"][2], wrong_log_order["members"][1] + ) + wrong_log_order["observation_set_sigil"] = content_sigil({ + key: member for key, member in wrong_log_order.items() if key != "observation_set_sigil" + }) + with pytest.raises(Exception, match="Log streams are not in fixed order"): + validate_execution_output_storage_observation_set_v1(wrong_log_order) + + missing_blob = deepcopy(observation_set) + missing_blob["blob_sigils"] = [] + missing_blob["observation_set_sigil"] = content_sigil({ + key: member for key, member in missing_blob.items() if key != "observation_set_sigil" + }) + with pytest.raises(Exception, match="Blob Sigils disagree"): + validate_execution_output_storage_observation_set_v1(missing_blob) + + mismatched_protection = deepcopy(observation_set) + mismatched_protection["output_root_protection"] = { + "kind": "NO_HOLD", + "terminalization_storage_manifest_binding": { + "kind": "FROZEN", "storage_root_manifest_id": "ESM-" + "B" * 64, + "storage_root_manifest_sigil": SIGIL_B, + }, + } + mismatched_protection["observation_set_id"] = derive_execution_output_storage_observation_set_id_v1( + mismatched_protection + ) + mismatched_protection["observation_set_sigil"] = content_sigil({ + key: member for key, member in mismatched_protection.items() if key != "observation_set_sigil" + }) + with pytest.raises(Exception, match="protection disagrees"): + validate_execution_output_storage_observation_set_v1(mismatched_protection) + + pending_protection = deepcopy(observation_set) + pending_protection["output_root_protection"] = {"kind": "PENDING"} + pending_protection["observation_set_id"] = derive_execution_output_storage_observation_set_id_v1( + pending_protection + ) + pending_protection["observation_set_sigil"] = content_sigil({ + key: member for key, member in pending_protection.items() if key != "observation_set_sigil" + }) + with pytest.raises(Exception, match="requires a terminal output-root protection"): + validate_execution_output_storage_observation_set_v1(pending_protection) + + + +def test_jew4_owner_fences_and_supplied_receipt_comparison_fail_closed() -> None: + receipt = _receipt() + evidence = _evidence(receipt) + + bad_owner = deepcopy(evidence) + bad_owner["fence_tuple"]["executor_epoch"] = 2 + _reseal_evidence(bad_owner) + with pytest.raises(Exception, match="fence_tuple: executor_epoch"): + validate_execution_observation_evidence_v1(bad_owner) + + bad_receipt = deepcopy(receipt) + bad_receipt["receiver_identity"]["executor_epoch"] = 2 + _reseal_receipt(bad_receipt) + with pytest.raises(Exception, match="receiver epoch"): + validate_execution_observation_evidence_supplied_receipt_v1(evidence, bad_receipt) + + bad_subject = deepcopy(receipt) + bad_subject["result_observation_binding"]["observation_evidence_subject_sigil"] = SIGIL + _reseal_receipt(bad_subject) + with pytest.raises(Exception, match="observation subject Sigil"): + validate_execution_result_ingress_receipt_v1(bad_subject) + + mismatched_assessment = deepcopy(evidence) + mismatched_assessment["assessment"]["verified_runtime_observation"] = { + **mismatched_assessment["assessment"]["verified_runtime_observation"], + "process_count": 1, + } + _reseal_evidence(mismatched_assessment) + with pytest.raises(Exception, match="copy the Result observation"): + validate_execution_observation_evidence_v1(mismatched_assessment) + + mismatched_source = deepcopy(evidence) + mismatched_source["assessment"]["verified_source_binding"]["source_kind"] = "EXECUTOR_SUPERVISOR" + _reseal_evidence(mismatched_source) + with pytest.raises(Exception, match="source does not match"): + validate_execution_observation_evidence_v1(mismatched_source) + + mismatched_receipt = deepcopy(evidence) + mismatched_receipt["result_ingress_receipt_binding"]["ingress_receipt_sigil"] = SIGIL + _reseal_evidence(mismatched_receipt) + with pytest.raises(Exception, match="ingress receipt binding"): + validate_execution_observation_evidence_supplied_receipt_v1(mismatched_receipt, receipt) + + +def test_terminal_attempt_events_require_the_closed_terminal_evidence_shape() -> None: + event = _event_unsigned() + event.update({ + "event_type": "attempt.failed", "event_id": "JE-TERMINAL", "sequence": 3, + "previous_event_sigil": SIGIL, "entity_revisions": [{ + "entity_kind": "ATTEMPT", "entity_id": "AT-ONE", "preceding_revision": 1, "next_revision": 2, + }], + "payload": {"attempt_terminal_evidence": {}, "fencing_generation": 1, + "final_fence_floor": 2, "output_storage_roots": []}, + }) + with pytest.raises(Exception): + build_execution_journal_event_v1(event) + + sigil = SIGIL + evidence = { + "transition_cause": {"code": "COMPLETION_ESTABLISHED", "trigger_kind": "PRIOR_EVENT", "trigger_event_id": "JE-RESULT", "effective_sequence": 2, "evidence_sigil": sigil}, + "computation_status": "COMPLETED", "worker_status": "COMPLETED", "process_termination_status": "EXITED", "handle_revocation_status": "NOT_APPLICABLE", "cleanup_status": "VERIFIED", "mutable_resource_isolation_status": "NOT_APPLICABLE", "output_publication_status": "VERIFIED", "quarantine_status": "NOT_REQUIRED", + "termination_evidence_sigil": sigil, "handle_disposition_evidence_sigil": sigil, "cleanup_summary_sigil": sigil, "quarantine_evidence_sigil": sigil, "log_closure_sigil": sigil, "output_closure_sigil": sigil, + "result_binding": {"kind": "ACCEPTED", "result_sigil": sigil, "disposition_event_id": "JE-RESULT", "disposition_event_sigil": sigil, "disposition_sequence": 2}, + "attempt_authorization_state": {"kind": "NONE"}, "completion_anchor_binding": {"kind": "RESULT_ACCEPTED", "event_id": "JE-RESULT", "event_sigil": sigil, "sequence": 2, "result_sigil": sigil}, "worker_session_binding": {"kind": "NONE"}, "lease_terminal_binding": {"kind": "NONE"}, "first_stop_or_fence_binding": {"kind": "NONE"}, + "storage_observation_binding": {"kind": "FROZEN", "storage_journal_id": "SJ-ONE", "through_sequence": 1, "through_event_sigil": sigil, "output_storage_observation_set_id": "OS-ONE", "output_storage_observation_set_sigil": sigil}, + "accounting_capture_event_id": "JE-CAPTURE", "accounting_capture_event_sigil": sigil, + "control_evidence_set_binding": {"kind": "FROZEN", "control_evidence_set_id": "CES-" + "A" * 64, "control_evidence_set_sigil": sigil}, "quarantine_binding_set_binding": {"kind": "FROZEN", "quarantine_binding_set_id": "QBS-" + "A" * 64, "quarantine_binding_set_sigil": sigil}, + "terminalization_storage_manifest_binding": {"kind": "FROZEN", "storage_root_manifest_id": "ESM-" + "A" * 64, "storage_root_manifest_sigil": sigil}, "output_root_protection": {"kind": "NO_HOLD", "terminalization_storage_manifest_binding": {"kind": "FROZEN", "storage_root_manifest_id": "ESM-" + "A" * 64, "storage_root_manifest_sigil": sigil}}, "assurance_input_set_sigil": sigil, "terminal_source_binding": {"kind": "NOT_APPLICABLE"}, + } + event["payload"] = {"attempt_terminal_evidence": evidence, "fencing_generation": 1, "final_fence_floor": 2, "output_storage_roots": []} + event["event_type"] = "attempt.succeeded" + assert build_execution_journal_event_v1(event)["event_type"] == "attempt.succeeded" + evidence["transition_cause"]["code"] = "COMPUTATION_FAILED" + with pytest.raises(Exception, match="completion anchor"): + build_execution_journal_event_v1(event) + + +def test_terminalization_supplied_records_require_exact_attempt_bindings() -> None: + ces = _control_evidence_set() + manifest: dict[str, Any] = { + "schema_version": "execution-storage-root-manifest/1.0", "manifest_id": "", + "root_kind": "ATTEMPT_OUTPUT", "job_id": JOB_ID, "attempt_id": "AT-ONE", + "owner_binding": {"kind": "ATTEMPT_OUTPUT", "job_binding_sigil": SIGIL, + "attempt_binding_sigil": SIGIL, "result_binding": {"kind": "NONE"}, + "log_set_sigil": SIGIL, "output_set_sigil": SIGIL, + "control_evidence_set_binding": {"kind": "FROZEN", "control_evidence_set_id": ces["control_evidence_set_id"], "control_evidence_set_sigil": ces["control_evidence_set_sigil"]}, + "terminal_source_binding": {"kind": "NOT_APPLICABLE"}, "quarantine_plan_sigil": SIGIL}, + "entries": [], "blob_refs": [], "protection_plan": {"kind": "NONE"}, "created_at": STAMP, + "manifest_sigil": "", + } + manifest["manifest_id"] = derive_execution_storage_root_manifest_id_v1(manifest) + manifest["manifest_sigil"] = content_sigil({key: value for key, value in manifest.items() if key != "manifest_sigil"}) + frozen_manifest = {"kind": "FROZEN", "storage_root_manifest_id": manifest["manifest_id"], "storage_root_manifest_sigil": manifest["manifest_sigil"]} + qbs = _quarantine_binding_set() + qbs["terminalization_storage_manifest_binding"] = frozen_manifest + qbs["quarantine_binding_set_id"] = derive_execution_quarantine_binding_set_id_v1(qbs) + qbs["quarantine_binding_set_sigil"] = content_sigil({key: value for key, value in qbs.items() if key != "quarantine_binding_set_sigil"}) + frozen_ces = {"kind": "FROZEN", "control_evidence_set_id": ces["control_evidence_set_id"], "control_evidence_set_sigil": ces["control_evidence_set_sigil"]} + frozen_qbs = {"kind": "FROZEN", "quarantine_binding_set_id": qbs["quarantine_binding_set_id"], "quarantine_binding_set_sigil": qbs["quarantine_binding_set_sigil"]} + protection = {"kind": "NO_HOLD", "terminalization_storage_manifest_binding": frozen_manifest} + validate_execution_terminalization_supplied_records_v1(job_id=JOB_ID, attempt_id="AT-ONE", attempt_binding_sigil=SIGIL, terminalization_storage_manifest_binding=frozen_manifest, control_evidence_set_binding=frozen_ces, quarantine_binding_set_binding=frozen_qbs, output_root_protection=protection, manifest=manifest, control_evidence_set=ces, quarantine_binding_set=qbs) + with pytest.raises(Exception, match="disagree"): + validate_execution_terminalization_supplied_records_v1(job_id=JOB_ID, attempt_id="AT-ONE", attempt_binding_sigil=SIGIL, terminalization_storage_manifest_binding=frozen_manifest, control_evidence_set_binding=frozen_ces, quarantine_binding_set_binding=frozen_qbs, output_root_protection={"kind": "NO_HOLD", "terminalization_storage_manifest_binding": {**frozen_manifest, "storage_root_manifest_sigil": SIGIL}}, manifest=manifest, control_evidence_set=ces, quarantine_binding_set=qbs) + + +@pytest.mark.parametrize( + "loader,fixture", + [ + (load_execution_result_ingress_receipt_v1, "execution-result-ingress-receipt-v1"), + (load_execution_observation_evidence_v1, "execution-observation-evidence-v1"), + ], +) +def test_jew4_owner_loaders_reject_duplicate_bom_and_unknown_fields(loader: Any, fixture: str) -> None: + raw = (FIXTURES / fixture / "invalid-duplicate-key.json").read_text() + with pytest.raises(Exception, match="duplicate JSON key"): + loader(raw) + with pytest.raises(Exception, match="BOM"): + loader(b"\xef\xbb\xbf{}") + valid = _receipt() if "receipt" in fixture else _evidence(_receipt()) + valid["append_authority"] = True + self_member = "ingress_receipt_sigil" if "receipt" in fixture else "observation_evidence_sigil" + valid[self_member] = content_sigil({key: value for key, value in valid.items() if key != self_member}) + with pytest.raises(Exception): + loader(json.dumps(valid)) diff --git a/tests/test_execution_worker_session_replay_v1.py b/tests/test_execution_worker_session_replay_v1.py new file mode 100644 index 0000000..d72cd1a --- /dev/null +++ b/tests/test_execution_worker_session_replay_v1.py @@ -0,0 +1,210 @@ +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + +from benchwork.athanor import content_sigil +from benchwork.execution_contracts import ( + build_execution_journal_event_v1, + replay_execution_journal_prefix_v1, + replay_execution_journal_supplied_facts_v1, +) + + +ROOT = Path(__file__).parents[1] +INITIAL = json.loads( + ( + ROOT / "tests/fixtures/phase3/rfc0012/execution-journal-event-v1/valid-initial.json" + ).read_text() +) +SIGIL = "sha256:" + "a" * 64 +SESSION_ID = "WS-00000000000000000000000000" + + +def _worker() -> dict[str, Any]: + value: dict[str, Any] = { + "schema_version": "execution-worker/1.0", + "worker_id": "WK-ONE", + "definition_revision": 0, + "implementation_name": "local", + "implementation_version": "1.0", + "supported_runtimes": [ + {"runtime_id": "RT-ONE", "runtime_version": "1.0", "runtime_sigil": SIGIL} + ], + "resource_ceilings": { + "attempt_budget": { + "cpu_time_seconds": 1, + "peak_memory_bytes": 1, + "storage_bytes_written": 1, + "output_bytes": 1, + "log_bytes": 1, + "process_starts": 1, + "network_egress_bytes": 1, + "network_requests": 1, + }, + "maximum_open_files": 1, + "maximum_file_count": 1, + "maximum_concurrent_threads": 1, + }, + "declared_backend_capabilities": [], + "verified_capability_tuples": [], + "maximum_concurrency": 1, + "definition_created_at": "2026-08-06T00:00:01Z", + "worker_binding_sigil": "", + } + value["worker_binding_sigil"] = content_sigil( + {key: item for key, item in value.items() if key != "worker_binding_sigil"} + ) + return value + + +def _session(worker: dict[str, Any]) -> dict[str, Any]: + value: dict[str, Any] = { + "schema_version": "execution-worker-session/1.0", + "worker_session_id": SESSION_ID, + "worker_id": worker["worker_id"], + "worker_binding_sigil": worker["worker_binding_sigil"], + "executor_instance_id": INITIAL["executor_instance_id"], + "executor_epoch": INITIAL["executor_epoch"], + "host_identity_sigil": SIGIL, + "backend_session_identity": { + "backend_id": "local", + "backend_version": "1.0", + "backend_implementation_sigil": SIGIL, + "backend_configuration_sigil": SIGIL, + "process_identity_sigil": SIGIL, + "session_nonce_sigil": SIGIL, + }, + "control_channel_identity_sigil": SIGIL, + "verified_capability_tuple_sigil": SIGIL, + "maximum_concurrency": 1, + "opened_at": "2026-08-06T00:00:03Z", + "worker_session_binding_sigil": "", + } + value["worker_session_binding_sigil"] = content_sigil( + {key: item for key, item in value.items() if key != "worker_session_binding_sigil"} + ) + return value + + +def _event( + prior: dict[str, Any], + event_id: str, + event_type: str, + revisions: list[dict[str, Any]], + payload: dict[str, Any], +) -> dict[str, Any]: + return build_execution_journal_event_v1( + { + "schema_version": "execution-journal-event/1.0", + "journal_id": INITIAL["journal_id"], + "event_id": event_id, + "sequence": prior["sequence"] + 1, + "event_type": event_type, + "executor_instance_id": INITIAL["executor_instance_id"], + "executor_epoch": INITIAL["executor_epoch"], + "executor_build_sigil": INITIAL["executor_build_sigil"], + "recorded_at": f"2026-08-06T00:00:0{prior['sequence']}Z", + "observed_at": None, + "entity_revisions": revisions, + "causation_event_id": None, + "idempotency_key_sigil": None, + "recovery_action_binding": None, + "payload": payload, + "previous_event_sigil": prior["event_sigil"], + } + ) + + +def test_worker_session_registration_prefix_replays_to_ready() -> None: + worker = _worker() + registered = _event( + INITIAL, + "JE-TWO", + "worker.definition_registered", + [ + { + "entity_kind": "WORKER", + "entity_id": "WK-ONE", + "preceding_revision": None, + "next_revision": 0, + } + ], + { + "worker_binding_sigil": worker["worker_binding_sigil"], + "definition_revision": 0, + "supersedes_worker_binding_sigil": SIGIL, + }, + ) + enabled = _event( + registered, + "JE-THREE", + "worker.enabled", + [ + { + "entity_kind": "WORKER", + "entity_id": "WK-ONE", + "preceding_revision": 0, + "next_revision": 1, + } + ], + { + "worker_binding_sigil": worker["worker_binding_sigil"], + "verification_evidence_set_sigil": SIGIL, + }, + ) + session = _session(worker) + session_registered = _event( + enabled, + "JE-FOUR", + "worker_session.registered", + [ + { + "entity_kind": "WORKER_SESSION", + "entity_id": SESSION_ID, + "preceding_revision": None, + "next_revision": 0, + } + ], + { + "worker_session_binding_sigil": session["worker_session_binding_sigil"], + "worker_binding_sigil": worker["worker_binding_sigil"], + "backend_session_identity": session["backend_session_identity"], + "control_channel_identity_sigil": SIGIL, + }, + ) + ready = _event( + session_registered, + "JE-FIVE", + "worker_session.ready", + [ + { + "entity_kind": "WORKER_SESSION", + "entity_id": SESSION_ID, + "preceding_revision": 0, + "next_revision": 1, + } + ], + { + "verification_evidence_set_sigil": SIGIL, + "capacity": 1, + "worker_session_heartbeat_policy_id": "WSHP-" + "A" * 64, + "worker_session_heartbeat_policy_sigil": SIGIL, + "initial_heartbeat_due_at": "2026-08-06T00:01:00Z", + }, + ) + state = replay_execution_journal_prefix_v1( + [INITIAL, registered, enabled, session_registered, ready], + supplied_workers=[worker], + supplied_worker_sessions=[session], + ) + supplied_state = replay_execution_journal_supplied_facts_v1( + [INITIAL, registered, enabled, session_registered, ready], + supplied_workers=[worker], + supplied_worker_sessions=[session], + ) + assert supplied_state == state + assert state["workers"][0]["state"] == "ENABLED" + assert state["worker_sessions"][0]["state"] == "READY" + assert state["worker_sessions"][0]["capacity"] == 1 diff --git a/tests/test_execution_worker_session_v1_contract.py b/tests/test_execution_worker_session_v1_contract.py new file mode 100644 index 0000000..8ddc749 --- /dev/null +++ b/tests/test_execution_worker_session_v1_contract.py @@ -0,0 +1,172 @@ +from __future__ import annotations + +from copy import deepcopy + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.execution_contracts import ( + validate_execution_lease_supplied_bindings_v1, + validate_execution_lease_v1, + validate_execution_worker_session_supplied_worker_v1, + validate_execution_worker_session_v1, + validate_execution_worker_v1, +) + + +SIGIL = "sha256:" + "a" * 64 + + +def _worker() -> dict[str, object]: + worker: dict[str, object] = { + "schema_version": "execution-worker/1.0", + "worker_id": "WK-ONE", + "definition_revision": 0, + "implementation_name": "local", + "implementation_version": "1.0", + "supported_runtimes": [ + {"runtime_id": "RT-ONE", "runtime_version": "1.0", "runtime_sigil": SIGIL} + ], + "resource_ceilings": { + "attempt_budget": { + "cpu_time_seconds": 1, + "peak_memory_bytes": 1, + "storage_bytes_written": 1, + "output_bytes": 1, + "log_bytes": 1, + "process_starts": 1, + "network_egress_bytes": 1, + "network_requests": 1, + }, + "maximum_open_files": 1, + "maximum_file_count": 1, + "maximum_concurrent_threads": 1, + }, + "declared_backend_capabilities": [], + "verified_capability_tuples": [], + "maximum_concurrency": 1, + "definition_created_at": "2026-08-06T00:00:00Z", + "worker_binding_sigil": "", + } + worker["worker_binding_sigil"] = content_sigil( + {key: value for key, value in worker.items() if key != "worker_binding_sigil"} + ) + return worker + + +def _session(worker: dict[str, object]) -> dict[str, object]: + session: dict[str, object] = { + "schema_version": "execution-worker-session/1.0", + "worker_session_id": "WS-00000000000000000000000000", + "worker_id": worker["worker_id"], + "worker_binding_sigil": worker["worker_binding_sigil"], + "executor_instance_id": "XI-ONE", + "executor_epoch": 1, + "host_identity_sigil": SIGIL, + "backend_session_identity": { + "backend_id": "local", + "backend_version": "1.0", + "backend_implementation_sigil": SIGIL, + "backend_configuration_sigil": SIGIL, + "process_identity_sigil": SIGIL, + "session_nonce_sigil": SIGIL, + }, + "control_channel_identity_sigil": SIGIL, + "verified_capability_tuple_sigil": SIGIL, + "maximum_concurrency": 1, + "opened_at": "2026-08-06T00:00:01Z", + "worker_session_binding_sigil": "", + } + session["worker_session_binding_sigil"] = content_sigil( + {key: value for key, value in session.items() if key != "worker_session_binding_sigil"} + ) + return session + + +def test_worker_and_session_self_bindings_are_closed() -> None: + worker = _worker() + session = _session(worker) + validate_execution_worker_v1(worker) + validate_execution_worker_session_v1(session) + validate_execution_worker_session_supplied_worker_v1(session, worker) + + wrong = deepcopy(session) + wrong["maximum_concurrency"] = 2 + wrong["worker_session_binding_sigil"] = content_sigil( + {key: value for key, value in wrong.items() if key != "worker_session_binding_sigil"} + ) + with pytest.raises(AthanorError, match="disagrees"): + validate_execution_worker_session_supplied_worker_v1(wrong, worker) + + +def test_lease_binds_exact_attempt_worker_and_session() -> None: + worker = _worker() + session = _session(worker) + attempt = { + "schema_version": "execution-attempt/1.0", + "attempt_id": "AT-ONE", + "job_id": "JB-" + "A" * 64, + "job_binding_sigil": SIGIL, + "retry_ordinal": 1, + "fencing_generation": 1, + "assurance_requirement": { + "requested_level": "SANCTUM-A0", + "profile_version": "1.0", + "profile_sigil": SIGIL, + "conformance_suite_id": "CS-ONE", + "conformance_suite_sigil": SIGIL, + }, + "backend_identity": "local", + "backend_version": "1.0", + "backend_implementation_sigil": SIGIL, + "backend_configuration_sigil": SIGIL, + "base_identity": None, + "base_sigil": None, + "input_identities": [], + "resume_mode": "FRESH", + "crucible_id": "CU-ONE", + "output_namespace_id": "ON-ONE", + "log_stream_ids": {"STDOUT": "LG-ONE", "STDERR": "LG-TWO", "STRUCTURED": "LG-THREE"}, + "budget_reservation": { + "attempts": 1, + "cpu_time_seconds": 1, + "storage_bytes_written": 1, + "output_bytes": 1, + "log_bytes": 1, + "process_starts": 1, + "network_egress_bytes": 1, + "network_requests": 1, + }, + "attempt_authorization_requirement": {"kind": "NONE", "effects": []}, + "created_at": "2026-08-06T00:00:00Z", + "deadline_due_at": "2026-08-06T01:00:00Z", + "attempt_binding_sigil": "", + } + attempt["attempt_binding_sigil"] = content_sigil( + {key: value for key, value in attempt.items() if key != "attempt_binding_sigil"} + ) + lease = { + "schema_version": "execution-lease/1.0", + "lease_id": "LS-00000000000000000000000000", + "job_id": attempt["job_id"], + "attempt_id": attempt["attempt_id"], + "worker_id": worker["worker_id"], + "worker_binding_sigil": worker["worker_binding_sigil"], + "worker_session_id": session["worker_session_id"], + "worker_session_binding_sigil": session["worker_session_binding_sigil"], + "executor_instance_id": "XI-ONE", + "executor_epoch": 1, + "fencing_generation": 1, + "offered_at": "2026-08-06T00:00:01Z", + "claim_due_at": "2026-08-06T00:00:02Z", + "initial_expiry_due_at": "2026-08-06T00:00:03Z", + "maximum_expiry_due_at": "2026-08-06T00:00:04Z", + "heartbeat_policy": {"heartbeat_interval_seconds": 1, "heartbeat_timeout_seconds": 1}, + "lease_credential_digest": SIGIL, + "lease_binding_sigil": "", + } + lease["lease_binding_sigil"] = content_sigil( + {key: value for key, value in lease.items() if key != "lease_binding_sigil"} + ) + validate_execution_lease_v1(lease) + validate_execution_lease_supplied_bindings_v1(lease, attempt, worker, session) diff --git a/tests/test_patch_promotion_attempt_v1_contract.py b/tests/test_patch_promotion_attempt_v1_contract.py new file mode 100644 index 0000000..9d04844 --- /dev/null +++ b/tests/test_patch_promotion_attempt_v1_contract.py @@ -0,0 +1,46 @@ +from __future__ import annotations + +from copy import deepcopy + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.patch_promotion_contracts import validate_patch_promotion_attempt_v1 + + +SIGIL = "sha256:" + "a" * 64 + + +def _seal(attempt: dict[str, object]) -> dict[str, object]: + attempt["attempt_sigil"] = content_sigil({key: value for key, value in attempt.items() if key != "attempt_sigil"}) + return attempt + + +def _attempt() -> dict[str, object]: + return _seal({ + "schema_version": "patch-promotion-attempt/1.0", "attempt_id": "PAT-ONE", + "authorization": {"id": "PAU-ONE", "sigil": SIGIL}, "operation_sigil": SIGIL, + "target": {"target_id": "PT-ONE", "target_class": "DIRECTORY", + "identity_profile": {"id": "PBIP-ONE", "sigil": SIGIL}, + "root_identity": {"root_object_sigil": SIGIL, "root_generation": "generation", "topology_sigil": SIGIL}, + "selection_authorization_sigil": SIGIL}, + "target_content_generation": "generation", "adapter": {"id": "PPA-ONE", "sigil": SIGIL}, + "mode": "FULL_TREE_ATOMIC_CAS", "created_at": "2026-08-06T00:00:00Z", + "state": "CREATED", "revision": 0, "attempt_sigil": "", + }) + + +def test_promotion_attempt_checks_closed_wire_and_self_sigil() -> None: + attempt = _attempt() + validate_patch_promotion_attempt_v1(attempt) + + tampered = deepcopy(attempt) + tampered["state"] = "MUTATING" + with pytest.raises(AthanorError, match="self-Sigil"): + validate_patch_promotion_attempt_v1(tampered) + + malformed = deepcopy(attempt) + malformed["revision"] = True + _seal(malformed) + with pytest.raises(AthanorError, match="validation failed"): + validate_patch_promotion_attempt_v1(malformed) diff --git a/tests/test_patch_promotion_bundle_v1_contract.py b/tests/test_patch_promotion_bundle_v1_contract.py new file mode 100644 index 0000000..a9e0e50 --- /dev/null +++ b/tests/test_patch_promotion_bundle_v1_contract.py @@ -0,0 +1,143 @@ +from __future__ import annotations + +from copy import deepcopy +import hashlib + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.patch_promotion_contracts import validate_patch_bundle_v1 + + +SIGIL = "sha256:" + "a" * 64 +FILE_SIGIL = "sha256:" + hashlib.sha256(b"x").hexdigest() + + +def _seal(bundle: dict[str, object]) -> dict[str, object]: + bundle["bundle_sigil"] = content_sigil( + {key: value for key, value in bundle.items() if key != "bundle_sigil"}, + ) + return bundle + + +def _bundle() -> dict[str, object]: + payload = { + "sigil": FILE_SIGIL, + "size_bytes": 1, + "media_type": "application/octet-stream", + } + return _seal({ + "schema_version": "patch-bundle/1.0", + "bundle_id": "PBU-ONE", + "base": {"id": "PB-ONE", "sigil": SIGIL}, + "postimage": { + "identity_profile": {"id": "PBIP-ONE", "sigil": SIGIL}, + "tree": { + "manifest_sigil": SIGIL, + "root_entry_sigil": SIGIL, + "entry_count": 1, + "total_bytes": 1, + }, + "manifest_blob": payload, + }, + "operations": [{ + "path_bytes": "file.txt", + "operation": "ADD", + "preimage": {"kind": "ABSENT"}, + "postimage": { + "kind": "FILE", + "blob_sigil": FILE_SIGIL, + "size_bytes": 1, + "executable": False, + }, + "payload_sigil": FILE_SIGIL, + }], + "payloads": [payload], + "renderings": [], + "attachments": [], + "source": { + "kind": "RETAINED_TERMINAL_SOURCE", + "terminal_source_sigil": SIGIL, + "execution_event_sigil": SIGIL, + "frozen_at": "2026-08-06T00:00:00Z", + }, + "agent_result_receipt": { + "receipt_id": "RC-ONE", + "receipt_sigil": SIGIL, + "event_id": "CE-ONE", + "event_body_sigil": SIGIL, + }, + "limits": { + "max_paths": 1, + "max_blobs": 1, + "max_total_bytes": 1, + "max_payload_bytes": 1, + }, + "bundle_sigil": "", + }) + + +def test_patch_bundle_checks_self_sigil_operations_and_exact_payloads() -> None: + bundle = _bundle() + validate_patch_bundle_v1(bundle) + + invalid_transition = deepcopy(bundle) + invalid_transition["operations"][0]["operation"] = "MODIFY" # type: ignore[index] + _seal(invalid_transition) + with pytest.raises(AthanorError, match="operation disagrees"): + validate_patch_bundle_v1(invalid_transition) + + missing_payload = deepcopy(bundle) + missing_payload["payloads"] = [] + _seal(missing_payload) + with pytest.raises(AthanorError, match="exact postimage payload set"): + validate_patch_bundle_v1(missing_payload) + + +def test_patch_bundle_checks_payload_limits_and_blob_union_metadata() -> None: + bundle = _bundle() + over_limit = deepcopy(bundle) + over_limit["limits"]["max_payload_bytes"] = 0 # type: ignore[index] + _seal(over_limit) + with pytest.raises(AthanorError, match="max_payload_bytes"): + validate_patch_bundle_v1(over_limit) + + inconsistent = deepcopy(bundle) + inconsistent["attachments"] = [{ # type: ignore[index] + "sigil": FILE_SIGIL, + "size_bytes": 2, + "media_type": "application/octet-stream", + }] + inconsistent["limits"]["max_total_bytes"] = 3 # type: ignore[index] + _seal(inconsistent) + with pytest.raises(AthanorError, match="inconsistent metadata"): + validate_patch_bundle_v1(inconsistent) + + +def test_patch_bundle_recomputes_symlink_target_identity() -> None: + bundle = _bundle() + target = "target" + target_sigil = "sha256:" + hashlib.sha256(target.encode()).hexdigest() + bundle["operations"] = [{ # type: ignore[index] + "path_bytes": "link", + "operation": "ADD", + "preimage": {"kind": "ABSENT"}, + "postimage": {"kind": "SYMLINK", "target": target, "target_sigil": target_sigil}, + "payload_sigil": target_sigil, + }] + bundle["payloads"] = [{ # type: ignore[index] + "sigil": target_sigil, + "size_bytes": len(target.encode()), + "media_type": "application/octet-stream", + }] + bundle["limits"] = {"max_paths": 1, "max_blobs": 1, "max_total_bytes": 6, "max_payload_bytes": 6} + _seal(bundle) + validate_patch_bundle_v1(bundle) + + wrong = deepcopy(bundle) + wrong["operations"][0]["postimage"]["target_sigil"] = SIGIL # type: ignore[index] + wrong["operations"][0]["payload_sigil"] = SIGIL # type: ignore[index] + wrong["payloads"][0]["sigil"] = SIGIL # type: ignore[index] + _seal(wrong) + with pytest.raises(AthanorError, match="target Sigil"): + validate_patch_bundle_v1(wrong) diff --git a/tests/test_patch_promotion_checkpoint_v1_contract.py b/tests/test_patch_promotion_checkpoint_v1_contract.py new file mode 100644 index 0000000..a3aa3b8 --- /dev/null +++ b/tests/test_patch_promotion_checkpoint_v1_contract.py @@ -0,0 +1,86 @@ +from __future__ import annotations + +from copy import deepcopy +import hashlib + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.patch_promotion_contracts import validate_patch_promotion_checkpoint_v1 + + +SIGIL = "sha256:" + "a" * 64 +FILE_SIGIL = "sha256:" + hashlib.sha256(b"x").hexdigest() + + +def _seal(checkpoint: dict[str, object]) -> dict[str, object]: + checkpoint["checkpoint_sigil"] = content_sigil( + {key: value for key, value in checkpoint.items() if key != "checkpoint_sigil"}, + ) + return checkpoint + + +def _checkpoint() -> dict[str, object]: + blob = {"sigil": FILE_SIGIL, "size_bytes": 1, "media_type": "application/octet-stream"} + return _seal({ + "schema_version": "patch-promotion-checkpoint/1.0", + "checkpoint_id": "PCK-ONE", + "attempt_id": "PAT-ONE", + "target_id": "PT-ONE", + "base": {"id": "PB-ONE", "sigil": SIGIL}, + "affected_paths": ["file.txt"], + "entries": [{ + "path_bytes": "file.txt", + "preimage": {"kind": "FILE", "blob_sigil": FILE_SIGIL, "size_bytes": 1, "executable": False}, + "checkpoint_blob": blob, + "verification_sigil": SIGIL, + }], + "checkpoint_blobs": [blob], + "created_at": "2026-08-06T00:00:00Z", + "verified_at": "2026-08-06T00:00:01Z", + "checkpoint_sigil": "", + }) + + +def test_checkpoint_checks_self_sigil_paths_and_exact_preimage_blobs() -> None: + checkpoint = _checkpoint() + validate_patch_promotion_checkpoint_v1(checkpoint) + + extra_path = deepcopy(checkpoint) + extra_path["affected_paths"] = ["file.txt", "other.txt"] + _seal(extra_path) + with pytest.raises(AthanorError, match="exact affected path set"): + validate_patch_promotion_checkpoint_v1(extra_path) + + wrong_blob = deepcopy(checkpoint) + wrong_blob["entries"][0]["checkpoint_blob"]["size_bytes"] = 2 + wrong_blob["checkpoint_blobs"][0]["size_bytes"] = 2 + _seal(wrong_blob) + with pytest.raises(AthanorError, match="Blob disagrees"): + validate_patch_promotion_checkpoint_v1(wrong_blob) + + +def test_checkpoint_requires_no_blob_for_absent_or_directory_preimage() -> None: + checkpoint = _checkpoint() + checkpoint["entries"][0]["preimage"] = {"kind": "ABSENT"} + checkpoint["entries"][0]["checkpoint_blob"] = None + checkpoint["checkpoint_blobs"] = [] + _seal(checkpoint) + validate_patch_promotion_checkpoint_v1(checkpoint) + + unexpected = deepcopy(checkpoint) + unexpected["entries"][0]["checkpoint_blob"] = { + "sigil": FILE_SIGIL, "size_bytes": 1, "media_type": "application/octet-stream", + } + unexpected["checkpoint_blobs"] = [unexpected["entries"][0]["checkpoint_blob"]] + _seal(unexpected) + with pytest.raises(AthanorError, match="Blob presence"): + validate_patch_promotion_checkpoint_v1(unexpected) + + +def test_checkpoint_rejects_reverse_time() -> None: + checkpoint = _checkpoint() + checkpoint["verified_at"] = "2026-08-05T23:59:59Z" + _seal(checkpoint) + with pytest.raises(AthanorError, match="precedes"): + validate_patch_promotion_checkpoint_v1(checkpoint) diff --git a/tests/test_patch_promotion_journal_v1_contract.py b/tests/test_patch_promotion_journal_v1_contract.py new file mode 100644 index 0000000..1255c3d --- /dev/null +++ b/tests/test_patch_promotion_journal_v1_contract.py @@ -0,0 +1,109 @@ +from __future__ import annotations + +from copy import deepcopy + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.patch_promotion_contracts import ( + require_patch_promotion_runtime_authority_v1, + validate_patch_promotion_journal_event_v1, + validate_patch_promotion_journal_head_v1, + validate_patch_promotion_journal_prefix_v1, +) + + +SIGIL = "sha256:" + "a" * 64 + + +def _head() -> dict[str, object]: + head: dict[str, object] = { + "schema_version": "patch-promotion-journal-head/1.0", "journal_id": "PJ-ONE", + "coordinator_epoch": 1, "event_count": 0, "last_sequence": 0, + "last_event_sigil": None, "committed_offset": 0, + "frames_file_sigil_prefix": SIGIL, "projected_state_sigil": SIGIL, + "head_generation": 0, "head_sigil": "", + } + head["head_sigil"] = content_sigil({key: value for key, value in head.items() if key != "head_sigil"}) + return head + + +def _event(sequence: int, previous: str | None, event_id: str) -> dict[str, object]: + event: dict[str, object] = { + "schema_version": "patch-promotion-journal-event/1.0", "journal_id": "PJ-ONE", + "event_id": event_id, "sequence": sequence, "coordinator_id": "PC-ONE", + "coordinator_epoch": 1, "event_type": "coordinator.epoch-started", + "recorded_at": f"2026-08-06T00:00:0{sequence}Z", + "entity_revisions": [{"entity_type": "COORDINATOR", "entity_id": "PC-ONE", "prior_revision": sequence - 1, "next_revision": sequence}], + "causation_event_id": None, "idempotency_key_sigil": None, + "payload": { + "prior_epoch": 0, "new_epoch": 1, "replayed_head": _head(), + "replayed_state_sigil": SIGIL, "clock_evidence_sigil": SIGIL, + "completed_tail_recovery_id": None, "deactivated_operational_root_ids": [], + "started_at": f"2026-08-06T00:00:0{sequence}Z", + }, + "previous_event_sigil": previous, "event_sigil": "", + } + event["event_sigil"] = content_sigil({key: value for key, value in event.items() if key != "event_sigil"}) + return event + + +def test_patch_promotion_journal_event_and_head_self_sigils_are_checked() -> None: + event = _event(1, None, "PJE-ONE") + validate_patch_promotion_journal_event_v1(event) + validate_patch_promotion_journal_head_v1(_head()) + + wrong = deepcopy(event) + wrong["event_sigil"] = SIGIL + with pytest.raises(AthanorError, match="self-Sigil"): + validate_patch_promotion_journal_event_v1(wrong) + + wrong_revision = deepcopy(event) + wrong_revision["entity_revisions"][0]["next_revision"] = 7 + wrong_revision["event_sigil"] = content_sigil({ + key: value for key, value in wrong_revision.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="revision algebra"): + validate_patch_promotion_journal_event_v1(wrong_revision) + + duplicate_revision = deepcopy(event) + duplicate_revision["entity_revisions"].append({ + "entity_type": "COORDINATOR", "entity_id": "PC-ONE", + "prior_revision": 1, "next_revision": 2, + }) + duplicate_revision["event_sigil"] = content_sigil({ + key: value for key, value in duplicate_revision.items() if key != "event_sigil" + }) + with pytest.raises(AthanorError, match="duplicate entity revisions"): + validate_patch_promotion_journal_event_v1(duplicate_revision) + + +def test_patch_promotion_prefix_and_head_require_one_contiguous_chain() -> None: + first = _event(1, None, "PJE-ONE") + second = _event(2, first["event_sigil"], "PJE-TWO") + head = _head() + head.update({"event_count": 2, "last_sequence": 2, "last_event_sigil": second["event_sigil"]}) + head["head_sigil"] = content_sigil({key: value for key, value in head.items() if key != "head_sigil"}) + validate_patch_promotion_journal_prefix_v1([first, second], head=head) + + broken = deepcopy(second) + broken["previous_event_sigil"] = SIGIL + broken["event_sigil"] = content_sigil({key: value for key, value in broken.items() if key != "event_sigil"}) + with pytest.raises(AthanorError, match="broken Event chain"): + validate_patch_promotion_journal_prefix_v1([first, broken]) + + noninitial = deepcopy(first) + noninitial["event_type"] = "coordinator.replay-started" + with pytest.raises(AthanorError): + validate_patch_promotion_journal_prefix_v1([noninitial]) + + wrong_head = deepcopy(head) + wrong_head["last_sequence"] = 1 + wrong_head["head_sigil"] = content_sigil({key: value for key, value in wrong_head.items() if key != "head_sigil"}) + with pytest.raises(AthanorError, match="Head terminal fields disagree"): + validate_patch_promotion_journal_prefix_v1([first, second], head=wrong_head) + + +def test_patch_promotion_contract_validation_grants_no_runtime_authority() -> None: + with pytest.raises(AthanorError, match="authority is unavailable"): + require_patch_promotion_runtime_authority_v1() diff --git a/tests/test_patch_promotion_mutation_intent_v1_contract.py b/tests/test_patch_promotion_mutation_intent_v1_contract.py new file mode 100644 index 0000000..7f64d56 --- /dev/null +++ b/tests/test_patch_promotion_mutation_intent_v1_contract.py @@ -0,0 +1,102 @@ +from __future__ import annotations + +from copy import deepcopy + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.patch_promotion_contracts import validate_patch_promotion_mutation_intent_v1 + + +SIGIL = "sha256:" + "a" * 64 + + +def _seal(intent: dict[str, object]) -> dict[str, object]: + intent["intent_sigil"] = content_sigil( + {key: value for key, value in intent.items() if key != "intent_sigil"}, + ) + return intent + + +def _intent() -> dict[str, object]: + root = {"root_object_sigil": SIGIL, "root_generation": "generation-1", "topology_sigil": SIGIL} + tree = {"manifest_sigil": SIGIL, "root_entry_sigil": SIGIL, "entry_count": 1, "total_bytes": 1} + postimage = { + "identity_profile": {"id": "PBIP-ONE", "sigil": SIGIL}, + "tree": tree, + "manifest_blob": {"sigil": SIGIL, "size_bytes": 1, "media_type": "application/octet-stream"}, + } + return _seal({ + "schema_version": "patch-promotion-mutation-intent/1.0", + "intent_id": "PMI-ONE", + "attempt_id": "PAT-ONE", + "authorization": {"id": "PAU-ONE", "sigil": SIGIL}, + "operation_sigil": SIGIL, + "guard": {"id": "PG-ONE", "sigil": SIGIL}, + "fencing_generation": 1, + "fence_floor": 1, + "target_content_generation": "generation-1", + "checkpoint": {"id": "PCK-ONE", "sigil": SIGIL}, + "base": {"id": "PB-ONE", "sigil": SIGIL}, + "postimage": postimage, + "operations_sigil": SIGIL, + "topology_plan": { + "mode": "FULL_TREE_ATOMIC_CAS", + "target_wide_generation": "generation-1", + "root_identity": root, + "ancestor_set_sigil": SIGIL, + "operation_order": ["file.txt"], + "plan_sigil": SIGIL, + }, + "root_identity": root, + "ancestor_identities": [{ + "path_bytes": "parent", + "object_identity_sigil": SIGIL, + "generation": "generation-1", + }], + "adapter": {"id": "PPA-ONE", "sigil": SIGIL}, + "verification_method": { + "kind": "FULL_TREE_IDENTITY", + "identity_profile": {"id": "PBIP-ONE", "sigil": SIGIL}, + "expected_tree": tree, + "verifier_profile_sigil": SIGIL, + }, + "committed_at": "2026-08-06T00:00:00Z", + "intent_sigil": "", + }) + + +def test_mutation_intent_checks_self_sigil_and_cross_record_identity() -> None: + intent = _intent() + validate_patch_promotion_mutation_intent_v1(intent) + + wrong_root = deepcopy(intent) + wrong_root["root_identity"] = { # type: ignore[index] + **wrong_root["root_identity"], "root_generation": "generation-2", + } + _seal(wrong_root) + with pytest.raises(AthanorError, match="topology root"): + validate_patch_promotion_mutation_intent_v1(wrong_root) + + wrong_tree = deepcopy(intent) + wrong_tree["verification_method"]["expected_tree"] = { # type: ignore[index] + **wrong_tree["verification_method"]["expected_tree"], "entry_count": 2, + } + _seal(wrong_tree) + with pytest.raises(AthanorError, match="verification method"): + validate_patch_promotion_mutation_intent_v1(wrong_tree) + + +def test_mutation_intent_checks_topology_generation_and_ancestor_order() -> None: + intent = _intent() + wrong_generation = deepcopy(intent) + wrong_generation["topology_plan"]["target_wide_generation"] = "generation-2" # type: ignore[index] + _seal(wrong_generation) + with pytest.raises(AthanorError, match="topology generation"): + validate_patch_promotion_mutation_intent_v1(wrong_generation) + + duplicate_order = deepcopy(intent) + duplicate_order["topology_plan"]["operation_order"] = ["file.txt", "file.txt"] # type: ignore[index] + _seal(duplicate_order) + with pytest.raises(AthanorError, match="operation_order|operation order"): + validate_patch_promotion_mutation_intent_v1(duplicate_order) diff --git a/tests/test_patch_promotion_outcome_v1_contract.py b/tests/test_patch_promotion_outcome_v1_contract.py new file mode 100644 index 0000000..07b2f9f --- /dev/null +++ b/tests/test_patch_promotion_outcome_v1_contract.py @@ -0,0 +1,171 @@ +from __future__ import annotations + +from copy import deepcopy + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.patch_promotion_contracts import ( + derive_patch_promotion_outcome_id_v1, + validate_patch_promotion_outcome_supplied_attempt_v1, + validate_patch_promotion_outcome_v1, +) + + +SIGIL = "sha256:" + "a" * 64 + + +def _seal(outcome: dict[str, object]) -> dict[str, object]: + outcome["outcome_id"] = derive_patch_promotion_outcome_id_v1( + str(outcome["attempt_id"]), + str(outcome["terminal_journal_event_id"]), + str(outcome["terminal_journal_event_sigil"]), + ) + outcome["outcome_sigil"] = content_sigil( + {key: value for key, value in outcome.items() if key != "outcome_sigil"} + ) + return outcome + + +def _outcome() -> dict[str, object]: + tree = {"manifest_sigil": SIGIL, "root_entry_sigil": SIGIL, "entry_count": 1, "total_bytes": 1} + blob = {"sigil": SIGIL, "size_bytes": 1, "media_type": "application/octet-stream"} + return _seal( + { + "schema_version": "patch-promotion-outcome/1.0", + "outcome_id": "", + "authorization_receipt": { + "receipt_id": "RC-ONE", + "receipt_sigil": SIGIL, + "event_id": "CE-ONE", + "event_body_sigil": SIGIL, + }, + "attempt_id": "PAT-ONE", + "terminal_journal_event_id": "PJE-ONE", + "terminal_journal_event_sigil": SIGIL, + "operation_sigil": SIGIL, + "adapter": {"id": "PPA-ONE", "sigil": SIGIL}, + "before_identity": tree, + "after_identity": tree, + "before_generation": "generation", + "after_generation": "generation", + "checkpoint": None, + "mutation_intent": None, + "guard": None, + "timestamps": { + "created_at": "2026-08-06T00:00:00Z", + "mutation_started_at": None, + "verification_started_at": None, + "terminal_at": "2026-08-06T00:00:01Z", + }, + "status": "CANCELLED", + "path_observations": [ + { + "path_bytes": "file", + "expected_preimage_sigil": SIGIL, + "observed_preimage_sigil": SIGIL, + "expected_postimage_sigil": SIGIL, + "observed_postimage_sigil": SIGIL, + "status": "MATCH", + } + ], + "adapter_write_evidence": None, + "verifier_evidence": [blob], + "diagnostics": "cancelled", + "outcome_sigil": "", + } + ) + + +def test_promotion_outcome_checks_self_sigil_time_and_path_order() -> None: + outcome = _outcome() + validate_patch_promotion_outcome_v1(outcome) + + reverse_time = deepcopy(outcome) + reverse_time["timestamps"]["terminal_at"] = "2026-08-05T23:59:59Z" + _seal(reverse_time) + with pytest.raises(AthanorError, match="timestamps"): + validate_patch_promotion_outcome_v1(reverse_time) + + duplicate_paths = deepcopy(outcome) + duplicate_paths["path_observations"].append(deepcopy(duplicate_paths["path_observations"][0])) + _seal(duplicate_paths) + with pytest.raises(AthanorError, match="validation failed|path observations"): + validate_patch_promotion_outcome_v1(duplicate_paths) + + +def test_promotion_outcome_requires_per_entry_evidence_for_each_path() -> None: + outcome = _outcome() + outcome["status"] = "APPLIED" + outcome["checkpoint"] = {"id": "PCK-ONE", "sigil": SIGIL} + outcome["mutation_intent"] = {"id": "PMI-ONE", "sigil": SIGIL} + outcome["guard"] = {"id": "PG-ONE", "sigil": SIGIL} + outcome["adapter_write_evidence"] = { + "mode": "PER_ENTRY_GENERATIONAL_CAS", + "transaction_id_sigil": SIGIL, + "receipt_sigils": [SIGIL], + "before_generation": "generation", + "after_generation": "generation", + "causal_evidence_sigil": SIGIL, + } + _seal(outcome) + validate_patch_promotion_outcome_v1(outcome) + + extra_path = deepcopy(outcome) + extra_path["path_observations"].append( + {**extra_path["path_observations"][0], "path_bytes": "other"} + ) + _seal(extra_path) + with pytest.raises(AthanorError, match="per-entry evidence"): + validate_patch_promotion_outcome_v1(extra_path) + + wrong_generation = deepcopy(outcome) + wrong_generation["adapter_write_evidence"]["after_generation"] = "other" + _seal(wrong_generation) + with pytest.raises(AthanorError, match="evidence disagrees with generations"): + validate_patch_promotion_outcome_v1(wrong_generation) + + +def _attempt_for(outcome: dict[str, object]) -> dict[str, object]: + attempt = { + "schema_version": "patch-promotion-attempt/1.0", + "attempt_id": outcome["attempt_id"], + "authorization": {"id": "PAU-ONE", "sigil": SIGIL}, + "operation_sigil": outcome["operation_sigil"], + "target": { + "target_id": "PT-ONE", + "target_class": "DIRECTORY", + "identity_profile": {"id": "PBIP-ONE", "sigil": SIGIL}, + "root_identity": { + "root_object_sigil": SIGIL, + "root_generation": "generation", + "topology_sigil": SIGIL, + }, + "selection_authorization_sigil": SIGIL, + }, + "target_content_generation": "generation", + "adapter": outcome["adapter"], + "mode": "FULL_TREE_ATOMIC_CAS", + "created_at": outcome["timestamps"]["created_at"], + "state": outcome["status"], + "revision": 1, + "attempt_sigil": "", + } + attempt["attempt_sigil"] = content_sigil( + {key: value for key, value in attempt.items() if key != "attempt_sigil"} + ) + return attempt + + +def test_promotion_outcome_binds_to_a_terminal_supplied_attempt() -> None: + outcome = _outcome() + attempt = _attempt_for(outcome) + validate_patch_promotion_outcome_supplied_attempt_v1(outcome, attempt) + + nonterminal = deepcopy(attempt) + nonterminal["state"] = "READY" + nonterminal["attempt_sigil"] = content_sigil( + {key: value for key, value in nonterminal.items() if key != "attempt_sigil"} + ) + with pytest.raises(AthanorError, match="terminal supplied Attempt"): + validate_patch_promotion_outcome_supplied_attempt_v1(outcome, nonterminal) diff --git a/tests/test_patch_promotion_recovery_record_v1_contract.py b/tests/test_patch_promotion_recovery_record_v1_contract.py new file mode 100644 index 0000000..ff0def7 --- /dev/null +++ b/tests/test_patch_promotion_recovery_record_v1_contract.py @@ -0,0 +1,221 @@ +from __future__ import annotations + +from copy import deepcopy + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.patch_promotion_contracts import ( + derive_patch_promotion_recovery_record_id_v1, + validate_patch_promotion_recovery_record_supplied_attempt_v1, + validate_patch_promotion_recovery_record_v1, +) + + +SIGIL = "sha256:" + "a" * 64 +RECEIPT = { + "receipt_id": "RC-ONE", + "receipt_sigil": SIGIL, + "event_id": "CE-ONE", + "event_body_sigil": SIGIL, +} +TREE = {"manifest_sigil": SIGIL, "root_entry_sigil": SIGIL, "entry_count": 1, "total_bytes": 1} +LINEAGE = { + "target_id": "PT-ONE", + "logical_fence_generation": 1, + "logical_fence_revision": 1, + "logical_fence_sigil": SIGIL, + "predecessor_head_sigil": SIGIL, + "predecessor": { + "kind": "PROMOTION_PARTIAL", + "parent_attempt_id": "PAT-ONE", + "outcome_id": "PO-ONE", + "outcome_sigil": SIGIL, + "receipt": RECEIPT, + }, +} + + +def _seal(record: dict[str, object]) -> dict[str, object]: + record["recovery_record_id"] = derive_patch_promotion_recovery_record_id_v1( + str(record["recovery_attempt_id"]), + str(record["terminal_journal_event_id"]), + str(record["terminal_journal_event_sigil"]), + ) + record["recovery_record_sigil"] = content_sigil( + {key: value for key, value in record.items() if key != "recovery_record_sigil"} + ) + return record + + +def _record() -> dict[str, object]: + return _seal( + { + "schema_version": "patch-promotion-recovery-record/1.0", + "recovery_record_id": "", + "recovery_attempt_id": "PRA-ONE", + "authorization_receipt": RECEIPT, + "parent_attempt_id": "PAT-ONE", + "parent_outcome_receipt": RECEIPT, + "action": "RESTORE_BASE", + "guard": {"id": "PG-ONE", "sigil": SIGIL}, + "checkpoint": {"id": "PCK-ONE", "sigil": SIGIL}, + "recovery_intent": {"id": "PRI-ONE", "sigil": SIGIL}, + "lineage": LINEAGE, + "before_identity": TREE, + "after_identity": TREE, + "before_generation": "generation", + "after_generation": "generation", + "resulting_logical_fence_generation": 1, + "verifier_evidence": [ + {"sigil": SIGIL, "size_bytes": 1, "media_type": "application/octet-stream"} + ], + "terminal_journal_event_id": "PJE-ONE", + "terminal_journal_event_sigil": SIGIL, + "status": "BASE_RESTORED", + "abandonment_disposition": None, + "recovery_record_sigil": "", + } + ) + + +def _attempt(record: dict[str, object]) -> dict[str, object]: + attempt = { + "schema_version": "patch-promotion-recovery-attempt/1.0", + "recovery_attempt_id": record["recovery_attempt_id"], + "parent_attempt_id": record["parent_attempt_id"], + "parent_outcome_receipt": record["parent_outcome_receipt"], + "authorization": {"id": "PAU-ONE", "sigil": SIGIL}, + "action": record["action"], + "target": { + "target_id": "PT-ONE", + "target_class": "DIRECTORY", + "identity_profile": {"id": "PBIP-ONE", "sigil": SIGIL}, + "root_identity": { + "root_object_sigil": SIGIL, + "root_generation": "generation", + "topology_sigil": SIGIL, + }, + "selection_authorization_sigil": SIGIL, + }, + "bound_before_identity": TREE, + "bound_before_generation": "generation", + "checkpoint": record["checkpoint"], + "lineage": record["lineage"], + "created_at": "2026-08-06T00:00:00Z", + "state": record["status"], + "revision": 1, + "recovery_attempt_sigil": "", + } + attempt["recovery_attempt_sigil"] = content_sigil( + {key: value for key, value in attempt.items() if key != "recovery_attempt_sigil"} + ) + return attempt + + +def _abandoned_record() -> dict[str, object]: + record = _record() + record["status"] = "ABANDONED" + record["action"] = "ABANDON" + disposition: dict[str, object] = { + "kind": "ABANDONED_OPERATIONAL_ROOT_DISPOSITION", + "recovery_attempt_id": record["recovery_attempt_id"], + "parent_attempt_id": record["parent_attempt_id"], + "authorization_receipt": record["authorization_receipt"], + "actor": { + "actor_id": "ACTOR", "actor_kind": "HUMAN", + "authentication_context_sigil": SIGIL, + }, + "disposition_policy_id": "PDP-ABANDONED-ROOT-DISPOSITION-V1", + "disposition_policy_sigil": SIGIL, + "terminal_event": { + "protocol_id": "benchwork.patch-promotion", "protocol_version": "1.0", + "journal_id": "PJ-ONE", "event_id": record["terminal_journal_event_id"], + "sequence": 1, "event_type": "recovery.abandoned", + "event_sigil": record["terminal_journal_event_sigil"], + }, + "observed_partial_identity": record["before_identity"], + "observed_generation": record["before_generation"], + "logical_fence_generation": record["resulting_logical_fence_generation"], + "guard_completion": { + "kind": "TERMINAL_GUARD", "guard": record["guard"], + "terminal_event": { + "protocol_id": "benchwork.patch-promotion", "protocol_version": "1.0", + "journal_id": "PJ-ONE", "event_id": "PJE-GUARD", "sequence": 2, + "event_type": "target.guard-released", "event_sigil": SIGIL, + }, "terminal_state": "RELEASED", + }, + "root_dispositions": [{ + "operational_root_id": "PROOT-ONE", "active_operational_root_sigil": SIGIL, + "operational_root_plan": {"schema_version": "control-record/1.0", "record_id": "PLAN", "record_sigil": SIGIL}, + "hold_id": "SH-ONE", "reference_set": {"reference_set_id": "RS-ONE", "reference_set_sigil": SIGIL}, + "policy_id": "SP-ONE", "policy_sigil": SIGIL, + "disposition": "RELEASE_OPERATIONAL_HOLD_AFTER_CANONICAL_ABANDONMENT", + }], + "physical_byte_authority": "NONE", "logical_fence_disposition": "PRESERVE", + "disposition_sigil": "", + } + disposition["disposition_sigil"] = content_sigil({ + key: value for key, value in disposition.items() if key != "disposition_sigil" + }) + record["abandonment_disposition"] = disposition + return _seal(record) + + +def test_recovery_record_checks_identity_and_supplied_attempt() -> None: + record = _record() + validate_patch_promotion_recovery_record_v1(record) + validate_patch_promotion_recovery_record_supplied_attempt_v1(record, _attempt(record)) + + changed = deepcopy(record) + changed["terminal_journal_event_id"] = "PJE-TWO" + changed["recovery_record_sigil"] = content_sigil( + {key: value for key, value in changed.items() if key != "recovery_record_sigil"} + ) + with pytest.raises(AthanorError, match="ID"): + validate_patch_promotion_recovery_record_v1(changed) + + nonterminal = _attempt(record) + nonterminal["state"] = "READY" + nonterminal["recovery_attempt_sigil"] = content_sigil( + {key: value for key, value in nonterminal.items() if key != "recovery_attempt_sigil"} + ) + with pytest.raises(AthanorError, match="terminal supplied Attempt"): + validate_patch_promotion_recovery_record_supplied_attempt_v1(record, nonterminal) + + +def test_abandoned_recovery_record_closes_nested_disposition() -> None: + record = _abandoned_record() + validate_patch_promotion_recovery_record_v1(record) + + tampered = deepcopy(record) + tampered["abandonment_disposition"]["observed_generation"] = "other" + tampered["recovery_record_sigil"] = content_sigil({ + key: value for key, value in tampered.items() if key != "recovery_record_sigil" + }) + with pytest.raises(AthanorError, match="abandonment disposition self-Sigil mismatch"): + validate_patch_promotion_recovery_record_v1(tampered) + + wrong_terminal = deepcopy(record) + wrong_terminal["abandonment_disposition"]["terminal_event"]["event_type"] = "recovery.failed" + wrong_terminal["abandonment_disposition"]["disposition_sigil"] = content_sigil({ + key: value for key, value in wrong_terminal["abandonment_disposition"].items() + if key != "disposition_sigil" + }) + wrong_terminal["recovery_record_sigil"] = content_sigil({ + key: value for key, value in wrong_terminal.items() if key != "recovery_record_sigil" + }) + with pytest.raises(AthanorError, match="terminal Event type is invalid"): + validate_patch_promotion_recovery_record_v1(wrong_terminal) + + wrong_guard = deepcopy(record) + wrong_guard["abandonment_disposition"]["guard_completion"]["terminal_event"]["event_type"] = "target.guard-fenced" + wrong_guard["abandonment_disposition"]["disposition_sigil"] = content_sigil({ + key: value for key, value in wrong_guard["abandonment_disposition"].items() + if key != "disposition_sigil" + }) + wrong_guard["recovery_record_sigil"] = content_sigil({ + key: value for key, value in wrong_guard.items() if key != "recovery_record_sigil" + }) + with pytest.raises(AthanorError, match="guard completion Event type is invalid"): + validate_patch_promotion_recovery_record_v1(wrong_guard) diff --git a/tests/test_patch_promotion_target_guard_v1_contract.py b/tests/test_patch_promotion_target_guard_v1_contract.py new file mode 100644 index 0000000..243d787 --- /dev/null +++ b/tests/test_patch_promotion_target_guard_v1_contract.py @@ -0,0 +1,67 @@ +from __future__ import annotations + +from copy import deepcopy + +import pytest + +from benchwork.athanor import AthanorError, content_sigil +from benchwork.patch_promotion_contracts import validate_patch_promotion_target_guard_v1 + + +SIGIL = "sha256:" + "a" * 64 + + +def _seal(guard: dict[str, object]) -> dict[str, object]: + guard["guard_sigil"] = content_sigil({key: value for key, value in guard.items() if key != "guard_sigil"}) + return guard + + +def _guard() -> dict[str, object]: + return _seal({ + "schema_version": "patch-promotion-target-guard/1.0", "guard_id": "PG-ONE", "target_id": "PT-ONE", + "owner_kind": "PROMOTION", "owner_attempt_id": "PAT-ONE", "coordinator_id": "PC-ONE", + "coordinator_epoch": 1, "state": "HELD", "backend_generation": "generation-1", + "fencing_generation": 2, "fence_floor": 1, "target_content_generation": "target-generation", + "deadline_policy_sigil": SIGIL, "clock_anchor_evidence_sigil": SIGIL, "original_remaining_ns": 1, + "acquired_at": "2026-08-06T00:00:00Z", "expires_at": "2026-08-06T00:00:01Z", + "recovery_of_guard_id": None, "revision": 1, "guard_sigil": "", + }) + + +def test_target_guard_checks_self_sigil_deadlines_and_fences() -> None: + guard = _guard() + validate_patch_promotion_target_guard_v1(guard) + + missing_anchor = deepcopy(guard) + missing_anchor["original_remaining_ns"] = None + _seal(missing_anchor) + with pytest.raises(AthanorError, match="anchor fields"): + validate_patch_promotion_target_guard_v1(missing_anchor) + + reverse_time = deepcopy(guard) + reverse_time["expires_at"] = "2026-08-05T23:59:59Z" + _seal(reverse_time) + with pytest.raises(AthanorError, match="expires before"): + validate_patch_promotion_target_guard_v1(reverse_time) + + bad_fence = deepcopy(guard) + bad_fence["fence_floor"] = 3 + _seal(bad_fence) + with pytest.raises(AthanorError, match="fence floor"): + validate_patch_promotion_target_guard_v1(bad_fence) + + +def test_none_target_guard_has_no_physical_fields() -> None: + guard = _guard() + guard.update({ + "state": "NONE", "backend_generation": None, "clock_anchor_evidence_sigil": None, + "original_remaining_ns": None, "acquired_at": None, "expires_at": None, + }) + _seal(guard) + validate_patch_promotion_target_guard_v1(guard) + + invalid = deepcopy(guard) + invalid["backend_generation"] = "generation-1" + _seal(invalid) + with pytest.raises(AthanorError, match="empty Target Guard"): + validate_patch_promotion_target_guard_v1(invalid)