# 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. |