2443909362
---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).
10 KiB
10 KiB
CLARIFY — Nova Platform v1.0 (Phase 0)
25 decisions (D-011..D-035) resolving remaining specification ambiguities. Init already locked D-001..D-010. Autonomy: supervised (present + wait for human review).
Architecturally significant (highest impact)
D-011: Resolver purity vs file I/O
resolve() is declared pure (no I/O) in REQ-03 but must load
interface.json / composition data from disk.
- Default: Add
modules_dir: Pathas 3rd param. "No I/O" means no network/side-effects — local file reads for module metadata are permitted. The registry provides paths; the resolver reads the files. - Confidence: 0.82
- Alternatives: [pre-enrich registry inline (truly pure); caller pre-loads interfaces as 4th dict; take contract_path string like ref]
D-012: L2 representation — opaque vs expanded
Does the resolver expand L2 compositions into individual L1 stack resources, or treat L2 as a single opaque resource?
- Default: L2 is a single opaque resource. Stack has one entry:
{module:"microservice", version, source:"modules/l2/microservice/terraform", inputs}. The L2'sterraform/main.tfcomposes L1 internally viamoduleblocks. Resolver does NOT expand children. - Confidence: 0.88
- Alternatives: [keep reference expansion (children/wires, needs richer stack schema — contradicts REQ-04's flat shape); hybrid]
D-013: L2 file naming + registry terraform_dir
REQ-12 says L2 has interface.json (reference uses composition.json).
Reference L2 registry entries omit terraform_dir but the flat stack
needs source.
- Default: L2 uses
interface.json(L2-level inputs/outputs, no children/wires — those are in terraform/main.tf). L2 registry entries DO includeterraform_dir: "modules/l2/<name>/terraform"(deviation from ref L2 entries which omit it — required by flat stacksource).kind: "l2"retained. - Confidence: 0.80
- Alternatives: [keep
composition.jsonname but simplified content; keep ref L2 shape exactly]
Contract / schema details
D-015: Contract field constraints
- Default: Keep ref
idpattern^[a-z][a-z0-9-]{2,5}$,nameminLength:3.versionOPTIONAL (defaults to latest non-deprecated).infrastructure[]items:module(required),version(optional, semver^\d+\.\d+\.\d+$),inputs(required, object,additionalProperties:false). - Confidence: 0.85
D-016: Interpolation ${env.*} / ${contract.*}
- Default: KEEP interpolation. Resolver expands
${env.<field>}and${contract.<field>}after environment_check loads env JSON. Sample contracts use${env.region},${env.account_id}for naming. Unknown tokens raiseValueError. - Confidence: 0.78
D-017: schemas/environment.schema.json — keep or drop?
- Default: KEEP but simplify to match reduced field set (D-018).
Validates
core/environments/*.json. - Confidence: 0.70 (below supervised threshold — escalate)
D-033: Per-env contract variants
- Default: Variants differ ONLY in
environmentfield. All other fields identical. Interpolation resolves per-env at resolver time. - Confidence: 0.85
D-035: index_document input — L1 s3 or L2 static-assets?
- Default:
index_documentis an L2static-assetsinput (passthrough to s3 website config in L2 terraform). L1s3does NOT gain it (stays ref interface:bucket_name/region/kms_key_arn/enabled). - Confidence: 0.80
Resolver / adapter / interface
D-014: L1 interface.json field set
- Default: Keep
name,version,kind,type,description,inputs,outputs,resources(multi-resource array for vpc/ ecs-service/alb). Dropnfrs(feeds confidence signal — OOS) andintra_refs(feeds wire engine — eliminated by D-012). - Confidence: 0.72 (below threshold — escalate)
Environment model
D-018: core/environments/dev.json field set
- Default: Keep
name,description,account_id,region,state_backend(bucket, lock_table),network(vpc_cidr, azs). Droprunner_role_arn(ABAC OOS),autonomy(HITL OOS),confidence_threshold(OOS). - Confidence: 0.80
D-019: environment_check.check() signature
- Default: Use REQ-05 signature:
check(env_name: str, environments_dir: Path) -> dict. RaisesEnvironmentNotFoundError. Drop ref's(ok, message)tuple + onboarding prompt printing. - Confidence: 0.90
Shell scripts
D-020: run_platform.sh stages (policy/confidence/outbox dropped)
- Default:
--check-only(offline): env_check → validate contract → resolve → adapter compiles → validate output structure → print=== PLATFORM CHECK OK ===→ exit 0--plan-only(AWS): above + load creds → terraform init → validate → plan → print=== PLATFORM PLAN OK ===- default (AWS, apply): above +
terraform apply -auto-approve→ print=== PLATFORM APPLY OK === --quiet: suppresses TF streaming.--help: flags.
- Confidence: 0.85
D-021: run_ci.sh Stage 1 py_compile
- Default: Glob:
python3 -m py_compile $(find core/ adapters/ scripts/ -name '*.py'). No hardcoded file list (no OOS Python files exist). - Confidence: 0.82
D-031: run_platform.sh flag set
- Default: Keep only REQ-20's four:
--check-only,--plan-only,--quiet,--help(+-h). Default = apply. Drop--apply,--destroy,--local,--decommission,--deploy-uptime,--environment. - Confidence: 0.87
Terraform / bootstrap
D-022: Bootstrap DynamoDB table
- Default: Dedicated lock table
nova-tfstate-locks(S3 backendlock_tablepoints to it). NOnova-outboxtable (outbox OOS). S3 state bucketnova-tfstate-<account>-<region>with versioning kept. - Confidence: 0.78
D-023: terraform/platform/main.tf content
- Default: ONLY shared platform VPC:
aws_vpc.nova_shared,aws_subnet.nova_shared(count=2), IGW, route table, ECS SG, outputs (vpc_id,subnet_ids,ecs_security_group_id). State backend references. Drop Lambda, DynamoDB contracts, KMS, Secrets, SNS, consumer_invoke_policy — all OOS. - Confidence: 0.83
D-024: terraform/ci-vpc/main.tf role
- Default: Short-lived test VPC for module lifecycle testing (ref
convention preserved). The shared platform VPC lives in
terraform/platform/main.tf(D-023). REQ-16's description was a mischaracterization. - Confidence: 0.86
D-025: Onboarding static-key alternative
- DECISION (human override):
terraform/onboarding/main.tfcreates an IAM ROLE (not a user) with a trust policy allowing the platform's runner user to assume it (cross-account assume role pattern). No OIDC.consumer_repo/owner_idvars kept for tagging. README documents this is dev-only static-key (OIDC is production path, OOS for v1.0). The consumer's CI runner assumes this role viasts assume-roleusing the platform runner's static credentials. - Confidence: 0.72 → locked by human review at 1.0
D-026: IAM runner policy scoping
- Default: Static inline policy
terraform/bootstrap/ spike_runner_policy.jsonscoped to platform account+region, granting Terraform-deployable resource permissions. NOT ABAC-scoped. Account ID parameterized via variable (not hardcoded). Attached tonova-spike-runneruser bycreate_iam_user.py. - Confidence: 0.75
Python packaging / naming / docs / tests
D-027: pyproject.toml — CLI package or scripts only?
- Default: No CLI package.
pyproject.tomlconfigures pytest + py_compile + project metadata. No[project.scripts]. Nonova/package dir. Invoked via shell scripts. Python modules run as scripts. - Confidence: 0.85
D-028: docs/modules/ layout
- Default:
docs/modules/index.md(catalog table linking tomodules/l1/<name>/README.mdandmodules/l2/<name>/README.md). Per-module docs live inmodules/, notdocs/modules/. Mirrors ref exactly. - Confidence: 0.82
D-029: modules/STANDARDS.md + README-TEMPLATE.md
- Default: Keep
modules/README.md(REQ-13, trimmed of security/attestation). Keepmodules/README-TEMPLATE.md(per-module template). Dropmodules/STANDARDS.md(673 lines, mostly security/compliance/attestation — OOS). - Confidence: 0.75
D-030: moto usage in tests
- Default: moto pinned in requirements-test.txt (REQ-31) but used minimally. Check-only is offline (no AWS). Most tests are pure (resolver, adapter, schemas). moto kept for future AWS-touching tests. If unused, harmless pinned dep.
- Confidence: 0.68 (below threshold — escalate)
D-032: NOVA_* env var naming
- Default: Keep
NOVA_*prefix:NOVA_AWS_ACCESS_KEY_ID,NOVA_AWS_SECRET_ACCESS_KEY,NOVA_BOOTSTRAP_AWS_*,NOVA_FORGE_TOKEN..env.secretsusesNOVA_AWS_*keys.run_platform.shcopiesNOVA_AWS_*toAWS_*env vars. - Confidence: 0.88
D-034: Engine-boundary test (REQ-09) file scope
- Default: Scan
.pyfiles only (incore/,schemas/,contracts/,tests/,scripts/, root). Excludeadapters/terraform/(the boundary),modules/,.tf,.md,.jsonin modules/envs (data files withterraform_dirpaths — not engine logic). - Confidence: 0.83
Grill fixes (D-037, D-038 — locked from GRILL.md conditions)
D-037: Resolver-source / engine-boundary / adapter-signature (C-1 fix)
- DECISION (human-locked): Match the reference design. Drop
sourcefromstack.schema.json(REQ-04). Changeadapt(stack, modules_dir)→adapt(stack, repo_root)(REQ-07). The adapter loadsregistry.jsoninternally to mapmodule→terraform_dir— this happens inside the engine boundary (adapters/terraform/), so it's permitted. The resolver never writes Terraform paths into the stack. Stack is engine-agnostic:{contract_id, contract_name, environment, resources: [{module, version, inputs}]}. Side effect (C-4): P2 (adapter) gains a dependency on P3-W1 (registry.json) — reorder P3-W1 before P2-W1. - Confidence: 1.0 (human-locked grill fix)
- Alternatives: [keep
source+ relax boundary test (fragile); rename tomodule_path(doesn't fix the substring match)]
D-038: L2 child set (C-2 fix)
- DECISION (human-locked): Lock the ARCHITECTURE.md compositions as
D-036.
microservice= vpc + ecs-cluster + ecs-service + iam-role + ecr + alb (6 L1s).static-assets= s3 + cloudfront + kms-key (3 L1s, drops waf from reference). These are fresh compositions under the opaque L2 model (D-012) — not reference mirrors. - Confidence: 1.0 (human-locked grill fix)
- Alternatives: [match reference children exactly (microservice no vpc, static-assets keeps waf); microservice + kms (7 L1s)]