Files
acdl/.ciagent/PLAN.md
T
Jon Chery 045c7279aa docs(P28-38): create 11 phase plans for v1.8
---ci---
project: acdl
phase: 28-38
milestone: v1.8
status: plan
---/ci---

11 phase plans created covering 24 requirements (REQ-76..99):
P28: adapter WAF + resolver outputs (P1-4,5,7)
P29: SSM KMS + invoke policy (P1-3,6)
P30: run-platform isolation + API portability + S1 (P1-8,9,S1)
P31: encryption-by-default + per-stack CMK
P32: deletion-protection-by-default + L2 feature flag
P33: uptime-kuma primitive + pipeline stage
P34: decommission alias + CMDB validation
P35: module engineering standards
P36: schemas/adapters/pipelines READMEs
P37: verify (4-layer)
P38: review-audit-complete
2026-07-22 22:02:09 +00:00

14 KiB
Raw Permalink Blame History

phase, name, milestone, requirements, type
phase name milestone requirements type
28-38 v1.8-p1-remediation-uptime-standards-encryption-decommission-docs v1.8
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
fix/feat/docs

ACDL v1.8 — Phase Plans

Milestone: v1.8. Planner: ci-planner. Status: active. 11 phases (2838), 24 requirements (REQ-76..99).

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

Requirements: REQ-76 (WAF nested rules + default_action), REQ-77 (L2 outputs resolution) Personas: platform-engineer (lead), backend-engineer Type: fix

Tasks (Wave 1 — sequential):

  1. platform-engineer: Fix WAF rules emission in adapters/terraform/adapter.py:346-348 — replace rules = {_value_expr(...)} with nested rules { ... } block emission per rule. Read inputs.get("default_action") (line 334) and emit allow {} / block {} based on input (default allow if absent).
  2. backend-engineer: Implement L2 composition outputs[] processing in core/contract_resolver.py resolve_l2() — after building resources (line 232), parse composition.get("outputs", []), resolve source via child_outputs, build stack_instance["outputs"] dict.
  3. platform-engineer: Extend adapter.py adapt() to emit output "<outName>" { value = <ref> } blocks from stack_instance.get("outputs", {}).
  4. platform-engineer: Add tests to tests/test_adapter.py (WAF custom rules, default_action block, output blocks) + tests/test_contract_resolver.py (L2 outputs for static-assets).

Must-haves:

  • WAF with custom rules emits rules { blocks, not rules = [
  • WAF default_action: block emits block {}
  • L2 resolution yields stack.outputs.*
  • Adapter emits output blocks
  • pytest passes (275 → ~285)

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

Requirements: REQ-78 (SSM fail-loud), REQ-79 (Terraform-rendered invoke policy) Personas: backend-engineer (lead), lambda-engineer, security-engineer Type: fix

Tasks (Wave 1):

  1. backend-engineer: Change core/output_publisher.py:54-55 _kms_key_id() — raise RuntimeError when ACDL_KMS_KEY_ID unset; add ACDL_ALLOW_DEFAULT_KMS=1 escape hatch.
  2. lambda-engineer: Convert terraform/platform/consumer_invoke_policy.json to Terraform-rendered template — add terraform/platform/variables.tf with data "aws_caller_identity" "current" {} + templatestring or replace() for account ID injection.
  3. backend-engineer: Add tests/test_output_publisher.py cases: test_kms_unset_raises, test_kms_unset_allow_default_kms. Add tests/test_invoke_policy.py asserting rendered policy has no 000000000000.

Must-haves:

  • SSM raises RuntimeError without CMK; escape hatch works
  • Rendered invoke policy has live account ID
  • pytest passes (~290)

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

Requirements: REQ-80 (temp dir), REQ-81 (forge-agnostic URLs), REQ-82 (static-key override) Personas: backend-engineer (lead), lambda-engineer Type: fix

Tasks (Wave 1 — parallel):

  1. backend-engineer: Change scripts/run_platform.sh:122 adapter target from terraform/spike to $WORK/tf. Update all downstream references. Remove committed terraform/spike/*.tf. Update tests/test_pipeline.py. Update deploy.yml artifact upload path.
  2. lambda-engineer: Add _github_api_base() + _forge_type() to core/lambda/contract_ingestor.py. Replace hardcoded URLs at lines 109, 149, 163. Add tests/test_contract_ingestor.py Gitea base URL test.
  3. backend-engineer: Restructure configure-aws-credentials step in both deploy workflows (byte-identical) — single conditional step with access-key/secret-key inputs when static key present. Update tests/test_pipeline_contract.py.

Must-haves:

  • run_platform.sh --check-only writes to temp dir
  • contract_ingestor.py uses GITHUB_API_BASE
  • Deploy workflow static-key override wired
  • Both deploy workflows byte-identical
  • pytest passes (~295)

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

Requirements: REQ-83 (kms-key primitive), REQ-84 (encryption NFRs on all primitives), REQ-85 (L2 CMK wiring) Personas: platform-engineer (lead), security-engineer Type: feat

Tasks (Wave 1 — kms-key primitive + adapter):

  1. platform-engineer: Create modules/l1/kms-key/ with interface.json (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) + instance.json + README.md + examples/.
  2. platform-engineer: Add aws:kms:key → aws_kms_key + aws:kms:alias → aws_kms_alias to adapter TYPE_MAP. Emit enable_key_rotation = true + alias.

Tasks (Wave 2 — encryption NFRs on all primitives, after Wave 1):

  1. platform-engineer: Add encryption_enabled NFR (default true) + kms_key_arn input to every L1 interface.json (s3, rds, ecr, ecs-service, ecs-cluster, alb, cloudfront, waf, vpc, iam-role). Update adapter to emit encryption blocks referencing the CMK when kms_key_arn is provided; managed KMS fallback with stderr warning when not.
  2. platform-engineer: Update both L2 composition.json files — add kms-key child + wires connecting kms_key_arn output to each child's kms_key_arn input.
  3. platform-engineer: Add tests/test_encryption.py — assert every primitive has encryption NFRs; assert adapter emits encryption blocks; assert L2 wires CMK; assert enable_key_rotation = true.

Must-haves:

  • kms-key primitive exists + registered
  • All primitives have encryption_enabled NFR + kms_key_arn input
  • L2 modules wire per-stack CMK
  • Adapter emits encryption blocks
  • pytest passes (~310)

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

Requirements: REQ-86 (deletion_protection NFR on all primitives), REQ-87 (L2 feature flag) Personas: platform-engineer (lead), backend-engineer Type: feat

Tasks (Wave 1):

  1. platform-engineer: Add deletion_protection NFR (boolean, default true) to every L1 interface.json (rds already has it). Update adapter to emit lifecycle { prevent_destroy = true } when NFR is true; omit when false. RDS gets BOTH deletion_protection arg + prevent_destroy lifecycle.
  2. backend-engineer: Add features object support to schemas/stack.schema.json (optional features.deletion_protection). Update core/contract_resolver.py resolve_l2() to propagate features.deletion_protection to each child's deletion_protection NFR. Add inputs.deletion_protection to schemas/contract.schema.json (optional boolean).
  3. platform-engineer: Add tests/test_deletion_protection.py — assert every primitive has the NFR; assert adapter emits prevent_destroy; assert L2 feature flag propagation.

Must-haves:

  • Every primitive has deletion_protection NFR (default true)
  • Adapter emits prevent_destroy = true when true
  • L2 feature flag propagates
  • pytest passes (~320)

Phase 33 — uptime-kuma-primitive

Requirements: REQ-88 (uptime primitive), REQ-89 (deployed by default after L2), REQ-90 (feature flag), REQ-91 (pipeline stage) Personas: platform-engineer (lead), backend-engineer Type: feat

Tasks (Wave 1 — primitive + adapter):

  1. platform-engineer: Create modules/l1/uptime/ with interface.json (type aws:ecs:uptime-service, inputs: container_image/region/monitored_endpoints/static_checks/alert_channels/feature_flag_enabled/cpu/memory, outputs: uptime_url/service_arn/task_definition_arn, NFRs: deletion_protection/encryption_enabled) + instance.json + README.md + examples/simple.yaml + examples/complex.yaml.
  2. platform-engineer: Add aws:ecs:uptime-service to adapter TYPE_MAP. Emit ECS Fargate task + service + ALB + listener + EFS volume + CloudWatch log group. When feature_flag_enabled=false, emit NO resources. Register in registry.json.

Tasks (Wave 2 — pipeline + script, after Wave 1):

  1. backend-engineer: Add deploy-uptime stage to pipelines/deploy.yaml (after publish-outputs). Update both deploy workflows (byte-identical) with the stage. Add scripts/seed_uptime_monitors.py for post-deploy monitor seeding via uptime-kuma API.
  2. backend-engineer: Update scripts/run_platform.sh — add deploy-uptime step: read L2 stack outputs, construct synthetic uptime contract with monitored_endpoints from outputs, run second terraform apply with separate state ($WORK/uptime-tf/), publish uptime URL via PR comment. Skip when inputs.uptime_enabled=false.
  3. backend-engineer: Add tests/test_uptime_primitive.py — validate interface; assert adapter emits ECS service when flag=true; assert no resources when flag=false; assert deploy-uptime stage in pipeline contract.

Must-haves:

  • Uptime primitive exists with feature flag + alert channels
  • Deployed by default after L2 (separate state)
  • Uptime URL published via PR comment
  • Feature flag disables deployment
  • deploy-uptime stage in deploy contract + byte-identical workflows
  • pytest passes (~335)

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

Requirements: REQ-92 (decommission mode), REQ-93 (CMDB validation), REQ-94 (consumer docs) Personas: backend-engineer (lead), lambda-engineer, security-engineer Type: feat

Tasks (Wave 1 — CMDB + Lambda, parallel):

  1. lambda-engineer: Add acdl-change-requests DynamoDB table to terraform/platform/main.tf (PK changeRequestId, SK submittedAt, SSE via CMK, PITR). Add validate_change_request action to core/lambda/contract_ingestor.py — query table, assert status=approved + consumerRepo match, return CR details or 403.
  2. backend-engineer: Add decommission_transform(stack_instance) to core/contract_resolver.py — zero all counts (desired_count=0 for ECS, etc.).

Tasks (Wave 2 — pipeline + docs, after Wave 1):

  1. backend-engineer: Add mode: decommission to deploy workflow inputs. Add decommission stages to pipelines/deploy.yaml: validate-change-request → disable-deletion-protection (HITL SRE gate via GitHub environment) → zero-counts (second HITL SRE gate) → confirm-decommission. Update both deploy workflows (byte-identical).
  2. backend-engineer: Update docs/CONSUMER_GUIDE.md with "Decommissioning a stack" section (request CR, trigger decommission, HITL gates, what happens).
  3. backend-engineer: Add tests/test_decommission.py — assert decommission_transform zeroes counts; assert validate_change_request rejects invalid CRs; assert decommission stages in pipeline contract.

Must-haves:

  • Decommission mode on existing deploy pipeline
  • 2-step with HITL SRE gates
  • CR ID validated against DynamoDB CMDB
  • Documented in consumer guide
  • pytest passes (~345)

Phase 35 — module-engineering-standards

Requirements: REQ-95 (STANDARDS.md), REQ-96 (catalog fix + template update) Personas: lead-developer (lead), platform-engineer, backend-engineer Type: docs + refactor

Tasks (Wave 1):

  1. lead-developer: Author modules/STANDARDS.md — comprehensive L1+L2 authoring + review standards (scanned from current modules per RESEARCH TARGET 6): required files, interface schema, input/output/NFR conventions, encryption + deletion protection as mandatory NFRs, naming, multi-resource pattern, adapter extension pattern, code review checklist.
  2. lead-developer: Fix modules/README.md catalog index — add rds + uptime + kms-key to Primitives table. Update modules/README-TEMPLATE.md — add ## NFRs section.
  3. backend-engineer: Add tests/test_module_standards.py — automated enforcement: every L1 has deletion_protection + encryption_enabled NFRs; every L2 has valid structure; every module registered; every module has README + examples.

Must-haves:

  • modules/STANDARDS.md exists with L1+L2 standards
  • Catalog index includes all primitives
  • Template has NFRs section
  • Automated standards test passes
  • pytest passes (~355)

Phase 36 — schemas-adapters-pipelines-readmes

Requirements: REQ-97 (schemas README), REQ-98 (pipelines README), REQ-99 (adapters README) Personas: lead-developer (lead), backend-engineer, platform-engineer Type: docs

Tasks (Wave 1 — parallel):

  1. lead-developer: Author schemas/README.md — how to write schemas, wire into platform, test in CI, dependencies, existing catalog.
  2. lead-developer: Author pipelines/README.md — how to write pipeline contracts, wire into workflows, test, dependencies, catalog.
  3. lead-developer: Author adapters/README.md — how to write adapters, wire into platform, test, dependencies, catalog.
  4. backend-engineer: Add tests/test_docs_coverage.py — assert all 3 READMEs exist + contain required sections.

Must-haves:

  • All 3 READMEs exist with comprehensive documentation
  • CI validates presence
  • pytest passes (~358)

Phase 37 — verify

Personas: lead-developer (lead), all personas Type: verify

Tasks:

  1. Structural: all new files present.
  2. Behavioral: pytest passes (~358); run_ci.sh exits 0; run_platform.sh --check-only exits 0.
  3. Security: no secrets; CMK enforced; no placeholder account IDs; deletion protection on by default.
  4. Quality: each P1 fix + each new feature has a dedicated test.

Phase 38 — review-audit-complete

Personas: lead-developer (lead), all personas Type: review + audit + complete

Tasks:

  1. Review: 0 new P0/P1; all P1-3..P1-9 + S1 resolved; 3 new requirements delivered.
  2. Audit: reconstruction, file discipline, branch hygiene, commit discipline.
  3. Complete: update REQUIREMENTS.md (REQ-76..99), ROADMAP.md, PROJECT.md. Tag v1.8.0. Update floating v1.8 + v1 tags. Bump uses: to @v1.8.