# PLAN — v1.26 (Live Pilot Estate Activation) > Feature milestone. Tags on the **v1.25.x** line: v1.25.0 (P0) → > v1.25.1 (P1) → v1.25.2 (P2) → v1.25.3 (P3) → v1.25.4 (P4) → v1.25.5 > (P5 final = milestone release). 13 requirements (REQ-310..322), > 5 phases (P0 pre-execution + 4 execution + 1 final). Multi-project: > `acdl` (platform) + `nova-blockchain-exchange` (consumer). Tags run > on the previous minor's patch line per `run.md` versioning logic > (feature milestone — at least one feat phase; progressive patches per > phase; the final phase's patch IS the milestone release; no separate > minor tag). --- ## Phase 0 — Pre-Execution (complete, tag v1.25.0) SPECIFY → CLARIFY → RESEARCH → IDEATE → PLAN → GRILL. All `.ciagent/` MD, research, plans. Ships as `v1.25.0` on the v1.25.x line. **Pre-run (Workstream A, on main before branch gate):** - A1: flaky test fix (commit `8c68d68`, pushed). - A2: ACDL_*→NOVA_* bootstrap migration (commit `f844fea`, pushed). - A3: AWS bootstrap — S3 state bucket + DynamoDB outbox created. - A4: `nova-blockchain-exchange` Gitea repo created + cloned. **Phase 0 stages (on `phase/00-specify-clarify-research-plan`):** - SPECIFY: v1.26 established in config.json + PROJECT.md + ROADMAP.md + `.ciagent/nova-blockchain-exchange/{PROJECT,REQUIREMENTS,ROADMAP}.md`. - CLARIFY: 10 ambiguities resolved (D-200..D-213). - RESEARCH: PoA blockchain, deploy model, DynamoDB gap (REQ-322), metric grounding, persona assessment (5 personas). - IDEATE: 7 ideas accepted (I1..I7 → REQ-315..322), 3 deferred. - PLAN: this file. - GRILL: adversarial review (binding verdicts). --- ## Phase 1 — blockchain-core (tag v1.25.1) **Goal:** The consumer repo has a working homegrown PoA blockchain + order-matching engine + settlement service. All unit tests pass in the consumer repo's own CI. **Project:** `nova-blockchain-exchange` (consumer repo). **Branch:** `nova-blockchain-exchange/phase/01-blockchain-core`. **Persona:** blockchain-engineer (primary), lead-developer (coordination). ### Wave 1 — chain core (REQ-310) - **Task 1.1** (blockchain-engineer): `chain/block.py` — Block dataclass (index, timestamp, prev_hash, transactions, nonce, hash). `compute_hash()` deterministic (SHA-256). Unit test: `test_block.py`. - **Task 1.2** (blockchain-engineer): `chain/ledger.py` — Ledger class: `append_block()`, `verify_chain()`, `get_block(index)`, `get_latest_block()`. Genesis block on init. Unit test: `test_ledger.py`. - **Task 1.3** (blockchain-engineer): `chain/validator.py` — PoA validator: single validator (config-driven), `propose_block(transactions)` → Block, `commit_block(block)`. Unit test: `test_validator.py`. ### Wave 2 — order engine + settlement (REQ-311, REQ-312) — parallel with Wave 1 tail - **Task 2.1** (blockchain-engineer): `engine/order.py` — Order dataclass (id, side, symbol, price, size, timestamp). - **Task 2.2** (blockchain-engineer): `engine/order_book.py` — OrderBook: `add_order(order)`, `match_orders()` → list of Match (price-time priority, partial fills). Unit test: `test_order_book.py`. - **Task 2.3** (blockchain-engineer): `settlement/service.py` — SettlementService: `settle(match)` → SettlementTransaction, `submit(ledger)`. Idempotent (re-settling a match is a no-op once final). Finality = block commit. Unit test: `test_settlement.py`. ### Wave 3 — consumer CI (cross-cutting) - **Task 3.1** (blockchain-engineer): `.github/workflows/ci.yml` + `.gitea/workflows/ci.yml` — lint + pytest on chain/engine/settlement. - **Task 3.2** (lead-developer): `nova-blockchain-exchange/README.md` — repo overview + dev setup. **Must-haves (verify before ship):** - `pytest tests/` in the consumer repo passes (chain integrity, hash determinism, genesis, append/verify, match priority, partial fills, settlement idempotency, finality check). - The chain is deterministic (replay produces the same hash chain). - The consumer CI workflow runs on push. **Ship:** tag `v1.25.1`, merge `phase/01` → `milestone/v1.26-pilot-activation`, Gitea release (best-effort). Delete `phase/01`. --- ## Phase 2 — consumer-contract-and-deploy (tag v1.25.2) **Goal:** The consumer repo declares its infrastructure via `contract.yaml` (validated against the platform's schema) + invokes the platform's `deploy.yml@v1.25` workflow. The contract references the `microservice` (ECS), `dynamodb`, + `s3` modules. **Project:** `nova-blockchain-exchange` (consumer repo) + `acdl` (platform repo — for the `deploy.yml@v1.25` ref + the `v1.25` floating tag). **Branch:** `nova-blockchain-exchange/phase/02-contract-and-deploy`. **Persona:** blockchain-engineer (contract authoring), data-engineer (registry/DynamoDB dependency check), lead-developer (deploy.yml ref). ### Wave 1 — contract (REQ-313) - **Task 1.1** (blockchain-engineer): `contract.yaml` — id (`blkex`), name (`blockchain-exchange`), environment (dev), infrastructure block (microservice + dynamodb + s3). - **Task 1.2** (blockchain-engineer): `contracts/blockchain-exchange.dev.yml`, `.qa.yml`, `.prod.yml` — per-env variants. - **Task 1.3** (blockchain-engineer): `tests/test_contract_validates.py` — schema validation against the platform's `schemas/contract.schema.json`. ### Wave 2 — deploy invocation (REQ-314) - **Task 2.1** (blockchain-engineer): `.github/workflows/deploy.yml` — `uses: acdl/.github/workflows/deploy.yml@v1.25` with `with: { contract: contract.yaml, mode: full, environment: dev }`. - **Task 2.2** (blockchain-engineer): `.gitea/workflows/deploy.yml` — byte-identical mirror. - **Task 2.3** (blockchain-engineer): `tests/test_deploy_workflow_invocation.py` — asserts the `uses:` ref + inputs. ### Wave 3 — platform floating tag (cross-cutting) - **Task 3.1** (lead-developer, on `acdl` repo): verify the `v1.25` floating tag exists (created by `release.yml` on merge to main). If not, create it pointing at the `v1.25.0` tag (Phase 0 ship). **Must-haves (verify before ship):** - `contract.yaml` validates against `schemas/contract.schema.json`. - The deploy workflow invocation asserts the correct `uses:` ref + inputs. - The `v1.25` floating tag resolves. **Ship:** tag `v1.25.2`, merge `phase/02` → milestone, Gitea release. Delete `phase/02`. --- ## Phase 3 — pilot-metrics-and-policies (tag v1.25.3) **Goal:** The platform repo gains the metric-grounding emitters, the kyverno-json pilot policies, the DynamoDB L1 primitive, the env-JSON wiring reconciliation, + the pilot regression CAP. The Post-Pilot metrics are grounded (outcome backfill + escalation reason); the pilot- readiness + settlement-finality policies are in place. **Project:** `acdl` (platform repo) + `nova-blockchain-exchange` (consumer repo — the Gitea adapter rewrites the consumer's `deploy.yml`). **Branch:** `acdl/phase/03-pilot-metrics-and-policies` (platform branch). **Personas:** backend-engineer (emitters + adapter + regression), data-engineer (DynamoDB primitive + env JSON + collector), policy-engineer (kyverno-json policies), lead-developer (Gitea adapter + deploy.yml drift + rotation workflow). ### Wave 0 — Gitea reusable-workflow adapter (SPEC §10 Q1, resolved by evidence) — lead-developer + blockchain-engineer > **Highest-priority gap.** The v0.2 P3 `workflow_dispatch` (Gitea > Actions run id=6199) failed: Gitea Actions rejects cross-repo `uses:` > (`acdl/.github/workflows/deploy.yml@v1.25`) with `expected format > {owner}/{repo}/.{git_platform}/workflows/{filename}@{ref}`. The > consumer's `deploy.yml` is frozen at the v0.1 byte-identical mirror; > the platform adapts (option c — inline checkout-then-call), not > vice-versa. - **Task 0.1** (lead-developer): rewrite `nova-blockchain-exchange/.gitea/workflows/deploy.yml` + byte-identical `.github/workflows/deploy.yml` — drop the `uses:` indirection; single `deploy` job on `ubuntu-latest` that `actions/checkout@v4` the consumer, `actions/checkout@v4` `acdl/acdl` @ `ref: v1.25` into `platform/`, setup-python 3.12, install deps (jsonschema/pyyaml/boto3 + checkov), install Terraform 1.9.*, configure AWS (static-key path: `aws-region: ${{ secrets.AWS_DEFAULT_REGION }}`, `access-key-id` + `secret-access-key` from `NOVA_AWS_*` secrets; no OIDC token minted), run `bash platform/scripts/run_platform.sh $MODE_FLAG $ENV_FLAG contract.yaml`. Preserve `on: workflow_dispatch` inputs (mode choice default full; environment choice default "") + `permissions: {id-token: write, contents: read}` + `secrets: inherit`. - **Task 0.2** (blockchain-engineer): update `nova-blockchain-exchange/tests/test_deploy_workflow_invocation.py` + `test_deploy_gitea_invocation.py` — assert no cross-repo `uses:`, assert `ref: v1.25`, assert `secrets: inherit`, assert `run_platform.sh` invoked, assert `AWS_DEFAULT_REGION` wired. - **Task 0.3** (lead-developer): `acdl/.github/workflows/deploy.yml` stays as the GitHub Actions reference impl (the `workflow_call` reusable workflow — used by GitHub-hosted consumers); document in `adapters/README.md` that Gitea consumers use the inline adapter, not the reusable `uses:`. ### Wave 0.5 — kyverno-json substrate fix (v1.25 skip-masked bug) — backend-engineer > The v1.25 kyverno-json engine + policies were never validated > against the real `kj` binary (tests `pytest.skip("kj not installed")` > when absent). With `kj` now installed (v0.0.3), 3 policy tests > failed. Root cause: (a) `kj` v0.0.3 does not load `.json` policy > files (only `.yaml`/`.yml`) — the engine now materializes `.yaml` > twins at runtime; (b) the `validate` wrapper is not supported — > `assert` goes directly under the rule; (c) the check syntax was > inverted (`expression: expected_value`, not `key: expression`); > (d) the engine `_translate` expected `{"results": [...]}` but `kj` > returns a bare list with `results[].policy.metadata.name` + > `results[].rules[].violations[]`. DONE (committed 59d837f). Also > fixed `scripts/install-kyverno-json.sh` (the `cmd/kj@latest` path > fails — the real binary is `kyverno-json`, symlinked as `kj`). - **Task 0.5.1** (backend-engineer): rewrite `adapters/kyverno-json/kyverno_json_engine.py` `_translate` for the bare-list output format + add `_materialize_yaml_policy_dir` (DONE). - **Task 0.5.2** (backend-engineer): remove the `validate` wrapper + fix check syntax across all 16 existing policies (DONE). - **Task 0.5.3** (backend-engineer): fix `scripts/install-kyverno-json.sh` (DONE). - **Task 0.5.4** (backend-engineer): resolve pre-existing P2 drift uncovered by the full-suite run — dynamodb `examples/simple.yml` + `complex.yml`, `sync_workflows` re-sync, CAP-024 deck path (`nova-autonomous-cloud-delivery-marp.md`) + slide-count bound + `class="benefit"` div count (DONE, committed 3735330). ### Wave 1 — DynamoDB primitive (REQ-322) — data-engineer — verify-only (done in P2 W0) - **Task 1.1** (data-engineer): verify `modules/l1/dynamodb/` resolves + emits valid Terraform via `tests/test_adapter.py` (the primitive shipped in P2 W0; this wave is a re-verify, not re-authoring). ### Wave 2 — metric grounding (REQ-317, REQ-318) — backend-engineer + data-engineer — parallel - **Task 2.1** (backend-engineer): `core/metrics/outcome_backfill.py` — `backfill(decision_id, outcome)` updates `fact_decision.outcome` + `backfilled_at`. Reads run-manifest events. - **Task 2.2** (backend-engineer): `core/metrics/collector.py` — invokes backfill after run completion. - **Task 2.3** (backend-engineer): `tests/test_outcome_backfill.py`. - **Task 2.4** (backend-engineer): `core/confidence_signal.py` — `ai.decision.made` gains `escalation_reason: 'confidence'` when `band == 'block'`. - **Task 2.5** (backend-engineer): `core/metrics/collector.py` — persists `escalation_reason` into `fact_run`. - **Task 2.6** (backend-engineer): `tests/test_confidence_escalation_reason.py`. ### Wave 3 — env-JSON wiring + adapter (REQ-319) — backend-engineer + data-engineer — parallel - **Task 3.1** (backend-engineer): `adapters/terraform/adapter.py` — reads `env.state_backend.bucket` when present (fallback to computed name for backwards compat). - **Task 3.2** (data-engineer): `core/environments/dev.json` — `account_id` → `581513795199`, `state_backend.bucket` → `nova-tfstate-581513795199-us-east-1`. - **Task 3.3** (data-engineer): `core/environments/{qa,prod,dr}.json` — `state_backend.bucket` updated; `account_id` stays placeholder (pilot-readiness policy blocks apply on placeholder, D-208). - **Task 3.4** (backend-engineer): `tests/test_adapter_state_backend.py`. - **Task 3.5** (backend-engineer): `tests/test_adapter.py` — add `dynamodb` to `EXPECTED_L1_KEYS` + a resolution + emission test (cross-territory: data-engineer authored the module, backend-engineer owns the test). ### Wave 4 — kyverno-json policies (REQ-315, REQ-320) — policy-engineer — parallel - **Task 4.1** (policy-engineer): `adapters/kyverno-json/policies/settlement-finality/all-matches-committed.json` — kyverno-json policy over settlement-service status JSON (asserts `all_committed: true`). **Note (G-Q6):** the policy is authored + tested in v1.26; *enforcement* is deferred to the milestone that binds qa/prod/dr (D-208 — the policy gates promotions, not dev applies). - **Task 4.2** (policy-engineer): `adapters/kyverno-json/policies/pilot-readiness/no-placeholder-account.json` — kyverno-json policy over env JSON (asserts `account_id != "000000000000"`). - **Task 4.3** (policy-engineer): `tests/test_settlement_finality_policy.py` — passing + failing fixtures; **runs against real `kj`** (not skipped — `kj` is installed via `scripts/install-kyverno-json.sh`). - **Task 4.4** (policy-engineer): `tests/test_pilot_readiness_policy.py` — passing (real account) + failing (placeholder) fixtures; **runs against real `kj`** (not skipped). ### Wave 5 — regression CAP (REQ-316) — backend-engineer - **Task 5.1** (backend-engineer): `core/regression_verify.py` — CAP-025 (live-pilot-apply): the round-trip assertion. - **Task 5.2** (backend-engineer): `tests/test_regression_pilot.py`. ### Wave 6 — deploy.yml drift fixes (SPEC §5.1/§5.2) — lead-developer + backend-engineer > The platform reference `workflows-src/deploy.yml` (synced to > `.github`+`.gitea`) has three drifts vs the SPEC: (a) `aws-region` > hardcoded `us-east-1` (SPEC wants `NOVA_AWS_REGION`/`AWS_DEFAULT_REGION` > from secret); (b) platform checkout `ref: v1.9` (SPEC wants `v1.25`); > (c) the local `scripts/run_platform.sh` fallback exports raw > `NOVA_AWS_*` names into shell env (SPEC §5.2 constraint: consume as > workflow secrets, not shell env — `blocked_env_vars`). - **Task 6.1** (lead-developer): `workflows-src/deploy.yml` — `aws-region: ${{ secrets.AWS_DEFAULT_REGION || 'us-east-1' }}`; platform checkout `ref: v1.25`; re-sync to `.github`+`.gitea`. - **Task 6.2** (backend-engineer): `scripts/run_platform.sh` — source `AWS_DEFAULT_REGION` from `.env.secrets` for the local fallback (not raw `NOVA_AWS_*`); the CI path already consumes secrets via the `configure-aws-credentials` action. - **Task 6.3** (backend-engineer): `tests/test_deploy_workflow_env_input.py` — assert `AWS_DEFAULT_REGION` wired + `ref: v1.25` + no raw `NOVA_AWS_*` in shell env. ### Wave 7 — secret rotation scheduled workflow (SPEC §5.9) — lead-developer > SPEC §5.9: "the rotation mechanism must *exist* (not have run)." > A platform-managed scheduled workflow wraps the existing > `scripts/rotate_spike_key.sh` (manual today) on a daily cron. - **Task 7.1** (lead-developer): `workflows-src/rotate-aws-key.yml` — `on: { schedule: [{cron: "0 0 * * *"}], workflow_dispatch:}`, single job that checks out the platform repo + runs `bash scripts/rotate_spike_key.sh` with `NOVA_AWS_*` bootstrap secrets; sync to `.github`+`.gitea`. - **Task 7.2** (lead-developer): verify `scripts/rotate_spike_key.sh` is idempotent (deactivates old key only after the new key propagates to the Gitea Actions secret store). - **Task 7.3** (lead-developer): `tests/test_rotate_key_workflow.py` — structural test (the workflow file declares `schedule` + invokes `rotate_spike_key.sh`); document in `.ciagent/ARCHITECTURE.md` §12.8 that the mechanism exists (v0.2 scope: exists-not-ran per SPEC §5.9). **Must-haves (verify before ship):** - `pytest tests/` in the platform repo passes (the 170 baseline held inaccurately — the real P2 baseline had 7 pre-existing failures uncovered by W0.5; all now fixed). Full suite green. - `pytest tests/` in the consumer repo passes (deploy invocation tests updated for the inline adapter). - The kyverno-json substrate works against real `kj` (W0.5 — DONE). - The Gitea adapter: consumer `deploy.yml` has no cross-repo `uses:`; inline checkout `acdl@v1.25` + `run_platform.sh` (W0). - The DynamoDB primitive resolves + emits valid Terraform (W1 verify). - The outcome backfill updates `fact_decision.outcome` (not `pending`) (W2). - The `escalation_reason` field is emitted on `block` band (W2). - The adapter reads `env.state_backend.bucket` from the env JSON (W3). - The 2 new kyverno-json policies pass on valid fixtures + fail on invalid fixtures, against real `kj` (W4 — not skipped). - CAP-025 is in the regression gate (W5). - The deploy.yml drifts fixed: `AWS_DEFAULT_REGION` wired, `ref: v1.25`, no raw `NOVA_AWS_*` in shell env (W6). - The rotation scheduled workflow exists (W7). **Ship:** tag `v1.25.3`, merge `phase/03` → milestone, Gitea release. Delete `phase/03`. --- ## Phase 4 — pilot-run-and-docs (tag v1.25.4) **Goal:** The pilot estate runs end-to-end against live AWS `581513795199` (contract resolve → adapter compile → terraform plan → policy scan → confidence signal → attestation → outbox record). Docs + adapter README + onboarding guide are complete. **Project:** `nova-blockchain-exchange` (consumer repo — the run) + `acdl` (platform repo — docs). **Branch:** `acdl/phase/04-pilot-run-and-docs` (platform branch for docs); the run happens via the consumer's `deploy.yml` invocation. **Personas:** blockchain-engineer (the run), lead-developer (docs), backend-engineer (regression CAP-025 verification). ### Wave 1 — the pilot run (REQ-316 verification, live) - **Task 1.1** (blockchain-engineer): trigger the consumer's `deploy.yml` with `mode: full, environment: dev` against `581513795199`. The workflow checks out the consumer + platform repos, runs `run_platform.sh`, applies the contract (ECS + DynamoDB + S3), records the decision + attestation. - **Task 1.2** (backend-engineer): verify CAP-025 (regression gate) passes against the live run. - **Task 1.3** (blockchain-engineer): capture the run's `ai.decision.made` + `attestation.recorded` events from the Decision Ledger → evidence for the milestone ship. ### Wave 2 — docs (REQ-321) - **Task 2.1** (lead-developer): `adapters/README.md` — new consumer row + fix the stale `TYPE_MAP` references (IDEATE I8). - **Task 2.2** (lead-developer): `docs/METRICS.md` — Post-Pilot metrics grounded note (the 3 targets now have non-zero denominators post-run). - **Task 2.3** (lead-developer): `.ciagent/ARCHITECTURE.md` §12.8 (Pilot Estate). - **Task 2.4** (lead-developer): `.ciagent/nova-blockchain-exchange/README.md` — consumer onboarding guide (how to invoke `deploy.yml@v1.25`, what secrets to set, what the contract shape is). **Must-haves (verify before ship):** - The pilot run completes end-to-end (apply succeeds, decision recorded, attestation recorded for dev — autonomous, no human approver). - CAP-025 passes. - The 3 Post-Pilot metrics have non-zero denominators (the run contributed to `fact_run` + `fact_decision`). - Docs are complete (adapter README, METRICS.md, ARCHITECTURE.md §12.8, consumer onboarding guide). **Ship:** tag `v1.25.4`, merge `phase/04` → milestone, Gitea release. Delete `phase/04`. --- ## Phase 5 — final review + audit + milestone ship (tag v1.25.5) **Goal:** Multi-persona code review across P1..P4. Audit (reconstruction test, branch hygiene, commit discipline). Milestone ship: merge to main, tag `v1.25.5` (= the v1.26 release), Gitea release with full milestone summary, delete all milestone branches. **Project:** both (`acdl` + `nova-blockchain-exchange`). **Branch:** `phase/05-final-review-ship`. **Personas:** lead-developer (review + audit + ship), backend-engineer (review), data-engineer (review), policy-engineer (review), blockchain-engineer (review — the chain core is reviewed). ### Wave 1 — review - **Task 1.1** (lead-developer): `ciagent-review` — multi-persona code review across P1..P4. Auto-fix P0; flag P1+ for post-hoc review. - **Task 1.2** (all personas): fix P0 issues in this phase. ### Wave 2 — audit - **Task 2.1** (lead-developer): `ciagent-audit` — reconstruction test (git log ↔ `.ciagent/`), branch hygiene, commit discipline. - **Task 2.2** (lead-developer): fix critical audit issues in this phase. ### Wave 3 — milestone ship - **Task 3.1** (lead-developer): merge `phase/05` → `milestone/v1.26-pilot-activation` → `main`. - **Task 3.2** (lead-developer): tag `v1.25.5` (= the v1.26 release per prev-minor tagging rule). - **Task 3.3** (lead-developer): create Gitea release with full milestone summary (all phases, all 13 requirements). - **Task 3.4** (lead-developer): delete all milestone branches (local + remote). Tags preserve all history. - **Task 3.5** (lead-developer): update `.ciagent/nova-blockchain-exchange/REQUIREMENTS.md` (mark REQ-310..322 complete), `.ciagent/ROADMAP.md` (mark v1.26 complete), `.ciagent/NORTH_STAR.md` (note Strategic Objectives #1 + #3 — first real consumer estate; Post-Pilot denominators activated). - **Task 3.6** (lead-developer): write checkpoint `stage: complete, phase: 5, phase_role: final` + clear checkpoint (milestone complete). **Must-haves (verify before ship):** - Review: 0 P0 issues unfixed; P1+ flagged for post-hoc. - Audit: reconstruction test passes; branch hygiene clean; commit discipline clean. - Ship: `v1.25.5` tag exists; Gitea release created; milestone branches deleted; main has the milestone merge. --- ## Requirement → Phase Mapping | REQ | Phase | Wave | Persona | |---|---|---|---| | REQ-310 (blockchain core) | P1 | W1 | blockchain-engineer | | REQ-311 (order engine) | P1 | W2 | blockchain-engineer | | REQ-312 (settlement) | P1 | W2 | blockchain-engineer | | REQ-313 (contract.yaml) | P2 | W1 | blockchain-engineer | | REQ-314 (deploy invocation) | P2 | W2 | blockchain-engineer | | REQ-315 (settlement-finality policy) | P3 | W4 | policy-engineer | | REQ-316 (pilot regression CAP) | P3 | W5 + P4 W1 | backend-engineer | | REQ-317 (outcome backfill) | P3 | W2 | backend-engineer | | REQ-318 (escalation reason) | P3 | W2 | backend-engineer | | REQ-319 (env-JSON wiring) | P3 | W3 | backend + data-engineer | | REQ-320 (pilot-readiness policy) | P3 | W4 | policy-engineer | | REQ-321 (docs) | P4 | W2 | lead-developer | | REQ-322 (DynamoDB primitive) | P3 | W1 | data-engineer | --- ## Wave Ordering Rationale - **P1 W1 → W2:** the chain core (block + ledger + validator) must land before the order engine + settlement (they submit transactions to the ledger). W3 (CI) is cross-cutting + can land any time after W1. - **P2 W1 → W2:** the contract must land before the deploy invocation (the invocation references the contract). W3 (floating tag) is cross- cutting. - **P3 W1 (DynamoDB) first:** the contract (P2) references `dynamodb` — the primitive must exist before P2's contract can resolve. **Risk:** P2's contract references a module that doesn't exist until P3. Resolution: P2's contract is authored but the `test_contract_validates.py` test only checks schema validity (not registry resolution) — the registry resolution test is in P3 (after the primitive lands). The contract's `dynamodb` block is schema-valid (the schema is open); the registry resolution happens at apply time (P4). - **Alternative:** move REQ-322 to P2 W0 (before the contract). This avoids the P2→P3 dependency. **Decision: move REQ-322 to P2 W0.** See revised mapping below. ### Revised: REQ-322 → P2 W0 REQ-322 (DynamoDB primitive) lands in P2 Wave 0 (before the contract) so the contract's `dynamodb` block resolves at registry time, not just schema time. This makes P2 self-contained: the primitive + the contract + the deploy invocation all land in P2. | REQ | Phase | Wave | Persona | |---|---|---|---| | REQ-310 (blockchain core) | P1 | W1 | blockchain-engineer | | REQ-311 (order engine) | P1 | W2 | blockchain-engineer | | REQ-312 (settlement) | P1 | W2 | blockchain-engineer | | REQ-322 (DynamoDB primitive) | P2 | W0 | data-engineer | | REQ-313 (contract.yaml) | P2 | W1 | blockchain-engineer | | REQ-314 (deploy invocation) | P2 | W2 | blockchain-engineer | | REQ-315 (settlement-finality policy) | P3 | W4 | policy-engineer | | REQ-316 (pilot regression CAP) | P3 | W5 + P4 W1 | backend-engineer | | REQ-317 (outcome backfill) | P3 | W2 | backend-engineer | | REQ-318 (escalation reason) | P3 | W2 | backend-engineer | | REQ-319 (env-JSON wiring) | P3 | W3 | backend + data-engineer | | REQ-320 (pilot-readiness policy) | P3 | W4 | policy-engineer | | REQ-321 (docs) | P4 | W2 | lead-developer | This revision is a binding plan decision (G-Q8 in the grill may challenge it). --- ## Future Hardening Items (not in v1.26 scope, documented per grill G-Q9) - **`NOVA_AWS_*` key-split:** v1.26 uses a single `NOVA_AWS_*` key with root-equivalent permissions (D-207, confirmed empirically by the bootstrap). A future hardening milestone should split this into a `NOVA_BOOTSTRAP_AWS_*` root key (bootstrap only) + a least-privilege `NOVA_AWS_*` runner key (the spike-runner pattern). The pilot scope (single account, no production workloads, OIDC default) bounds the risk. - **Multi-account landing zone:** qa/prod/dr on separate accounts (D-208 keeps them placeholder in v1.26). - **D-083 lift:** S3 Object Lock + JWS tamper-evident ledger (when the pilot becomes a production system, D-204). - **Multi-validator BFT consensus:** D-201. - **Other security types:** bonds (T+2), derivatives, options (D-200).