c99da9a58c
---ci---
project: acdl
phase: 0
milestone: v1.8
status: complete
requirements:
covered: [REQ-76, REQ-77, REQ-78, REQ-79, REQ-80, REQ-81, REQ-82, REQ-83, REQ-84, REQ-85, REQ-86, REQ-87, REQ-88, REQ-89, REQ-90, REQ-91, REQ-92, REQ-93, REQ-94, REQ-95, REQ-96, REQ-97, REQ-98, REQ-99]
partial: []
---/ci---
v1.8 milestone complete. 11 phases (28-38), 24 requirements (REQ-76..99).
Track 1 — P1 Remediation (8 issues, all resolved):
- P1-3: SSM fail-loud without CMK + escape hatch
- P1-4: WAF custom rules emit nested HCL blocks
- P1-5: WAF default_action input honored
- P1-6: Terraform-rendered invoke policy (no placeholder account ID)
- P1-7: L2 composition outputs resolved + adapter output blocks
- P1-8: Per-run temp dir (terraform/spike removed)
- P1-9: Forge-agnostic API URLs (GITHUB_API_BASE)
- S1: Static-key override wired to configure-aws-credentials inputs
Track 2 — Encryption + Deletion Protection by Default:
- Per-stack CMK (kms-key primitive, 90-day rotation, no shared keys)
- All 12 primitives have encryption_enabled NFR + kms_key_arn input
- L2 modules wire per-stack CMK to all children
- All 12 primitives have deletion_protection NFR (default true)
- Adapter emits lifecycle { prevent_destroy = true }
- L2 feature flag propagation (inputs.deletion_protection)
Track 3 — Uptime + Standards + Docs:
- uptime-kuma primitive (ECS Fargate, feature flag, alert channels)
- deploy-uptime pipeline stage (separate state)
- Decommission mode (2-step HITL SRE gates + CMDB validation)
- modules/STANDARDS.md (L1+L2 authoring + review standards)
- schemas/README.md, pipelines/README.md, adapters/README.md
Tests: 275 -> 350 (+75 new). All pass. run_ci.sh + check-only green.
Zero pending P1 issues remaining.
42 KiB
42 KiB
ACDL — Requirements
v1
Category: Repos & Org
- REQ-01: All demo code lives under the
continuous-intelligenceGitea org athttps://git.cloudinit.dev. - REQ-09: Three repos exist:
acdl(platform + stubs + reusable workflows),acdl-contracts(developer surface),acdl-evidence(Pages audit timeline).
Category: L1 Modules
- REQ-02: 8 L1 module folders exist under
acdl/modules/l1/:l1-eks-fargate,l1-iam-role,l1-lambda,l1-api-gateway,l1-eventbridge,l1-sqs,l1-s3,l1-cloudwatch. - REQ-03: Each L1 module has a
manifest.yaml(declaring inputs) and amock_apply.shthat echoes success, sleeps 1s, and exits 0.
Category: L2 Modules
- REQ-04: 4 L2 modules exist under
acdl/modules/l2/:l2-invoice-service,l2-commodity-price-feed,l2-energy-analytics-api,l2-regulatory-reporting, each composing the specified L1s. - REQ-05: L2 modules compose L1 primitives into deployable shapes with a maximum depth of 5.
Category: Core Scripts
- REQ-06:
mock_executor.shreads an L2 composition, invokes each L1mock_apply.sh, and writesstate.json. - REQ-07:
policy_checker.pyreadscontract.yamland fails withPOLICY_VIOLATION:PUBLIC_INGRESSonpublic-ingress: true; otherwise passes. - REQ-08:
confidence_signal.pyreturns a base score of 0.90 and drops to 0.40 (with reason code) when policy fails; gate threshold is ≥ 0.50.
Category: Evidence Stream
- REQ-11:
evidence_writer.pyappends events toaudit.jsonand links each event to the previous via a SHA-256 hash chain (prev_hash+ ownhash). - REQ-13:
acdl-evidenceis Pages-enabled and servesaudit.jsonplusindex.html.
Category: Pipeline
- REQ-10: The reusable pipeline runs Dev (autonomous), pauses at QA (manual approval), pauses at Prod (manual approval), then finalizes by committing
audit.jsontoacdl-evidence. - REQ-12: Opening an Issue in
acdl-contractsrunsl3b_agent_stub.py, commits a generatedcontract.yamlto a new branch, closes the Issue, and triggers the main pipeline.
Category: Demo Acts
- REQ-14:
index.htmluses vanilla JS to fetchaudit.jsonfrom the Pages URL and render events as a timeline. - REQ-15: All four demo acts (Friction, Developer Self-Service, Citizen Developer, Safety Net) reproduce deterministically in a dry run.
v2
(None — v1 covers the complete demo.)
v1.1 (Prior milestone — architecture finalization + v1 spike, complete)
Category: Architecture Finalization
- REQ-16: Architecture reaches v1.0 — all 11 open decisions in
docs/architecture.md§13 are resolved and recorded inPROJECT.md(W1.A, W1.B, W2.A, W3.D, W3.E, BA.A–F, OpenTofu timing). - REQ-17: Target Stack IR is defined as a JSON Schema under
schemas/ir.schema.json; substrate-agnostic (resources, relationships, composition max-depth-5, policy hooks). - REQ-18:
PolicyCheckResultnormalized schema is defined underschemas/policy_check_result.schema.json; a Checkov adapter translates Checkov JSON to this schema. - REQ-19: Six-input confidence signal is specified under
platform/confidence_signal.pywith per-env thresholds (dev 0.50 / qa 0.75 / prod 0.90 / dr 0.95) and severity→penalty mapping (critical=hard override, high=-0.2, medium=-0.05, low=-0.01, info=0.0). - REQ-20: Tiered audit ledger design is authored: S3 Object Lock (compliance mode, 7-yr) + DynamoDB outbox (RPO=0, JWS detached signatures,
prev_event_hashchain, daily checkpoints). - REQ-21: Full 8-concern HITL matrix + separation-of-duties design is authored (CODEOWNERS routing + DynamoDB identity-distinctness check; pre-execution gate model; 1d warn / 2d freeze timeout).
- REQ-22: Contract schema (JSON Schema draft 2020-12) is defined under
schemas/contract.schema.jsonwith per-env mandatory/optional inputs (W3.E) andprofile: agenticmarker for L3B fields.
Category: AWS OIDC Bootstrap
- REQ-23: AWS auth bootstrap + state backend for the spike: an S3 state bucket + DynamoDB lock/outbox table + an IAM user with a minimal scoped policy (S3 + DynamoDB + plan-only). The temporary long-lived key is used once (waiver D-034) then rotated via
scripts/rotate_spike_key.shafter each spike run (D-039). Real OIDC federation is deferred to v1.2 — Gitea Actions does not supportid-token: write(RESEARCH TARGET 1, conf 0.95), blocked on go-gitea/gitea#36988.
Category: v1 Spike — IR, L1, Adapter
- REQ-24: One real L1 module
l1-s3exists undermodules-ir/l1/l1-s3/with an IR-typed interface (typed inputs/outputs/NFRs) registered in the L1 registry. - REQ-25: One real L2 thin-composition
l2-static-assetsexists undermodules-ir/l2/l2-static-assets/referencingl1-s3only (depth 1, within max-depth-5). - REQ-26: The Terraform adapter (
adapters/terraform/) compiles the IR-typed L1 interface to Terraformvariable/outputblocks and the L2 thin-composition tree to a Terraform root module; it emits a realterraform planagainst AWS via OIDC; state is stored in S3 + DynamoDB.
Category: v1 Spike — End-to-End
- REQ-27: One end-to-end contract submission (
contracts/spike.yamlforl2-static-assets) flows through: contract schema validation → contract→IR resolution →terraform plan(real AWS) → CheckovPolicyCheckResult→ confidence signal → evidence event written to the DynamoDB outbox. - REQ-28: Spike verification (
scripts/verify_phase10.sh) proves the IR-shaped commitments hold: the adapter is the only substrate-specific code; no polyglot mess; the L1 content, contract YML, and thin-composition tree are substrate-agnostic.
Out of Scope (v1.1)
| Feature | Reason |
|---|---|
| Full HITL matrix wiring (qa/prod/dr) | Spike is dev-only (terraform plan); HITL wiring is v1.2. |
| Kyverno + OPA policy engines | Spike uses Checkov only; Kyverno/OPA are v1.2. |
| MCP skill catalog + real L3B agent | L3B spike = a single stub contract submission; the 5-skill catalog is v1.2. |
| GitOps reconciler (ArgoCD/Flux) | v1.2. |
| Multi-region state / outbox | Single-region in v1 (§9, §12.3). |
| Prod/dr environments | v1.2. |
Terraform apply (real provisioning) |
Spike runs plan only; apply is gated by HITL in v1.2. |
v1.2 (Prior milestone — platform hardening + first real consumer deployment, complete, tag v1.3.0)
Category: Documentation & Simplification
- REQ-29:
README.mdis fully rewritten to reflect the v1.1-complete platform: the actual spike flow (contract → IR →terraform plan→ Checkov → confidence signal → outbox), how to run it (scripts/run_platform.sh), the real repo layout (acdl_platform/,schemas/,adapters/,terraform/,modules-ir/,contracts/,demo/), and the v1.2 objective. No stale "v1.1 (active)" framing. - REQ-30: NFR hardening of the v1.1 spike: (a)
terraform/bootstrap/spike_runner_policy.jsonaudited to least-privilege (S3 + DynamoDB + ECS + ECR + ELB + IAM plan-only, no wildcards beyond the documented exceptions); (b)create_state_backend.pyandcreate_iam_user.pyare idempotent (re-running exits 0 without duplicating resources); (c)run_spike_plan.sh+run_spike_e2e.shconsolidated into a singlescripts/run_platform.shwith proper exit codes and error handling; (d) P1-1 carried forward from the v1.1 audit — the two AWS access key IDs in.ciagent/VERIFY.mdPhase 09 narrative are redacted to placeholders; (e) any remaining staleplatform/paths in.ciagent/are corrected toacdl_platform/.
Category: L1 Catalog Expansion (ECS Fargate)
- REQ-31: Six new IR-typed L1 modules exist under
modules-ir/l1/and are registered inmodules-ir/registry.json: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(application load balancer + listener + target group),l1-ecr(ECR repository). Each has aninterface.jsonvalid againstschemas/ir.schema.jsonand produces a validterraform planfragment via the Terraform adapter. The adapterTYPE_MAPis expanded to cover all six IR resource types.
Category: L2 Composition & Contract Schema
- REQ-32:
l2-microservicethin-composition exists undermodules-ir/l2/l2-microservice/referencing the six ECS L1s (depth ≤ 5, within max-depth-5).schemas/contract.schema.jsonis extended with microservice inputs (image: string,port: integer,env: map,healthcheck: object) and validates acontracts/microservice.yamlsubmission. Contract→IR resolution (acdl_platform/contract_resolver.py) yields a complete target stack forl2-microservice.
Category: Real Provisioning
- REQ-33: The platform runs
terraform apply(not justplan) for thedevenvironment, autonomous per §10 (confidence ≥ 0.50, no HITL). The apply creates real AWS resources (VPC, ECS cluster, ECR repo, ALB, ECS service) and the result is captured in the evidence stream.applyfor qa/prod/dr remains HITL-gated and out of scope for v1.2.
Category: Consumer Repo
- REQ-34: A new Gitea repo
acdl-consumer-microserviceexists under thecontinuous-intelligenceorg, containing: a basic HTTP microservice (e.g., a tiny Python/Go server returning 200), aDockerfile, an ECR push step, and acontracts/microservice.yamlsubmission forl2-microservice(dev environment).
Category: End-to-End Verification
- REQ-35: One end-to-end flow: consumer commit to
acdl-consumer-microservice→ pipeline triggered → contract→IR resolution →terraform plan→terraform apply(dev) → a live ECS Fargate service serving HTTP 200 on its ALB → evidence event written to the DynamoDB outbox → the event renders on theacdl-evidencetimeline.scripts/verify_phase16.shproves the full flow green.
v1.3 (Prior — module documentation + thin-composition removal, complete)
Category: Thin-Composition Removal
- REQ-36: The L2 thin-composition layer is removed completely:
composition.jsonfiles,acdl_platform/contract_resolver.py,schemas/contract.schema.json,contracts/spike.yaml,contracts/microservice.yaml, and L2 entries inmodules-ir/registry.jsonare deleted. The L2 directories are kept as placeholders with READMEs. The downstream pipeline (adapter → checkov → confidence → outbox) is patched to load a pre-existing IR instance instead of resolving a contract. - REQ-37: A
modules-ir/README-TEMPLATE.mdexists that works for both L1 and L2 modules, written in plain language (no jargon), with sections for Overview, Resources, Inputs, Outputs, Usage, Compliance extension points, and Versioning. - REQ-38: Every module has a
README.md: the 7 L1 modules have full READMEs with Resources/Inputs/Outputs/Usage/Compliance-extension-points/Versioning sections derived from theirinterface.json; the 2 L2 modules have placeholder READMEs noting the composition is under redesign. Amodules-ir/README.mdcatalog index lists all modules with one-line descriptions and links.
Category: Testing
- REQ-39: A pytest test suite exists under
tests/covering the platform components offline (no AWS, no Checkov, no DynamoDB): the Terraform adapter (adapters/terraform/adapter.py), the confidence signal (acdl_platform/confidence_signal.py), the Checkov adapter (adapters/terraform/policy/checkov_adapter.py), and the outbox writer (acdl_platform/outbox_writer.py). The suite validates the IR schema, registry, spike_instance, and adapter output structure.pyproject.toml+requirements-test.txtpin test dependencies (pytest, jsonschema, pyyaml, boto3-stubs or moto for outbox mocking).
Category: Shell Reproducibility
- REQ-40:
scripts/run_platform.shhas a--check-onlymode that runs offline: loads the pre-existing IR instance, runs the adapter to emit Terraform, validates the JSON structure — without AWS credentials, Checkov, or DynamoDB. The existing--plan-onlyand full modes continue to require AWS. The--check-onlymode is what CI pipelines run.
Category: CI/CD Pipelines
-
REQ-41: Identical CI/CD pipelines exist for both Gitea Actions (
.gitea/workflows/ci.yml, dev environment) and GitHub Actions (.github/workflows/ci.yml, production). Both run the same three stages: (1) lint —py_compileall Python files, (2) test —pytest, (3) check-only —bash scripts/run_platform.sh --check-only. Both trigger on push to main + pull request. Both useubuntu-latest. Identical outcomes — the only difference is the runner environment. -
REQ-42:
pyproject.tomlexists at the repo root with pytest configuration (testpaths, markers) and the project metadata.requirements-test.txtpins test-only dependencies separate from runtime dependencies.
v1.4 (Active — central pipeline contract + shell reproducibility + streaming)
Category: Central Pipeline Contract
- REQ-43: A central pipeline contract exists as
schemas/pipeline.schema.json(JSON Schema draft 2020-12) +pipelines/ci.yaml(YAML instance). The contract declares the pipeline name, triggers (push/PR branches), runner, Python version, and stages (name + command + required + install + description). Both.gitea/workflows/ci.yml(Gitea Actions, dev) and.github/workflows/ci.yml(GitHub Actions, production) implement the same stages, commands, triggers, and runner as declared in the contract. A test (tests/test_pipeline_contract.py) validates the contract against the schema and asserts both workflows conform (same jobs, same commands, same triggers, same runner, byte-identical).
Category: Shell Reproducibility
- REQ-44:
scripts/run_ci.shreproduces the CI pipeline locally — runs the same 3 stages (lint, test, check-only) in sequence with proper exit codes, failing on first error. The script exits 0 with "CI PIPELINE OK" on success. A--quietflag suppresses per-stage banners. The script mirrors the central pipeline contract (pipelines/ci.yaml) so the shell and CI environments produce identical outcomes.
Category: Pipeline Streaming
- REQ-45:
scripts/run_platform.shstreams output by default: terraform init/validate/plan output is piped to stdout viatee(visible to the user and logged), Checkov results are printed in human-readable form, and PolicyCheckResult records are displayed with severity, rule ID, and pass/fail status per record. The--check-onlymode streams the emitted Terraform file content. A--quietflag suppresses streaming (output to log files only) for backwards compatibility. Both gitea and github workflows are byte-identical (identical outcomes — the only difference is the forge runtime).
v1.5 (Prior — consumer happy path + zero-trust docs + reusable deploy workflow, complete)
Category: Consumer Happy Path Documentation
- REQ-46:
README.mdis rewritten so the consumer model is unambiguous: this repo is the platform source; a consumer never clones it. A consumer repo contains only app code +contract.yamlreferencing the central pipeline + contract. The platform-flow diagram is a mermaidflowchart TD(replacing the ASCII art). "L3A"/"L3B" nomenclature is removed from README (single-surface model). "spike" nomenclature is removed from prose (code paths in bash blocks are kept verbatim). - REQ-47:
docs/CONSUMER_GUIDE.md(all-caps) replacesdocs/consumer-guide-static-assets.md. It is generic across all L2 modules (static-assetsas the worked example), uses mermaid diagrams (model + pipeline flow), documents versioneduses:references (floating MAJOR+MINOR tags — bare/@maindiscouraged), scopes prerequisites to consumer-repo bootstrap only (no Terraform/Checkov/boto3/runner-key — those are platform-repo concerns), and documents that the pipeline fetches the ACDL repo at run time via a reusable workflow (consumers never invokescripts/run_platform.shlocally for the happy path). - REQ-48:
README.mdCredentials section is rewritten to express the zero-trust target model: consumer repos use OIDC federation (no long-lived keys) with attribute-based authorization (ABAC) — IAM roles + session policies scoped by repository identity and resource-creation tags so a consumer can only view/update resources it created (blast-radius containment). A documented override allows a static key in GitHub Secrets (consumer repo) or.env.secrets(local testing), rotated by a platform-managed scheduled pipeline on a daily cadence; when.env.secretsis used locally, rotating out of band is the consumer's responsibility.
Category: Reusable Deploy Workflow
- REQ-49: A reusable deploy workflow exists as byte-identical
.gitea/workflows/deploy.yml(Gitea, dev) and.github/workflows/deploy.yml(GitHub, production), implementing the central deployment pipeline contract (pipelines/deploy.yamlvalidated againstschemas/deploy-pipeline.schema.json). It is invoked by consumer repos viauses: acdl/.gitea/workflows/deploy.yml@vMAJOR.MINOR(versioned tag). The workflow checks out the consumer repo, checks out the ACDL platform repo into the runner workspace, installs runtime deps (Python, Terraform, Checkov), and invokesscripts/run_platform.shagainst the consumer's contract path (passed as a workflow input). OIDC is the default auth (permissions: id-token: write); a static-key override reads from repository secrets. - REQ-50:
contracts/static-assets.yamluses a versioneduses:reference (@v1.4, MAJOR+MINOR) — not bare@v1or@main— as the canonical example the consumer guide points at. - REQ-51:
tests/test_pipeline_contract.pyis extended to validate the new deploy workflows: both files exist, are byte-identical, and conform toschemas/deploy-pipeline.schema.json(stages present, names matchpipelines/deploy.yamlstage names). The existing CI-workflow conformance tests continue to pass unchanged.
v1.6 (Active — consumer-facing docs restructure + terminology normalization + environments concept)
Category: Internal-surface scrub
- REQ-52: No consumer-facing documentation (README.md, docs/, modules//README.md, contracts/**) references
.ciagent/— it is local CIAgent metadata, never visible to platform engineers or consumers. The README repository-layout table has no.ciagent/row. No.gitea/references appear in consumer-facing docs (consumers use GitHub only); the README repository-layout table has no.gitea/workflows/row. - REQ-53:
acdl_platform/is renamed tocore/across the directory, all imports in tests/scripts/pipelines/workflows, and all doc references. (platform/was the original target but shadows Python's stdlibplatformmodule —core/was chosen to stay importable.)grep -R "acdl_platform" .(excluding.ciagent/,demo/,.git/) returns 0 hits. The test suite passes after the rename.
Category: Docs site restructure
- REQ-54:
docs/is restructured into a Jekyll-style GitHub Pages site:docs/_config.yml,docs/index.md(landing),docs/modules/(catalog + per-module Pages-friendly copies),docs/contracts/index.md,docs/pipeline/index.md+docs/pipeline/versioning.md,docs/environments/index.md,docs/consumer-guide.md,docs/architecture.md(consolidated from architecture.md + architecture-v1.0.md, current-architecture only),docs/vision.md. No.ciagent/links anywhere indocs/. Consumer-facing content (modules, contracts, pipeline, versioning) lives in Pages.
Category: Terminology normalization
- REQ-55: Consumer-facing docs drop the "L2" nomenclature — L2 modules are referred to as "modules". "L1" label is dropped in consumer-facing docs — L1 primitives are referred to as "primitives". The "composition" terminology is changed to "pattern" for modules in prose (the on-disk
composition.jsonfiles and code references are unchanged this phase). A roadmap entry records that "composition" will later describe the thin orchestration where consumers dynamically create a module directly from the contract file (future implementation, not implemented now). - REQ-56: The term "forge" is replaced in consumer-facing docs with "platform runners" / "platform-managed" as appropriate. The term "forge" remains only in internal architecture docs.
Category: README rewrite
- REQ-57: README.md repository-roles section is restated to match reality: a consumer repo contains (a) its application code, (b) one or more contracts (
.acdl/contract.yaml), and (c) one or more CI definitions (a thin.github/workflows/deploy.ymlthatuses:the central reusable workflow, pointing at the appropriate environment + contract). The platform repo (this one) owns modules/adapters/schemas/pipelines/scripts/workflows. A consumer never clones the platform repo. - REQ-58: README.md Status section is replaced with a Features list (referenceable by consumers and platform engineers) and a Roadmap subsection listing only planned future features (no internal CIAgent status, no version-by-version changelog).
- REQ-59: README.md "How the platform works" mermaid diagram is revised so all node text is visible (no overflow): labels are split with
<br/>, boxes widened as needed. A security-checks stage is added before the policy-checks stage. Specific tools (Checkov, Terraform) are not named — they are "security checks (adapter)", "policy checks (adapter)", "infrastructure plan". An "infrastructure apply" stage is added at the appropriate level (dev only, after confidence). - REQ-60: README.md Credentials & zero-trust section removes the "go-gitea/gitea#36988 blocked" mention and the "waivers D-039/D-047" language (not consumer/platform-engineer facing). It states: default OIDC + ABAC; alternative is a static AWS key (GitHub Secrets for platform-runner runs, or
.env.secretslocally) with the expectation of daily rotation (platform-managed for runner runs) or out-of-band rotation (consumer-managed for local.env.secrets).
Category: Environments concept + onboarding
- REQ-61: The concept of platform-managed environments is introduced: consumers are not required to provide an AWS account, VPC, subnet, S3 state bucket, or runner key.
docs/environments/index.mddocuments that a named environment is a platform-owned AWS account + network + state backend + IAM role surfaced to the consumer via ABAC, selected by name in the contract. The old README environments table (dev/qa/prod/dr) is removed completely. A minimal onboarding scaffold exists:platform/environments/with a sampledev.json+ README,platform/environment_check.py, a wire-in at the top ofscripts/run_platform.sh, a friendly first-run onboarding message when no environment is defined for the repo, andtests/test_environment_check.pycovering the missing-env and present-env cases.
v1.7 (Active — production platform + contract ingestion + pipeline maturation)
Category: Rename + production-ready stack
- REQ-62:
static-assetsis renamed tostatic-assetseverywhere (D-048 — including.ciagent/historical narrative: verbatim phase descriptions, REQ-25/27/50 text, D-036, RESEARCH.md).grep -R "static-assets[^s]" .(excluding.git/) returns 0 hits. The module dirmodules/l2/static-assets/→modules/l2/static-assets/;contracts/static-assets.yaml→contracts/static-assets.yaml; the registry key is renamed; all scripts, tests, docs, and.ciagent/files usestatic-assets. The reconstruction test is updated to expectstatic-assetsthroughout. - REQ-63: Two new primitives exist:
cloudfront(distribution + OAC, stack typesaws:cloudfront:distribution+aws:cloudfront:originaccesscontrol) andwaf(WAFv2 web ACL, stack typeaws:wafv2:webacl), each with aninterface.jsonvalid againstschemas/stack.schema.jsonand a full README (Resources/Inputs/Outputs/Usage/Compliance/Versioning). Both are registered inmodules/registry.json. The Terraform adapterTYPE_MAP/INPUT_MAP/OUTPUT_MAPcovers the new stack types. - REQ-64: The
static-assetsmodule is augmented to a production-ready stack referencing s3 + cloudfront + waf (depth 1, D-049).composition.jsonwires the s3 bucket regional domain name to the CloudFront origin, and the WAF web ACL ARN to the CloudFront distribution.schemas/contract.schema.jsonis extended for the new module inputs (price_class,viewer_protocol_policy,waf_enabled,default_ttl,max_ttl). Theuses:/ref:tag advances from@v1.4to@v1.6(D-056/D-057); floating git tagsv1.6+v1are created pointing atv1.6.0.
Category: Tagging standards + security adapters
- REQ-65: A required-tag set is defined in
schemas/tagging-standard.json(acdl:owner,acdl:contract,acdl:environment,acdl:cost-center). A Checkov custom YAML rule atadapters/terraform/policy/custom_rules/acdl_tagging.yamlfails (severitymedium) when required tags are missing on taggable resources.checkov_adapter.pyremoves the_emit_tag_naming_skipped()placeholder (D-043 closure) and mapsACDL_TAG_NAMINGas a real rule.scripts/run_platform.shStep 5 passes--external-checks-dirto load the custom rule. - REQ-66: A Wiz adapter stub exists at
adapters/wiz/wiz_adapter.pytranslating Wiz API issues →PolicyCheckResultrecords (engine: "wiz", D-052). It degrades gracefully when unconfigured (emits a singleSKIPPEDWIZ_NOT_CONFIGUREDrecord).tests/test_wiz_adapter.pypasses offline with a fixture response. The pipeline invokes it optionally (Step 5b) whenWIZ_API_TOKENis set. - REQ-67: A Kyverno K8s-native adapter exists at
adapters/kyverno/kyverno_adapter.pytranslating KyvernoPolicyReportresults →PolicyCheckResultrecords (engine: "kyverno", D-053). Sample policies exist atadapters/kyverno/policies/(disallow-privileged, require-labels, require-image-digests).tests/test_kyverno_adapter.pypasses offline. The adapter is inactive for Terraform-only stacks (the platform emits Terraform, not K8s manifests); it is ready for the GitOps reconciler roadmap item.schemas/policy_check_result.schema.jsonengine enum includescheckov | kyverno | opa | wiz.
Category: Platform Lambda + contract ingestion
- REQ-68: A platform Lambda (
core/lambda/contract_ingestor.py) is invoked via a Function URL (IAM auth) and accepts{ consumerRepo, contractId, contract, environment, action }. It writes contracts to a DynamoDB tableacdl-contracts(PKconsumerRepo, SKcontractId#submittedAt, SSE via a customer-managed CMK, point-in-time recovery) (D-051).terraform/platform/main.tfdefines the table, Lambda, Function URL, KMS key, Secrets Manager secret (acdl/github-token), and Lambda execution role.terraform/platform/consumer_invoke_policy.jsongrants the consumer's deploy rolelambda:InvokeFunctionUrlon the Lambda ARN, scoped via ABAC (cross-account). Onboarding grants the Lambda-invoke permission;docs/environments/index.mddocuments this.tests/test_contract_ingestor.pypasses offline (moto-mocked DynamoDB).
Category: Deploy outputs + error reporting + stage comments
- REQ-69:
scripts/run_platform.shhas apublish-outputsstep (after apply) that writes deploy outputs to SSM Parameter Store asSecureString(KMS-encrypted, namespaced/acdl/{env}/{contractId}/{output_name}) for runtime-injectable values, and acomment-outputsstep that posts a structured GitHub PR comment / job summary with human-readable connection strings (D-050).core/output_publisher.pyimplements the SSM write + GitHub comment formatting.tests/test_output_publisher.pypasses offline (moto + mocked GitHub API).pipelines/deploy.yaml+ both deploy workflow YAMLs declare the new stages (byte-identical). - REQ-70: The Lambda
report_erroraction (core/lambda/contract_ingestor.py) creates a GitHub issue on the platform repo (acdl/acdl) via the GitHub API using a token from Secrets Manager (D-055). Idempotent (comments on an existing open issue rather than duplicating)..github/workflows/deploy.yml+.gitea/workflows/deploy.yml(byte-identical) have anif: failure()error-report step invoking the Lambda viaaws lambda invoke-function-url(SigV4-signed). Gitea is excluded (only the CIAgent uses it; platform engineers and consumers use GitHub). - REQ-71:
.github/workflows/deploy.yml+.gitea/workflows/deploy.yml(byte-identical) post a PR comment after every successful pipeline stage (validate-contract, resolve-stack, plan, checkov, confidence, apply, publish-outputs) viascripts/post_stage_comment.sh(usesGITHUB_TOKEN+gh api; no-op when not in a PR context). The comment includes the stage name, status (pass), and key metrics (plan counts, confidence score, outputs published).
Category: Platform pipelines + release automation
- REQ-72: Three platform pipelines exist: (1)
.github/workflows/platform-test.yml(PR, stages: lint, unit-test, integration-test — runsrun_platform.sh --check-onlyfor every sample contract, schema-validation — validates allschemas/*.json+modules/**/interface.json+modules/**/composition.json+modules/<name>/examples/*.yamlagainst their schemas); (2).github/workflows/primitives-plan.yml(PR, plan-only for all L1 primitives via matrix,scripts/run_primitive_plan.sh); (3).github/workflows/patterns-plan.yml(PR, plan-only for all L2 modules via matrix,scripts/run_pattern_plan.sh). - REQ-73:
.github/workflows/release.ymlruns on merge tomain, 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, and creates a GitHub release with an auto-generated body (D-057).tests/test_release_logic.pypasses (unit test the semver computation + tag-update logic with a mockedgit describe).
Category: Remove legacy consumer-repos + module examples + RDS primitive
- REQ-74: The legacy consumer-repos directory is deleted entirely (a v1.2 artifact removed in v1.7; references in
.ciagent/historical narrative are rewritten per D-048). A recursive grep for the legacy directory name (excluding.git/) returns 0 hits. - REQ-75: A new RDS primitive (
modules/l1/rds/) with anengineinput (enum: postgres, mysql, etc.) demonstrates multi-engine variation (D-059). Every module (primitives + patterns) has amodules/<name>/examples/directory withsimple.yaml+complex.yaml(+ variation files) validated againstschemas/contract.schema.jsonin the platform-test pipeline schema-validation stage (D-058). Each module'sREADME.md## Examplessection references + excerpts the validated files.docs/modules/index.md+docs/consumer-guide.md+docs/contracts/index.mdare updated with the new module names + examples.
v1.8 (Active — P1 remediation + uptime + engineering standards + encryption/deletion-protection by default + decommission + docs)
Category: P1 Fixes
- REQ-76: WAF adapter emits custom
rulesas nested HCL blocks (not attribute syntax) and honorsdefault_actioninput (allow/block) — P1-4, P1-5 closed. - REQ-77: L2 composition
outputs[]array is resolved bycontract_resolver.pyintostack.outputs; the adapter emits correspondingoutputblocks — P1-7 closed. - REQ-78: SSM publisher fails loud when
ACDL_KMS_KEY_IDis unset (no silent AWS-managed-key fallback);ACDL_ALLOW_DEFAULT_KMS=1escape hatch for local testing — P1-3 closed. - REQ-79:
consumer_invoke_policyis rendered via Terraform with the caller's live account ID (no000000000000placeholder) — P1-6 closed. - REQ-80:
run_platform.shemits adapter output to a per-run temp dir, not committedterraform/spike/*.tf; the committed files are removed — P1-8 closed. - REQ-81:
contract_ingestor.pyreadsGITHUB_API_BASEenv for forge-agnostic API URLs (GitHub + Gitea) — P1-9 closed. - REQ-82: Deploy workflow static-key override is wired to
configure-aws-credentialsinputs (access-key/secret-key), not inert env vars — S1 closed.
Category: Encryption by Default
- REQ-83: A per-stack CMK primitive (
kms-key) exists with 90-day rotation enabled at creation; one key per L2 deployment; no shared keys across stacks. - REQ-84: All primitives have encryption by default (
encryption_enabledNFR, default true) + optionalkms_key_arninput. CMK is prioritized; managed KMS is the fallback when no CMK is provided. - REQ-85: L2 modules wire a per-stack CMK child + connect its
kms_key_arnoutput to each child'skms_key_arninput.
Category: Deletion Protection by Default
- REQ-86:
deletion_protectionNFR (boolean, default true) on every L1 primitive; the adapter emitsprevent_destroylifecycle meta-arg when true. - REQ-87: L2 modules expose a
features.deletion_protectionflag (default true); consumers can disable via contractinputs.deletion_protection: false.
Category: Uptime Monitoring
- REQ-88: An uptime-kuma L1 primitive exists (ECS Fargate) with:
feature_flag_enabled(boolean, default true),monitored_endpoints(array of HTTP/DNS/TCP checks),static_checks(pre-defined health checks),alert_channels(Teams webhook, email, SMS, GitHub issues). - REQ-89: Uptime is deployed by default after any L2 module deploy (separate terraform state, separate terraform run); L2 module outputs (endpoints) are passed to the uptime deployment as
monitored_endpoints. The uptime URL is published to the consumer via PR comment. - REQ-90: The
feature_flag_enabledinput (set from consumer contractinputs.uptime_enabled, default true) disables the uptime deployment entirely (no resources emitted). - REQ-91: A
deploy-uptimepipeline stage is declared inpipelines/deploy.yaml+ both deploy workflow YAMLs (byte-identical).
Category: Decommission + CMDB
- REQ-92: A decommission mode on the deploy pipeline (
mode: decommission) implements a 2-step pipeline: (1) plan/apply to disable deletion protection with an HITL SRE gate, (2) plan/apply with all counts set to 0 with a second HITL SRE gate. Uses the existing deploy pipeline with different behavior. - REQ-93: A DynamoDB
acdl-change-requeststable serves as the CMDB. The decommission alias accepts achangeRequestIdinput validated via avalidate_change_requestLambda action (CR status must beapproved). - REQ-94: The decommission flow is documented in
docs/CONSUMER_GUIDE.md(how to request a CR, trigger decommission, HITL gates, what happens).
Category: Engineering Standards
- REQ-95:
modules/STANDARDS.mdexists with comprehensive L1 + L2 authoring + code review standards (scanned from current modules): required files, interface schema, input/output/NFR conventions, encryption + deletion protection as mandatory NFRs, naming, adapter extension pattern, code review checklist. - REQ-96:
modules/README.mdcatalog index includes all primitives (rds + uptime + kms-key added);modules/README-TEMPLATE.mdupdated with## NFRssection.
Category: Path Documentation
- REQ-97:
schemas/README.mddocuments how to write a schema, wire it into the platform, test it in CI, where to write tests, dependencies, and the existing schema catalog. - REQ-98:
pipelines/README.mddocuments how to write a pipeline contract, wire it into workflows, test it, dependencies, and the existing pipeline catalog. - REQ-99:
adapters/README.mddocuments how to write an adapter, wire it into the platform, test it, dependencies, and the existing adapter catalog.
Out of Scope (v1.2)
| REQ | Original criterion | Clarified criterion (effective) | Decision |
|---|---|---|---|
| REQ-09 | Three repos exist | Three repos exist (acdl, acdl-contracts, acdl-evidence) under continuous-intelligence; new repos use default_branch: "main", auto_init: true |
D-015 |
| REQ-10 | "Pages returns 200 with placeholder index.html" on acdl-evidence |
Gitea has no Pages; substitute: an HTTP GET against the raw file URL https://git.cloudinit.dev/continuous-intelligence/acdl-evidence/raw/branch/main/index.html returns 200 with the placeholder HTML body |
D-012, D-016 |
| REQ-10 | "qa and prod environments exist on acdl-contracts" |
Gitea has no environments API and ignores environment: blocks; substitute: the reusable workflow defines qa-gate and prod-gate jobs gated by workflow_dispatch approval inputs (D-004 fallback); a qa and prod branch may be created on acdl-contracts as a visible stand-in for environments |
D-013 |
Out of Scope (v1.0 demo — retained for history)
| Feature | Reason |
|---|---|
| Real cloud provisioning (AWS/GCP/Azure) | Demo explicitly stubs all infrastructure; no cloud access available. |
| Real LLM inference / external AI APIs | Spec forbids external AI; L3B is a keyword parser. |
| Production-grade infrastructure | Demo target is a 30-minute executive show, not a production system. |
| Adversarial tamper-proofing of evidence | Hash chain is demonstrative; not cryptographically secure against a determined attacker. |
| Multi-tenant isolation | Out of demo scope. |
Traceability
v1.0 (prior — demo)
| Requirement | Phase | Status |
|---|---|---|
| REQ-01 | 1 | complete (v1.0.1) |
| REQ-02 | 2 | complete (v1.0.2) |
| REQ-03 | 2 | complete (v1.0.2) |
| REQ-04 | 3 | complete (v1.0.3) |
| REQ-05 | 3 | complete (v1.0.3) |
| REQ-06 | 3 | complete (v1.0.3) |
| REQ-07 | 3 | complete (v1.0.3) |
| REQ-08 | 3 | complete (v1.0.3) |
| REQ-09 | 1 | complete (v1.0.1) |
| REQ-10 | 4 | complete (v1.0.4) |
| REQ-11 | 3 | complete (v1.0.3) |
| REQ-12 | 4 | complete (v1.0.4) |
| REQ-13 | 5 | complete (v1.0.5) |
| REQ-14 | 5 | complete (v1.0.5) |
| REQ-15 | 5 | complete (v1.0.5) |
v1.1 (prior — architecture finalization + v1 spike, complete)
| Requirement | Phase | Status |
|---|---|---|
| REQ-16 | 07 | complete (v1.1.2) |
| REQ-17 | 07 | complete (v1.1.2) |
| REQ-18 | 07 | complete (v1.1.2) |
| REQ-19 | 07 | complete (v1.1.2) |
| REQ-20 | 07 | complete (v1.1.2) |
| REQ-21 | 07 | complete (v1.1.2) |
| REQ-22 | 07 | complete (v1.1.2) |
| REQ-23 | 08 | complete (v1.1.3) |
| REQ-24 | 09 | complete (v1.1.4) |
| REQ-25 | 10 | complete (v1.1.5) |
| REQ-26 | 09 | complete (v1.1.4) |
| REQ-27 | 10 | complete (v1.1.5) |
| REQ-28 | 10 | complete (v1.1.5) |
v1.2 (prior — platform hardening + first real consumer deployment, complete)
| Requirement | Phase | Status |
|---|---|---|
| REQ-29 | 11 | complete (v1.2.1) |
| REQ-30 | 12 | complete (v1.2.2) |
| REQ-31 | 13 | complete (v1.2.3) |
| REQ-32 | 14 | complete (v1.2.4) |
| REQ-33 | 15 | partial (v1.2.5, IAM-blocked) |
| REQ-34 | 15 | complete (v1.2.5) |
| REQ-35 | 16 | partial (v1.2.6, IAM-blocked) |
v1.3 (prior — module documentation + thin-composition removal, complete)
| Requirement | Phase | Status |
|---|---|---|
| REQ-36 | 17 | complete (v1.3.1) |
| REQ-37 | 17 | complete (v1.3.1) |
| REQ-38 | 17 | complete (v1.3.1) |
| REQ-39 | 18 | complete (v1.3.2) |
| REQ-40 | 18 | complete (v1.3.2) |
| REQ-41 | 18 | complete (v1.3.2) |
| REQ-42 | 18 | complete (v1.3.2) |
v1.4 (prior — central pipeline contract + shell reproducibility + streaming)
| Requirement | Phase | Status |
|---|---|---|
| REQ-43 | 19 | complete (v1.4.1) |
| REQ-44 | 19 | complete (v1.4.1) |
| REQ-45 | 19 | complete (v1.4.1) |
v1.5 (prior — consumer happy path + zero-trust docs + reusable deploy workflow, complete)
| Requirement | Phase | Status |
|---|---|---|
| REQ-46 | 20 | complete (v1.5.0) |
| REQ-47 | 20 | complete (v1.5.0) |
| REQ-48 | 20 | complete (v1.5.0) |
| REQ-49 | 20 | complete (v1.5.0) |
| REQ-50 | 20 | complete (v1.5.0) |
| REQ-51 | 20 | complete (v1.5.0) |
v1.6 (complete — consumer-facing docs restructure + terminology normalization + environments concept, tag v1.6.0)
| Requirement | Phase | Status |
|---|---|---|
| REQ-52 | 21 | complete (v1.6.0) |
| REQ-53 | 21 | complete (v1.6.0) |
| REQ-54 | 21 | complete (v1.6.0) |
| REQ-55 | 21 | complete (v1.6.0) |
| REQ-56 | 21 | complete (v1.6.0) |
| REQ-57 | 21 | complete (v1.6.0) |
| REQ-58 | 21 | complete (v1.6.0) |
| REQ-59 | 21 | complete (v1.6.0) |
| REQ-60 | 21 | complete (v1.6.0) |
| REQ-61 | 21 | complete (v1.6.0) |
v1.7 (complete — production platform + contract ingestion + pipeline maturation, tag v1.7.0)
| Requirement | Phase | Status |
|---|---|---|
| REQ-62 | 22 | complete (v1.7.0) |
| REQ-63 | 22 | complete (v1.7.0) |
| REQ-64 | 22 | complete (v1.7.0) |
| REQ-65 | 23 | complete (v1.7.0) |
| REQ-66 | 23 | complete (v1.7.0) |
| REQ-67 | 23 | complete (v1.7.0) |
| REQ-68 | 24 | complete (v1.7.0) |
| REQ-69 | 25 | complete (v1.7.0) |
| REQ-70 | 25 | complete (v1.7.0) |
| REQ-71 | 25 | complete (v1.7.0) |
| REQ-72 | 26 | complete (v1.7.0) |
| REQ-73 | 26 | complete (v1.7.0) |
| REQ-74 | 27 | complete (v1.7.0) |
| REQ-75 | 27 | complete (v1.7.0) |
v1.8 (complete — P1 remediation + uptime + standards + encryption/deletion-protection by default + decommission + docs, tag v1.8.0)
| Requirement | Phase | Status |
|---|---|---|
| REQ-76 | 28 | complete (v1.8.0) |
| REQ-77 | 28 | complete (v1.8.0) |
| REQ-78 | 29 | complete (v1.8.0) |
| REQ-79 | 29 | complete (v1.8.0) |
| REQ-80 | 30 | complete (v1.8.0) |
| REQ-81 | 30 | complete (v1.8.0) |
| REQ-82 | 30 | complete (v1.8.0) |
| REQ-83 | 31 | complete (v1.8.0) |
| REQ-84 | 31 | complete (v1.8.0) |
| REQ-85 | 31 | complete (v1.8.0) |
| REQ-86 | 32 | complete (v1.8.0) |
| REQ-87 | 32 | complete (v1.8.0) |
| REQ-88 | 33 | complete (v1.8.0) |
| REQ-89 | 33 | complete (v1.8.0) |
| REQ-90 | 33 | complete (v1.8.0) |
| REQ-91 | 33 | complete (v1.8.0) |
| REQ-92 | 34 | complete (v1.8.0) |
| REQ-93 | 34 | complete (v1.8.0) |
| REQ-94 | 34 | complete (v1.8.0) |
| REQ-95 | 35 | complete (v1.8.0) |
| REQ-96 | 35 | complete (v1.8.0) |
| REQ-97 | 36 | complete (v1.8.0) |
| REQ-98 | 36 | complete (v1.8.0) |
| REQ-99 | 36 | complete (v1.8.0) |