---ci--- project: acdl phase: 0 milestone: v1.26 status: research requirements: [REQ-310..REQ-322] personas: [lead-developer, backend-engineer, data-engineer, policy-engineer, blockchain-engineer] ---/ci---
10 KiB
Requirements — nova-blockchain-exchange (v1.26 pilot)
Project: nova-blockchain-exchange — blockchain stock exchange (pilot) Milestone: v1.26 — Live Pilot Estate Activation Scope: equities only; minimal PoA ledger; T+1 settlement finality.
v1.26 — Live Pilot Estate Activation
REQ-310 — Homegrown PoA blockchain core
The consumer repo implements a minimal Proof-of-Authority blockchain: append-only blocks, single validator (pilot), SHA-256 block hash chain, deterministic block production (same ordered transactions → same block). The chain records every order, match, and settlement as transactions. Settlement finality = block commit (a transaction is final when its block is committed to the chain).
Must-haves:
chain/block.py— Block dataclass (index, timestamp, prev_hash, transactions, nonce, hash).compute_hash()deterministic.chain/ledger.py— Ledger class:append_block(),verify_chain(),get_block(index),get_latest_block(). Genesis block on init.chain/validator.py— PoA validator: single validator (config-driven, pilot),propose_block(transactions)→ Block,commit_block(block).tests/test_block.py,tests/test_ledger.py,tests/test_validator.py— chain integrity, hash determinism, genesis, append/verify.
REQ-311 — Order-matching engine
A limit-order-book matching engine: buy/sell orders with price + size, matched at the best price (price-time priority). Produces match transactions recorded on the chain.
Must-haves:
engine/order_book.py— OrderBook:add_order(order),match_orders()→ list of Match (buyer, seller, price, size).engine/order.py— Order dataclass (id, side, symbol, price, size, timestamp).tests/test_order_book.py— match priority, partial fills, no-match.
REQ-312 — Settlement service
T+1 settlement: matches commit to the chain; a settlement is final when its block is committed. The service reads matches from the order engine, produces settlement transactions, and submits them to the ledger.
Must-haves:
settlement/service.py— SettlementService:settle(match)→ SettlementTransaction,submit(ledger). Idempotent (re-settling a match is a no-op once final).tests/test_settlement.py— happy path, idempotency, finality check.
REQ-313 — Consumer contract.yaml
The consumer repo declares its infrastructure via a contract.yaml at
the repo root, validated against schemas/contract.schema.json. The
contract references the Nova platform's deploy workflow
(uses: acdl/.github/workflows/deploy.yml@v1.25) and declares the
blockchain exchange stack (the AWS resources the app needs: ECS for
the matching engine, DynamoDB for the ledger, S3 for block storage).
The DynamoDB L1 primitive (REQ-322) must land before this contract can
declare dynamodb — ECS + S3 already exist.
Must-haves:
contract.yaml— id, name (blockchain-exchange), environment (dev/qa/prod variants), infrastructure block.contracts/blockchain-exchange.dev.yml,.qa.yml,.prod.yml— per-environment variants (per-env promotion model, REQ-105).tests/test_contract_validates.py— schema validation against the platform'sschemas/contract.schema.json.
REQ-314 — Consumer deploy workflow invocation
The consumer repo's GitHub/Gitea Actions invoke the Nova platform's
reusable deploy.yml@v1.25 workflow with mode: full for the pilot.
The workflow checks out the consumer repo + the platform repo, runs
scripts/run_platform.sh, and records the apply decision + attestation
in the Nova Decision Ledger.
Must-haves:
.github/workflows/deploy.yml—uses: acdl/.github/workflows/deploy.yml@v1.25withwith: { contract: contract.yaml, mode: full, environment: dev }..gitea/workflows/deploy.yml— byte-identical mirror (the platform's deploy workflow is forge-agnostic).tests/test_deploy_workflow_invocation.py— asserts theuses:ref- inputs are correct.
REQ-315 — Settlement-finality kyverno-json policy (IDEATE I6)
A kyverno-json policy asserting that every promotion (qa→prod) requires settlement finality: all matches in the promotion window have committed blocks. This is the securities-specific extension of v1.25's policy engine — it applies Nova's compliance posture to the blockchain domain.
Must-haves:
policies/settlement-finality.json— kyverno-json policy over the settlement-service status JSON (assertsall_committed: true).tests/test_settlement_finality_policy.py— passing + failing fixtures; skip whenkjabsent.
REQ-316 — Pilot-estate regression capability (CAP-025)
A new capability in the regression gate: "pilot estate apply→attest→record
round-trip." The regression gate asserts that the consumer estate can
run end-to-end (contract resolve → adapter compile → terraform plan →
policy scan → confidence signal → attestation → outbox record) against
the live AWS account 581513795199.
Must-haves:
core/regression_verify.pygains CAP-025 (live-pilot-apply).tests/test_regression_pilot.py— the round-trip assertion.
REQ-317 — Outcome-backfill emitter (IDEATE I1)
Wire apply.completed / apply.failed events back into fact_decision
in the cold store so the AI Decision Accuracy metric has a non-pending
outcome. Today fact_decision.outcome is stuck at pending (D-096
blocker). The backfill emitter reads run_manifest.completed/failed
events and updates the corresponding decision's outcome.
Must-haves:
core/metrics/outcome_backfill.py—backfill(decision_id, outcome)updatesfact_decision.outcome+fact_decision.backfilled_at.core/metrics/collector.py— invokes backfill after run completion.tests/test_outcome_backfill.py.
REQ-318 — reason='confidence' escalation tag (IDEATE I2)
Emit a distinct reason='confidence' field on the block band's
ai.decision.made event so the Human Escalation Frequency metric has a
discriminated numerator. Today hitl_block is a boolean from the
manifest; the reason discriminator is not stored.
Must-haves:
core/confidence_signal.py—ai.decision.madegainsescalation_reason: 'confidence'whenband == 'block'.core/metrics/collector.py— persistsescalation_reasonintofact_run.tests/test_confidence_escalation_reason.py.
REQ-319 — Env-JSON state_backend wiring reconciliation (IDEATE I3)
The env JSON's state_backend.bucket field is currently unused by the
adapter (the adapter computes nova-tfstate-<AWS_ACCOUNT_ID> directly).
Reconcile: the adapter reads state_backend.bucket from the env JSON
(falling back to the computed name for backwards compat). This closes
the wiring gap so the pilot's env JSON is the single source of truth.
Must-haves:
adapters/terraform/adapter.py— readsenv.state_backend.bucketwhen present.tests/test_adapter_state_backend.py.core/environments/*.json—state_backend.bucketupdated to the real bucket namenova-tfstate-581513795199-us-east-1.
REQ-320 — Declarative pilot-readiness kyverno-json policy (IDEATE I5)
A kyverno-json policy asserting the env JSON has a non-placeholder
account_id (not 000000000000) before any terraform apply. This is
the declarative gate that prevents a pilot run against a placeholder
account.
Must-haves:
adapters/kyverno-json/policies/pilot-readiness/no-placeholder-account.jsontests/test_pilot_readiness_policy.py.
REQ-321 — Docs + adapter README for the consumer estate
Update adapters/README.md (new consumer row), docs/METRICS.md (the
3 Post-Pilot metrics now grounded post-pilot), .ciagent/ARCHITECTURE.md
(§12.8 — Pilot Estate), and .ciagent/nova-blockchain-exchange/README.md
(consumer onboarding guide).
Must-haves:
adapters/README.md— consumer-repo row.docs/METRICS.md— Post-Pilot metrics grounded note..ciagent/ARCHITECTURE.md— §12.8 Pilot Estate..ciagent/nova-blockchain-exchange/README.md— onboarding guide.
REQ-322 — DynamoDB L1 primitive (platform-side)
The blockchain exchange's ledger table needs a DynamoDB L1 primitive.
Research (RESEARCH §3) confirmed the adapter is stateless/registry-
driven (no TYPE_MAP — deleted in v1.11); a new stack type requires a
new L1 module, not an adapter change. The dynamodb primitive mirrors
the existing s3 / rds primitives: interface.json (stack type
aws:dynamodb:table, inputs table_name/region/pk/sk/billing_mode,
outputs table_arn/table_name), terraform/main.tf
(resource "aws_dynamodb_table" "this"), README.md, instance.json,
- a
registry.jsonentry. The pilot contract'sinfrastructure.dynamodbblock references this primitive. This is the single platform-side module build-out for the milestone (ECS + S3 already exist).
Must-haves:
modules/l1/dynamodb/interface.json— stack typeaws:dynamodb:table, inputs, outputs.modules/l1/dynamodb/terraform/main.tf—resource "aws_dynamodb_table" "this"(PK + optional SK,billing_mode = PAY_PER_REQUESTdefault, encryption + point-in-time- recovery enabled per v1.8 NFR defaults).modules/l1/dynamodb/README.md— module doc.modules/l1/dynamodb/instance.json— sample instance.modules/registry.json—dynamodbentry (kindl1,terraform_dir: modules/l1/dynamodb/terraform).tests/test_adapter.py— adddynamodbtoEXPECTED_L1_KEYS+ a resolution + emission test.modules/README.md— catalog index updated.
Summary
13 requirements (REQ-310..322). Equities-only pilot; minimal PoA ledger;
T+1 settlement; consumer deploy via deploy.yml@v1.25; 3 Post-Pilot
metrics grounded (outcome backfill + escalation reason + pilot runs);
3 kyverno-json policies extending v1.25 (settlement-finality,
pilot-readiness, + the existing meta-policies apply); env-JSON wiring
reconciled; DynamoDB L1 primitive authored (the single platform-side
module build-out — the adapter is stateless/registry-driven, so the
primitive is a new modules/l1/dynamodb/ module + registry entry, not
an adapter change).