---ci--- project: nova-platform milestone: v1.0 status: complete requirements: covered: [REQ-01,REQ-02,REQ-03,REQ-04,REQ-05,REQ-06,REQ-07,REQ-08,REQ-09,REQ-10,REQ-11,REQ-12,REQ-13,REQ-14,REQ-15,REQ-16,REQ-17,REQ-18,REQ-19,REQ-20,REQ-21,REQ-22,REQ-23,REQ-24,REQ-25,REQ-26,REQ-27,REQ-28,REQ-29,REQ-30,REQ-31,REQ-32,REQ-33,REQ-34,REQ-35,REQ-36,REQ-37,REQ-38] partial: [] ---/ci--- v1.0 milestone complete: simplified infrastructure-delivery platform derived from Nova (acdl). 6 phases (P0-P5 + P6 final). 38 REQ-IDs. 38 decisions (D-001..D-038). 76 tests pass. Engine boundary holds. Happy paths green (check-only + CI). 13 L1 + 2 L2 modules. 5 terraform roots. Shell reproducibility. Zero OOS files. Tags: v0.1.0 (P0) → v0.1.1..v0.1.5 (P1..P5) → v0.1.6 (P6 = milestone release on v0.1 patch line).
8.0 KiB
Consumer Guide — Declare intent, deploy to AWS
This guide walks a consumer through creating a repo, writing a contract,
validating it offline, and running it against AWS. It is generic across
all modules in the registry; static-assets is the worked example, but
every step applies to microservice and any future module.
The model
You write a contract YAML file and the platform does the rest. Your repository contains only your application code and your contracts. You do not write infrastructure modules or adapter code.
flowchart LR
A["your repo<br/>(app code + contract)"] -->|run_platform.sh| B
B["platform<br/>(resolver + adapter + modules)"] -->|contract -> stack -> terraform -> apply| C
C["your resources in AWS"]
Prerequisites
- A consumer repository for your application code + contract.
- A platform-managed environment bound to your repo. The platform team provisions the AWS account, network, and state backend. See Environments.
- AWS credentials for the target environment, in
.ciagent/.env.secrets(gitignored) using theNOVA_AWS_*prefix. See the platform README andterraform/bootstrap/README.md.
Step 1 — Create a consumer repo
Create a repository for your application. The top level holds your app
code; your contract lives at the repo root (or wherever you point
run_platform.sh). Example for a static site:
my-static-site/
index.html
assets/
style.css
logo.png
contract.yml
Example for a microservice:
my-microservice/
app.py
Dockerfile
contract.yml
Step 2 — Define the contract
Write contract.yml. The static-assets example:
id: stsi
name: Static Assets Site
environment: dev
infrastructure:
- module: static-assets
version: "1.0.0"
inputs:
bucket_name: "${env.environment}-${contract.id}-assets"
index_document: index.html
A microservice example:
id: msvc
name: Microservice
environment: dev
infrastructure:
- module: microservice
version: "1.0.0"
inputs:
service_name: "${env.environment}-${contract.id}-svc"
desired_count: 2
Contract fields
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Short operational acronym (^[a-z][a-z0-9-]{2,5}$, 3-6 chars). Becomes the stack name used for the Terraform state key and resource naming prefix. Stable across deploys and environment promotions. |
name |
string | yes | Full human-readable stack name (min 3 chars). |
environment |
string | yes | The platform-managed environment to deploy to (dev/qa/prod/dr). See Environments. |
infrastructure |
array | yes | Array of modules to deploy (D-015). Each entry carries a module name (matching a registry key), an optional version (defaults to latest non-deprecated), and required inputs. One entry = single-module deploy; N entries = multi-module manifest. |
Infrastructure item fields
| Field | Type | Required | Description |
|---|---|---|---|
module |
string | yes | Module name from modules/registry.json (^[a-z][a-z0-9-]*$). |
version |
string | no | Semver pin X.Y.Z. Omitted = latest non-deprecated version. |
inputs |
object | yes | Module-specific inputs (see the module's README). No aws_* keys — the contract is engine-agnostic. |
Each module declares its inputs in its interface.json. Consult the
module catalog for the full list, or read the module's
own README under modules/l1/<name>/ or modules/l2/<name>/.
The contract is validated against schemas/contract.schema.json. An invalid
contract (missing field, unknown module, wrong type) fails at the
validate-contract stage with a clear error.
Interpolation reference (D-016)
The resolver expands ${env.*} and ${contract.*} tokens after the
environment is loaded. Unknown tokens raise ValueError (fail loud).
Expansion is recursive (nested map/list values expand too).
| Token | Resolves to | Example |
|---|---|---|
${env.name} |
the environment name | dev |
${env.region} |
the environment's AWS region | us-east-1 |
${env.account_id} |
the environment's AWS account id | 000000000000 |
${env.state_backend.bucket} |
the environment's state bucket | nova-tfstate-dev-us-east-1 |
${env.state_backend.lock_table} |
the environment's lock table | nova-tfstate-locks |
${env.network.vpc_cidr} |
the environment's VPC CIDR | 10.0.0.0/16 |
${contract.id} |
the contract's operational acronym | stsi |
${contract.name} |
the contract's name field | Static Assets Site |
${contract.environment} |
the contract's environment field | dev |
Step 3 — Validate offline (no AWS required)
Before touching AWS, validate the contract end-to-end offline. Clone the
Nova Platform repo and run --check-only against your contract:
bash scripts/run_platform.sh --check-only path/to/your/contract.yml
# Expected: "=== PLATFORM CHECK OK ==="
This runs: environment check → contract schema validation → resolve to stack → adapter compiles to HCL → output structure validation. No AWS credentials are needed.
Step 4 — Run against live AWS
Once the contract validates offline, run the full pipeline against AWS.
Ensure your credentials are in .ciagent/.env.secrets (see
Credentials):
bash scripts/run_platform.sh contracts/static-assets.yml
# Expected: "=== PLATFORM APPLY OK ==="
The full path: environment check → validate contract → resolve to stack →
adapter compiles to HCL → load AWS credentials → terraform init →
terraform validate → terraform plan → terraform apply -auto-approve.
To stop before apply (review the plan only):
bash scripts/run_platform.sh --plan-only contracts/static-assets.yml
# Expected: "=== PLATFORM PLAN OK ==="
Step 5 — What gets created
After a successful dev run, the resources declared by your module's
pattern exist in your AWS account.
For the static-assets example (s3 + cloudfront + kms-key, D-038):
- An S3 bucket (named via your
bucket_nameinput, interpolation expanded) with versioning enabled. - A CloudFront distribution with the S3 bucket as the origin.
- A KMS key for SSE.
For other modules, consult the module's README
(modules/l1/<name>/README.md or modules/l2/<name>/README.md) for the
exact resources created.
Step 6 — Upload your content (static-assets example)
The platform provisions the infrastructure; you upload your content. For the
static-assets module:
aws s3 sync ./assets s3://<your-bucket-name>/
For a microservice, the platform provisions the ECS service and ALB; you
push your container image to the ECR repo the platform created.
Reference
| Resource | Path | Description |
|---|---|---|
| Contract schema | schemas/contract.schema.json |
JSON Schema for consumer contracts. |
| Stack schema | schemas/stack.schema.json |
JSON Schema for the resolved stack instance. |
| Module catalog | modules/ | All primitives and modules. |
| Sample contract | contracts/static-assets.yml |
The reference example contract. |
| Sample contract | contracts/microservice.yml |
The microservice example contract. |
| Module examples | modules/<name>/examples/ |
Validated per-module example contracts. |
| Contract resolver | core/contract_resolver.py |
Resolves contracts to stack instances. |
| Terraform adapter | adapters/terraform/adapter.py |
Compiles stack instances to Terraform. |
| Pipeline runner | scripts/run_platform.sh |
The pipeline runner. |
| Environments | environments/ | Platform-managed environments. |
| Platform README | README.md |
How the platform works + how to run it. |
| Credentials | README.md#credentials |
The static-key model + bootstrap runbook. |