# nova-blockchain-exchange — Consumer Onboarding Guide

> **Milestone:** v1.26 — the first real Nova consumer estate. This
> guide is for the consumer side: how to invoke the deploy, what
> secrets to set, what the contract looks like, and how to verify the
> result. The platform side is documented in
> `.ciagent/ARCHITECTURE.md` §12.8; the live-pilot evidence is in
> `.ciagent/archive/P4-PILOT-RUN-EVIDENCE-v1.26.md` (archived v1.27).

This is a **consumer** of the Nova platform, not a fork. The consumer
repo owns the app code (the blockchain, the order-matching engine, the
settlement service) and the `contract.yaml` that declares the
infrastructure. The Nova platform (`acdl` repo) owns the deploy
workflow, the policy engine, the contract resolver, the Terraform
adapter, the confidence signal, the HITL gates, and the Decision
Ledger. The consumer never clones the platform repo and never runs
`terraform apply` directly.

---

## 1. Invoke the deploy

The consumer's `.github/workflows/deploy.yml` (and its
`.gitea/workflows/deploy.yml` mirror) is a `workflow_dispatch` workflow.
It does **not** use cross-repo `uses:` (SPEC §10 Q1 — the Gitea forge
rejects it). Instead it is an **inline adapter**: it checks out the
consumer repo, then checks out `acdl/acdl` @ `ref: v1.29` (bumped from
`v1.25` at v1.29 P5, REQ-CONSUMER-BUMP) into `platform/`, then runs
`bash platform/scripts/run_platform.sh`.

To run a deploy:

1. In the consumer repo's Actions UI, pick the **Deploy** workflow.
2. Click **Run workflow**.
3. Inputs:
   - `mode` = `full` (the default — applies the Terraform). Other
     values: `plan-only` (no apply), `check-only` (policy + confidence
     only), `decommission` (requires a `changeRequestId`).
   - `environment` = `dev` (the pilot scope — equities only, dev only,
     D-020/D-200). Leave empty to use the contract's `environment`
     field.
4. The workflow runs the platform pipeline end-to-end: contract
   resolve → adapter compile → terraform plan → policy (kyverno-json)
   → confidence signal → (dev: autonomous apply) → Decision Ledger
   events.

For the pilot, the documented invocation is `mode=full,
environment=dev`. The first live run was `blkex-pilot-apply-v0.2`
(2026-08-19).

---

## 2. Secrets to set

Set these in the forge's Actions secret store (the consumer repo's
"Secrets and variables → Actions" page). The platform-managed
scheduled workflow `rotate-aws-key.yml` rotates the `NOVA_AWS_*` key
daily (SPEC §5.9 — the v0.2 deploy uses the currently-active key).

| Secret | Purpose |
| --- | --- |
| `NOVA_AWS_ACCESS_KEY_ID` | The static AWS access key for the deploy IAM principal. Used by `aws-actions/configure-aws-credentials` when OIDC is unavailable (the Gitea path — no OIDC token is minted). |
| `NOVA_AWS_SECRET_ACCESS_KEY` | The matching secret key. Rotated by `workflows-src/rotate-aws-key.yml`. |
| `AWS_DEFAULT_REGION` | The target region (`us-east-1` for the pilot). |

The platform's `.github/workflows/deploy.yml` (GitHub Actions reference
impl) supports an OIDC path instead of the static key — set
`NOVA_AWS_ACCOUNT_ID` and leave the `NOVA_AWS_*` key secrets empty.
The Gitea inline adapter uses the static-key path.

---

## 3. The contract shape

The consumer declares its infrastructure in `contract.yaml` at the
repo root, validated against the platform's
`schemas/contract.schema.json`. The pilot contract has the shape:

```yaml
id: blkex
name: blockchain-exchange
environment: dev
infrastructure:
  microservice:   # the L2 composition (ECS Fargate + ALB + roles)
    ...
  dynamodb:       # the L1 DynamoDB table (the ledger)
    ...
  s3:             # the L1 S3 bucket (block storage)
    ...
```

Three `infrastructure.*` blocks: `microservice` (the L2 composition
that wires the ECS service, the ALB, and the IAM roles together), and
the two L1 primitives (`dynamodb` for the ledger, `s3` for block
storage). Per-environment variants live in
`contracts/blockchain-exchange.{dev,qa,prod}.yml` (the per-env
promotion model, REQ-105). The pilot runs the `dev` variant.

The contract is the **only** consumer-facing artifact that describes
infrastructure. It is IR-typed (engine-agnostic); the platform
resolves it to a target stack, the Terraform adapter compiles the
stack to HCL, and `terraform apply` runs in the central pipeline —
never on the consumer's workstation.

---

## 4. What the platform does

When `run_platform.sh` runs against `contract.yaml`:

1. **Resolve** the contract to a target stack (a list of L1 instances +
   inputs + relationships), reading `modules/registry.json` for each
   L1's `terraform_dir`.
2. **Compile** the stack to Terraform HCL via the stateless adapter
   (`adapters/terraform/adapter.py`) — emits `module "<rid>" { source }
   ` blocks + wired `ref:` refs. No `TYPE_MAP` — each L1 owns its
   shape.
3. **Plan** — `terraform plan` against the live AWS account. Infracost
   runs on the plan JSON and emits `nova.cost.estimated`.
4. **Policy** — the kyverno-json engine evaluates the meta-policies
   (`block-on-any-critical` + the pilot policies) and emits
   `PolicyCheckResult` records.
5. **Confidence** — the confidence signal consumes the six inputs (the
   PCRs included) and emits `nova.confidence.computed` with
   `{ score, band, perInput, reasonCodes }`. Dev threshold = 0.50.
6. **Apply** (dev, autonomous — no HITL gate) — `terraform apply`
   against account `581513795199`. On success, `nova.ai.decision.made`
   + `nova.run.completed` land in the Decision Ledger.
7. **Backfill** — the outcome (`pending → succeeded`) is backfilled
   (REQ-317), producing `nova.outcome.backfilled`. The SQLite
   hash-chain is extended, not torn up.

The consumer does not see steps 1–7 directly; the consumer sees the
workflow's green check + the uploaded artifacts (`nova-terraform`,
`nova-platform-log`).

---

## 5. How to verify post-deploy

Two independent verifications — read the AWS API and read the Decision
Ledger. Neither trusts the other.

**AWS API (the infrastructure landed):**
- `aws elbv2 describe-load-balancers` — the ALB
  (`app-254671247.us-east-1.elb.amazonaws.com` for the pilot).
- `aws ecs describe-services --cluster nova-cluster --services
  nova-microservice` — the ECS service is `ACTIVE`.
- `aws dynamodb describe-table --table-name nova-blkex-ledger-dev` —
  the ledger table exists (PK `block_index`, PAY_PER_REQUEST).
- `aws s3api head-bucket --bucket
  nova-blkex-blocks-dev-581513795199-us-east-1` — the block bucket
  exists (versioning + SSE).

**Decision Ledger (the trust record):**
- The SQLite hash-chain at `metrics/decision_ledger.db` has the
  `nova.ai.decision.made` row for `blkex-pilot-apply-v0.2` (chosen
  action `pass`, `human_override` false) + the
  `nova.outcome.backfilled` row (outcome `pending → succeeded`).
- The chain is valid (`prev_event_hash` links, 0 breaks). The
  Trust Snapshot (`metrics/TRUST_SNAPSHOT.md`) records the verdict.

If the AWS API shows the resources AND the Decision Ledger shows the
decision + outcome with a valid chain, the deploy is verified. See
`.ciagent/archive/P4-PILOT-RUN-EVIDENCE-v1.26.md` for the full pilot-evidence
checklist (every ARN, the confidence JSON, the backfill timestamp; archived v1.27).

---

## References

- `.ciagent/ARCHITECTURE.md` §12.8 — the pilot-estate architecture
  (this guide is the consumer-facing companion to that section).
- `.ciagent/archive/P4-PILOT-RUN-EVIDENCE-v1.26.md` — the live-pilot evidence
  (run `blkex-pilot-apply-v0.2`; archived v1.27).
- `.ciagent/nova-blockchain-exchange/PROJECT.md` — the consumer
  project charter (vision, scope, decisions D-200..D-205).
- `.ciagent/nova-blockchain-exchange/REQUIREMENTS.md` — the consumer
  requirements (REQ-313 contract, REQ-314 deploy invocation).
- `adapters/README.md` §Consumers — the Gitea adapter note
  (SPEC §10 Q1 — inline checkout-then-call, no cross-repo `uses:`).