# 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.
```mermaid
flowchart LR
A["your repo
(app code + contract)"] -->|run_platform.sh| B
B["platform
(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](environments/index.md).
- **AWS credentials** for the target environment, in `.ciagent/.env.secrets`
(gitignored) using the `NOVA_AWS_*` prefix. See the
[platform README](../README.md#credentials) and
[`terraform/bootstrap/README.md`](../terraform/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:
```yaml
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:
```yaml
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](environments/index.md). |
| `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](modules/index.md) for the full list, or read the module's
own README under `modules/l1//` or `modules/l2//`.
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
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](../README.md#credentials)):
```bash
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
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_name` input, 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//README.md` or `modules/l2//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:
```bash
aws s3 sync ./assets s3:///
```
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/](modules/index.md) | 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//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/](environments/index.md) | 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. |