Files
acdl/.ciagent/ROADMAP.md
T
Jon Chery bee9d02f01 feat(P40): contract interpolation + environment JSON schema
---ci---
project: acdl
phase: 40
milestone: v1.9
status: execute
---/ci---

Phase 40 — contract-interpolation (REQ-103, REQ-104, D-081):

Interpolation:
- core/contract_resolver.py: _expand_vars(value, context) recursively
  expands ${env.<field>} + ${contract.<field>} tokens (dotted paths
  supported, e.g. ${env.state_backend.bucket}). Unknown tokens raise
  ValueError (fail loud). Expansion is post-schema-validation,
  pre-IR-resolution.
- resolve() accepts environment_override (D-088) — overrides the
  contract's environment field BEFORE schema validation so interpolation
  context is consistent.
- env context loaded via _load_env (self-contained, works as script +
  package import); 'environment' alias for env 'name' so
  ${env.environment} resolves.

Environment schema + bindings:
- schemas/environment.schema.json (draft 2020-12): name, account_id,
  region, state_backend, network, runner_role_arn, autonomy, confidence_threshold.
- core/environments/qa.json, prod.json, dr.json placeholder bindings
  (attested, thresholds 0.75/0.90/0.95, placeholder account_id with
  stderr warning at load).
- core/environment_check.py: load(env_name) helper + placeholder warning.

Sample contracts:
- contracts/static-assets.yaml + microservice.yaml use
  acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}
  naming pattern (region + account id + environment).

Tests: +35 (test_environment_schema.py, test_interpolation.py,
test_sample_contracts_interpolate.py). 406 passed; run_ci.sh green;
run_platform.sh --check-only green. Existing fixture-based tests
preserved (instance.json static fixtures unaffected).
2026-07-23 04:30:30 +00:00

56 KiB
Raw Blame History

ACDL — Roadmap

Overview

  • v1.0 (demo): complete — tag v1.1.0, 2026-07-21. All 5 phases shipped + audited PASS.
  • v1.1 (complete): architecture finalization + v1 spike. 5 phases (0610). Tag v1.2.0, 2026-07-21. All 5 phases shipped + verified; review READY TO SHIP (0 P0); audit CLEAN. Gitea release id 202.
  • v1.2 (complete): platform hardening + first real consumer deployment. 6 phases (1116). Tag v1.3.0, 2026-07-21. All 6 phases shipped + verified; review READY TO SHIP (1 P0 operator action, 1 P1 deferred); audit CLEAN.
  • v1.3 (complete): module documentation + thin-composition removal. The L2 composition layer is removed; module READMEs are built out. Tag v1.3.2.
  • v1.4 (complete): central pipeline contract + shell reproducibility + output streaming. A declarative pipeline contract (schemas/pipeline.schema.json + pipelines/ci.yaml) binds the Gitea and GitHub workflows to a single source of truth. scripts/run_ci.sh mirrors the CI pipeline locally. scripts/run_platform.sh streams terraform/checkov output by default.
  • v1.5 (complete, tag v1.5.0): consumer happy path + zero-trust docs + reusable deploy workflow. README rewritten so the consumer model is unambiguous (consumer owns only contract + app code; the rest is the platform source). Platform-flow + consumer-guide diagrams converted to mermaid. Legacy surface + implementation nomenclature removed from docs. Credentials section rewritten for zero-trust OIDC + ABAC (with a static-key override + daily rotation). A generic docs/CONSUMER_GUIDE.md (all L2 modules, versioned uses:, consumer-scoped prereqs, run-time platform fetch) replaces the module-specific guide. A byte-identical reusable deploy.yml workflow (Gitea + GitHub) implements pipelines/deploy.yaml and is invoked by consumer repos via a versioned tag.
  • v1.6 (complete, tag v1.6.0): consumer-facing docs restructure + terminology normalization + environments concept. docs/ becomes a Jekyll-style GitHub Pages site. acdl_platform/ is renamed to core/. L2 → "modules", L1 → "primitives", "composition" → "pattern" in prose. README restructured: Features + Roadmap (no internal status), repository roles restated (consumer = app code + contracts + CI definitions), mermaid fixed (visible text, security-checks + infrastructure-apply stages, no tool names), credentials section minus go-gitea/waivers. Platform-managed environments concept + a minimal onboarding scaffold. .ciagent/ + .gitea/ references removed from all consumer-facing docs.
  • v1.7 (complete, tag v1.7.0): production platform + contract ingestion + pipeline maturation. Rename static-assetsstatic-assets (D-048 — incl. .ciagent/ historical narrative). Author cloudfront + waf primitives; augment static-assets to a production-ready S3 + CloudFront (OAC) + WAF stack (D-049). Tagging-standard enforcement (Checkov custom rule, D-043 closure, D-054). Wiz adapter stub (D-052) + Kyverno K8s-native adapter (D-053). Platform Lambda + DynamoDB acdl-contracts table for contract ingestion (D-051) + cross-account IAM. Deploy outputs via SSM SecureString + GitHub PR comment (D-050). Uniform error reporting via the Lambda report_error action → GitHub issue on the platform repo (D-055); Gitea excluded. Stage comments after every successful pipeline stage. Three platform pipelines (platform-test unit+integration, primitives-plan, patterns-plan). Release job with semver + MAJOR.MINOR/MAJOR tag maintenance (D-057). uses:/ref: bumped to @v1.6; floating v1.6 + v1 tags created in Phase 22. Remove the legacy consumer-repos directory (a v1.2 artifact, removed in v1.7); add validated per-module examples (modules/<name>/examples/, D-058) including a new RDS primitive demonstrating multi-engine variation (D-059).
  • v1.8 (complete, tag v1.8.0): P1 remediation + uptime monitoring + engineering standards + encryption/deletion-protection by default + decommission alias + path documentation. Clears 8 pending P1 issues (P1-3..P1-9 + S1). Adds per-stack CMK + encryption-by-default for all primitives. Adds deletion-protection-by-default + L2 feature flag. Adds uptime-kuma primitive (ECS Fargate, deployed by default after L2, separate state, feature flag, alert channels). Adds decommission mode (2-step pipeline with HITL SRE gates + CMDB-validated change request). Adds modules/STANDARDS.md (L1+L2 authoring + review standards). Adds schemas/README.md, pipelines/README.md, adapters/README.md.
  • v1.0 demo URL: https://git.cloudinit.dev/continuous-intelligence/acdl-evidence/raw/branch/main/index.html

v1.0 (Prior — the demo, complete)

Five-phase breakdown that took ACDL from empty repo to a reproducible 4-act executive demo. Milestone v1.0-initial covered the full demo build. Each phase produced a runnable increment and ended with a phase-completion commit

  • tag. All phases complete; demo archived to demo/ in v1.1 Phase 06.

Phases

Phase 01 — repo-scaffolding

  • Description: Create the three repos under continuous-intelligence (acdl-contracts, acdl-evidence; acdl already exists), seed directory layouts, configure Pages on acdl-evidence, add environment protection for qa and prod on acdl-contracts.
  • Status: complete (v1.0.1)
  • Depends on:
  • Requirements: REQ-01, REQ-09, REQ-10
  • Success Criteria:
    • acdl-contracts and acdl-evidence exist and are pushable.
    • acdl-evidence Pages returns 200 with placeholder index.html.
    • qa and prod environments exist on acdl-contracts.

Phase 02 — l1-modules

  • Description: Create all 8 L1 module folders under acdl/modules/l1/, each with manifest.yaml (declared inputs) and mock_apply.sh (uniform echo + 1s sleep + exit 0).
  • Status: complete (v1.0.2)
  • Depends on: [1]
  • Requirements: REQ-02, REQ-03
  • Success Criteria:
    • All 8 L1s present; mock_apply.sh runs and exits 0 for each.
    • manifest.yaml validates against the L1 schema.

Phase 03 — l2-modules-and-core-scripts

  • Description: Create the 4 L2 compositions under acdl/modules/l2/ referencing L1s, plus the 5 core scripts in acdl/scripts/ (mock_executor.sh, policy_checker.py, confidence_signal.py, evidence_writer.py, l3b_agent_stub.py).
  • Status: complete (v1.0.3)
  • Depends on: [2]
  • Requirements: REQ-04, REQ-05, REQ-06, REQ-07
  • Success Criteria:
    • mock_executor.sh applies each L1 in an L2 and writes state.json.
    • policy_checker.py fails on public-ingress: true with POLICY_VIOLATION:PUBLIC_INGRESS.
    • confidence_signal.py returns 0.90 (pass) / 0.40 (fail).
    • evidence_writer.py appends an event with a valid hash chain.
    • l3b_agent_stub.py maps the Act 3 example issue to l2-commodity-price-feed.

Phase 04 — pipeline-and-approval-gates

  • Description: Build the reusable pipeline workflow in acdl/.gitea/workflows/ (Dev → QA → Prod → Finalize) plus the issue-triggered L3B workflow in acdl-contracts/.gitea/workflows/. Wire environment protection for QA and Prod.
  • Status: complete (v1.0.4)
  • Depends on: [3]
  • Requirements: REQ-08, REQ-09, REQ-10, REQ-12
  • Success Criteria:
    • Pushing a valid contract.yaml runs Dev automatically and pauses at QA.
    • Approving QA moves to Prod; approving Prod finalizes.
    • Opening an Issue with the Act 3 text generates a contract.yaml commit and triggers the pipeline.

Phase 05 — evidence-ui-and-demo-dry-run

  • Description: Build index.html (vanilla JS, fetches audit.json, renders timeline) and run all four acts end-to-end as a dry run.
  • Status: complete (v1.0.5)
  • Depends on: [4]
  • Requirements: REQ-11, REQ-13, REQ-14, REQ-15
  • Success Criteria:
    • Pages timeline renders events from audit.json.
    • Act 2: valid contract passes through all gates; timeline shows the full flow.
    • Act 3: Issue text produces the expected l2-commodity-price-feed contract and triggers the pipeline.
    • Act 4: malicious public-ingress: true contract halts in Dev with confidence < 0.50 and a visible rejection reason on the timeline.

v1.1 (Complete — architecture finalization + v1 spike, 2026-07-21, tag v1.2.0)

Five-phase breakdown to finalize the architecture to v1.0 and prove the locked commitments with one end-to-end implementation spike. Milestone v1.1-spike covered the real platform's first materialization. Ship tag at milestone COMPLETE: v1.2.0 (feature milestone, next minor per ship.md). Status: COMPLETE — all 5 phases shipped (v1.1.1..v1.1.5) + verified; review READY TO SHIP (0 P0); audit CLEAN; Gitea release id 202. D-034 closed (root key deactivated by user).

Phase 06 — archive-demo-and-reorient

  • Description: Move the v1.0 demo (modules/, scripts/, evidence-ui/, contracts/, demo .gitea/workflows/) to demo/. Establish the new repo layout (platform/, schemas/, adapters/, terraform/, modules-ir/). Rewrite README to reflect the real platform. Verify the demo still runs from demo/ (regression check).
  • Status: complete (v1.1.1)
  • Depends on:
  • Requirements: (no new REQ; repo hygiene)
  • Success Criteria:
    • demo/ contains the full v1.0 demo; demo/scripts/run_demo.sh --no-upload still exits 0.
    • New top-level dirs exist and are empty-but-scaffolded: platform/, schemas/, adapters/, terraform/, modules-ir/.
    • README reflects the real platform (vision + architecture links, new layout).

Phase 07 — architecture-v1-finalization

  • Description: Resolve the 11 open decisions in docs/architecture.md §13 (already recorded in PROJECT.md). Author the locked schemas + designs: schemas/ir.schema.json (REQ-17), schemas/policy_check_result.schema.json (REQ-18), schemas/contract.schema.json (REQ-22), platform/confidence_signal.py spec (REQ-19), platform/audit_ledger_design.md (REQ-20), platform/hitl_matrix_design.md (REQ-21). Mark architecture v1.0.
  • Status: complete (v1.1.2)
  • Depends on: [06]
  • Requirements: REQ-16, REQ-17, REQ-18, REQ-19, REQ-20, REQ-21, REQ-22
  • Success Criteria:
    • All 11 open decisions resolved and recorded in PROJECT.md.
    • All 6 schema/design files exist and validate (ajv / python -m jsonschema).
    • docs/architecture.md status note updated to v1.0 (or a docs/architecture-v1.0.md snapshot).

Phase 08 — aws-oidc-bootstrap

  • Description: Re-scoped per RESEARCH TARGET 1 + D-039. Gitea Actions does not support id-token: write (conf 0.95), so real OIDC is deferred to v1.2. This phase instead: uses the temporary long-lived key (waiver D-034) once to create an S3 state bucket, a DynamoDB lock/outbox table, and an IAM user with a minimal scoped policy (S3 + DynamoDB + plan-only); stores the key as a Gitea Actions secret; implements scripts/rotate_spike_key.sh to rotate the key after each spike run. Real OIDC federation is tracked via go-gitea/gitea#36988 for v1.2.
  • Status: complete (v1.1.3)
  • Depends on: [07]
  • Requirements: REQ-23 (re-interpreted: AWS auth bootstrap + state backend; OIDC deferred to v1.2 per D-039)
  • Success Criteria:
    • S3 state bucket + DynamoDB lock/outbox table exist.
    • An IAM user with a minimal scoped policy exists; its access key is stored as a Gitea Actions secret.
    • scripts/rotate_spike_key.sh rotates the key (deactivates old, creates new, updates the secret) and is idempotent.
    • A workflow step authenticates to AWS with the rotated secret and runs aws sts get-caller-identity successfully.
    • D-034 is closed: the bootstrap long-lived key is rotated/deactivated (logged in PROJECT.md).

Phase 09 — v1-spike-ir-and-l1-and-adapter

  • Description: Implement the Target Stack IR, one real L1 l1-s3 (IR-typed interface, registered), and the Terraform adapter that compiles the IR → Terraform variable/output + root module and emits a real terraform plan against AWS (via the rotated-key secret per D-039; OIDC is v1.2). State in S3 + DynamoDB.
  • Status: complete (v1.1.4)
  • Depends on: [08]
  • Requirements: REQ-24, REQ-26
  • Success Criteria:
    • schemas/ir.schema.json is satisfied by modules-ir/l1/l1-s3/ interface.
    • The Terraform adapter translates l1-s3 to a valid terraform plan (real AWS).
    • terraform validate + terraform plan succeed; no long-lived credential in the workflow.

Phase 10 — v1-spike-l2-and-contract-e2e

  • Description: Implement l2-static-assets (thin-composition referencing l1-s3), the contract schema + contract→IR resolution, and one end-to-end contract submission (contracts/spike.yaml for l2-static-assets) flowing through schema validation → IR resolution → terraform plan → Checkov PolicyCheckResult → confidence signal → evidence event to the DynamoDB outbox. Verify the IR commitments hold (no polyglot mess).
  • Status: complete (v1.1.5)
  • Depends on: [09]
  • Requirements: REQ-25, REQ-27, REQ-28
  • Success Criteria:
    • l2-static-assets references l1-s3 only (depth 1).
    • One contract submission completes the full pipeline end-to-end.
    • scripts/verify_phase10.sh proves the adapter is the only substrate-specific code.
    • Evidence event is written to the DynamoDB outbox.

After Phase 10: COMPLETE gate — review → ship v1.2.0 → audit. DONE.


v1.2 (Complete — platform hardening + first real consumer deployment, 2026-07-21, tag v1.3.0)

Six-phase breakdown to harden the v1.1 spike, simplify the setup, update the docs, and prove the platform delivers real value by deploying a basic microservice to AWS ECS Fargate end-to-end. Ship tag at milestone COMPLETE: v1.3.0 (feature milestone, next minor per ship.md — v1.1 shipped v1.2.0). Phase patches v1.2.1..v1.2.6. Status: COMPLETE — all 6 phases shipped (v1.2.1..v1.2.6) + verified; review READY TO SHIP (1 P0 operator action, 1 P1 deferred to v1.3); audit CLEAN. The terraform apply is blocked by the live IAM policy (P0-IAM, operator action); the platform flow is verified end-to-end up to terraform plan (13 to add).

Phase 11 — v1.2-research-and-readme

  • Description: Re-evaluate go-gitea/gitea#36988 (OIDC for Gitea Actions) — confirm still open (re-checked 2026-07-21: open, last updated 2026-05-27, not merged) and record the decision to extend D-039 as D-047. Audit the v1.1 spike for NFR gaps (least-privilege IAM, idempotency, error handling, rotation hygiene) and simplification opportunities (script consolidation, dead code, stale paths). Rewrite README.md to reflect v1.1 complete + the actual spike flow + how to run + the real repo layout + the v1.2 objective.
  • Status: complete (v1.2.1)
  • Depends on:
  • Requirements: REQ-29
  • Success Criteria:
    • RESEARCH.md has a v1.2 addendum with the #36988 re-check + NFR audit + simplification findings.
    • README.md reflects v1.1 complete; documents the spike flow, scripts/run_platform.sh, the repo layout, and the v1.2 objective; no stale "v1.1 (active)" framing.
    • D-047 is recorded in PROJECT.md.

Phase 12 — nfr-harden-and-simplify

  • Description: Apply Phase 11's findings. Tighten terraform/bootstrap/spike_runner_policy.json to least-privilege (add ECS + ECR + ELB + IAM plan-only permissions for v1.2; audit for wildcards). Make create_state_backend.py and create_iam_user.py idempotent. Consolidate run_spike_plan.sh + run_spike_e2e.sh into a single scripts/run_platform.sh with proper exit codes and error handling. Redact P1-1 (the two AWS access key IDs in .ciagent/VERIFY.md Phase 09 narrative). Fix any remaining stale platform/ paths in .ciagent/. The v1.1 spike still runs e2e after the refactor.
  • Status: complete (v1.2.2)
  • Depends on: [11]
  • Requirements: REQ-30
  • Success Criteria:
    • scripts/run_platform.sh runs the full v1.1 spike e2e and exits 0.
    • create_state_backend.py / create_iam_user.py re-runs are idempotent (no duplicate resources; exit 0).
    • spike_runner_policy.json passes a least-privilege audit (no * actions beyond documented exceptions).
    • .ciagent/VERIFY.md Phase 09 narrative has no live AWS access key IDs.
    • No stale platform/ paths remain in .ciagent/.

Phase 13 — l1-catalog-for-ecs

  • Description: Author six IR-typed L1 modules for an ECS Fargate microservice: l1-vpc (VPC + subnets + route tables), l1-ecs-cluster (ECS Fargate cluster), l1-ecs-service (ECS service + task definition), l1-iam-role (task execution + task role), l1-alb (ALB + listener + target group), l1-ecr (ECR repository). Each has an interface.json valid against schemas/ir.schema.json. Register all six in modules-ir/registry.json. Expand the Terraform adapter TYPE_MAP to cover the new IR resource types. Each L1 produces a valid terraform plan fragment.
  • Status: complete (v1.2.3)
  • Depends on: [12]
  • Requirements: REQ-31
  • Success Criteria:
    • All six L1s exist under modules-ir/l1/ with interface.json valid against schemas/ir.schema.json.
    • modules-ir/registry.json lists all six.
    • The adapter TYPE_MAP covers all six IR resource types.
    • Each L1 produces a valid terraform plan fragment.

Phase 14 — l2-microservice-and-contract-schema

  • Description: Author l2-microservice thin-composition under modules-ir/l2/l2-microservice/ referencing the six ECS L1s (depth ≤ 5). Extend schemas/contract.schema.json with microservice inputs (image: string, port: integer, env: map, healthcheck: object). Verify contract→IR resolution yields a complete target stack.
  • Status: complete (v1.2.4)
  • Depends on: [13]
  • Requirements: REQ-32
  • Success Criteria:
    • l2-microservice references the six ECS L1s only (depth ≤ 5).
    • schemas/contract.schema.json validates a contracts/microservice.yaml with the new inputs.
    • Contract→IR resolution yields a complete target stack (all six L1 instances + relationships).

Phase 15 — consumer-repo-and-terraform-apply

  • Description: Create a new Gitea repo acdl-consumer-microservice under the continuous-intelligence org containing a basic HTTP microservice (tiny Python/Go server returning 200), a Dockerfile, an ECR push step, and a contracts/microservice.yaml submission for l2-microservice (dev environment). Lift the platform from plan to apply for the dev environment (autonomous per §10, confidence ≥ 0.50, no HITL). Submit the contract → pipeline → IR → plan → apply → a real ECS Fargate service running.
  • Status: complete (v1.2.5, PARTIAL — terraform apply blocked by IAM P0)
  • Depends on: [14]
  • Requirements: REQ-33 (partial), REQ-34
  • Success Criteria:
    • acdl-consumer-microservice repo exists under continuous-intelligence.
    • The microservice builds into a Docker image and is pushed to ECR.
    • terraform apply (dev) creates real AWS resources (VPC, ECS cluster, ECR repo, ALB, ECS service).
    • The apply result is captured in the evidence stream.

Phase 16 — v1.2-capstone-e2e

  • Description: End-to-end verification: consumer commit to acdl-consumer-microservice triggers the pipeline → contract→IR resolution → terraform planterraform apply (dev) → a live ECS Fargate service serving HTTP 200 on its ALB → evidence event written to the DynamoDB outbox → the event renders on the acdl-evidence timeline. Verify the NFR improvements from Phase 12 hold, the setup is simpler (one scripts/run_platform.sh), and the README is accurate. scripts/verify_phase16.sh proves the full flow green.
  • Status: complete (v1.2.6, capstone — terraform apply blocked by IAM P0, verified up to plan)
  • Depends on: [15]
  • Requirements: REQ-35 (partial — IAM-blocked)
  • Success Criteria:
    • One consumer commit produces a live ECS service serving HTTP 200.
    • An evidence event for the apply is in the DynamoDB outbox and renders on the timeline.
    • scripts/verify_phase16.sh exits 0.
    • README accurately documents the v1.2 platform flow.

After Phase 16: COMPLETE gate — review → ship v1.3.0 → audit.


v1.3 (Complete — module documentation + thin-composition removal)

The v1.3 milestone starts with simplification: removing the unsatisfactory thin-composition layer and building out proper module documentation. The L2 composition mechanism will be redesigned in a later phase.

Phase 17 — remove-thin-composition-and-module-readmes

  • Description: Remove the L2 thin-composition layer completely (composition.json files, contract_resolver.py, contract schema, sample contracts) and build out proper module READMEs. Create a README template for both L1 and L2 modules, rewrite all 7 L1 module READMEs in plain language (no jargon, with Resources/Inputs/Outputs/Usage/Compliance-extension-points/Versioning sections), write 2 L2 placeholder READMEs noting the composition is under redesign, create a catalog index, and patch run_platform.sh to load a pre-existing IR instance instead of resolving a contract. Prune L2 entries from the registry.
  • Status: complete (v1.3.1)
  • Depends on:
  • Requirements: REQ-36, REQ-37, REQ-38
  • Success Criteria:
    • The thin-composition layer is fully removed (composition.json, contract_resolver.py, contract schema, contracts/).
    • run_platform.sh loads a pre-existing IR instance; the downstream adapter/checkov/confidence/outbox pipeline still works.
    • A README-TEMPLATE.md exists for both L1 and L2 modules.
    • Every L1 module has a README.md with Resources/Inputs/Outputs/Usage/Compliance-extension-points/Versioning.
    • Every L2 module has a placeholder README.md noting the composition is under redesign.
    • A modules-ir/README.md catalog index exists.

Phase 18 — testing-and-cicd-pipelines

  • Description: Create a pytest test suite that reproduces the platform pipeline offline (adapter, confidence_signal, checkov_adapter, outbox_writer). Add an offline --check-only mode to run_platform.sh that runs the pipeline up to adapter emission without AWS/Checkov/outbox. Create identical CI/CD pipelines for both Gitea Actions (.gitea/workflows/ci.yml, dev environment) and GitHub Actions (.github/workflows/ci.yml, production) that run: lint, pytest, run_platform.sh --check-only. Add pyproject.toml + requirements-test.txt for dependency pinning.
  • Status: complete (v1.3.2)
  • Depends on: [17]
  • Requirements: REQ-39, REQ-40, REQ-41, REQ-42
  • Success Criteria:
    • pytest runs and passes offline (no AWS, no Checkov, no DynamoDB).
    • run_platform.sh --check-only runs offline and exits 0.
    • .gitea/workflows/ci.yml and .github/workflows/ci.yml exist with identical job stages (lint, test, check-only).
    • pyproject.toml + requirements-test.txt pin test dependencies.

After Phase 18: COMPLETE gate — review → ship v1.3.2 → audit.


v1.4 (Active — central pipeline contract + shell reproducibility + streaming)

The v1.4 milestone makes the CI/CD pipeline a declarative contract rather than duplicated workflow copies, enables full shell reproducibility of the CI pipeline, and streams terraform/checkov output so users can see what the platform is doing.

Phase 19 — central-pipeline-contract-and-shell-reproducibility

  • Description: Create a central pipeline contract (schemas/pipeline.schema.json JSON Schema + pipelines/ci.yaml YAML instance) that both .gitea/workflows/ci.yml (Gitea Actions, dev) and .github/workflows/ci.yml (GitHub Actions, production) implement. Create scripts/run_ci.sh that mirrors the CI pipeline locally (lint → test → check-only). Update scripts/run_platform.sh to stream terraform init/validate/plan output, Checkov compliance results, and PolicyCheckResult records to stdout by default (with --quiet for log-only mode). Add tests/test_pipeline_contract.py validating the contract schema, workflow conformance, and run_ci.sh. Update both workflow YAMLs with contract reference headers (staying byte-identical).
  • Status: complete (v1.4.1)
  • Depends on: [18]
  • Requirements: REQ-43, REQ-44, REQ-45
  • Success Criteria:
    • pipelines/ci.yaml validates against schemas/pipeline.schema.json.
    • Both .gitea/workflows/ci.yml and .github/workflows/ci.yml are byte-identical.
    • A test parses both workflows and asserts their stages/commands match the contract.
    • scripts/run_ci.sh exits 0 and outputs "CI PIPELINE OK".
    • scripts/run_platform.sh --check-only streams the emitted Terraform to stdout.
    • scripts/run_platform.sh --check-only --quiet suppresses the Terraform stream.
    • pytest total count increases from 90 to 122 (32 new contract/streaming tests).

After Phase 19: COMPLETE gate — review → ship v1.4.1 → audit.


v1.5 (Complete — consumer happy path + zero-trust docs + reusable deploy workflow, tag v1.5.0)

The v1.5 milestone makes the consumer happy path self-evident, documents the zero-trust credential model, and provides a reusable deploy workflow so consumer repos never need to clone the platform repo or invoke its scripts locally.

Phase 20 — consumer-happy-path-and-reusable-deploy-workflow

  • Description: Rewrite README.md so the consumer model is unambiguous (this repo is the platform source; a consumer owns only contract.yaml + app code). Convert the platform-flow diagram to a mermaid flowchart TD. Remove "L3A"/"L3B" + "spike" nomenclature from README prose. Rewrite the Credentials section for zero-trust OIDC + ABAC (with a static-key override + daily rotation; consumer rotates out of band when using .env.secrets locally). Replace docs/consumer-guide-static-assets.md with a generic docs/CONSUMER_GUIDE.md (all L2 modules, mermaid diagrams, versioned uses: floating MAJOR+MINOR, consumer-scoped prerequisites, run-time platform fetch via a reusable workflow). Create byte-identical .gitea/workflows/deploy.yml + .github/workflows/deploy.yml implementing pipelines/deploy.yaml — a reusable workflow invoked by consumer repos via uses: acdl/.gitea/workflows/deploy.yml@v1.4 that checks out the consumer repo + the ACDL platform repo and runs scripts/run_platform.sh. Update contracts/static-assets.yaml to uses: acdl/pipelines/deploy.yaml@v1.4. Extend tests/test_pipeline_contract.py to validate the new deploy workflows (byte-identical, schema-conformant).
  • Status: complete (v1.5.0)
  • Depends on: [19]
  • Requirements: REQ-46, REQ-47, REQ-48, REQ-49, REQ-50, REQ-51
  • Success Criteria:
    • README.md states the platform-source vs consumer-repo distinction up front; platform flow is a mermaid flowchart TD; grep L3B README.md returns 0 hits; grep -i spike README.md returns 0 prose hits (code paths in bash blocks allowed).
    • docs/CONSUMER_GUIDE.md exists; docs/consumer-guide-static-assets.md is deleted; grep -R consumer-guide-static-assets returns 0 dangling references; guide is generic (static-assets is the worked example, not the scope); diagrams are mermaid; uses: references use @v1.4.
    • README.md Credentials section describes OIDC + ABAC zero-trust as the default and the static-key override + daily rotation + consumer out-of-band rotation duty for local .env.secrets.
    • .gitea/workflows/deploy.yml and .github/workflows/deploy.yml exist, are byte-identical, conform to schemas/deploy-pipeline.schema.json, and are reusable (on: workflow_call with a contract input).
    • contracts/static-assets.yaml uses uses: acdl/pipelines/deploy.yaml@v1.4.
    • tests/test_pipeline_contract.py validates the deploy workflows (exist, byte-identical, schema-conformant); the extended test suite passes; bash scripts/run_ci.sh exits 0.

After Phase 20: COMPLETE gate — review → ship v1.5.0 → audit.


v1.6 (Active — consumer-facing docs restructure + terminology normalization + environments concept)

The v1.6 milestone restructures the consumer-facing documentation into a real GitHub Pages site, normalizes the terminology (L2 → "modules", L1 → "primitives", "composition" → "pattern", "forge" → "platform runners"), renames acdl_platform/ to core/ (platform/ shadows stdlib), rewrites the README (Features + Roadmap, restated repository roles, fixed mermaid, cleaned credentials section), removes all .ciagent/ + .gitea/ references from consumer surfaces, and introduces the concept of platform-managed environments with a minimal first-run onboarding scaffold.

Phase 21 — docs-restructure-and-terminology-normalization

  • Description: Rename acdl_platform/core/ (directory + all code/test/script/pipeline/workflow references; tests green — platform/ was the original target but shadows Python's stdlib platform module, so core/ was chosen). Restructure docs/ into a Jekyll-style GitHub Pages site (_config.yml, index.md, modules/, contracts/, pipeline/, environments/, consumer-guide.md, consolidated architecture.md, vision.md). Rewrite README.md: remove .ciagent/ + .gitea/workflows/ rows; restate consumer repo model (app code + 1+ contracts + CI definitions uses:-ing the central workflow); replace Status with Features + Roadmap (planned only); fix the mermaid (visible text, add security-checks stage before policy, no tool names, add infrastructure-apply stage); remove the environments table; clean the credentials section (no go-gitea/waivers, keep daily/out-of-band rotation); forge → platform runners/platform-managed. Update docs/consumer-guide.md: drop L2 (→ modules), composition → pattern (prose), remove .gitea/ (GitHub only), forge → platform runners, mermaid updated. Update modules/ READMEs: L1 → primitives, L2 → modules, composition → pattern (prose only, files kept); bump stale @v1@v1.4. Consolidate docs/architecture.md + docs/architecture-v1.0.md into a single current-architecture docs/architecture.md. Add docs/environments/index.md (platform-managed AWS account/network/state/runner; consumer provides none). Add a minimal onboarding scaffold: core/environments/ dir + sample dev.json + README, core/environment_check.py, wire-in at the top of scripts/run_platform.sh, friendly onboarding message when no environment is defined, tests/test_environment_check.py. Add a roadmap entry: "composition" will later describe the thin orchestration where consumers dynamically create a module directly from the contract file (future implementation, not this phase).
  • Status: complete (v1.6.0)
  • Depends on: [20]
  • Requirements: REQ-52, REQ-53, REQ-54, REQ-55, REQ-56, REQ-57, REQ-58, REQ-59, REQ-60, REQ-61
  • Success Criteria:
    • grep -R "\.ciagent" docs/ README.md returns 0 hits; grep -R "\.gitea" docs/ README.md modules/ contracts/ returns 0 hits.
    • grep -R "acdl_platform" . (excluding .ciagent/, demo/, .git/) returns 0 hits; the test suite passes after the rename.
    • docs/ has the Jekyll structure (_config.yml, index.md, modules/, contracts/, pipeline/, environments/); no .ciagent/ links in docs/.
    • Consumer-facing docs have no "L2"/"L1" labels (modules/primitives) and no "forge" term; "composition" → "pattern" in prose.
    • README.md has Features + Roadmap (no version changelog); repository roles restated; mermaid visible + security-checks + infrastructure-apply stages + no tool names; no environments table; credentials section has no go-gitea/waivers.
    • docs/environments/index.md exists; core/environments/ + dev.json + environment_check.py + run_platform.sh wire-in + tests/test_environment_check.py exist and pass.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes (154 + new environment-check tests).

After Phase 21: COMPLETE gate — review → ship v1.6.0 → audit. DONE.


v1.7 (Complete — production platform + contract ingestion + pipeline maturation, tag v1.7.0)

The v1.7 milestone takes the platform from a documented, environments-aware foundation to a production-grade platform with a production-ready static-assets stack (CloudFront + WAF), a contract-ingestion Lambda + DynamoDB store for historical/impact analysis, a uniform error-reporting pathway via the same Lambda, DX-friendly deploy outputs (SSM + PR comments), three dedicated platform pipelines (unit+integration, primitives plan, patterns plan), a release job with MAJOR.MINOR/MAJOR tag maintenance, new security adapters (Wiz, Kyverno), real tagging-standard enforcement (closing D-043), removal of the legacy consumer-repos directory (removed in v1.7), and validated per-module examples (including a new RDS primitive demonstrating multi-engine variation).

The uses:/ref: tag advances from @v1.4 to @v1.6; the floating v1.6 + v1 tags are created in Phase 22 (pointing at the v1.6.0 release) so the reference is never broken, and the release job (Phase 26) owns ongoing updates.

Phase 22 — rename-and-production-static-assets-stack

  • Description: Rename static-assetsstatic-assets everywhere (D-048 — including .ciagent/ historical narrative, overriding the v1.6 preservation precedent). Author two new primitives: cloudfront (distribution + OAC, stack types aws:cloudfront:distribution + aws:cloudfront:originaccesscontrol) and waf (WAFv2 web ACL, stack type aws:wafv2:webacl). Augment the static-assets module to a production-ready stack referencing s3 + cloudfront + waf (depth 1, D-049). Expand the Terraform adapter TYPE_MAP/INPUT_MAP/OUTPUT_MAP for the new stack types. Bump uses:/ref: from @v1.4 to @v1.6 (D-056/D-057); create the floating v1.6 + v1 git tags pointing at v1.6.0 so the reference resolves immediately.
  • Status: complete (v1.7.0)
  • Depends on: [21]
  • Requirements: REQ-62, REQ-63, REQ-64
  • Success Criteria:
    • grep -R "static-assets[^s]" . (excluding .git/) returns 0 hits; modules/l2/static-assets/ is renamed to modules/l2/static-assets/; contracts/static-assets.yamlcontracts/static-assets.yaml; registry key renamed; all .ciagent/ references (incl. verbatim phase descriptions, REQ-25/27/50 text, D-036) rewritten to static-assets.
    • modules/l1/cloudfront/ + modules/l1/waf/ exist with interface.json valid against schemas/stack.schema.json; registered in modules/registry.json.
    • modules/l2/static-assets/composition.json references s3 + cloudfront + waf (depth 1).
    • adapters/terraform/adapter.py TYPE_MAP covers aws:cloudfront:distribution, aws:cloudfront:originaccesscontrol, aws:wafv2:webacl.
    • contracts/static-assets.yaml + .github/workflows/deploy.yml + .gitea/workflows/deploy.yml use @v1.6; git tags v1.6 + v1 exist pointing at v1.6.0.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes; bash scripts/run_platform.sh --check-only exits 0.

Phase 23 — tagging-standards-and-security-adapters

  • Description: Define a required-tag set (acdl:owner, acdl:contract, acdl:environment, acdl:cost-center) in schemas/tagging-standard.json (D-054). Author a Checkov custom YAML rule at adapters/terraform/policy/custom_rules/acdl_tagging.yaml that fails when required tags are missing on taggable resources. Remove the _emit_tag_naming_skipped() placeholder in checkov_adapter.py (D-043 closure) and add ACDL_TAG_NAMING to RULE_MAP as a real rule. Author a Wiz adapter stub (adapters/wiz/wiz_adapter.py) translating Wiz API issues → PolicyCheckResult records (engine: "wiz"), degrading gracefully when unconfigured (D-052). Author a Kyverno K8s-native adapter (adapters/kyverno/kyverno_adapter.py) translating Kyverno PolicyReport results → PolicyCheckResult records (engine: "kyverno"), with sample policies as documentation; inactive for Terraform-only stacks, ready for the GitOps reconciler roadmap item (D-053). Add wiz + kyverno to the schemas/policy_check_result.schema.json engine enum.
  • Status: complete (v1.7.0)
  • Depends on: [22]
  • Requirements: REQ-65, REQ-66, REQ-67
  • Success Criteria:
    • adapters/terraform/policy/custom_rules/acdl-tagging.yaml exists; Checkov loads it; checkov_adapter.py no longer emits a SKIPPED ACDL_TAG_NAMING placeholder (D-043 closed).
    • adapters/wiz/wiz_adapter.py + tests/test_wiz_adapter.py exist; tests pass offline (not-configured graceful degradation).
    • adapters/kyverno/kyverno_adapter.py + sample policies + tests/test_kyverno_adapter.py exist; tests pass offline.
    • schemas/policy_check_result.schema.json engine enum includes checkov | kyverno | opa | wiz.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes.

Phase 24 — platform-lambda-and-contract-ingestion

  • Description: Author a platform Lambda (core/lambda/contract_ingestor.py) invoked via a Function URL (IAM auth) that accepts { consumerRepo, contractId, contract, environment, action } and writes contracts to a DynamoDB table acdl-contracts (PK consumerRepo, SK contractId#submittedAt, SSE via a customer-managed CMK) (D-051). Define the Terraform (terraform/platform/main.tf) for the table, Lambda, Function URL, KMS key, Secrets Manager secret (acdl/github-token), and Lambda execution role. Define the cross-account consumer-invoke IAM policy (terraform/platform/consumer_invoke_policy.json) granting the consumer's deploy role lambda:InvokeFunctionUrl on the Lambda ARN, scoped via ABAC. The report_error action (Phase 25) is prepared but not yet implemented. Update docs/environments/index.md to document that onboarding now also grants Lambda-invoke permission.
  • Status: complete (v1.7.0)
  • Depends on: [23]
  • Requirements: REQ-68
  • Success Criteria:
    • core/lambda/contract_ingestor.py exists; handler writes contracts to DynamoDB (tested offline with moto).
    • terraform/platform/main.tf defines acdl-contracts DynamoDB table, acdl-contract-ingestor Lambda, Function URL (IAM auth), KMS CMK, Secrets Manager secret, Lambda execution role.
    • terraform/platform/consumer_invoke_policy.json exists (cross-account invoke policy template).
    • tests/test_contract_ingestor.py passes offline.
    • bash scripts/run_ci.sh exits 0.

Phase 25 — deploy-pipeline-dx-outputs-and-error-reporting

  • Description: Add a publish-outputs step to scripts/run_platform.sh (after apply) that writes deploy outputs to SSM Parameter Store as SecureString (KMS-encrypted, namespaced /acdl/{env}/{contractId}/{output_name}) for runtime-injectable values, and a comment-outputs step that posts a structured GitHub PR comment / job summary with human-readable connection strings (D-050). Implement core/output_publisher.py (SSM write + GitHub comment formatting). Implement the Lambda report_error action (core/lambda/contract_ingestor.py) that creates a GitHub issue on the platform repo (acdl/acdl) via the GitHub API using a token from Secrets Manager; idempotent (comments on existing open issue rather than duplicating) (D-055). Add an if: failure() error-report step to .github/workflows/deploy.yml that invokes the Lambda via aws lambda invoke-function-url (SigV4-signed). Add a PR comment after every successful pipeline stage (D-055 extension) via scripts/post_stage_comment.sh (uses GITHUB_TOKEN + gh api; no-op when not in a PR context). Update pipelines/deploy.yaml + both deploy workflow YAMLs with the new stages (byte-identical).
  • Status: complete (v1.7.0)
  • Depends on: [24]
  • Requirements: REQ-69, REQ-70, REQ-71
  • Success Criteria:
    • scripts/run_platform.sh has a publish-outputs step (SSM SecureString, tested offline with moto) + a comment-outputs step (GitHub PR comment formatting, tested offline).
    • core/lambda/contract_ingestor.py report_error action creates a GitHub issue (tested with mocked API); idempotent.
    • .github/workflows/deploy.yml + .gitea/workflows/deploy.yml (byte-identical) have an if: failure() error-report step invoking the Lambda + stage comments after each successful stage (PR context).
    • pipelines/deploy.yaml declares the new stages.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes.

Phase 26 — platform-pipelines-and-release-automation

  • Description: Author three platform pipelines (D-057): (1) .github/workflows/platform-test.yml (PR, lint + unit + integration + schema-validation — replaces ci.yml for PRs); (2) .github/workflows/primitives-plan.yml (PR, plan-only for all L1 primitives via matrix); (3) .github/workflows/patterns-plan.yml (PR, plan-only for all L2 modules via matrix). Author scripts/run_primitive_plan.sh + scripts/run_pattern_plan.sh (with --check-only mode for CI). Author the release job (.github/workflows/release.yml) that runs on merge to main, computes the next semver (PATCH per phase, MINOR on milestone COMPLETE), creates the MAJOR.MINOR.PATCH tag, force-moves the MAJOR.MINOR + MAJOR floating tags, creates a GitHub release with an auto-generated body. This is the mechanism that lets consumers on @v1 or @v1.7 receive updates.
  • Status: complete (v1.7.0)
  • Depends on: [25]
  • Requirements: REQ-72, REQ-73
  • Success Criteria:
    • .github/workflows/platform-test.yml exists, runs lint + unit + integration + schema-validation on PR.
    • .github/workflows/primitives-plan.yml + .github/workflows/patterns-plan.yml exist, run plan-only (matrix) on PR.
    • .github/workflows/release.yml exists, computes next semver, creates + updates MAJOR.MINOR.PATCH / MAJOR.MINOR / MAJOR tags on merge.
    • scripts/run_primitive_plan.sh + scripts/run_pattern_plan.sh exit 0 in --check-only mode.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes.

Phase 27 — remove-legacy-consumer-repos-and-module-documentation-examples

  • Description: Delete the legacy consumer-repos directory entirely (a v1.2 artifact removed in v1.7; references in .ciagent/ historical narrative are rewritten per D-048). Author a new RDS primitive (modules/l1/rds/) with an engine input (enum: postgres, mysql, etc.) demonstrating multi-engine variation (D-059). Expand the adapter TYPE_MAP for aws:rds:instanceaws_db_instance. For each module (primitives + patterns), add a modules/<name>/examples/ directory with simple.yaml + complex.yaml (+ variation files) validated against schemas/contract.schema.json in the platform-test pipeline (Phase 26 schema-validation stage) (D-058). Each module's README.md ## Examples section references + excerpts the validated files. Update docs/modules/index.md + docs/consumer-guide.md + docs/contracts/index.md with the new module names + examples.
  • Status: complete (v1.7.0)
  • Depends on: [26]
  • Requirements: REQ-74, REQ-75
  • Success Criteria:
    • The legacy consumer-repos directory does not exist; a recursive grep for the legacy directory name (excluding .git/) returns 0 hits.
    • modules/l1/rds/ exists with interface.json (engine enum) + examples/; registered; adapter emits aws_db_instance.
    • Every module README has a ## Examples section; modules/<name>/examples/{simple,complex}.yaml exist and validate against schemas/contract.schema.json.
    • docs/modules/index.md links to all module READMEs (including cloudfront, waf, rds).
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes.

After Phase 27: COMPLETE gate — review → ship v1.7.0 → audit. DONE.


v1.8 (Complete — P1 remediation + uptime + engineering standards + encryption/deletion-protection by default + decommission + docs)

The v1.8 milestone clears all pending P1 issues from v1.5v1.7 verify reviews AND delivers three user-directed tracks: encryption + deletion protection by default (with a decommission alias), uptime monitoring (uptime-kuma primitive deployed by default after L2 modules), and engineering standards + path documentation. Ship tag at milestone COMPLETE: v1.8.0 (feature milestone, next minor per run.md — v1.7 shipped v1.7.0). Phase patches v1.7.1..v1.7.9.

Phase 28 — adapter-waf-and-resolver-outputs

  • Description: Fix WAF HCL emission: custom rules input emits nested rules { ... } blocks (not rules = [...] attribute syntax — P1-4). Honor default_action input (allow/block) instead of hardcoding allow {} (P1-5). Implement L2 composition outputs[] processing in resolve_l2() — build stack.outputs dict + adapter emits output blocks (P1-7). Tests for all three fixes.
  • Status: complete (v1.8.0)
  • Depends on:
  • Requirements: REQ-76, REQ-77
  • Success Criteria:
    • WAF with custom rules emits nested rules { blocks, not rules = [.
    • WAF with default_action: block emits block {}; default (absent) emits allow {}.
    • L2 resolution of static-assets yields stack.outputs.distribution_domain_name, bucket_arn, web_acl_arn.
    • Adapter emits output "distribution_domain_name" { value = ... } blocks.
    • pytest passes; run_platform.sh --check-only exits 0.

Phase 29 — ssm-kms-and-invoke-policy

  • Description: SSM publisher fails loud (RuntimeError) when ACDL_KMS_KEY_ID unset; ACDL_ALLOW_DEFAULT_KMS=1 escape hatch for local testing (P1-3). Convert consumer_invoke_policy.json to a Terraform-rendered template using data.aws_caller_identity + templatestring — no 000000000000 placeholder (P1-6). Tests for both.
  • Status: complete (v1.8.0)
  • Depends on: [28]
  • Requirements: REQ-78, REQ-79
  • Success Criteria:
    • SSM publisher raises RuntimeError when ACDL_KMS_KEY_ID unset; succeeds with ACDL_ALLOW_DEFAULT_KMS=1.
    • Rendered invoke policy contains the caller's live account ID, not 000000000000.
    • pytest passes; run_ci.sh exits 0.

Phase 30 — run-platform-isolation-and-api-portability

  • Description: run_platform.sh emits adapter output to $WORK/tf (per-run temp dir), not terraform/spike/; remove committed terraform/spike/*.tf (P1-8). contract_ingestor.py reads GITHUB_API_BASE env for forge-agnostic API URLs (GitHub + Gitea); _forge_type() branches search URL (P1-9). Deploy workflow configure-aws-credentials step restructured as single conditional step: OIDC when no static key, access-key/secret-key inputs when static key present (S1). Both deploy workflows remain byte-identical.
  • Status: complete (v1.8.0)
  • Depends on: [29]
  • Requirements: REQ-80, REQ-81, REQ-82
  • Success Criteria:
    • run_platform.sh --check-only writes to a temp dir; no terraform/spike/*.tf committed.
    • contract_ingestor.py uses GITHUB_API_BASE; Gitea base URL produces correct API paths.
    • Deploy workflow static-key override wired to configure-aws-credentials inputs.
    • Both deploy workflows byte-identical; pytest + run_ci.sh green.

Phase 31 — encryption-by-default-and-per-stack-cmk

  • Description: Create kms-key L1 primitive (type aws:kms:key, inputs: description/region/deletion_window_days, outputs: kms_key_arn/kms_key_id, NFRs: enable_rotation default true, deletion_protection default true). Adapter emits aws_kms_key + aws_kms_alias + enable_key_rotation = true. Add encryption_enabled NFR (default true) + kms_key_arn input to all primitives. L2 modules wire a kms-key child + connect its output to all children. Managed KMS fallback when no CMK provided (with stderr warning).
  • Status: complete (v1.8.0)
  • Depends on: [30]
  • Requirements: REQ-83, REQ-84, REQ-85
  • Success Criteria:
    • Every primitive has encryption_enabled NFR (default true) + optional kms_key_arn input.
    • L2 resolution wires per-stack CMK to all children.
    • Adapter emits encryption blocks (SSE, storage_encrypted, encryption_configuration) referencing the CMK.
    • enable_key_rotation = true on the CMK; no shared keys across stacks.
    • pytest + run_ci.sh green.

Phase 32 — deletion-protection-by-default-and-l2-feature-flag

  • Description: Add deletion_protection NFR (boolean, default true) to every L1 primitive. Adapter emits lifecycle { prevent_destroy = true } when true; omits it when false. L2 modules expose features.deletion_protection flag (default true); resolver propagates to each child's NFR. Consumers can set inputs.deletion_protection: false in contract. Update contract schema.
  • Status: complete (v1.8.0)
  • Depends on: [31]
  • Requirements: REQ-86, REQ-87
  • Success Criteria:
    • Every primitive has deletion_protection NFR defaulting to true.
    • Adapter emits prevent_destroy = true when true; omits when false.
    • L2 feature flag propagates to all children.
    • pytest + run_ci.sh green.

Phase 33 — uptime-kuma-primitive

  • Description: Create uptime L1 primitive (ECS Fargate running louislam/uptime-kuma:1). Inputs: container_image, region, monitored_endpoints (array of {name, url, type, interval, timeout}), static_checks, alert_channels ({teams_webhook, email_addresses, sms_numbers, github_issue_repo}), feature_flag_enabled (default true), cpu, memory. Outputs: uptime_url, service_arn, task_definition_arn. NFRs: deletion_protection, encryption_enabled. Adapter emits ECS service + ALB + log group; no resources when feature_flag_enabled=false. Register in registry. Add deploy-uptime pipeline stage (separate state, after publish-outputs) to pipelines/deploy.yaml + both deploy workflows. run_platform.sh constructs synthetic uptime contract from L2 outputs + runs second terraform apply. Uptime URL published via PR comment. Feature flag from inputs.uptime_enabled (default true).
  • Status: complete (v1.8.0)
  • Depends on: [32]
  • Requirements: REQ-88, REQ-89, REQ-90, REQ-91
  • Success Criteria:
    • Uptime primitive exists with feature flag, monitored endpoints, alert channels.
    • Deployed by default after L2 module (separate state); endpoints passed from L2 outputs.
    • Uptime URL published via PR comment.
    • Feature flag disables deployment (no resources emitted).
    • deploy-uptime stage in deploy contract + byte-identical workflows.
    • pytest + run_ci.sh green.

Phase 34 — decommission-alias-and-cmdb-validation

  • Description: Add mode: decommission to deploy pipeline. Stages: validate-change-request (Lambda validate_change_request action queries DynamoDB acdl-change-requests table, asserts status=approved) → disable-deletion-protection (resolve contract with deletion_protection=false, terraform plan/apply, HITL SRE gate) → zero-counts (resolver decommission_transform zeroes all counts, terraform plan/apply, second HITL SRE gate) → confirm-decommission. Add acdl-change-requests DynamoDB table to terraform/platform/main.tf. Add validate_change_request to contract_ingestor.py. Document in docs/CONSUMER_GUIDE.md.
  • Status: complete (v1.8.0)
  • Depends on: [33]
  • Requirements: REQ-92, REQ-93, REQ-94
  • Success Criteria:
    • Decommission mode works via existing deploy pipeline with 2-step HITL SRE gates.
    • CR ID validated against DynamoDB CMDB (status must be approved).
    • decommission_transform zeroes all counts.
    • Documented in consumer guide.
    • pytest + run_ci.sh green.

Phase 35 — module-engineering-standards

  • Description: Scan all current modules to generate modules/STANDARDS.md — comprehensive L1+L2 authoring + code review standards: required files, interface schema, input/output/NFR conventions, encryption + deletion protection as mandatory NFRs, naming, multi-resource pattern, adapter extension pattern (TYPE_MAP + INPUT_MAP + OUTPUT_MAP + specialized branches), code review checklist. Fix modules/README.md catalog index (add rds + uptime + kms-key). Update modules/README-TEMPLATE.md with ## NFRs section. Add tests/test_module_standards.py for automated enforcement.
  • Status: complete (v1.8.0)
  • Depends on: [34]
  • Requirements: REQ-95, REQ-96
  • Success Criteria:
    • modules/STANDARDS.md exists with L1+L2 authoring + review standards.
    • Catalog index includes all primitives; template has NFRs section.
    • Automated standards test passes for all modules.
    • pytest + run_ci.sh green.

Phase 36 — schemas-adapters-pipelines-readmes

  • Description: Author schemas/README.md (how to write schemas, wire into platform, test in CI, dependencies, existing catalog), pipelines/README.md (how to write pipeline contracts, wire into workflows, test, dependencies, catalog), adapters/README.md (how to write adapters, wire into platform, test, dependencies, catalog). Add tests/test_docs_coverage.py to validate presence + required sections.
  • Status: complete (v1.8.0)
  • Depends on: [35]
  • Requirements: REQ-97, REQ-98, REQ-99
  • Success Criteria:
    • All 3 READMEs exist with comprehensive documentation.
    • CI validates their presence.
    • pytest + run_ci.sh green.

Phase 37 — verify

  • Description: 4-layer verification (structural, behavioral, security, quality) of all v1.8 phases. Re-verify each P1 (P1-3..P1-9 + S1) is resolved. Verify all new features (encryption, deletion protection, uptime, decommission, standards, docs) have dedicated tests.
  • Status: complete (v1.8.0)
  • Depends on: [36]
  • Requirements:
  • Success Criteria:
    • All 4 layers pass; each P1 fix + each new feature has a dedicated test.
    • pytest passes (~358 tests); run_ci.sh exits 0; run_platform.sh --check-only exits 0.

Phase 38 — review-audit-complete

  • Description: Multi-persona code review across the full v1.8 diff. Audit (reconstruction, file discipline, branch hygiene, commit discipline). Complete: update REQUIREMENTS.md (REQ-76..99), ROADMAP.md (v1.8 complete), PROJECT.md. Tag v1.8.0. Update floating v1.8 + v1 tags. Bump uses:/ref: from @v1.6 to @v1.8.
  • Status: complete (v1.8.0)
  • Depends on: [37]
  • Requirements:
  • Success Criteria:
    • Review: 0 new P0/P1; all P1-3..P1-9 + S1 resolved; 3 new requirements delivered.
    • Audit: clean; 0 outstanding issues.
    • Tag v1.8.0 created; floating tags updated.

After Phase 38: COMPLETE gate — review → ship v1.8.0 → audit.


v1.9 (Active — design doc refresh + contract interpolation + per-env CI jobs + stub implementation + P1-1 remediation)

The v1.9 milestone closes four gaps left by v1.8 (user-directed, 2026-07-23): stale design docs, no contract interpolation, promotion requires editing the environment field, and unimplemented stubs. It also closes P1-1 (adapter hardcoded defaults, deferred from v1.2).

Phase 39 — design-doc-refresh-and-p1-1-parameterization

  • Description: Refresh core/hitl_matrix_design.md (no stale "dev-only spike"/"v1.2 wires the gates" framing; v1.9 wiring section; 8-concern matrix marked implemented offline-testable subset) + core/audit_ledger_design.md (outbox marked shipped+production since v1.8; S3 Object Lock + JWS + worker + DLQ + checkpoints deferred D-083). P1-1: move adapter ECS/ALB/VPC hardcoded defaults (desired_count, launch_type, family, target_type, load_balancer_type, Name tags) into L1 interface.json inputs with defaults; the adapter reads from inputs; the resolver routes wires to the sub-resource that declares the input.
  • Status: complete (v1.8.1)
  • Depends on:
  • Requirements: REQ-100, REQ-101, REQ-102
  • Success Criteria:
    • Both design docs refreshed; no stale framing; test_design_docs_current.py passes.
    • Adapter has no hardcoded ECS/ALB/VPC defaults; overrides flow through; test_p1_1_adapter_parameterization.py passes.
    • v1.1 S3 regression passes; pytest 371 (was 350, +21); run_ci.sh exits 0; run_platform.sh --check-only exits 0.

Phase 40 — contract-interpolation

  • Description: ${env.<field>} + ${contract.<field>} resolver expansion from environment onboarding JSON (D-081). Environment JSON schema (schemas/environment.schema.json) + qa/prod/dr placeholder bindings. core/environment_check.py gains load(). Sample contracts use naming patterns that include region, account id, environment (e.g. acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}). Expansion is recursive (D-087), post-schema-validation, pre-IR-resolution; unknown tokens raise ValueError. resolve() accepts environment_override (D-088).
  • Status: complete (v1.8.2)
  • Depends on: [39]
  • Requirements: REQ-103, REQ-104
  • Success Criteria:
    • schemas/environment.schema.json exists; 4 env files validate; load() works.
    • _expand_vars in resolver; unknown tokens raise; recursive over dicts/lists/strings.
    • Sample contracts use ${env.*} + ${contract.*} naming patterns; resolve to concrete values.
    • tests/test_environment_schema.py + tests/test_interpolation.py + tests/test_sample_contracts_interpolate.py pass.
    • pytest 406 (was 371, +35); run_ci.sh exits 0; run_platform.sh --check-only exits 0.