---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).
5.8 KiB
Architecture
Status: v1.0 (current). This document mirrors
.ciagent/ARCHITECTURE.md. Where the two conflict,.ciagent/ARCHITECTURE.mdwins.
0. Purpose
Nova Platform is the infrastructure-delivery core. A consumer declares intent in a YAML contract; the platform resolves it to a stack, compiles it through the Terraform adapter, and applies it. The DevSecOps, identity, audit-ledger, and central CI-pipeline-contract machinery of the Nova reference are intentionally removed — see the OOS list below.
1. Layers (4)
┌──────────────────────────────────────────────────────┐
│ 1. Contract Surface schemas/contract.schema.json
│ contracts/*.yml (samples)
├──────────────────────────────────────────────────────┤
│ 2. Resolution core/contract_resolver.py
│ core/environment_check.py
│ schemas/stack.schema.json
├──────────────────────────────────────────────────────┤
│ 3. Engine Adapter adapters/terraform/ (the only
│ (only engine-specific) engine-specific code)
├──────────────────────────────────────────────────────┤
│ 4. Apply terraform/ (bootstrap, modules)
│ scripts/run_platform.sh
└──────────────────────────────────────────────────────┘
Layer 1 — Contract Surface
A consumer writes a small YAML contract. The infrastructure field is an
array (D-015), not a map:
id: stsi
name: My Static Site
environment: dev
infrastructure:
- module: static-assets
version: "1.0.0"
inputs:
bucket_name: my-static-site-assets
index_document: index.html
Validated against schemas/contract.schema.json. The contract is the only
consumer-facing surface. It is engine-agnostic — no aws_* terms.
Layer 2 — Resolution
core/contract_resolver.py resolves a validated contract to a Stack
instance (a typed structure conforming to schemas/stack.schema.json).
Resolution is pure: contract in, stack out. No I/O beyond local file reads
for module metadata (D-011). No engine terms.
core/environment_check.py validates that the named environment exists in
core/environments/*.json and returns its definition. Environments are
platform-managed (consumers provide no AWS account, VPC, or state bucket).
Interpolation (D-016): the resolver expands ${env.<field>} and
${contract.<field>} tokens after the environment is loaded. Unknown tokens
raise ValueError.
Layer 3 — Engine Adapter
adapters/terraform/ is the only engine-specific code. It takes a Stack
and emits Terraform (module "x" { source = "../../modules/..." } blocks).
The adapter is a stateless assembler — lifecycle ownership belongs to
Terraform via the shell orchestrator. This is the only place aws_* /
Terraform terms appear.
Layer 4 — Apply
scripts/run_platform.sh orchestrates: contract → resolve → adapter →
terraform init → terraform plan → terraform apply. Modes (D-031):
--check-only (offline, structure validation), --plan-only (no apply),
full (apply). --quiet suppresses streaming.
2. Engine Boundary (Enforced)
The engine boundary is strict. Code outside adapters/terraform/ MUST NOT
contain engine-specific terms (aws_s3_bucket, aws_*, Terraform HCL).
This invariant is verified by tests (tests/test_engine_boundary.py,
scope per D-034: .py files in core/, schemas/, contracts/,
tests/, scripts/, root — excluding adapters/terraform/, modules/,
.tf/.md/.json data files).
3. What is NOT here (intentionally removed vs the reference)
Nova Platform is a simplified, infrastructure-only platform. The following reference features are out of scope for v1.0:
- No confidence signal — no score gating apply.
- No audit outbox — no hash-chained evidence events.
- No policy engine / policy adapter — no policy checks.
- No identity layer, no attribute-based authorization, no human-in-the-loop approval gates.
- No reusable CI workflow — local shell only (
scripts/run_ci.sh). - No central pipeline contract — no
pipelines/directory. - No platform telemetry / metrics.
- No decommission transform, env-transition transform, or onboarding flow beyond bootstrap.
- No leadership decks or slide rendering.
4. Module Catalog
L1 primitives (single resources) + L2 patterns (composites of primitives).
Each module has an interface.json (inputs/outputs, no engine terms) and a
terraform/ directory. modules/registry.json indexes every module +
version.
L1 (primitives — 13): s3, vpc, ecs-cluster, ecs-service,
iam-role, alb, ecr, cloudfront, waf, rds, kms-key,
dynamodb, uptime.
L2 (patterns — 2):
| Module | Composes (D-038) | Description |
|---|---|---|
microservice |
vpc + ecs-cluster + ecs-service + iam-role + ecr + alb (6 L1s) | Container microservice with a public ALB |
static-assets |
s3 + cloudfront + kms-key (3 L1s) | Static site fronted by CloudFront |
L2 modules are opaque stack entries (D-012): the resolver does not expand
their children. The L2's terraform/main.tf composes L1 modules internally
via module blocks. See docs/modules/index.md for the
full catalog and each module's README.