Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 71bd61ceb1 |
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"phase": 0,
|
||||
"stage": "grill",
|
||||
"milestone": "v1.14",
|
||||
"phase_role": "pre_execution",
|
||||
"attempts": 0,
|
||||
"updated_at": "2026-07-29T20:25:00Z"
|
||||
}
|
||||
@@ -251,3 +251,56 @@ in weakened form; the adoption, architecture, and risks axes apply in full.
|
||||
### Escalations
|
||||
- **[G-005] risks** — 6 cloud capabilities (CAP-017..022: DynamoDB contracts table, Lambda contract-ingestor, ECS service live, CloudFront production stack, uptime-kuma, OIDC role) are deploy-unverified. The `acdl-spike-runner` IAM user cannot fix its own IAM (chicken-and-egg). Either re-bootstrap IAM with an admin principal to re-verify, or explicitly mark these 6 as "design-verified, deploy-unverified" in every leadership deck before the pitch. Resolves: project-killing risk (Axis 7 Q3).
|
||||
- **[G-008] budget** — No cost documentation exists in `.ciagent/` despite live AWS resources (account 581513795199, CAP-013..016 verified). Either add a `COST.md` documenting monthly AWS spend, or explicitly document that ACDL runs at zero cloud cost (local emulators are the primary tier; live-AWS is a one-off spike per milestone). Resolves: financial-control gap (Axis 6 Q1-Q4).
|
||||
|
||||
---
|
||||
|
||||
## Run: 2026-07-29 20:25 (mode: adversarial, focus: v1.14 NFR plan)
|
||||
|
||||
### Verdict: FEASIBLE WITH BINDING DECISIONS (confidence: 0.72)
|
||||
|
||||
The v1.14 milestone is a sound, well-evidenced NFR sweep with a genuine,
|
||||
traceable backlog. Not fundamentally infeasible. Four binding decisions
|
||||
close plan defects + unverified assumptions that would otherwise re-expose
|
||||
the v1.11 4-VPC failure mode. One escalation (E-001) auto-resolved at full
|
||||
autonomy with assumption logging.
|
||||
|
||||
### 9-Axis scores
|
||||
|
||||
| Axis | Confidence | Forcing question (short) |
|
||||
|------|-----------|---------------------------|
|
||||
| 1 Business | 0.80 | Real backlog (5 P1 + 4 P2 + 6 swallowed errors + 15+ hardcoded IDs); cancellation survivable but inherits decay risk |
|
||||
| 2 Scope | 0.70 | User-directed + frozen; P13 has a hidden feature door (implement vs remove); P2 conditional-child edges past wiring |
|
||||
| 3 Architecture | 0.62 | P8 grep unsatisfiable for backend blocks; P8 state-bucket continuity unguarded; P9 IAM naming unverified; P4/P8 file overlap |
|
||||
| 4 People | 0.85 | Agentic single-operator; runtime availability is the key-person risk |
|
||||
| 5 Timeline | 0.68 | No deadline; 20-phase unverified span is the longest since G-007; P8 is the latent multi-phase-rework risk |
|
||||
| 6 Budget | 0.85 | NFR-only, no new AWS resources; P8 re-creation is a one-shot accident not structural cost |
|
||||
| 7 Risks | 0.60 | A1 (acdl-* naming unverified), A2 (fallback constant unbound), A3 (P4 gate hardening); kill-risk = P8 orphans state |
|
||||
| 8 Governance | 0.72 | Full autonomy; no mid-milestone stop trigger; per-phase "green" ≠ "capabilities Verified" |
|
||||
| 9 Adoption | 0.70 | No external users; rollback is git-level for code, AWS-state rollback unaddressed if P8 misfires pre-detection |
|
||||
|
||||
### Binding Decisions
|
||||
|
||||
| ID | Axis | Decision | Confidence |
|
||||
|----|------|----------|-----------|
|
||||
| G-101 | architecture | P8 grep scope amended to exclude terraform `backend "s3"` blocks (bucket arg is static-config-only, evaluated pre-init; cannot reference `data.aws_caller_identity`). Resource ARNs in policy/code ARE externalized; backend blocks stay literal or move to `-backend-config` (separate change). | 0.80 |
|
||||
| G-102 | risks | P8 must bind `ACDL_AWS_ACCOUNT_ID` fallback to the live account ID (not a placeholder) AND the lifecycle workflow (full-mode jobs) must set `ACDL_AWS_ACCOUNT_ID` from `aws sts get-caller-identity` before any lifecycle invocation. No full-mode run proceeds with the env unset. | 0.78 |
|
||||
| G-103 | scope | P13 must take the removal+documentation path (remove `--kube-version` + document deferral to GitOps reconciler roadmap), NOT the implementation path. Implementing version-aware policy selection is a new feature, violating D-095. | 0.85 |
|
||||
| G-104 | architecture | P9 must verify (grep/audit of `modules/l1/*/terraform/main.tf` + `modules/l2/*/composition.json`) that every IAM role + KMS key created by the lifecycle pipeline matches `acdl-*` prefix before merge. CloudFront + WAFv2 (CloudFront scope) remain `Resource: "*"` with a documented global-ARN constraint. | 0.70 |
|
||||
| G-105 | governance | P4's regression-gate hardening must be validated by running the full regression gate immediately after P4 lands (not deferred to P21). Gate must pass clean post-P4 before W2 begins. | 0.70 |
|
||||
| G-106 | governance | A mid-milestone regression-gate checkpoint is added after W2 (P12), before W3 begins. Gate runs offline (D-091); a non-Verified result halts W3 until fixed. Not a re-litigation of G-007 (per-phase stays deferred) — a single checkpoint at the natural seam after the security wave. | 0.65 |
|
||||
|
||||
### Escalations
|
||||
|
||||
- **[E-001] risks** — P8 state-bucket continuity re-exposes the v1.11 4-VPC
|
||||
root cause. G-102 proposes a binding mitigation (bind fallback + wire env
|
||||
into workflow), but the residual risk (a future full-mode lifecycle run
|
||||
with a misconfigured env orphans live state and re-creates resources)
|
||||
cannot be reduced below 0.20 by plan-level decisions alone. **Auto-
|
||||
resolved at full autonomy (D-101):** accept the residual risk; G-102's
|
||||
binding mitigation (fallback bound to live account ID + workflow env
|
||||
wiring) is the control. The lifecycle pipeline defaults to plan-only
|
||||
(REQ-134) — full-mode runs are workflow_dispatch only, reducing the
|
||||
accident surface. If the user prefers zero residual risk, direct that
|
||||
P8 exclude the state-bucket name from externalization entirely
|
||||
(externalize only resource ARNs, leave the backend `bucket` literal).
|
||||
Confidence 0.55; auto-resolved per `config.autonomy.level=full`.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
project: acdl
|
||||
milestone: v1.11
|
||||
generated_at: 2026-07-28
|
||||
milestone: v1.14
|
||||
generated_at: 2026-07-29
|
||||
generator: lead-developer
|
||||
verification_toolchain:
|
||||
typecheck: "terraform validate && python3 -m py_compile core/**/*.py && python3 -m jsonschema schemas/*.schema.json"
|
||||
@@ -18,6 +18,10 @@ verification_toolchain:
|
||||
against live AWS. No per-module Python/pytest. This override is
|
||||
documented here as the single source of truth; the ci-* agents read
|
||||
PERSONAS.md before running verification commands.
|
||||
v1.14 note: NFR-only milestone (bug fixes, security, tests, docs).
|
||||
Roster carries forward from v1.11 unchanged. frontend-engineer stays
|
||||
inactive (no frontend; decks are markdown = lead-developer
|
||||
territory). No custom personas needed (no new domains).
|
||||
---
|
||||
|
||||
# ACDL — Persona Roster (project-level, v1.11 RESTART)
|
||||
|
||||
+376
-38
@@ -1,55 +1,393 @@
|
||||
---
|
||||
phase: P65
|
||||
name: rewrite-caps-decks
|
||||
milestone: v1.11
|
||||
requirements: [REQ-116, REQ-118]
|
||||
wave: 4
|
||||
depends_on: [P64]
|
||||
phase: P0
|
||||
name: pre-execution
|
||||
milestone: v1.14
|
||||
requirements: [REQ-135, REQ-136, REQ-137, REQ-138, REQ-139, REQ-140, REQ-141, REQ-142, REQ-143, REQ-144, REQ-145, REQ-146, REQ-147, REQ-148, REQ-149, REQ-150, REQ-151, REQ-152, REQ-153, REQ-154]
|
||||
wave: 0
|
||||
depends_on: []
|
||||
---
|
||||
|
||||
# P65 — Rewrite Caps + Decks
|
||||
# v1.14 — NFR Refinement Plan (20 execution phases + 1 final)
|
||||
|
||||
**Phase:** P65
|
||||
**Milestone:** v1.11 (RESTART)
|
||||
**Requirements:** REQ-116 (CAP-017..022 Verified), REQ-118 (decks rewritten)
|
||||
**Wave:** 4 (final phase before COMPLETE)
|
||||
**Branch:** `milestone/v1.11-restart`
|
||||
**Milestone:** v1.14 (NFR — bug fixes, security, stubs, tests, docs)
|
||||
**Type:** NFR (all phases fix/test/docs/chore/refactor). Final patch IS
|
||||
the release. Tags: `v1.13.3` (P0) → `v1.13.4..v1.13.23` (P1–P20) →
|
||||
`v1.13.24` (P21 = milestone release).
|
||||
**Branch:** `milestone/v1.14-refinement` → `phase/NN-<slug>`
|
||||
|
||||
## Goal
|
||||
## Wave ordering (D-098)
|
||||
|
||||
Rewrite CAPABILITY_INVENTORY.md, PROJECT.md §Capability Status, and both
|
||||
leadership decks: CAP-017..022 → "Verified live-aws via lifecycle pipeline;
|
||||
torn down to zero-cost steady state." Remove the IAM-drift framing. Add
|
||||
the cost appendix slide (P63) + pre-mortem reference (P64). `ci-doc-verifier`
|
||||
confirms no stale "deploy-unverified" claims remain.
|
||||
- **Wave 1 (P1–P6):** bug fixes. P1→P2 sequential (composition depends
|
||||
on dedup correctness); P3–P6 independent. **G-105: full regression
|
||||
gate run after P4** (validates the hardened gate before W2).
|
||||
- **Wave 2 (P7–P12):** security. P8→P9 sequential (IAM ARNs reference
|
||||
externalized account ID); rest independent. **G-106: mid-milestone
|
||||
regression-gate checkpoint after P12** (offline gate run; non-Verified
|
||||
halts W3 until fixed).
|
||||
- **Wave 3 (P13–P17):** stub/test/CI/hygiene. P15 depends on P7
|
||||
(hardened errors before script tests); P17 depends on P14 (both touch
|
||||
config.json); P13 independent.
|
||||
- **Wave 4 (P18–P20):** standards/docs/VPC. P19 depends on P1–P18
|
||||
(reflects all prior phases); P18 + P20 independent.
|
||||
|
||||
## Tasks
|
||||
## Execution approach
|
||||
|
||||
### Task 1 — Update CAPABILITY_INVENTORY.md
|
||||
Each phase: EXECUTE (persona-assigned task groups) → VERIFY (4 layers +
|
||||
regression gate at milestone complete) → SHIP (patch tag). Phase
|
||||
boundary checkpoint resets context. The execute workflow reads this
|
||||
PLAN.md + ROADMAP.md §v1.14 + PERSONAS.md for task decomposition.
|
||||
|
||||
Mark CAP-017..022 as "Verified live-aws via lifecycle pipeline" (no longer
|
||||
"not auto-verified"). Remove the IAM-drift framing. Reference the lifecycle
|
||||
pipeline as the evidence source.
|
||||
---
|
||||
|
||||
### Task 2 — Update PROJECT.md §Capability Status
|
||||
## Wave 1 — Bug Fixes (P1–P6)
|
||||
|
||||
Update the capability status section to reflect Verified status for
|
||||
CAP-017..022.
|
||||
### P1 — adapter-dedup-diagnostic (REQ-135)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `adapters/terraform/adapter.py`
|
||||
**Tasks:**
|
||||
1. In the dedup loop (`adapter.py:159-170`), when `tf_dir` is `None`,
|
||||
raise `ValueError(f"no terraform_dir in registry for module
|
||||
{module}")` instead of silently skipping.
|
||||
2. Verify registered-module dedup behavior preserved (multi-resource L1s
|
||||
still merge into one `module "x" { ... }` block).
|
||||
3. Run `pytest tests/test_adapter.py` + `run_ci.sh`.
|
||||
|
||||
### Task 3 — Update decks (if present)
|
||||
### P2 — static-assets-wiring-fix (REQ-136)
|
||||
**Persona:** data-engineer
|
||||
**Territory:** `modules/l2/static-assets/`
|
||||
**Tasks:**
|
||||
1. Wire `default_ttl`/`max_ttl`/`price_class`/`viewer_protocol_policy`
|
||||
in `composition.json` to the cloudfront child's inputs.
|
||||
2. Add a `waf_enabled` feature flag (default true) to the
|
||||
static-assets composition; make the WAF child conditional on it.
|
||||
3. Update `examples/complex.yml` to set `waf_enabled: true` + non-default
|
||||
TTLs so it resolves to a different resource set than `simple.yml`.
|
||||
4. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
If leadership deck source files exist (PPTX/HTML/markdown), update them to
|
||||
reflect verified-then-torn-down status. Add the cost appendix (P63) +
|
||||
pre-mortem reference (P64). Remove stale "deploy-unverified" claims.
|
||||
### P3 — lifecycle-script-arg-cleanup (REQ-137)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `scripts/run_l2_lifecycle_*.sh`
|
||||
**Tasks:**
|
||||
1. Remove the `[ci-vpc-outputs.json]` token from the usage strings of
|
||||
`run_l2_lifecycle_test.sh` + `run_l2_lifecycle_destroy.sh`, OR add a
|
||||
comment documenting the L2-uses-remote-state design + parity reason.
|
||||
2. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### Task 4 — ci-doc-verifier check
|
||||
### P4 — regression-gate-evidence-hardening (REQ-138)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `core/regression_verify.py`, `.ciagent/CAPABILITY_INVENTORY.md`
|
||||
**Binding decisions:** G-105 (gate must pass clean post-P4 before W2)
|
||||
**Tasks:**
|
||||
1. Add a `terraform validate` step to
|
||||
`_check_lifecycle_module_terraform` (or document why it's too slow +
|
||||
fall back to a `terraform fmt -check` syntax probe).
|
||||
2. Tighten CAPABILITY_INVENTORY + docstrings to "offline proxy; live
|
||||
apply/modify/destroy verified by the modules-lifecycle workflow run,
|
||||
not by this gate."
|
||||
3. **Run the full regression gate immediately after P4 lands** (G-105).
|
||||
Gate must pass clean before W2 begins.
|
||||
4. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
Run the doc-verifier to confirm no stale "deploy-unverified" claims remain
|
||||
in any .ciagent/ or deck files.
|
||||
### P5 — adapter-behavior-tests (REQ-139)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `tests/test_adapter.py`
|
||||
**Tasks:**
|
||||
1. Add `test_adapter_dedup_merges_same_module` — two resources with the
|
||||
same `module` collapse to one `module "<first_id>" { ... }` block with
|
||||
merged inputs.
|
||||
2. Add `test_adapter_remote_state_key_override` — `ACDL_REMOTE_STATE_KEY`
|
||||
overrides the default `platform/terraform.tfstate` key in the emitted
|
||||
`data terraform_remote_state` block.
|
||||
3. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
## Success Criteria (phase gate)
|
||||
### P6 — alb-name-prefix-fix (REQ-140)
|
||||
**Persona:** data-engineer
|
||||
**Territory:** `modules/l1/alb/terraform/main.tf`
|
||||
**Tasks:**
|
||||
1. Change `name_prefix = "tg-ci-"` to `name_prefix = "${var.name}-"` so
|
||||
the consumer's name prefixes the target group.
|
||||
2. Run `terraform validate` in the alb module dir standalone.
|
||||
3. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
1. CAPABILITY_INVENTORY + PROJECT reflect "Verified live-aws via lifecycle
|
||||
pipeline; torn down to zero-cost."
|
||||
2. `ci-doc-verifier` confirms no stale "deploy-unverified" claims.
|
||||
3. Full offline pytest suite green.
|
||||
---
|
||||
|
||||
## Wave 2 — Security (P7–P12)
|
||||
|
||||
### P7 — swallowed-error-hardening (REQ-141)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `core/local_emulators.py`, `core/lambda/contract_ingestor.py`,
|
||||
`terraform/bootstrap/create_state_backend.py`, `core/output_publisher.py`,
|
||||
`terraform/bootstrap/apply_iam_baseline.py`
|
||||
**Tasks:**
|
||||
1. `local_emulators.py:374` — narrow `except Exception: pass` to catch
|
||||
`AttributeError`/`TypeError` (monkeypatch setup); log + re-raise if
|
||||
patching fails (prevents network egress).
|
||||
2. `contract_ingestor.py:157` — catch `urllib.error.URLError`/
|
||||
`HTTPError` specifically; log the search failure; keep `existing = []`
|
||||
only on `404`/network, re-raise on auth errors.
|
||||
3. `create_state_backend.py:51` — catch `ClientError` with
|
||||
`NoSuchBucket`/`404` error code; re-raise on permissions/network.
|
||||
4. `output_publisher.py:100,168` — catch `ClientError`/`HTTPError`
|
||||
specifically; log with context.
|
||||
5. `apply_iam_baseline.py:78` — catch `NoSuchEntityException` on
|
||||
old-version delete; re-raise on other errors.
|
||||
6. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### P8 — account-id-externalization (REQ-142)
|
||||
**Persona:** backend-engineer + data-engineer
|
||||
**Territory:** `adapters/terraform/adapter.py`, `terraform/bootstrap/`,
|
||||
`scripts/push_consumer_image.py`, terraform resource ARNs
|
||||
**Binding decisions:** G-101 (grep excludes backend blocks), G-102
|
||||
(fallback bound to live account ID + workflow env wiring)
|
||||
**Tasks:**
|
||||
1. `adapter.py:125,140` — read `ACDL_AWS_ACCOUNT_ID` env; build the
|
||||
state-bucket name dynamically. **Fallback constant = `581513795199`**
|
||||
(the live account ID, NOT a placeholder — G-102). Documented for
|
||||
offline tests.
|
||||
2. `apply_iam_baseline.py:33`, `create_state_backend.py:33,35` — read
|
||||
from env (same fallback).
|
||||
3. `push_consumer_image.py:32` — read from env.
|
||||
4. Terraform: use `data.aws_caller_identity.current.account_id` for
|
||||
**resource ARNs** in `spike_runner_policy.json` + resource names.
|
||||
**Exclude terraform `backend "s3"` blocks** (`terraform/*/terraform.tf`,
|
||||
`terraform/ci-vpc/main.tf`, `terraform/platform/main.tf`,
|
||||
`terraform/microservice/terraform.tf`) — backend `bucket` args are
|
||||
static-config-only, evaluated pre-init (G-101). Leave backend blocks
|
||||
literal or move to `terraform init -backend-config` (separate change,
|
||||
not in P8 scope).
|
||||
5. **Lifecycle workflow env wiring (G-102):** the `modules-lifecycle.yml`
|
||||
full-mode jobs must set `ACDL_AWS_ACCOUNT_ID` from
|
||||
`aws sts get-caller-identity --query Account --output text` before
|
||||
any `run_platform.sh`/lifecycle invocation. No full-mode run proceeds
|
||||
with the env unset.
|
||||
6. Run `pytest` + `run_ci.sh`; verify
|
||||
`grep -rn "581513795199" adapters/ scripts/ terraform/bootstrap/ core/`
|
||||
returns 0 hits (excluding tests + docs + terraform backend blocks).
|
||||
|
||||
### P9 — iam-policy-least-privilege (REQ-143)
|
||||
**Persona:** data-engineer
|
||||
**Territory:** `terraform/bootstrap/spike_runner_policy.json`,
|
||||
`tests/test_iam_policy_baseline.py`, `modules/l1/*/terraform/main.tf`,
|
||||
`modules/l2/*/composition.json`
|
||||
**Binding decisions:** G-104 (verify acdl-* naming before merge)
|
||||
**Tasks:**
|
||||
1. Scope `iam:CreateRole` etc. (line 236) to
|
||||
`arn:aws:iam::*:role/acdl-*`.
|
||||
2. Scope KMS (line 218) to `arn:aws:kms::*:key/acdl-*` (or
|
||||
`alias/acdl-*`).
|
||||
3. CloudFront (line 117) + WAFv2 (line 129) remain `Resource: "*"` with
|
||||
a documented global-ARN constraint (CloudFront ARNs are global;
|
||||
cannot be account-scoped — G-104).
|
||||
4. **Verify acdl-* naming (G-104):** grep/audit
|
||||
`modules/l1/*/terraform/main.tf` + `modules/l2/*/composition.json`
|
||||
for every IAM role + KMS key name created by the lifecycle pipeline.
|
||||
If any non-`acdl-*` name is found, rename the resource or widen that
|
||||
one statement (documented).
|
||||
5. Add a regression test in `test_iam_policy_baseline.py` asserting no
|
||||
new `Resource: "*"` on non-global actions.
|
||||
6. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### P10 — contract-ingestor-identity-validation (REQ-144)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `core/lambda/contract_ingestor.py`, `tests/test_contract_ingestor.py`
|
||||
**Tasks:**
|
||||
1. Add `contractId` format validation (regex, ≤64 chars).
|
||||
2. Add `environment` enum validation (dev/qa/prod/dr).
|
||||
3. Add `error` length cap (truncate `stackTrace` at a reasonable limit).
|
||||
4. Document the ABAC reliance in the `_validate_caller_identity`
|
||||
docstring + add a note to ARCHITECTURE.md (P19 will land it).
|
||||
5. Add a spoofing-resistance test (caller submits a `consumerRepo` they
|
||||
don't own → rejected if ABAC misconfigured; documented best-effort).
|
||||
6. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### P11 — schema-input-validation-hardening (REQ-145)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `schemas/contract.schema.json`, `schemas/environment.schema.json`,
|
||||
`tests/test_environment_schema.py`, `tests/test_contract_schema.py`
|
||||
**Tasks:**
|
||||
1. Add `"additionalProperties": false` to both schemas' top-level
|
||||
objects.
|
||||
2. Add `maxItems`/`maxProperties` bounds to `infrastructure` map +
|
||||
`monitored_endpoints` array.
|
||||
3. Add `pattern` validation for `state_backend.bucket` (S3 naming
|
||||
rules: lowercase, 3-63 chars, no underscores).
|
||||
4. Add `pattern` validation for `runner_role_arn` (ARN format).
|
||||
5. Add `pattern` validation for `vpc_cidr` (CIDR format).
|
||||
6. Add tests asserting rejection of undocumented fields + malformed
|
||||
values.
|
||||
7. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### P12 — gitignore-credential-hygiene (REQ-146)
|
||||
**Persona:** lead-developer
|
||||
**Territory:** `.gitignore`, `tests/test_no_secrets_tracked.py`
|
||||
**Tasks:**
|
||||
1. Add credential-pattern catch-all to `.gitignore`:
|
||||
`*.pem`, `*.key`, `*.p12`, `*.pfx`, `*.cer`, `*.crt`, `*.jks`.
|
||||
2. Create `tests/test_no_secrets_tracked.py` — runs
|
||||
`git ls-files | grep -E '\.(pem|key|p12|pfx|cer|crt|jks)$'` and
|
||||
asserts 0 hits.
|
||||
3. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
---
|
||||
|
||||
## Wave 3 — Stub / Test / CI / Hygiene (P13–P17)
|
||||
|
||||
### P13 — kyverno-kube-version-resolution (REQ-147)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `adapters/kyverno/kyverno_adapter.py`, `tests/test_kyverno_adapter.py`
|
||||
**Binding decisions:** G-103 (removal+documentation path, NOT implementation)
|
||||
**Tasks:**
|
||||
1. **Remove the `--kube-version` flag** from
|
||||
`kyverno_adapter.py:11,115-116` (G-103 — implementing version-aware
|
||||
policy selection would be a new feature, violating D-095).
|
||||
2. Add a docstring documenting the deferral to the GitOps reconciler
|
||||
roadmap (D-053): the Kyverno adapter is inactive for Terraform-only
|
||||
stacks; `--kube-version` will be relevant when the GitOps reconciler
|
||||
emits K8s manifests.
|
||||
3. Update `test_kyverno_adapter.py` to remove the `--kube-version` test
|
||||
cases + assert the flag is absent.
|
||||
4. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### P14 — orphan-artifact-and-dead-config-cleanup (REQ-148)
|
||||
**Persona:** lead-developer
|
||||
**Territory:** `scripts/__pycache__/`, `pyproject.toml`, `.ciagent/config.json`
|
||||
**Tasks:**
|
||||
1. Delete the orphan
|
||||
`scripts/__pycache__/verify_deploy_microservice.cpython-312.pyc`.
|
||||
2. Fix `pyproject.toml` coverage source: `acdl_platform` → `core`.
|
||||
3. Bump `pyproject.toml` version `1.3.0` → current (v1.14).
|
||||
4. Remove dead JS allowlist entries from `config.json`
|
||||
`bash_allowlist.allowed_commands` (npm/node/npx/pnpm/yarn/jest/eslint/
|
||||
tsc/prettier — no package.json).
|
||||
5. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### P15 — untested-scripts-coverage (REQ-149)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `tests/` (new test files for 7 scripts)
|
||||
**Tasks:**
|
||||
1. `tests/test_seed_uptime_monitors.py` — mock the uptime-kuma API;
|
||||
assert monitor creation from a JSON file.
|
||||
2. `tests/test_push_consumer_image.py` — mock `subprocess.run` (docker
|
||||
login/build/push) + boto3 ECR; assert the flow.
|
||||
3. `tests/test_sync_to_gl.sh` (shell test) — dry-run mode; assert the
|
||||
copy + push commands are constructed correctly.
|
||||
4. `tests/test_post_stage_comment.sh` (shell test) — no-op when not in
|
||||
a PR context; assert the `gh api` call structure when in PR.
|
||||
5. `tests/test_rotate_spike_key.sh` (shell test) — mock `aws iam`;
|
||||
assert deactivate/create/update-secret flow.
|
||||
6. `tests/test_create_state_backend.py` — mock boto3 S3/DynamoDB;
|
||||
assert idempotent creation.
|
||||
7. `tests/test_create_iam_user.py` — mock boto3 IAM; assert idempotent
|
||||
user/policy/key creation.
|
||||
8. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### P16 — workflow-parity-and-script-flags (REQ-150)
|
||||
**Persona:** backend-engineer
|
||||
**Territory:** `.gitea/workflows/`, `scripts/rotate_spike_key.sh`,
|
||||
`scripts/sync_to_gl.sh`
|
||||
**Tasks:**
|
||||
1. Either mirror the 4 GitHub-only workflows (patterns-plan,
|
||||
platform-test, primitives-plan, release) to `.gitea/workflows/`, or
|
||||
add a README documenting the Gitea limitation (Gitea runners don't
|
||||
use release/primitives-plan/patterns-plan; release is GitHub-only by
|
||||
design).
|
||||
2. Add `set -euo pipefail` to `rotate_spike_key.sh` (currently only
|
||||
`set -u`).
|
||||
3. Add `set -euo pipefail` to `sync_to_gl.sh` (currently no `set`
|
||||
flags).
|
||||
4. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### P17 — config-and-persona-hygiene (REQ-151)
|
||||
**Persona:** lead-developer
|
||||
**Territory:** `.ciagent/config.json`, `.ciagent/PERSONAS.md`
|
||||
**Tasks:**
|
||||
1. Mark `frontend-engineer` persona `active: false` in `config.json`
|
||||
`personas.personas[]` (PERSONAS.md:80 already says inactive).
|
||||
2. Fix `branching_strategy: "phase"` — either change to `"flat"` or
|
||||
document that the field is advisory + the project uses flat workflow
|
||||
(committed directly to main per established convention).
|
||||
3. Configure `ollama-cloud` backend: set `base_url` to the actual
|
||||
endpoint OR add a comment documenting why it's intentionally unset
|
||||
(the runtime uses the `glm-5.2` model via the opencode backend, not
|
||||
the `llm_backends` config).
|
||||
4. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
---
|
||||
|
||||
## Wave 4 — Standards / Docs / VPC (P18–P20)
|
||||
|
||||
### P18 — module-standards-consistency (REQ-152)
|
||||
**Persona:** data-engineer
|
||||
**Territory:** `modules/STANDARDS.md`, `modules/l1/{ecr,ecs-cluster,rds}/terraform/`
|
||||
**Tasks:**
|
||||
1. Either add `locals.tf` to `ecr`, `ecs-cluster`, `rds` (extract
|
||||
inlined locals from `main.tf`), OR reconcile STANDARDS §9.4 to
|
||||
explicitly allow inlining for trivial single-resource modules.
|
||||
2. Remove the stale `TYPE_MAP` reference in STANDARDS §8 (deleted in
|
||||
the v1.11 stateless rewrite).
|
||||
3. Run `pytest` + `run_ci.sh`.
|
||||
|
||||
### P19 — documentation-sync-v1.14 (REQ-153)
|
||||
**Persona:** lead-developer
|
||||
**Territory:** `.ciagent/ARCHITECTURE.md`, `docs/`, `README.md`,
|
||||
`.ciagent/COST.md`, `.ciagent/GRILL.md`, `.ciagent/IAM_POLICY.md`,
|
||||
`docs/presentations/`
|
||||
**Tasks:**
|
||||
1. ARCHITECTURE.md: add v1.11 addendum (stateless adapter, platform VPC,
|
||||
ACDL_LIFECYCLE_MODE), v1.12 addendum (CAP-013 fix, plan-only
|
||||
default), v1.13 addendum (config.json schema migration, badge
|
||||
cleanup, platform-architecture diagram), v1.14 addendum (all 20
|
||||
phases). Record D-083 deferral explicitly.
|
||||
2. Bump stale `@v1.6`–`@v1.9` → `@v1.13` across `README.md:225`,
|
||||
`docs/consumer-guide.md` (12 sites), `docs/architecture.md:233`,
|
||||
`docs/pipeline/versioning.md:29`, `docs/pipeline/index.md:42`.
|
||||
3. Sync decks to v1.13.2 reality (version refs, capability claims).
|
||||
4. Update COST.md window to v1.11–v1.14 (lifecycle pipeline live-runs +
|
||||
teardown).
|
||||
5. Resolve G-005/G-008 in GRILL.md (CAP-017..022 now Verified via
|
||||
lifecycle pipeline; COST.md now exists + covers v1.11+).
|
||||
6. Update IAM_POLICY.md for v1.12/v1.13/v1.14 (plan-only default,
|
||||
config.json schema, v1.14 IAM scoping from P9).
|
||||
7. Run `pytest` + `run_ci.sh`; verify
|
||||
`grep -rn "@v1\.[6-9]" docs/ README.md` returns 0 hits.
|
||||
|
||||
### P20 — platform-vpc-parameterization (REQ-154)
|
||||
**Persona:** data-engineer
|
||||
**Territory:** `terraform/platform/main.tf`
|
||||
**Tasks:**
|
||||
1. Add a `vpc_cidr` variable (default `10.0.0.0/16`); replace the
|
||||
hardcoded `cidr_block`.
|
||||
2. Replace `count = 2` subnets with
|
||||
`count = length(data.aws_availability_zones.available.names)`.
|
||||
3. Add a `data "aws_availability_zones" "available" {}` block.
|
||||
4. Document the `0.0.0.0/0` ingress on port 80 (ALB-fronted, acceptable
|
||||
for a public-facing service; add a comment).
|
||||
5. Run `terraform validate` + `pytest` + `run_ci.sh`.
|
||||
|
||||
---
|
||||
|
||||
## Final Phase — P21 (review + audit + ship)
|
||||
|
||||
**Persona:** lead-developer (review coordination) + ci-code-reviewer +
|
||||
ci-debugger (audit)
|
||||
**Tasks:**
|
||||
1. Multi-persona code review across all v1.14 phases (P1–P20). Auto-apply
|
||||
P0 fixes; flag P1+ for post-hoc review. If P1+ found, fix in-phase.
|
||||
2. Audit: reconstruction test (git log vs `.ciagent/` files), file
|
||||
discipline, branch hygiene, commit discipline. Fix critical issues
|
||||
in-phase.
|
||||
3. Complete: update REQUIREMENTS.md (REQ-135..154 → complete),
|
||||
ROADMAP.md (v1.14 complete), PROJECT.md.
|
||||
4. Tag `v1.13.24` (IS the milestone release). Merge
|
||||
`milestone/v1.14-refinement` → `main`. Create Gitea release with full
|
||||
milestone summary.
|
||||
|
||||
## Success Criteria (milestone gate)
|
||||
|
||||
1. All 20 REQ-135..REQ-154 marked complete in REQUIREMENTS.md.
|
||||
2. Review: 0 new P0; all P1-1..P1-5 + P2-1..P2-4 resolved.
|
||||
3. Audit: clean; reconstruction test passes.
|
||||
4. Regression gate (D-091) clean against the v1.14 state.
|
||||
5. `pytest` passes; `run_ci.sh` exits 0; `run_platform.sh --check-only`
|
||||
exits 0.
|
||||
6. Tag `v1.13.24` created; milestone merged to main.
|
||||
+74
-1
@@ -838,4 +838,77 @@ sign-off (autonomy = full; all within locked constraints).
|
||||
workflow if missing.
|
||||
- **`actions/configure-aws-credentials` action on act_runner** — if
|
||||
unavailable, fall back to `aws sts assume-role-with-web-identity` from a
|
||||
step.
|
||||
step.
|
||||
|
||||
## Objective for Milestone v1.14 (active — NFR Refinement)
|
||||
|
||||
Bug fixes, security posture improvements, stub/missing-functionality
|
||||
identification + implementation, and documentation + NFR refinement across
|
||||
the entire codebase. **No new features.** This is an NFR milestone — the
|
||||
final phase's patch IS the deliverable (no separate milestone tag).
|
||||
|
||||
The v1.13 line shipped the presentation polish + config.json schema
|
||||
migration + badge cleanup. The v1.11/v1.12 multi-persona reviews left a
|
||||
backlog of P1/P2 findings (5 P1 + 4 P2 open in `REVIEW.md`), the codebase
|
||||
has 6+ swallowed-error sites and 15+ hardcoded account-ID references, 7
|
||||
scripts have no test coverage, the regression gate's CAP-017..022 evidence
|
||||
is an offline proxy, ARCHITECTURE.md has no v1.11–v1.13 addendum, and
|
||||
consumer-facing docs reference stale `@v1.6`–`@v1.9` workflow tags. v1.14
|
||||
clears all of it in a 20-phase sweep.
|
||||
|
||||
**Scope axes (user-directed, 2026-07-29):**
|
||||
1. **Bug fixes** — clear all open P1/P2 findings from the v1.11 review
|
||||
(adapter dedup silent drop, static-assets unwired inputs, lifecycle
|
||||
script vestigial args, regression-gate offline-proxy evidence, ALB
|
||||
name_prefix, missing unit tests).
|
||||
2. **Security posture** — narrow 6 swallowed-`except` sites; externalize
|
||||
the hardcoded account ID; scope 6 `Resource: "*"` IAM statements to
|
||||
`acdl-*` ARNs; harden contract-ingestor identity validation; add
|
||||
`additionalProperties: false` + format validation to schemas; add
|
||||
credential-pattern catch-all to `.gitignore`.
|
||||
3. **Stub / missing functionality** — resolve the discarded
|
||||
`--kube-version` flag in the Kyverno adapter; clean up orphan bytecode
|
||||
+ dead config.
|
||||
4. **Documentation + NFR refinement** — ARCHITECTURE.md v1.11–v1.14
|
||||
addenda; bump stale `@v1.6–1.9` → `@v1.13` across 12+ sites; sync
|
||||
decks/COST.md/GRILL G-005+G-008/IAM_POLICY.md; reconcile
|
||||
modules/STANDARDS.md; record the D-083 audit-ledger deferral
|
||||
explicitly.
|
||||
5. **Test coverage** — add unit tests for 7 untested scripts + the
|
||||
adapter dedup/remote-state-key behaviors.
|
||||
|
||||
**Out of scope (v1.14):**
|
||||
- New features (feat phases). v1.14 is NFR-only.
|
||||
- D-083 audit ledger build-out (S3 Object Lock + JWS + SQS DLQ + async
|
||||
worker) — remains deferred; documented explicitly in ARCHITECTURE.md.
|
||||
- Real OIDC federation (blocked on go-gitea/gitea#36988).
|
||||
- Per-phase regression hardening (G-007, unchanged).
|
||||
- Boto3 post-deploy verification probes (deferred to a future QA
|
||||
milestone).
|
||||
|
||||
**Milestone type:** NFR (all phases are fix/test/docs/chore/refactor).
|
||||
**Ship tag:** final phase patch on the v1.13.x line IS the release.
|
||||
|
||||
## Milestone v1.14 Phases
|
||||
|
||||
| Phase | Name | Goal |
|
||||
|-------|------|------|
|
||||
| 0 | pre-execution | SPECIFY → CLARIFY → RESEARCH → IDEATE → PLAN → GRILL. Establish v1.14 milestone shell; ideate finds the concrete requirements; plan decomposes into 20 execution phases. |
|
||||
| 1–20 | execution | 20 phases of bug fixes, security hardening, stub resolution, test coverage, docs sync (wave-ordered). See ROADMAP.md §v1.14 for the phase list. |
|
||||
| 21 | final-review-ship | Multi-persona review + audit + milestone ship (merge to main, tag final patch = release). |
|
||||
|
||||
## Key Decisions (v1.14)
|
||||
|
||||
Resolved at the CLARIFY stage (full autonomy — all within locked
|
||||
constraints or user-directed scope). New v1.14 decisions (numbered
|
||||
D-095+ to continue from v1.10's D-094):
|
||||
|
||||
| ID | Decision | Rationale | Outcome |
|
||||
|----|----------|-----------|---------|
|
||||
| D-095 | v1.14 is an NFR milestone (no feat phases); final patch IS the release. | User directed: "No new features, only bug fixes, security posture improvements, identifying stub and implement missing/lacking functionality, refine all documentation + NFRs." NFR model per branch-strategy.md:181 — progressive patches, final patch = deliverable, no separate milestone tag. | 20 execution phases (P1–P20) + 1 final (P21). Tags v1.13.3 → v1.13.24. |
|
||||
| D-096 | D-083 (audit ledger JWS + S3 Object Lock + SQS DLQ + async worker) remains deferred; documented explicitly in ARCHITECTURE.md (P19), not implemented. | User chose "Skip — keep D-083 deferred." Requires non-offline-testable AWS infra (Object Lock bucket, KMS signing key, SQS). The hash-chain + DynamoDB outbox remains the v1.14 audit record. | P14 (originally JWS) replaced with orphan-artifact-and-dead-config-cleanup. D-083 deferral recorded in P19. |
|
||||
| D-097 | 20 execution phases is the target (not consolidated to ~10). | User chose "20 phases as planned." Finer ship granularity; longer milestone. G-007 (per-phase regression) accepted — regression gate runs at milestone COMPLETE. | 20 phases + 1 final = 21-phase milestone. |
|
||||
| D-098 | Wave ordering: W1 (P1–P6 bug fixes), W2 (P7–P12 security), W3 (P13–P17 stub/test/CI/hygiene), W4 (P18–P20 standards/docs/VPC). | Prerequisite chains: P2 depends on P1 (composition needs correct dedup); P9 depends on P8 (IAM ARNs reference externalized account ID); P15 depends on P7 (script tests benefit from hardened errors); P17 depends on P14 (both touch config.json); P19 lands last (reflects all prior phases). | 4 sequential waves; phases within a wave are independent (parallelizable when parallelization.enabled=true). |
|
||||
| D-099 | `--ideate` flag: run the IDEATE stage between RESEARCH and PLAN (per ideate.md:218). The ideation tiers mine the 50 `partial:` + 16 `lessons:` + 3 `escalation:` + 16 `decisions:` git-native signals to validate/enrich the 20-phase scope. | User invoked with `--ideate`. The v1.14 scope is already user-directed (20 phases defined), so IDEATE acts as validation + enrichment, not scope discovery. Accepted ideas become IDEATE-NN IDs appended to REQUIREMENTS.md. | IDEATE stage runs; interactive validation gate (accept/skip/modify). |
|
||||
| D-100 | Accept all 20 ideation findings as the v1.14 requirement set (REQ-135..REQ-154). | User accepted all 20 at the interactive validation gate. Mechanical + backend-enriched tiers confirmed the user-directed scope. | 20 REQs locked; PLAN.md formalizes the task decomposition. |
|
||||
| D-101 | E-001 (P8 state-bucket continuity residual risk) auto-resolved at full autonomy: accept the residual risk. G-102's binding mitigation (fallback bound to live account ID + workflow env wiring) is the control. The lifecycle pipeline defaults to plan-only (REQ-134) — full-mode runs are workflow_dispatch only, reducing the accident surface. | Grill escalation E-001 (confidence 0.55) re-exposes the v1.11 4-VPC root cause. At full autonomy, auto-decide with assumption logging. The residual risk (misconfigured env at live-run time) is runtime-dependent, not plan-resolvable. If the user prefers zero residual risk, direct that P8 exclude the state-bucket name from externalization entirely. | E-001 resolved; G-102 binding decision enforced in PLAN.md P8. |
|
||||
@@ -610,3 +610,106 @@ two probe fixes required to make the deck claims true.
|
||||
backwards-sequencing failure mode (PRE_MORTEM.md FM-3).
|
||||
- New capability claims beyond what v1.11 verified.
|
||||
- Per-phase regression hardening (G-007, unchanged).
|
||||
|
||||
---
|
||||
|
||||
## Milestone v1.14 — NFR Refinement (REQ-135..REQ-154)
|
||||
|
||||
**Objective:** Bug fixes, security posture improvements, stub/missing-
|
||||
functionality identification + implementation, and documentation + NFR
|
||||
refinement across the entire codebase. **No new features.** NFR milestone
|
||||
— the final phase's patch IS the deliverable.
|
||||
|
||||
The v1.11 multi-persona review left 5 P1 + 4 P2 findings open; the
|
||||
codebase has 6+ swallowed-error sites, 15+ hardcoded account-ID
|
||||
references, 7 untested scripts, an offline-proxy regression gate,
|
||||
ARCHITECTURE.md with no v1.11–v1.13 addendum, and consumer-facing docs
|
||||
referencing stale `@v1.6`–`@v1.9` workflow tags. v1.14 clears all of it
|
||||
in a 20-phase sweep.
|
||||
|
||||
### Requirements
|
||||
|
||||
- **REQ-135** — The adapter dedup loop raises `ValueError` for
|
||||
unregistered-module resources instead of silently dropping them (P1-1).
|
||||
(Phase P1)
|
||||
- **REQ-136** — The static-assets L2 composition wires `default_ttl`/
|
||||
`max_ttl`/`price_class`/`viewer_protocol_policy` and makes WAF
|
||||
conditional via `waf_enabled`, so `complex.yml` is a real modify (P1-2).
|
||||
(Phase P2)
|
||||
- **REQ-137** — The L2 lifecycle scripts' usage strings no longer
|
||||
advertise the vestigial `[ci-vpc-outputs.json]` arg, or document the
|
||||
remote-state design (P1-3). (Phase P3)
|
||||
- **REQ-138** — The regression gate's CAP-017..022 checks run
|
||||
`terraform validate` (not just file-existence + resolver); the
|
||||
offline-proxy caveat is documented honestly (P1-5). (Phase P4)
|
||||
- **REQ-139** — Unit tests for adapter dedup merge behavior +
|
||||
`ACDL_REMOTE_STATE_KEY` override exist and pass (P2-2). (Phase P5)
|
||||
- **REQ-140** — The ALB target group `name_prefix` derives from `var.name`
|
||||
(P2-1). (Phase P6)
|
||||
- **REQ-141** — 6 over-broad `except ...: pass` sites narrowed to specific
|
||||
exceptions; errors logged with context. (Phase P7)
|
||||
- **REQ-142** — The hardcoded account ID `581513795199` is externalized to
|
||||
`ACDL_AWS_ACCOUNT_ID` env / `data.aws_caller_identity` across 15+ sites.
|
||||
(Phase P8)
|
||||
- **REQ-143** — 6 `Resource: "*"` IAM statements scoped to `acdl-*` ARNs;
|
||||
regression test asserts the scoping. (Phase P9)
|
||||
- **REQ-144** — The contract ingestor validates `contractId`/`environment`/
|
||||
`error`; ABAC reliance documented; spoofing-resistance test passes.
|
||||
(Phase P10)
|
||||
- **REQ-145** — `contract.schema.json` + `environment.schema.json` reject
|
||||
undocumented fields (`additionalProperties: false`); format validation
|
||||
for bucket/ARN/CIDR. (Phase P11)
|
||||
- **REQ-146** — `.gitignore` has a credential-pattern catch-all;
|
||||
`test_no_secrets_tracked.py` passes. (Phase P12)
|
||||
- **REQ-147** — The Kyverno `--kube-version` flag is either implemented or
|
||||
removed with a documented deferral rationale. (Phase P13)
|
||||
- **REQ-148** — Orphan bytecode + dead config cleaned (orphan `.pyc`,
|
||||
stale coverage source, stale version, dead JS allowlist). (Phase P14)
|
||||
- **REQ-149** — 7 untested scripts have unit test coverage (≥1 test each).
|
||||
(Phase P15)
|
||||
- **REQ-150** — Gitea workflow parity resolved; `rotate_spike_key.sh` +
|
||||
`sync_to_gl.sh` have `set -euo pipefail`. (Phase P16)
|
||||
- **REQ-151** — `config.json` persona block + branching strategy +
|
||||
ollama-cloud backend aligned with PERSONAS.md + actual runtime.
|
||||
(Phase P17)
|
||||
- **REQ-152** — `modules/STANDARDS.md` internally consistent; no stale
|
||||
`TYPE_MAP` reference. (Phase P18)
|
||||
- **REQ-153** — ARCHITECTURE.md has v1.11–v1.14 addenda; stale `@v1.6–1.9`
|
||||
→ `@v1.13`; GRILL G-005/G-008 resolved; COST.md window covers v1.11–v1.14;
|
||||
D-083 deferral recorded. (Phase P19)
|
||||
- **REQ-154** — Platform VPC CIDR is a variable; subnet count is
|
||||
data-driven; `0.0.0.0/0` ingress documented. (Phase P20)
|
||||
|
||||
### v1.14 Traceability
|
||||
|
||||
| Requirement | Phase | Status |
|
||||
|-------------|-------|--------|
|
||||
| REQ-135 | P1 | pending |
|
||||
| REQ-136 | P2 | pending |
|
||||
| REQ-137 | P3 | pending |
|
||||
| REQ-138 | P4 | pending |
|
||||
| REQ-139 | P5 | pending |
|
||||
| REQ-140 | P6 | pending |
|
||||
| REQ-141 | P7 | pending |
|
||||
| REQ-142 | P8 | pending |
|
||||
| REQ-143 | P9 | pending |
|
||||
| REQ-144 | P10 | pending |
|
||||
| REQ-145 | P11 | pending |
|
||||
| REQ-146 | P12 | pending |
|
||||
| REQ-147 | P13 | pending |
|
||||
| REQ-148 | P14 | pending |
|
||||
| REQ-149 | P15 | pending |
|
||||
| REQ-150 | P16 | pending |
|
||||
| REQ-151 | P17 | pending |
|
||||
| REQ-152 | P18 | pending |
|
||||
| REQ-153 | P19 | pending |
|
||||
| REQ-154 | P20 | pending |
|
||||
|
||||
### Out of Scope (v1.14)
|
||||
- New features (feat phases). v1.14 is NFR-only.
|
||||
- D-083 audit ledger build-out (S3 Object Lock + JWS + SQS DLQ + async
|
||||
worker) — remains deferred; documented explicitly in ARCHITECTURE.md.
|
||||
- Real OIDC federation (blocked on go-gitea/gitea#36988).
|
||||
- Per-phase regression hardening (G-007, unchanged).
|
||||
- Boto3 post-deploy verification probes (deferred to a future QA
|
||||
milestone).
|
||||
|
||||
+177
-1
@@ -692,4 +692,180 @@ A6 section to both talking-points files.
|
||||
decision, 2026-07-29).
|
||||
- **D-109** — Decks use `@v1.11` in examples during Phase 68 (current
|
||||
state), bumped to `@v1.12` at Phase 70 complete after the tag exists.
|
||||
Avoids a dangling reference to a tag that doesn't exist yet.
|
||||
Avoids a dangling reference to a tag that doesn't exist yet.
|
||||
|
||||
---
|
||||
|
||||
## v1.14 Research Addendum — NFR Refinement scope audit (2026-07-29)
|
||||
|
||||
> Phase 0 RESEARCH for milestone v1.14 (NFR Refinement). A full codebase
|
||||
> survey (8 categories, file:line evidence) was conducted to populate the
|
||||
> 20-phase scope. This addendum records the findings; the phase list is
|
||||
> in ROADMAP.md §v1.14; the requirements are in REQUIREMENTS.md §v1.14.
|
||||
|
||||
### Survey method
|
||||
|
||||
Read-only survey of `/root/acdl` at v1.13.2 (HEAD `139224ff`, 533 tests
|
||||
collected). 8 categories: stubs, P1/P2 backlog, security, docs drift,
|
||||
test gaps, terraform gaps, workflow gaps, config hygiene. All file:line
|
||||
references verified against the live codebase.
|
||||
|
||||
### Finding 1 — Open P1/P2 backlog (REVIEW.md v1.11)
|
||||
|
||||
5 P1 + 4 P2 findings from the v1.11 multi-persona review remain open:
|
||||
|
||||
| ID | File:Line | Status | v1.14 phase |
|
||||
|----|-----------|--------|-------------|
|
||||
| P1-1 | `adapter.py:159-170` (silent drop of unregistered-module resources) | open | P1 |
|
||||
| P1-2 | `static-assets/composition.json` (unwired cloudfront inputs; WAF unconditional) | open | P2 |
|
||||
| P1-3 | `run_l2_lifecycle_*.sh` (vestigial `[ci-vpc-outputs.json]` arg) | open | P3 |
|
||||
| P1-4 | `CAPABILITY_INVENTORY.md:9-16` (summary table stale) | **fixed** (now 22/22) | — |
|
||||
| P1-5 | `regression_verify.py:432-519` (CAP-017..022 offline proxy, no `terraform validate`) | open | P4 |
|
||||
| P2-1 | `alb/main.tf:9` (`name_prefix="tg-ci-"` discards `var.name`) | open | P6 |
|
||||
| P2-2 | `test_adapter.py` (no dedup-merge or remote-state-key test) | open | P5 |
|
||||
| P2-3 | `waf/complex.yml` + `locals.tf` (redundant `upper()` + uppercase example) | open (post-hoc) | folded into P2 |
|
||||
| P2-4 | `COST.md:106` (account ID published; accepted exposure) | open (post-hoc) | folded into P8 (centralize code-side) |
|
||||
|
||||
### Finding 2 — Security posture gaps
|
||||
|
||||
**Swallowed errors (6 sites):**
|
||||
- `core/local_emulators.py:374` — `except Exception: pass` in
|
||||
`_fake_urlopen`; if patching fails, urlopen stays real → network
|
||||
egress. [SEC] → P7.
|
||||
- `core/lambda/contract_ingestor.py:157` — GitHub search failure →
|
||||
`existing = []` → duplicate issues. → P7.
|
||||
- `terraform/bootstrap/create_state_backend.py:51` — over-broad
|
||||
`except Exception:` on `head_bucket` → spurious `create_bucket` on
|
||||
permissions/network errors. → P7.
|
||||
- `core/output_publisher.py:100,168` — SSM/GitHub failure → silent
|
||||
`None`/`False`. → P7.
|
||||
- `terraform/bootstrap/apply_iam_baseline.py:78` — over-broad on
|
||||
old-version delete. → P7.
|
||||
|
||||
**Hardcoded account ID `581513795199` (15+ sites):**
|
||||
`adapter.py:125,140`, `apply_iam_baseline.py:33`,
|
||||
`create_state_backend.py:33,35`, `push_consumer_image.py:32`, terraform
|
||||
state-bucket names, ECR image ref. → P8 (externalize to
|
||||
`ACDL_AWS_ACCOUNT_ID` / `data.aws_caller_identity`).
|
||||
|
||||
**IAM policy wildcards (6 `Resource: "*"` statements):**
|
||||
`spike_runner_policy.json` — cloudfront (line 117), wafv2 (129), kms
|
||||
(218), iam (236). KMS allows key creation/deletion on ANY key; IAM
|
||||
allows role creation on ANY role. → P9 (scope to `acdl-*` ARNs).
|
||||
|
||||
**Contract-ingestor identity validation gap:**
|
||||
`contract_ingestor.py:221-245` — `_validate_caller_identity` validates
|
||||
`consumerRepo` format only; doesn't verify caller owns the repo (ABAC
|
||||
reliance). No `contractId`/`environment`/`error` validation. → P10.
|
||||
|
||||
**Schema validation gaps:**
|
||||
`contract.schema.json` + `environment.schema.json` — no
|
||||
`additionalProperties: false` (undocumented fields pass silently); no
|
||||
format validation for bucket/ARN/CIDR. → P11.
|
||||
|
||||
**Credential hygiene:**
|
||||
`.gitignore` covers `.env*`/`*.tfstate*` but no credential-pattern
|
||||
catch-all (`*.pem`/`*.key`/`*.p12`). → P12.
|
||||
|
||||
**Audit ledger integrity (D-083):**
|
||||
`audit_ledger_design.md:47-70` — JWS + Object Lock + DLQ deferred. Per
|
||||
D-096, stays deferred; documented in P19. The hash-chain + DynamoDB
|
||||
outbox is the v1.14 audit record.
|
||||
|
||||
### Finding 3 — Stubs / missing functionality
|
||||
|
||||
- `adapters/kyverno/kyverno_adapter.py:11,115-116` — `--kube-version`
|
||||
parsed then discarded (`_ = kube_version`). → P13 (implement or
|
||||
remove + document).
|
||||
- `scripts/__pycache__/verify_deploy_microservice.cpython-312.pyc` —
|
||||
orphan bytecode for a deleted source file. → P14.
|
||||
- `core/regression_verify.py:237` — DynamoDB write deferred to Phase 54
|
||||
(outbox hash-chain verified, no real DynamoDB write). Accepted
|
||||
deferral.
|
||||
- `adapters/wiz/wiz_adapter.py` — real GraphQL client (not a stub);
|
||||
degrades gracefully. OK.
|
||||
- `core/separation_of_duties.py` — `route_halt_artifact` is real (SNS +
|
||||
outbox fallback). OK.
|
||||
- `core/lambda/contract_ingestor.py` — `report_error` is real (GitHub
|
||||
issues via Secrets Manager). OK.
|
||||
|
||||
### Finding 4 — Documentation drift
|
||||
|
||||
- `ARCHITECTURE.md` — no v1.11/v1.12/v1.13/v1.14 addendum; line 500-506
|
||||
still describes the **old** parameterized adapter (pre-stateless
|
||||
rewrite). → P19.
|
||||
- Stale `@v1.6`–`@v1.9` workflow refs in `README.md:225`,
|
||||
`docs/consumer-guide.md` (12 sites), `docs/architecture.md:233`,
|
||||
`docs/pipeline/versioning.md:29`, `docs/pipeline/index.md:42`. → P19.
|
||||
- `modules/STANDARDS.md` §8 references `TYPE_MAP` (deleted in v1.11);
|
||||
§9.4 requires 5-file split but §489-492 allows inlining —
|
||||
inconsistent. → P18.
|
||||
- `COST.md` window stops at v1.10; no v1.11–v1.13 spend. → P19.
|
||||
- `GRILL.md` G-005/G-008 escalations — CAP-017..022 now Verified via
|
||||
lifecycle pipeline; COST.md now exists. → P19 (mark resolved).
|
||||
- `IAM_POLICY.md` — reflects v1.11 re-bootstrap but not v1.12/v1.13.
|
||||
→ P19.
|
||||
- Decks reference "v1.12" verification status; not re-synced for
|
||||
v1.13.2. → P19.
|
||||
|
||||
### Finding 5 — Test coverage gaps
|
||||
|
||||
- 533 tests collected; 5 `@pytest.mark.slow` (deselected from fast
|
||||
suite). 7 scripts with no test: `seed_uptime_monitors.py`,
|
||||
`push_consumer_image.py`, `sync_to_gl.sh`, `post_stage_comment.sh`,
|
||||
`rotate_spike_key.sh`, `create_state_backend.py`,
|
||||
`create_iam_user.py`. → P15.
|
||||
- Adapter dedup-merge + `ACDL_REMOTE_STATE_KEY` override — no unit
|
||||
test (P2-2). → P5.
|
||||
|
||||
### Finding 6 — Terraform gaps
|
||||
|
||||
- 3 L1 modules lack `locals.tf` (`ecr`, `ecs-cluster`, `rds`). → P18.
|
||||
- `static-assets/composition.json` unwired inputs (P1-2). → P2.
|
||||
- `terraform/platform/main.tf:255` — hardcoded CIDR; `count=2` subnets
|
||||
not data-driven. → P20.
|
||||
- `terraform/bootstrap/create_state_backend.py:51` — over-broad
|
||||
except (Finding 2). → P7.
|
||||
|
||||
### Finding 7 — Workflow / pipeline gaps
|
||||
|
||||
- 4 GitHub-only workflows (patterns-plan, platform-test,
|
||||
primitives-plan, release) — no Gitea mirror. → P16.
|
||||
- `rotate_spike_key.sh` (only `set -u`), `sync_to_gl.sh` (no `set`
|
||||
flags). → P16.
|
||||
- 3 shared workflows (ci, deploy, modules-lifecycle) byte-identical
|
||||
(verified). OK.
|
||||
- modules-lifecycle matrix covers all 12 L1 + 2 L2. OK.
|
||||
|
||||
### Finding 8 — Config / project hygiene
|
||||
|
||||
- `config.json` bash_allowlist has dead JS entries (npm/node/jest/eslint
|
||||
/tsc — no package.json). → P14/P17.
|
||||
- `config.json` `branching_strategy: "phase"` mismatched with
|
||||
flat-workflow practice. → P17.
|
||||
- `config.json` `ollama-cloud.base_url: ""` (empty; no `glm` model
|
||||
configured). → P17.
|
||||
- `config.json` `frontend-engineer` persona still in `personas[]`
|
||||
(PERSONAS.md:80 says inactive). → P17.
|
||||
- `pyproject.toml` version `1.3.0` (stale); coverage source
|
||||
`acdl_platform` (renamed to `core` in v1.6). → P14.
|
||||
|
||||
### Persona assessment (v1.14)
|
||||
|
||||
The v1.14 milestone is NFR-only (bug fixes, security, tests, docs). The
|
||||
active persona roster from v1.11 (PERSONAS.md) carries forward
|
||||
unchanged:
|
||||
|
||||
- **lead-developer** (active) — coordination; owns the wave ordering +
|
||||
cross-phase dependencies.
|
||||
- **backend-engineer** (active) — owns `adapters/`, `core/` (adapter
|
||||
dedup, contract ingestor, regression gate, output publisher).
|
||||
- **data-engineer** (active) — owns `terraform/`, `modules/` (ALB fix,
|
||||
static-assets wiring, platform VPC, IAM policy, STANDARDS).
|
||||
- **frontend-engineer** (inactive) — no frontend; decks are markdown
|
||||
(lead-developer territory). Stays deactivated per PERSONAS.md:80.
|
||||
|
||||
No custom personas needed for v1.14 (no new domains). Territory
|
||||
enforcement = `warn` (config.json:167). The v1.14 work is concentrated
|
||||
in `adapters/`, `core/`, `terraform/`, `scripts/`, `tests/`, `docs/`,
|
||||
`.ciagent/` — all within existing persona territories.
|
||||
|
||||
@@ -1060,3 +1060,375 @@ NFR patch (docs-only). Two presentation changes across both leadership decks
|
||||
total) synced. Both HTML decks re-rendered via Marp.
|
||||
|
||||
Docs-only NFR patch (no code changes).
|
||||
|
||||
---
|
||||
|
||||
## v1.14 (active — NFR Refinement: bug fixes, security, stubs, tests, docs)
|
||||
|
||||
The v1.14 milestone is a 20-phase NFR sweep — no new features. It clears
|
||||
the open P1/P2 backlog from the v1.11 review, hardens the security
|
||||
posture (swallowed errors, hardcoded account ID, IAM wildcards, schema
|
||||
validation, credential hygiene), resolves stub/missing functionality
|
||||
(Kyverno `--kube-version`, orphan artifacts), adds test coverage for 7
|
||||
untested scripts, and refines all documentation (ARCHITECTURE.md
|
||||
v1.11–v1.14 addenda, stale `@v1.6–1.9` → `@v1.13` refs, COST.md/GRILL/
|
||||
IAM_POLICY.md sync, STANDARDS.md reconciliation).
|
||||
|
||||
**Milestone type:** NFR (all phases fix/test/docs/chore/refactor). The
|
||||
final phase's patch IS the release — no separate milestone tag. Tags run
|
||||
on the v1.13.x line: `v1.13.3` (P0) → `v1.13.4..v1.13.23` (P1–P20) →
|
||||
`v1.13.24` (P21 final = milestone release).
|
||||
|
||||
**Wave ordering:**
|
||||
- Wave 1 (P1–P6): bug fixes — P1 before P2 (composition depends on dedup
|
||||
correctness); P3–P6 independent.
|
||||
- Wave 2 (P7–P12): security — P8 before P9 (externalized account ID for
|
||||
IAM ARNs); rest independent.
|
||||
- Wave 3 (P13–P17): stub/test/CI/hygiene — P15 benefits from P7 landing
|
||||
first; P17 after P14 (both touch config.json).
|
||||
- Wave 4 (P18–P20): standards/docs/VPC — P19 last (reflects all prior
|
||||
phases).
|
||||
|
||||
### Phase P1 — adapter-dedup-diagnostic (Wave 1)
|
||||
- **Description:** Fix P1-1 from the v1.11 review. The adapter dedup loop
|
||||
(`adapters/terraform/adapter.py:159-170`) silently drops resources whose
|
||||
module is not in the registry — a typo'd `module` field vanishes without
|
||||
diagnostic. Raise `ValueError` (preserving the pre-dedup contract) so the
|
||||
misconfiguration surfaces instead of being silently omitted.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-135
|
||||
- **Success Criteria:**
|
||||
- A resource with `module: nonexistent@1.0.0` raises `ValueError` with a
|
||||
descriptive message, not a silent drop.
|
||||
- Existing registered-module dedup behavior preserved (multi-resource L1s
|
||||
still merge into one `module "x" { ... }` block).
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P2 — static-assets-wiring-fix (Wave 1)
|
||||
- **Description:** Fix P1-2. `modules/l2/static-assets/composition.json`
|
||||
drops `default_ttl`/`max_ttl`/`price_class`/`viewer_protocol_policy`
|
||||
(accepted by `cloudfront/interface.json` but never wired) and WAF is
|
||||
unconditionally present (no `features`/conditional). Wire the cloudfront
|
||||
inputs; make WAF conditional via a `waf_enabled` feature flag so
|
||||
`examples/complex.yml` is a real modify (adds CDN + WAF), not a no-op
|
||||
re-apply.
|
||||
- **Status:** pending
|
||||
- **Depends on:** [P1]
|
||||
- **Requirements:** REQ-136
|
||||
- **Success Criteria:**
|
||||
- `complex.yml` resolves to a resource set that differs from `simple.yml`
|
||||
(WAF + CDN TTLs present when `waf_enabled: true`, absent when false).
|
||||
- The L2 static-assets lifecycle cell's "modify" step exercises a real
|
||||
terraform diff, not idempotent re-apply.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P3 — lifecycle-script-arg-cleanup (Wave 1)
|
||||
- **Description:** Fix P1-3. `scripts/run_l2_lifecycle_test.sh` and
|
||||
`run_l2_lifecycle_destroy.sh` advertise `[ci-vpc-outputs.json]` ($3) in
|
||||
their usage strings but never read it (the L2 path uses
|
||||
`terraform_remote_state`, not the file). Remove the vestigial arg or
|
||||
document that the L2 path uses remote state and the arg is
|
||||
accepted-but-ignored for workflow-argument parity with the L1 scripts.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-137
|
||||
- **Success Criteria:**
|
||||
- Usage strings no longer advertise a feature the scripts don't provide,
|
||||
OR a comment explains the L2-uses-remote-state design + parity reason.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P4 — regression-gate-evidence-hardening (Wave 1)
|
||||
- **Description:** Fix P1-5. `core/regression_verify.py:432-519`
|
||||
CAP-017..022 checks are offline proxies (files exist + contracts
|
||||
resolve) — a module with broken HCL would pass as long as files exist.
|
||||
Add a `terraform validate` step to
|
||||
`_check_lifecycle_module_terraform` so at least HCL syntax is verified
|
||||
at the gate. Tighten the CAPABILITY_INVENTORY wording to "offline proxy;
|
||||
live apply/modify/destroy verified by the modules-lifecycle workflow
|
||||
run, not by this gate."
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-138
|
||||
- **Success Criteria:**
|
||||
- `_check_lifecycle_module_terraform` runs `terraform validate` (or
|
||||
documents why it's too slow + falls back to a syntax probe).
|
||||
- CAPABILITY_INVENTORY + docstrings reflect the offline-proxy caveat
|
||||
honestly.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P5 — adapter-behavior-tests (Wave 1)
|
||||
- **Description:** Fix P2-2. Add `test_adapter_dedup_merges_same_module`
|
||||
(two resources with the same `module` collapse to one
|
||||
`module "<first_id>" { ... }` block with merged inputs) and
|
||||
`test_adapter_remote_state_key_override` (`ACDL_REMOTE_STATE_KEY`
|
||||
overrides the default `platform/terraform.tfstate` key in the emitted
|
||||
`data terraform_remote_state` block).
|
||||
- **Status:** pending
|
||||
- **Depends on:** [P1]
|
||||
- **Requirements:** REQ-139
|
||||
- **Success Criteria:**
|
||||
- Both unit tests exist in `tests/test_adapter.py` and pass.
|
||||
- `pytest` count increases; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P6 — alb-name-prefix-fix (Wave 1)
|
||||
- **Description:** Fix P2-1. `modules/l1/alb/terraform/main.tf:9` uses
|
||||
`name_prefix = "tg-ci-"` (hardcoded literal) which discards `var.name`
|
||||
entirely — the target group name is non-configurable and inconsistent
|
||||
with the LB name. Change to `name_prefix = "${var.name}-"` so the
|
||||
consumer's name prefixes the target group while preserving uniqueness.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-140
|
||||
- **Success Criteria:**
|
||||
- Target group `name_prefix` derives from `var.name`.
|
||||
- `terraform validate` passes for the alb module standalone.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P7 — swallowed-error-hardening (Wave 2)
|
||||
- **Description:** Narrow 6 over-broad `except ...: pass`/`except
|
||||
Exception:` sites: `core/local_emulators.py:374` (fake_urlopen swallow
|
||||
→ network egress risk if patching fails), `core/lambda/contract_ingestor.py:157`
|
||||
(GitHub search failure → duplicate issues),
|
||||
`terraform/bootstrap/create_state_backend.py:51` (over-broad → spurious
|
||||
create_bucket), `core/output_publisher.py:100,168`,
|
||||
`terraform/bootstrap/apply_iam_baseline.py:78`. Catch specific
|
||||
`ClientError`/`NoSuch*` exceptions; log + re-raise where silent failure
|
||||
masks a real defect.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-141
|
||||
- **Success Criteria:**
|
||||
- No bare `except Exception: pass` remains in the targeted files (grep
|
||||
clean for the 6 sites).
|
||||
- Specific exception types caught; errors logged with context.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P8 — account-id-externalization (Wave 2)
|
||||
- **Description:** Externalize the hardcoded account ID `581513795199`
|
||||
from 15+ sites: `adapters/terraform/adapter.py:125,140`,
|
||||
`terraform/bootstrap/apply_iam_baseline.py:33`,
|
||||
`terraform/bootstrap/create_state_backend.py:33,35`,
|
||||
`scripts/push_consumer_image.py:32`, terraform state-bucket names, ECR
|
||||
image refs. Read from `ACDL_AWS_ACCOUNT_ID` env (code) /
|
||||
`data.aws_caller_identity` (terraform); fall back to env for offline.
|
||||
Keep the COST.md account ID (accepted exposure per P2-4) but centralize
|
||||
the code-side.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-142
|
||||
- **Success Criteria:**
|
||||
- `grep -rn "581513795199" adapters/ scripts/ terraform/ core/` returns
|
||||
0 hits (excluding tests + docs).
|
||||
- `ACDL_AWS_ACCOUNT_ID` env read with a clear default/fallback.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P9 — iam-policy-least-privilege (Wave 2)
|
||||
- **Description:** Scope 6 `Resource: "*"` statements in
|
||||
`terraform/bootstrap/spike_runner_policy.json` (cloudfront, wafv2, kms,
|
||||
iam) to `acdl-*` ARNs. Scope `iam:CreateRole` etc. to
|
||||
`arn:aws:iam::...:role/acdl-*`; scope KMS to
|
||||
`arn:aws:kms:...:key/acdl-*`; narrow CloudFront/WAF where possible.
|
||||
Add a regression test asserting no new `Resource:"*"` on non-global
|
||||
actions.
|
||||
- **Status:** pending
|
||||
- **Depends on:** [P8]
|
||||
- **Requirements:** REQ-143
|
||||
- **Success Criteria:**
|
||||
- `Resource: "*"` remains only on actions that require it (sts, ce).
|
||||
- IAM/KMS/CloudFront/WAF scoped to `acdl-*` ARNs.
|
||||
- Regression test in `tests/test_iam_policy_baseline.py` asserts the
|
||||
scoping.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P10 — contract-ingestor-identity-validation (Wave 2)
|
||||
- **Description:** Harden `core/lambda/contract_ingestor.py:221-245`
|
||||
`_validate_caller_identity` — currently best-effort (validates
|
||||
`consumerRepo` format only, doesn't verify the caller owns the repo).
|
||||
Add `contractId` format validation, `environment` enum validation,
|
||||
`error` length cap. Document the ABAC reliance explicitly. Add a
|
||||
spoofing-resistance test.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-144
|
||||
- **Success Criteria:**
|
||||
- `contractId`, `environment`, `error` validated; malformed input
|
||||
rejected with 400.
|
||||
- ABAC reliance documented in the function docstring + ARCHITECTURE.md.
|
||||
- Spoofing-resistance test in `tests/test_contract_ingestor.py` passes.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P11 — schema-input-validation-hardening (Wave 2)
|
||||
- **Description:** Add `additionalProperties: false` to
|
||||
`schemas/contract.schema.json` + `schemas/environment.schema.json`
|
||||
(currently allows undocumented fields silently). Add `maxItems`/
|
||||
`maxProperties` bounds. Validate `state_backend.bucket` S3 naming
|
||||
rules, `runner_role_arn` ARN format, `vpc_cidr` CIDR format. Add tests
|
||||
asserting rejection of malformed input.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-145
|
||||
- **Success Criteria:**
|
||||
- Both schemas reject undocumented top-level fields.
|
||||
- Format validation (bucket/ARN/CIDR) rejects malformed values.
|
||||
- New tests in `tests/test_environment_schema.py` +
|
||||
`tests/test_contract_schema.py` pass.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P12 — gitignore-credential-hygiene (Wave 2)
|
||||
- **Description:** `.gitignore` covers `.env*`/`*.tfstate*` but lacks a
|
||||
credential-pattern catch-all (`*.pem`/`*.key`/`*.p12`/`*.pfx`). Add
|
||||
credential patterns. Add `tests/test_no_secrets_tracked.py` asserting no
|
||||
credential-looking file is tracked by git.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-146
|
||||
- **Success Criteria:**
|
||||
- `.gitignore` has credential-pattern catch-all.
|
||||
- `test_no_secrets_tracked.py` passes (grep `git ls-files` for
|
||||
credential patterns → 0 hits).
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P13 — kyverno-kube-version-resolution (Wave 3)
|
||||
- **Description:** Resolve the discarded `--kube-version` flag in
|
||||
`adapters/kyverno/kyverno_adapter.py:11,115-116` (`_ = kube_version`).
|
||||
Either implement version-aware policy selection (select policies by k8s
|
||||
version) or remove the flag and document why it's deferred to the
|
||||
GitOps reconciler roadmap. Resolve the ambiguity either way.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-147
|
||||
- **Success Criteria:**
|
||||
- `--kube-version` is either used (version-aware policy selection) or
|
||||
removed with a documented deferral rationale.
|
||||
- `tests/test_kyverno_adapter.py` updated to match.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P14 — orphan-artifact-and-dead-config-cleanup (Wave 3)
|
||||
- **Description:** Clean up orphan artifacts + dead config: the orphan
|
||||
`scripts/__pycache__/verify_deploy_microservice.cpython-312.pyc` (source
|
||||
deleted in v1.11); stale `pyproject.toml` coverage source
|
||||
`acdl_platform` → `core` (renamed in v1.6); `pyproject.toml` version
|
||||
`1.3.0` → current; dead JS allowlist entries in `config.json`
|
||||
(npm/node/jest/eslint/tsc — no package.json).
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-148
|
||||
- **Success Criteria:**
|
||||
- No orphan `.pyc` for a deleted source file.
|
||||
- `pyproject.toml` coverage source = `core`; version = current.
|
||||
- `config.json` bash_allowlist has no JS-only entries.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P15 — untested-scripts-coverage (Wave 3)
|
||||
- **Description:** Add unit tests for 7 scripts with no test coverage:
|
||||
`scripts/seed_uptime_monitors.py`, `scripts/push_consumer_image.py`,
|
||||
`scripts/sync_to_gl.sh`, `scripts/post_stage_comment.sh`,
|
||||
`scripts/rotate_spike_key.sh`, `terraform/bootstrap/create_state_backend.py`,
|
||||
`terraform/bootstrap/create_iam_user.py`. Mock boto3/subprocess for
|
||||
offline-testable coverage. Add `--check-only`/dry-run modes where
|
||||
missing.
|
||||
- **Status:** pending
|
||||
- **Depends on:** [P7]
|
||||
- **Requirements:** REQ-149
|
||||
- **Success Criteria:**
|
||||
- Each of the 7 scripts has a corresponding test file with ≥1 passing
|
||||
test.
|
||||
- `pytest` count increases by ≥7; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P16 — workflow-parity-and-script-flags (Wave 3)
|
||||
- **Description:** 4 GitHub-only workflows (patterns-plan, platform-test,
|
||||
primitives-plan, release) have no Gitea mirror — either mirror them or
|
||||
document the Gitea limitation. Fix `scripts/rotate_spike_key.sh` (only
|
||||
`set -u`, no `-e`/`pipefail`) and `scripts/sync_to_gl.sh` (no `set`
|
||||
flags at all) — add `set -euo pipefail`.
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-150
|
||||
- **Success Criteria:**
|
||||
- Gitea workflow parity resolved (mirrored or documented).
|
||||
- `rotate_spike_key.sh` + `sync_to_gl.sh` have `set -euo pipefail`.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P17 — config-and-persona-hygiene (Wave 3)
|
||||
- **Description:** Fix `config.json` hygiene: `branching_strategy: "phase"`
|
||||
mismatch with flat-workflow practice; empty `ollama-cloud` base_url (no
|
||||
`glm` model configured); `frontend-engineer` persona `active: false` in
|
||||
config.json (PERSONAS.md:80 already says inactive). Align config.json
|
||||
with PERSONAS.md + actual runtime.
|
||||
- **Status:** pending
|
||||
- **Depends on:** [P14]
|
||||
- **Requirements:** REQ-151
|
||||
- **Success Criteria:**
|
||||
- `config.json` persona block matches PERSONAS.md (frontend-engineer
|
||||
inactive).
|
||||
- `branching_strategy` reflects actual practice (or documented).
|
||||
- `ollama-cloud` backend configured or documented as intentionally
|
||||
unset.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P18 — module-standards-consistency (Wave 4)
|
||||
- **Description:** 3 L1 modules (`ecr`, `ecs-cluster`, `rds`) lack
|
||||
`locals.tf`; `modules/STANDARDS.md` §9.4 requires the full 5-file split
|
||||
but §489-492 allows inlining — internally inconsistent. Either add
|
||||
`locals.tf` to all 3 or reconcile STANDARDS §9.4 with the inline
|
||||
allowance. Remove the stale `TYPE_MAP` reference in §8 (deleted in the
|
||||
v1.11 stateless rewrite).
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-152
|
||||
- **Success Criteria:**
|
||||
- STANDARDS.md internally consistent (§8 + §9.4 agree).
|
||||
- No stale `TYPE_MAP` reference.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P19 — documentation-sync-v1.14 (Wave 4)
|
||||
- **Description:** ARCHITECTURE.md: add v1.11/v1.12/v1.13/v1.14 addenda
|
||||
(stateless adapter, platform VPC, ACDL_LIFECYCLE_MODE, all v1.14
|
||||
changes; record D-083 deferral explicitly). Bump stale `@v1.6–1.9` →
|
||||
`@v1.13` across `README.md`, `docs/consumer-guide.md` (12 sites),
|
||||
`docs/architecture.md`, `docs/pipeline/`. Sync decks to v1.13.2 reality.
|
||||
Update COST.md window to v1.11–v1.14. Resolve G-005/G-008 in GRILL.md
|
||||
(CAP-017..022 now Verified via lifecycle pipeline; COST.md now exists +
|
||||
covers v1.11+). Update IAM_POLICY.md for v1.12/v1.13/v1.14.
|
||||
- **Status:** pending
|
||||
- **Depends on:** [P1-P18]
|
||||
- **Requirements:** REQ-153
|
||||
- **Success Criteria:**
|
||||
- ARCHITECTURE.md has v1.11–v1.14 addenda; D-083 deferral recorded.
|
||||
- `grep -rn "@v1\.[6-9]" docs/ README.md` returns 0 hits (bumped to
|
||||
@v1.13).
|
||||
- GRILL G-005/G-008 marked resolved with evidence.
|
||||
- COST.md window covers v1.11–v1.14.
|
||||
- `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P20 — platform-vpc-parameterization (Wave 4)
|
||||
- **Description:** `terraform/platform/main.tf:255` hardcodes
|
||||
`cidr_block = "10.0.0.0/16"` (not `var.vpc_cidr`); `count = 2` subnets
|
||||
hardcoded (not data-driven AZs). Parameterize; document the
|
||||
`0.0.0.0/0` ingress on port 80 (ALB-fronted, acceptable but should be
|
||||
explicit).
|
||||
- **Status:** pending
|
||||
- **Depends on:** —
|
||||
- **Requirements:** REQ-154
|
||||
- **Success Criteria:**
|
||||
- VPC CIDR is a variable (default `10.0.0.0/16`); subnet count is
|
||||
data-driven (`length(data.aws_availability_zones.available)`).
|
||||
- `0.0.0.0/0` ingress documented.
|
||||
- `terraform validate` passes; `pytest` passes; `run_ci.sh` exits 0.
|
||||
|
||||
### Phase P21 — final-review-ship (Final Phase)
|
||||
- **Description:** Multi-persona code review across all v1.14 phases.
|
||||
Audit (reconstruction test, file discipline, branch hygiene, commit
|
||||
discipline). Complete: update REQUIREMENTS.md (REQ-135..154 marked
|
||||
complete), ROADMAP.md (v1.14 complete), PROJECT.md. Tag final patch
|
||||
`v1.13.24` (IS the milestone release). Merge `milestone/v1.14` → `main`.
|
||||
- **Status:** pending
|
||||
- **Depends on:** [P1-P20]
|
||||
- **Requirements:** —
|
||||
- **Success Criteria:**
|
||||
- Review: 0 new P0; all P1-1..P1-5 + P2-1..P2-4 resolved.
|
||||
- Audit: clean; reconstruction test passes.
|
||||
- Tag `v1.13.24` created; milestone merged to main.
|
||||
|
||||
After Phase P21: milestone COMPLETE — `v1.13.24` IS the v1.14 release.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
],
|
||||
"active_project": "acdl",
|
||||
"active_projects": ["acdl"],
|
||||
"active_milestone": "v1.14",
|
||||
"autonomy": {
|
||||
"level": "full",
|
||||
"escalation_hooks": ["deploy", "delete_data", "merge_to_main"],
|
||||
|
||||
Reference in New Issue
Block a user