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

228 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: 28-38
name: v1.8-p1-remediation-uptime-standards-encryption-decommission-docs
milestone: v1.8
requirements: [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]
type: 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):
3. **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.
4. **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.
5. **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):
3. **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.
4. **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`.
5. **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):
3. **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).
4. **backend-engineer:** Update `docs/CONSUMER_GUIDE.md` with "Decommissioning a stack" section (request CR, trigger decommission, HITL gates, what happens).
5. **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`.