From fee59944fde8389a08c7715b890e2ce9d99aff4c Mon Sep 17 00:00:00 2001 From: Jon Chery Date: Wed, 22 Jul 2026 19:47:08 +0000 Subject: [PATCH] docs(init): validate v1.7 specification ---ci--- project: acdl phase: 0 milestone: v1.7 status: specify ---/ci--- v1.7 milestone: production platform + contract ingestion + pipeline maturation. 12 user-directed scope axes (2026-07-22): 1. rename static-asset -> static-assets (D-048) 2. production-ready static-assets stack (cloudfront + waf, D-049) 3. DX-friendly deploy outputs (SSM + PR comment, D-050) 4. central pipeline error reporting via Lambda (D-055) 5. PR comments after every successful stage 6. three platform pipelines (platform-test, primitives-plan, patterns-plan) 7. release job with semver + MAJOR.MINOR/MAJOR tag updates (D-057) 8. platform Lambda + DynamoDB contract ingestion (D-051) 9. tagging standards (Checkov custom rule, D-054, D-043 closure) 10. Wiz adapter (D-052) 11. Kyverno adapter (D-053) 12. remove consumer-repos + validated per-module examples (D-058) + RDS primitive (D-059) 6 phases (22-27), 14 requirements (REQ-62..REQ-75). Ship tag: v1.7.0 (feature milestone, next minor; v1.6 shipped v1.6.0). --- .ciagent/PERSONAS.md | 77 +++++++++++++++++-------------- .ciagent/PROJECT.md | 92 ++++++++++++++++++++++++++++++++++++- .ciagent/REQUIREMENTS.md | 49 +++++++++++++++++++- .ciagent/ROADMAP.md | 97 +++++++++++++++++++++++++++++++++++++++- .ciagent/config.json | 2 +- 5 files changed, 279 insertions(+), 38 deletions(-) diff --git a/.ciagent/PERSONAS.md b/.ciagent/PERSONAS.md index de1b127..708c9d4 100644 --- a/.ciagent/PERSONAS.md +++ b/.ciagent/PERSONAS.md @@ -1,7 +1,7 @@ --- project: acdl -milestone: v1.1 -generated_at: 2026-07-21 +milestone: v1.7 +generated_at: 2026-07-22 generator: lead-developer verification_toolchain: typecheck: "terraform validate && python3 -m py_compile core/**/*.py && python3 -m jsonschema schemas/*.schema.json" @@ -16,7 +16,7 @@ verification_toolchain: ci-* agents read PERSONAS.md before running verification commands. --- -# ACDL — Persona Roster (project-level, v1.1) +# ACDL — Persona Roster (project-level, v1.7) ## Active personas @@ -27,34 +27,43 @@ verification_toolchain: - **Frameworks:** (none) - **Constraints:** pragmatic, battle-tested defaults, no-cross-territory-edits, vision-is-source-of-truth-for-why - **Territory:** `.ciagent/**`, `scripts/verify_phase*.sh`, `README.md`, `docs/**` (meta only — not architecture authoring), `.gitignore` -- **Reason:** Owns CIAgent metadata, cross-phase verification scripts, and the v1.1 phase orchestration. Resolves the 11 open decisions (D-038) and arbitrates persona conflicts. +- **Reason:** Owns CIAgent metadata, cross-phase verification scripts, and the v1.7 phase orchestration. Resolves the 12-scope-axis decomposition (D-048→D-060) and arbitrates persona conflicts. ### backend-engineer - **Domain:** backend - **Active:** true - **Phase-specific:** false -- **Frameworks:** python, json-schema, gitea-actions, act_runner, bash, yaml +- **Frameworks:** python, json-schema, gitea-actions, act_runner, bash, yaml, github-actions - **Constraints:** contract-schema-first, fail-fast-with-reason-codes, no-long-lived-credentials, severity-to-penalty-mapping-immutable -- **Territory:** `core/confidence_signal.py`, `core/contract_resolver.py`, `core/outbox_writer.py`, `schemas/**` (contract + IR + PolicyCheckResult), `contracts/**` (sample contracts), `.gitea/workflows/**` (pipeline) -- **Reason:** Owns the contract schema, contract→IR resolution, the confidence signal (6 inputs + severity mapping), the DynamoDB outbox writer, and the central pipeline workflow. +- **Territory:** `core/confidence_signal.py`, `core/contract_resolver.py`, `core/outbox_writer.py`, `core/output_publisher.py`, `core/environment_check.py`, `schemas/**` (contract + IR + PolicyCheckResult + tagging-standard + pipeline), `contracts/**` (sample contracts), `.gitea/workflows/**` + `.github/workflows/**` (pipeline + deploy + platform-test + primitives-plan + patterns-plan + release), `pipelines/**`, `scripts/run_ci.sh`, `scripts/run_platform.sh`, `scripts/post_stage_comment.sh`, `scripts/run_primitive_plan.sh`, `scripts/run_pattern_plan.sh` +- **Reason:** Owns the contract schema, contract→IR resolution, the confidence signal (6 inputs + severity mapping), the DynamoDB outbox writer, the output publisher (SSM + GitHub comment), the central pipeline workflows (CI + deploy + platform-test + primitives-plan + patterns-plan + release), and the deploy-pipeline DX (stage comments, error-report step). ### platform-engineer (custom) - **Domain:** infra - **Active:** true - **Phase-specific:** false -- **Frameworks:** terraform, aws-iam, aws-s3, aws-dynamodb, oidc, json-schema -- **Constraints:** ir-is-substrate-agnostic, adapter-is-only-substrate-specific-code, state-in-s3+dynamodb-single-region, oidc-only-no-long-lived-keys (waiver D-034 for bootstrap), terraform-plan-only-in-spike -- **Territory:** `adapters/terraform/**`, `modules-ir/**`, `terraform/**` (state backend, provider config), `modules-ir/registry.json` -- **Reason:** Owns the Target Stack IR, the L1/L2 IR-typed modules, the Terraform adapter, the AWS OIDC bootstrap, and the state backend. The IR is substrate-agnostic; the adapter is the only substrate-specific code (the binding constraint per §12). +- **Frameworks:** terraform, aws-iam, aws-s3, aws-dynamodb, aws-lambda, aws-cloudfront, aws-waf, aws-ssm, aws-secretsmanager, oidc, json-schema +- **Constraints:** ir-is-substrate-agnostic, adapter-is-only-substrate-specific-code, state-in-s3+dynamodb-single-region, oidc-only-no-long-lived-keys (waiver D-034 for bootstrap), terraform-plan-only-in-spike, cross-account-iam-scoped-via-abac +- **Territory:** `adapters/terraform/**`, `modules/**` (l1 + l2 + registry.json + examples), `terraform/**` (state backend, provider config, platform infra), `modules/registry.json` +- **Reason:** Owns the Target Stack IR, the L1/L2 IR-typed modules (incl. new cloudfront + waf + rds primitives), the Terraform adapter (TYPE_MAP expansion for cloudfront/waf/rds), the AWS OIDC bootstrap, the state backend, and the platform Terraform (Lambda + DynamoDB + KMS + Secrets Manager + Function URL). The IR is substrate-agnostic; the adapter is the only substrate-specific code (the binding constraint per §12). ### security-engineer (custom) - **Domain:** security - **Active:** true - **Phase-specific:** false -- **Frameworks:** aws-iam, oidc, checkov, json-schema -- **Constraints:** least-privilege, separation-of-duties-identity-distinctness, no-secrets-in-skill-markdown, audit-chain-extends-not-tears-up, critical-finding-hard-overrides-confidence -- **Territory:** `core/hitl_matrix_design.md`, `core/audit_ledger_design.md`, `adapters/terraform/policy/**` (Checkov adapter → PolicyCheckResult), `core/separation_of_duties.py` -- **Reason:** Owns the HITL matrix design, separation-of-duties (DynamoDB identity-distinctness), the audit ledger design (S3 Object Lock + JWS + chain), and the Checkov→PolicyCheckResult adapter. Enforces the "Safety is Computed, Not Assumed" + "Audit truth lives outside the repository" vision tenets. +- **Frameworks:** aws-iam, oidc, checkov, kyverno, wiz, json-schema +- **Constraints:** least-privilege, separation-of-duties-identity-distinctness, no-secrets-in-skill-markdown, audit-chain-extends-not-tears-up, critical-finding-hard-overrides-confidence, required-tags-enforced +- **Territory:** `core/hitl_matrix_design.md`, `core/audit_ledger_design.md`, `adapters/terraform/policy/**` (Checkov adapter + custom rules), `adapters/wiz/**` (Wiz adapter), `adapters/kyverno/**` (Kyverno adapter + sample policies), `core/separation_of_duties.py`, `schemas/tagging-standard.json`, `schemas/policy_check_result.schema.json` (engine enum) +- **Reason:** Owns the HITL matrix design, separation-of-duties, the audit ledger design, the Checkov→PolicyCheckResult adapter + the custom tagging rule (D-054, D-043 closure), the Wiz adapter (D-052), the Kyverno adapter (D-053), and the tagging standard. Enforces the "Safety is Computed, Not Assumed" + "Audit truth lives outside the repository" vision tenets. + +### lambda-engineer (custom, v1.7) +- **Domain:** serverless +- **Active:** true +- **Phase-specific:** true (created for v1.7; removed after milestone COMPLETE) +- **Frameworks:** python, aws-lambda, boto3, dynamodb, aws-secretsmanager, github-api +- **Constraints:** lambda-is-stateless, dynamodb-is-the-state-store, secrets-from-secrets-manager-never-logged, idempotent-actions, cross-account-iam-via-abac +- **Territory:** `core/lambda/**` (contract_ingestor.py + handler), `terraform/platform/main.tf` (Lambda + Function URL + DynamoDB + KMS + Secrets Manager + IAM), `terraform/platform/consumer_invoke_policy.json` +- **Reason:** Owns the platform Lambda for contract ingestion (D-051) + error reporting (D-055). The Lambda is stateless; all state is in DynamoDB. The Lambda holds a GitHub token (Secrets Manager) scoped to the platform repo. Cross-account invocation is scoped via ABAC. Created for v1.7; the role is removed from the roster after milestone COMPLETE (the code persists, but the persona is no longer active). ### frontend-engineer - **Domain:** frontend @@ -63,21 +72,21 @@ verification_toolchain: - **Frameworks:** vanilla-js, dom-api, fetch-api - **Constraints:** no-frameworks, single-file, fetch-from-same-origin-raw-url, relative-url-for-audit-json - **Territory:** `evidence-ui/**` (the timeline UI; pushed to `acdl-evidence`) -- **Reason:** Owns the evidence timeline UI (`index.html`). Carried over from v1.0; the UI continues to render the audit stream. The v1.1 spike writes events to the DynamoDB outbox; the UI continues to read `audit.json` published to `acdl-evidence`. +- **Reason:** Owns the evidence timeline UI (`index.html`). Carried over from v1.0; the UI continues to render the audit stream. The v1.7 spike writes events to the DynamoDB outbox; the UI continues to read `audit.json` published to `acdl-evidence`. ## Deactivated personas ### infra-stub-engineer (custom, v1.0 only) - **Domain:** backend - **Active:** false -- **Reason:** Owned L1 stub modules (`modules/l1/**`) in the v1.0 demo. The demo is archived to `demo/` in Phase 06; real L1 modules (`modules-ir/l1/**`) are owned by platform-engineer (substrate-agnostic IR + Terraform adapter). The stub engineer is no longer needed. +- **Reason:** Owned L1 stub modules (`modules/l1/**`) in the v1.0 demo. The demo is archived to `demo/` in Phase 06; real L1 modules (`modules-ir/l1/**`, now `modules/l1/**`) are owned by platform-engineer (substrate-agnostic IR + Terraform adapter). The stub engineer is no longer needed. - **Phase-specific:** false (was v1.0) - **Territory (would have been):** `demo/modules/l1/**` ### data-engineer - **Domain:** data - **Active:** false -- **Reason:** No ORM/persistence framework. The v1.1 outbox is DynamoDB but accessed via boto3 calls inside `core/outbox_writer.py` (owned by backend-engineer); the audit ledger is S3 Object Lock + JWS (owned by security-engineer). No schema-migration layer, no ORM, no data-engineer territory. +- **Reason:** No ORM/persistence framework. The v1.7 contract-ingestion table is DynamoDB but accessed via boto3 inside `core/lambda/contract_ingestor.py` (owned by lambda-engineer); the outbox is DynamoDB accessed via `core/outbox_writer.py` (owned by backend-engineer); the audit ledger is S3 Object Lock + JWS (owned by security-engineer). No schema-migration layer, no ORM, no data-engineer territory. - **Phase-specific:** false - **Frameworks:** (would have been: drizzle, prisma) - **Constraints:** (would have been: schema-first, type-safe-orm) @@ -87,32 +96,32 @@ verification_toolchain: | Phase | Personas active | Notes | |-------|------------------|-------| -| 06 archive-demo-and-reorient | lead-developer, frontend-engineer (demo UI move only) | backend/platform/security idle | -| 07 architecture-v1-finalization | lead-developer, backend-engineer (schemas), security-engineer (HITL/ledger/SoD), platform-engineer (IR) | frontend idle | -| 08 aws-oidc-bootstrap | platform-engineer (lead), security-engineer (trust policy review) | backend/frontend idle | -| 09 v1-spike-ir-and-l1-and-adapter | platform-engineer (lead), backend-engineer (IR schema co-author) | security/frontend idle | -| 10 v1-spike-l2-and-contract-e2e | platform-engineer (L2 + adapter), backend-engineer (contract→IR + confidence + outbox), security-engineer (Checkov→PolicyCheckResult), frontend-engineer (evidence event surfaces in timeline) | Full roster | +| 22 rename-and-production-static-assets-stack | lead-developer, platform-engineer (lead: rename + cloudfront/waf primitives + adapter), backend-engineer (contract schema + pipelines), security-engineer (review new primitives) | lambda/frontend idle | +| 23 tagging-standards-and-security-adapters | security-engineer (lead: tagging rule + Wiz + Kyverno), platform-engineer (custom rule loading), backend-engineer (schema enum) | lambda/frontend idle | +| 24 platform-lambda-and-contract-ingestion | lambda-engineer (lead: Lambda + DynamoDB + Terraform), platform-engineer (Terraform infra review), security-engineer (cross-account IAM review), backend-engineer (onboarding docs) | frontend idle | +| 25 deploy-pipeline-dx-outputs-and-error-reporting | backend-engineer (lead: outputs + stage comments + error-report step), lambda-engineer (report_error action), security-engineer (no-secrets-in-logs review) | platform/frontend idle | +| 26 platform-pipelines-and-release-automation | backend-engineer (lead: 3 pipelines + release job), lead-developer (verification scripts) | platform/security/lambda/frontend idle | +| 27 remove-consumer-repos-and-module-documentation-examples | lead-developer (lead: examples + docs), platform-engineer (RDS primitive + adapter), backend-engineer (schema-validation) | security/lambda/frontend idle | ## Domain priority (used by TaskDecomposer) -`coordination → security → platform → backend → frontend` +`coordination → security → platform → backend → lambda → frontend` -Rationale: in v1.1, the security/architecture commitments (IR, confidence, -HITL, ledger, SoD) are the binding constraints; the platform layer -materializes them; backend wires the pipeline; frontend surfaces the -evidence. The spike's correctness depends on the security + platform layers -being right before backend wiring. +Rationale: in v1.7, the security commitments (tagging, Wiz, Kyverno, cross-account IAM) and the platform commitments (CloudFront, WAF, RDS, Lambda, DynamoDB) are the binding constraints; backend wires the pipeline + outputs; lambda owns the ingestion + error reporting; frontend surfaces the evidence (unchanged from v1.0). ## Conflict resolutions (lead-developer arbitration) -- `backend-engineer` vs `platform-engineer` over `schemas/ir.schema.json`: platform-engineer owns the IR (it is substrate-agnostic but infra-shaped); backend-engineer owns the contract schema and the contract→IR resolution (contract is the consumer surface). Co-authoring is expected; conflict goes to lead-developer. -- `backend-engineer` vs `security-engineer` over `core/confidence_signal.py`: security-engineer owns the severity→penalty mapping + critical-override semantics; backend-engineer owns the 6-input weighted sum + per-env thresholds. The confidence signal is co-owned; conflicts go to lead-developer. -- `platform-engineer` vs `security-engineer` over `adapters/terraform/policy/**`: security-engineer owns the Checkov→PolicyCheckResult adapter (policy is a security concern); platform-engineer owns the Terraform adapter (substrate translation). No overlap. +- `backend-engineer` vs `platform-engineer` over `schemas/ir.schema.json` + `schemas/stack.schema.json`: platform-engineer owns the IR (substrate-agnostic but infra-shaped); backend-engineer owns the contract schema and the contract→IR resolution. Co-authoring is expected; conflict goes to lead-developer. +- `backend-engineer` vs `security-engineer` over `core/confidence_signal.py`: security-engineer owns the severity→penalty mapping + critical-override semantics; backend-engineer owns the 6-input weighted sum + per-env thresholds. Co-owned; conflicts go to lead-developer. +- `platform-engineer` vs `security-engineer` over `adapters/terraform/policy/**`: security-engineer owns the Checkov→PolicyCheckResult adapter + custom rules + the Wiz/Kyverno adapters (policy is a security concern); platform-engineer owns the Terraform adapter (substrate translation). No overlap. +- `lambda-engineer` vs `platform-engineer` over `terraform/platform/main.tf`: lambda-engineer owns the Lambda + DynamoDB + Secrets Manager definitions; platform-engineer reviews the Terraform structure + state backend. Co-authoring expected; conflicts go to lead-developer. +- `backend-engineer` vs `lambda-engineer` over `core/lambda/contract_ingestor.py` vs `scripts/run_platform.sh` + `.github/workflows/deploy.yml` error-report step: lambda-engineer owns the Lambda handler; backend-engineer owns the workflow step that invokes it. The interface (the JSON payload) is co-authored; conflicts go to lead-developer. - `lead-developer` vs any: lead-developer owns `.ciagent/**` + `docs/**` meta + verification scripts; persona engineers do not edit CIAgent metadata or the vision/architecture source docs. ## Territory enforcement mode `warn` — config.json has no `personas.territory_enforcement` field, so the default per execute.md is `warn`. Cross-territory edits are logged in the -commit message but do not fail the task. The spike's small scope means -co-authoring across territories is likely; `warn` keeps it frictionless. \ No newline at end of file +commit message but do not fail the task. v1.7's broad scope means +co-authoring across territories is likely (e.g. lambda + platform on +`terraform/platform/main.tf`); `warn` keeps it frictionless. \ No newline at end of file diff --git a/.ciagent/PROJECT.md b/.ciagent/PROJECT.md index b153447..2137a71 100644 --- a/.ciagent/PROJECT.md +++ b/.ciagent/PROJECT.md @@ -167,6 +167,75 @@ Three scope axes: Milestone COMPLETE gate: review → ship `v1.4.1` (feature milestone, next minor per ship.md — v1.3 shipped `v1.3.2`) → audit. +## Objective for Milestone v1.7 (active) + +Production platform + contract ingestion + pipeline maturation. The v1.6 +milestone left the platform documented and environments-aware; v1.7 takes it +to a production-grade platform. 12 user-directed scope axes (2026-07-22): + +1. **Rename `static-asset` → `static-assets`** (D-048 — including + `.ciagent/` historical narrative, overriding the v1.6 preservation + precedent). The reconstruction test is updated to expect `static-assets`. +2. **Augment `static-assets` to a production-ready stack** by authoring a + new `cloudfront` primitive + a `waf` primitive (D-049: S3 + CloudFront + OAC + WAF; Route53/ACM are domain-dependent and deferred to documented + extension points). +3. **DX-friendly deploy outputs** (D-050): SSM Parameter Store (KMS-encrypted + `SecureString`) for runtime-injectable values + GitHub PR comment / job + summary for human-readable connection strings. No raw secrets in logs. +4. **Central deploy pipeline error reporting** via the platform Lambda + `report_error` action (D-055): the Lambda creates a GitHub issue on the + platform repo. The consumer's onboarding-granted Lambda-invoke permission + is the only grant needed — uniform pathway, no separate GitHub + `issues: write` on the consumer side. Gitea is excluded (only the CIAgent + uses it). +5. **PR comments after every successful stage** so developers always know + where they stand. +6. **Three platform pipelines**: (1) platform-test (PR, unit + integration + + schema-validation); (2) primitives-plan (PR, plan-only for all L1 + primitives); (3) patterns-plan (PR, plan-only for all L2 modules). +7. **Release job** on merge to `main`: computes MAJOR.MINOR.PATCH semver, + creates the tag, then updates (force-moves) or creates the MAJOR.MINOR + + MAJOR floating tags (D-057). Consumers on `@v1` or `@v1.6` receive updates + depending on their pinned version. +8. **Platform Lambda** for one-way consumer→platform communication + (contracts). Onboarding grants the consumer repo's environment the right + to trigger the Lambda (cross-account IAM). The Lambda ingests contracts + and stores them in a DynamoDB table `acdl-contracts` (D-051) for + historical reference, impact analysis, CMDB-style application-state + queries, and pattern detection. The IAM policy reflects cross-account + invocation. +9. **Tagging standards** in policy/compliance checks (D-054): a required-tag + set (`acdl:owner`, `acdl:contract`, `acdl:environment`, `acdl:cost-center`) + enforced by a Checkov custom YAML rule. Closes the D-043 deferral (the + SKIPPED `ACDL_TAG_NAMING` placeholder becomes a real check). +10. **Wiz adapter** for security checks (D-052): a stub + schema path that + translates Wiz API issues → `PolicyCheckResult` records, degrading + gracefully when unconfigured. Matches the Checkov adapter pattern. +11. **Kyverno adapter** for compliance/security checks (D-053): a + K8s-native policy adapter that translates Kyverno `PolicyReport` results + → `PolicyCheckResult` records. Ready but inactive for Terraform-only + stacks (the platform emits Terraform, not K8s manifests); it activates + when the GitOps reconciler (roadmap) emits K8s manifests. +12. **Remove `consumer-repos/`** and add validated per-module examples + (D-058: `modules//examples/` with `simple.yaml` + `complex.yaml` + validated in CI) + a new RDS primitive demonstrating multi-engine + variation (D-059). + +## Milestone v1.7 Phases + +| Phase | Name | Goal | +|-------|------|------| +| 22 | rename-and-production-static-assets-stack | Rename `static-asset` → `static-assets` everywhere (D-048). Author `cloudfront` + `waf` primitives. Augment `static-assets` to S3 + CloudFront (OAC) + WAF (D-049). Expand adapter. Bump `uses:` to `@v1.6`; create floating `v1.6` + `v1` tags (D-057). | +| 23 | tagging-standards-and-security-adapters | Required-tag set + Checkov custom rule (D-054, D-043 closure). Wiz adapter stub (D-052). Kyverno K8s-native adapter (D-053). Schema engine enum updated. | +| 24 | platform-lambda-and-contract-ingestion | Platform Lambda + DynamoDB `acdl-contracts` table (D-051) + cross-account IAM + onboarding grant. | +| 25 | deploy-pipeline-dx-outputs-and-error-reporting | SSM SecureString + PR comment outputs (D-050). Lambda `report_error` → GitHub issue (D-055). Stage comments after each successful stage. | +| 26 | platform-pipelines-and-release-automation | 3 platform pipelines (platform-test, primitives-plan, patterns-plan). Release job with semver + MAJOR.MINOR/MAJOR tag updates (D-057). | +| 27 | remove-consumer-repos-and-module-documentation-examples | Delete `consumer-repos/`. RDS primitive (D-059). Validated per-module examples (D-058). Docs updates. | + +Milestone COMPLETE gate: review → ship `v1.7.0` (feature milestone, next +minor per ship.md — v1.6 shipped `v1.6.0`) → audit. + ## Requirements ### v1.0 (Prior milestone — the demo) @@ -223,7 +292,7 @@ New requirements REQ-29..REQ-35 — see `REQUIREMENTS.md` §v1.2. Summary: - **REQ-35:** End-to-end verification — consumer commit → live ECS service (HTTP 200) → evidence event → timeline. -### v1.4 (Active milestone — central pipeline contract + shell reproducibility + streaming) +### v1.4 (Prior milestone — central pipeline contract + shell reproducibility + streaming) New requirements REQ-43..REQ-45 — see `REQUIREMENTS.md` §v1.4. Summary: @@ -292,6 +361,27 @@ decisions: | D-046 | `act_runner` → `gitea-runner` rename: Phase 07 updates docs to use the current name `gitea-runner` (renamed 2026-04 in gitea/runner#850). | RESEARCH TARGET 1 + R-4: naming drift between v1.0 docs and the current runner. | Docs reflect the current binary name | | D-047 | v1.2 carries forward the D-039 per-run-rotated-key waiver. Real OIDC federation remains deferred to v1.3+, blocked on go-gitea/gitea#36988 (re-checked 2026-07-21: still **open**, last updated 2026-05-27, not merged). | §12.5 forbids long-lived creds; the Gitea Actions OIDC provider is still not merged. The waiver continues to satisfy §12.5's *intent* (no *persistently* long-lived key) for v1.2: `scripts/rotate_spike_key.sh` rotates the key, and Phase 12 tightens the IAM scoping + rotation hygiene. | v1.2 achieves `terraform apply` against AWS without a persistently long-lived key; real OIDC is a v1.3+ deliverable. | +## Key Decisions (v1.7) + +Resolved at the CLARIFY stage (full autonomy — all within locked constraints +or user-directed scope). New v1.7 decisions: + +| ID | Decision | Rationale | Outcome | +|----|----------|-----------|---------| +| D-048 | Rename `static-asset` → `static-assets`: **rewrite all occurrences** including verbatim historical phase descriptions in `.ciagent/` (ROADMAP, REQUIREMENTS, RESEARCH, decision tables), overriding the v1.6 audit precedent that preserved some historical references. | User chose full rewrite. Maximally consistent; the reconstruction test is updated to expect `static-assets` throughout. | Phase 22 rewrites every `static-asset` string to `static-assets`; no preserved historical tokens remain. | +| D-049 | Production static-assets stack = S3 + CloudFront (OAC) + WAF. | Self-contained, domain-free production edge. Route53/ACM are domain-dependent (consumer-supplied) and deferred to documented extension points / a complex example. | Phase 22 authors `cloudfront` + `waf` primitives and augments the module. | +| D-050 | Deploy outputs: SSM Parameter Store (`SecureString`, KMS-encrypted, namespaced `/acdl/{env}/{contractId}/{output_name}`) for runtime-injectable values + GitHub PR comment / job summary for human-readable connection strings. | Two canonical mechanisms: SSM for resources that read at runtime; PR comment for developers. No raw secrets in logs. | Phase 25 implements `core/output_publisher.py` + two new pipeline stages. | +| D-051 | Contract ingestion storage = DynamoDB table `acdl-contracts` (PK `consumerRepo`, SK `contractId#submittedAt`, SSE via customer-managed CMK, point-in-time recovery). | Enables historical queries, impact analysis, CMDB-style application-state queries, and pattern detection via DynamoDB queries. S3 flat-file mirror deferred (DynamoDB is sufficient for v1.7). | Phase 24 defines the table + Lambda. | +| D-052 | Wiz adapter = stub + schema path (no live Wiz tenant in CI). | Matches the Checkov adapter pattern; typed interface, offline-testable, degrades gracefully when unconfigured (emits `WIZ_NOT_CONFIGURED` SKIPPED record). | Phase 23 authors `adapters/wiz/wiz_adapter.py`. | +| D-053 | Kyverno adapter = K8s-native policy adapter translating `PolicyReport` results → `PolicyCheckResult`. Ready but inactive for Terraform-only stacks. | The platform emits Terraform, not K8s manifests. The adapter activates when the GitOps reconciler (roadmap) emits K8s manifests. Sample policies included as documentation. | Phase 23 authors `adapters/kyverno/kyverno_adapter.py` + sample policies. | +| D-054 | Tagging standard = required-tag set (`acdl:owner`, `acdl:contract`, `acdl:environment`, `acdl:cost-center`) enforced by a Checkov custom YAML rule. | Closes the D-043 deferral (the SKIPPED `ACDL_TAG_NAMING` placeholder becomes a real check). Naming-convention regex deferred (brittle across AWS resource types). | Phase 23 authors `schemas/tagging-standard.json` + `adapters/terraform/policy/custom_rules/acdl_tagging.yaml`. | +| D-055 | Error reporting = the platform Lambda `report_error` action creates a GitHub issue on the platform repo (`acdl/acdl`). Uniform communication pathway via the Lambda; the consumer's onboarding-granted Lambda-invoke permission is the only grant needed. No separate GitHub `issues: write` on the consumer side. Gitea is excluded (only the CIAgent uses it; platform engineers and consumers use GitHub). | Unifies requirements 4 + 8 around one mechanism. The Lambda holds a GitHub token (Secrets Manager) scoped to the platform repo. Idempotent (comments on existing open issue rather than duplicating). | Phase 24 prepares the action; Phase 25 implements it + wires the `if: failure()` workflow step. | +| D-056 | Ship `v1.7.0`; bump `uses:`/`ref:` from `@v1.4` to `@v1.6`. | Consumer-facing version tracks the last released MAJOR.MINOR. Consumers on `@v1.4` stay on v1.4 behavior until they bump. | Phase 22 bumps the references. | +| D-057 | The `uses:`/`ref:` bump + floating `v1.6`/`v1` tag creation happen in Phase 22 (pointing at `v1.6.0`), so the reference never points at a non-existent tag. The release job (Phase 26) owns ongoing tag updates. | Sequencing: if Phase 22 bumps `uses:` to `@v1.6` but the tag doesn't exist, the reference is temporarily broken. Creating the tag early (pointing at the last release) fixes this. | Phase 22 creates the floating tags; Phase 26's release job maintains them. | +| D-058 | Module examples = separate validated files in `modules//examples/` (`simple.yaml` + `complex.yaml` + variation files), validated against `schemas/contract.schema.json` in the platform-test pipeline schema-validation stage. Each module's README `## Examples` section references + excerpts them. | Examples cannot drift from the schema silently. | Phase 27 authors the example files; Phase 26's platform-test pipeline validates them. | +| D-059 | Add an RDS primitive (`modules/l1/rds/`) with an `engine` input (enum: postgres, mysql, etc.) + a multi-engine example demonstrating the variation pattern. | Concrete demonstration of the multi-engine variation the requirement calls out. Adds one primitive + examples. | Phase 27 authors the primitive + adapter expansion + examples. | +| D-060 | (Consolidated into D-058.) | — | — | + ### Open-decision resolutions (Phase 07 deliverable — recorded here for traceability) | ID | Question | Resolution | diff --git a/.ciagent/REQUIREMENTS.md b/.ciagent/REQUIREMENTS.md index fa6dcd1..7bb2853 100644 --- a/.ciagent/REQUIREMENTS.md +++ b/.ciagent/REQUIREMENTS.md @@ -154,6 +154,34 @@ ### Category: Environments concept + onboarding - **REQ-61:** The concept of platform-managed environments is introduced: consumers are not required to provide an AWS account, VPC, subnet, S3 state bucket, or runner key. `docs/environments/index.md` documents that a named environment is a platform-owned AWS account + network + state backend + IAM role surfaced to the consumer via ABAC, selected by name in the contract. The old README environments table (dev/qa/prod/dr) is removed completely. A minimal onboarding scaffold exists: `platform/environments/` with a sample `dev.json` + README, `platform/environment_check.py`, a wire-in at the top of `scripts/run_platform.sh`, a friendly first-run onboarding message when no environment is defined for the repo, and `tests/test_environment_check.py` covering the missing-env and present-env cases. +## v1.7 (Active — production platform + contract ingestion + pipeline maturation) + +### Category: Rename + production-ready stack +- **REQ-62:** `static-asset` is renamed to `static-assets` everywhere (D-048 — including `.ciagent/` historical narrative: verbatim phase descriptions, REQ-25/27/50 text, D-036, RESEARCH.md). `grep -R "static-asset[^s]" .` (excluding `.git/`) returns 0 hits. The module dir `modules/l2/static-asset/` → `modules/l2/static-assets/`; `contracts/static-asset.yaml` → `contracts/static-assets.yaml`; the registry key is renamed; all scripts, tests, docs, and `.ciagent/` files use `static-assets`. The reconstruction test is updated to expect `static-assets` throughout. +- **REQ-63:** Two new primitives exist: `cloudfront` (distribution + OAC, stack types `aws:cloudfront:distribution` + `aws:cloudfront:originaccesscontrol`) and `waf` (WAFv2 web ACL, stack type `aws:wafv2:webacl`), each with an `interface.json` valid against `schemas/stack.schema.json` and a full README (Resources/Inputs/Outputs/Usage/Compliance/Versioning). Both are registered in `modules/registry.json`. The Terraform adapter `TYPE_MAP`/`INPUT_MAP`/`OUTPUT_MAP` covers the new stack types. +- **REQ-64:** The `static-assets` module is augmented to a production-ready stack referencing s3 + cloudfront + waf (depth 1, D-049). `composition.json` wires the s3 bucket regional domain name to the CloudFront origin, and the WAF web ACL ARN to the CloudFront distribution. `schemas/contract.schema.json` is extended for the new module inputs (`price_class`, `viewer_protocol_policy`, `waf_enabled`, `default_ttl`, `max_ttl`). The `uses:`/`ref:` tag advances from `@v1.4` to `@v1.6` (D-056/D-057); floating git tags `v1.6` + `v1` are created pointing at `v1.6.0`. + +### Category: Tagging standards + security adapters +- **REQ-65:** A required-tag set is defined in `schemas/tagging-standard.json` (`acdl:owner`, `acdl:contract`, `acdl:environment`, `acdl:cost-center`). A Checkov custom YAML rule at `adapters/terraform/policy/custom_rules/acdl_tagging.yaml` fails (severity `medium`) when required tags are missing on taggable resources. `checkov_adapter.py` removes the `_emit_tag_naming_skipped()` placeholder (D-043 closure) and maps `ACDL_TAG_NAMING` as a real rule. `scripts/run_platform.sh` Step 5 passes `--external-checks-dir` to load the custom rule. +- **REQ-66:** A Wiz adapter stub exists at `adapters/wiz/wiz_adapter.py` translating Wiz API issues → `PolicyCheckResult` records (`engine: "wiz"`, D-052). It degrades gracefully when unconfigured (emits a single `SKIPPED` `WIZ_NOT_CONFIGURED` record). `tests/test_wiz_adapter.py` passes offline with a fixture response. The pipeline invokes it optionally (Step 5b) when `WIZ_API_TOKEN` is set. +- **REQ-67:** A Kyverno K8s-native adapter exists at `adapters/kyverno/kyverno_adapter.py` translating Kyverno `PolicyReport` results → `PolicyCheckResult` records (`engine: "kyverno"`, D-053). Sample policies exist at `adapters/kyverno/policies/` (disallow-privileged, require-labels, require-image-digests). `tests/test_kyverno_adapter.py` passes offline. The adapter is inactive for Terraform-only stacks (the platform emits Terraform, not K8s manifests); it is ready for the GitOps reconciler roadmap item. `schemas/policy_check_result.schema.json` engine enum includes `checkov | kyverno | opa | wiz`. + +### Category: Platform Lambda + contract ingestion +- **REQ-68:** A platform Lambda (`core/lambda/contract_ingestor.py`) is invoked via a Function URL (IAM auth) and accepts `{ consumerRepo, contractId, contract, environment, action }`. It writes contracts to a DynamoDB table `acdl-contracts` (PK `consumerRepo`, SK `contractId#submittedAt`, SSE via a customer-managed CMK, point-in-time recovery) (D-051). `terraform/platform/main.tf` defines the table, Lambda, Function URL, KMS key, Secrets Manager secret (`acdl/github-token`), and Lambda execution role. `terraform/platform/consumer_invoke_policy.json` grants the consumer's deploy role `lambda:InvokeFunctionUrl` on the Lambda ARN, scoped via ABAC (cross-account). Onboarding grants the Lambda-invoke permission; `docs/environments/index.md` documents this. `tests/test_contract_ingestor.py` passes offline (moto-mocked DynamoDB). + +### Category: Deploy outputs + error reporting + stage comments +- **REQ-69:** `scripts/run_platform.sh` has a `publish-outputs` step (after apply) that writes deploy outputs to SSM Parameter Store as `SecureString` (KMS-encrypted, namespaced `/acdl/{env}/{contractId}/{output_name}`) for runtime-injectable values, and a `comment-outputs` step that posts a structured GitHub PR comment / job summary with human-readable connection strings (D-050). `core/output_publisher.py` implements the SSM write + GitHub comment formatting. `tests/test_output_publisher.py` passes offline (moto + mocked GitHub API). `pipelines/deploy.yaml` + both deploy workflow YAMLs declare the new stages (byte-identical). +- **REQ-70:** The Lambda `report_error` action (`core/lambda/contract_ingestor.py`) creates a GitHub issue on the platform repo (`acdl/acdl`) via the GitHub API using a token from Secrets Manager (D-055). Idempotent (comments on an existing open issue rather than duplicating). `.github/workflows/deploy.yml` + `.gitea/workflows/deploy.yml` (byte-identical) have an `if: failure()` error-report step invoking the Lambda via `aws lambda invoke-function-url` (SigV4-signed). Gitea is excluded (only the CIAgent uses it; platform engineers and consumers use GitHub). +- **REQ-71:** `.github/workflows/deploy.yml` + `.gitea/workflows/deploy.yml` (byte-identical) post a PR comment after every successful pipeline stage (validate-contract, resolve-stack, plan, checkov, confidence, apply, publish-outputs) via `scripts/post_stage_comment.sh` (uses `GITHUB_TOKEN` + `gh api`; no-op when not in a PR context). The comment includes the stage name, status (pass), and key metrics (plan counts, confidence score, outputs published). + +### Category: Platform pipelines + release automation +- **REQ-72:** Three platform pipelines exist: (1) `.github/workflows/platform-test.yml` (PR, stages: lint, unit-test, integration-test — runs `run_platform.sh --check-only` for every sample contract, schema-validation — validates all `schemas/*.json` + `modules/**/interface.json` + `modules/**/composition.json` + `modules//examples/*.yaml` against their schemas); (2) `.github/workflows/primitives-plan.yml` (PR, plan-only for all L1 primitives via matrix, `scripts/run_primitive_plan.sh`); (3) `.github/workflows/patterns-plan.yml` (PR, plan-only for all L2 modules via matrix, `scripts/run_pattern_plan.sh`). +- **REQ-73:** `.github/workflows/release.yml` runs on merge to `main`, computes the next semver (PATCH per phase, MINOR on milestone COMPLETE), creates the MAJOR.MINOR.PATCH tag, force-moves the MAJOR.MINOR + MAJOR floating tags, and creates a GitHub release with an auto-generated body (D-057). `tests/test_release_logic.py` passes (unit test the semver computation + tag-update logic with a mocked `git describe`). + +### Category: Remove consumer-repos + module examples + RDS primitive +- **REQ-74:** The `consumer-repos/` directory is deleted entirely (a v1.2 artifact; references in `.ciagent/` historical narrative are rewritten per D-048). `grep -R "consumer-repos" .` (excluding `.git/`) returns 0 hits. +- **REQ-75:** A new RDS primitive (`modules/l1/rds/`) with an `engine` input (enum: postgres, mysql, etc.) demonstrates multi-engine variation (D-059). Every module (primitives + patterns) has a `modules//examples/` directory with `simple.yaml` + `complex.yaml` (+ variation files) validated against `schemas/contract.schema.json` in the platform-test pipeline schema-validation stage (D-058). Each module's `README.md` `## Examples` section references + excerpts the validated files. `docs/modules/index.md` + `docs/consumer-guide.md` + `docs/contracts/index.md` are updated with the new module names + examples. + ## Out of Scope (v1.2) | REQ | Original criterion | Clarified criterion (effective) | Decision | @@ -268,4 +296,23 @@ | REQ-58 | 21 | complete (v1.6.0) | | REQ-59 | 21 | complete (v1.6.0) | | REQ-60 | 21 | complete (v1.6.0) | -| REQ-61 | 21 | complete (v1.6.0) | \ No newline at end of file +| REQ-61 | 21 | complete (v1.6.0) | + +### v1.7 (active — production platform + contract ingestion + pipeline maturation) + +| Requirement | Phase | Status | +|-------------|-------|--------| +| REQ-62 | 22 | active | +| REQ-63 | 22 | active | +| REQ-64 | 22 | active | +| REQ-65 | 23 | active | +| REQ-66 | 23 | active | +| REQ-67 | 23 | active | +| REQ-68 | 24 | active | +| REQ-69 | 25 | active | +| REQ-70 | 25 | active | +| REQ-71 | 25 | active | +| REQ-72 | 26 | active | +| REQ-73 | 26 | active | +| REQ-74 | 27 | active | +| REQ-75 | 27 | active | \ No newline at end of file diff --git a/.ciagent/ROADMAP.md b/.ciagent/ROADMAP.md index 7689ec7..a533da4 100644 --- a/.ciagent/ROADMAP.md +++ b/.ciagent/ROADMAP.md @@ -9,6 +9,7 @@ - **v1.4 (complete):** central pipeline contract + shell reproducibility + output streaming. A declarative pipeline contract (`schemas/pipeline.schema.json` + `pipelines/ci.yaml`) binds the Gitea and GitHub workflows to a single source of truth. `scripts/run_ci.sh` mirrors the CI pipeline locally. `scripts/run_platform.sh` streams terraform/checkov output by default. - **v1.5 (complete, tag `v1.5.0`):** consumer happy path + zero-trust docs + reusable deploy workflow. README rewritten so the consumer model is unambiguous (consumer owns only contract + app code; the rest is the platform source). Platform-flow + consumer-guide diagrams converted to mermaid. Legacy surface + implementation nomenclature removed from docs. Credentials section rewritten for zero-trust OIDC + ABAC (with a static-key override + daily rotation). A generic `docs/CONSUMER_GUIDE.md` (all L2 modules, versioned `uses:`, consumer-scoped prereqs, run-time platform fetch) replaces the module-specific guide. A byte-identical reusable `deploy.yml` workflow (Gitea + GitHub) implements `pipelines/deploy.yaml` and is invoked by consumer repos via a versioned tag. - **v1.6 (complete, tag `v1.6.0`):** consumer-facing docs restructure + terminology normalization + environments concept. `docs/` becomes a Jekyll-style GitHub Pages site. `acdl_platform/` is renamed to `core/`. L2 → "modules", L1 → "primitives", "composition" → "pattern" in prose. README restructured: Features + Roadmap (no internal status), repository roles restated (consumer = app code + contracts + CI definitions), mermaid fixed (visible text, security-checks + infrastructure-apply stages, no tool names), credentials section minus go-gitea/waivers. Platform-managed environments concept + a minimal onboarding scaffold. `.ciagent/` + `.gitea/` references removed from all consumer-facing docs. +- **v1.7 (active, tag `v1.7.0`):** production platform + contract ingestion + pipeline maturation. Rename `static-asset` → `static-assets` (D-048 — incl. `.ciagent/` historical narrative). Author `cloudfront` + `waf` primitives; augment `static-assets` to a production-ready S3 + CloudFront (OAC) + WAF stack (D-049). Tagging-standard enforcement (Checkov custom rule, D-043 closure, D-054). Wiz adapter stub (D-052) + Kyverno K8s-native adapter (D-053). Platform Lambda + DynamoDB `acdl-contracts` table for contract ingestion (D-051) + cross-account IAM. Deploy outputs via SSM SecureString + GitHub PR comment (D-050). Uniform error reporting via the Lambda `report_error` action → GitHub issue on the platform repo (D-055); Gitea excluded. Stage comments after every successful pipeline stage. Three platform pipelines (platform-test unit+integration, primitives-plan, patterns-plan). Release job with semver + MAJOR.MINOR/MAJOR tag maintenance (D-057). `uses:`/`ref:` bumped to `@v1.6`; floating `v1.6` + `v1` tags created in Phase 22. Remove `consumer-repos/`; add validated per-module examples (`modules//examples/`, D-058) including a new RDS primitive demonstrating multi-engine variation (D-059). - **v1.0 demo URL:** https://git.cloudinit.dev/continuous-intelligence/acdl-evidence/raw/branch/main/index.html --- @@ -332,4 +333,98 @@ scaffold. - `docs/environments/index.md` exists; `core/environments/` + `dev.json` + `environment_check.py` + `run_platform.sh` wire-in + `tests/test_environment_check.py` exist and pass. - `bash scripts/run_ci.sh` exits 0; `python3 -m pytest tests/ -v` passes (154 + new environment-check tests). -After Phase 21: COMPLETE gate — review → ship `v1.6.0` → audit. **DONE.** \ No newline at end of file +After Phase 21: COMPLETE gate — review → ship `v1.6.0` → audit. **DONE.** + +--- + +## v1.7 (Active — production platform + contract ingestion + pipeline maturation) + +The v1.7 milestone takes the platform from a documented, environments-aware +foundation to a production-grade platform with a production-ready +`static-assets` stack (CloudFront + WAF), a contract-ingestion Lambda + DynamoDB +store for historical/impact analysis, a uniform error-reporting pathway via the +same Lambda, DX-friendly deploy outputs (SSM + PR comments), three dedicated +platform pipelines (unit+integration, primitives plan, patterns plan), a +release job with MAJOR.MINOR/MAJOR tag maintenance, new security adapters +(Wiz, Kyverno), real tagging-standard enforcement (closing D-043), removal of +the `consumer-repos/` legacy directory, and validated per-module examples +(including a new RDS primitive demonstrating multi-engine variation). + +The `uses:`/`ref:` tag advances from `@v1.4` to `@v1.6`; the floating `v1.6` + +`v1` tags are created in Phase 22 (pointing at the v1.6.0 release) so the +reference is never broken, and the release job (Phase 26) owns ongoing updates. + +### Phase 22 — rename-and-production-static-assets-stack +- **Description:** Rename `static-asset` → `static-assets` everywhere (D-048 — including `.ciagent/` historical narrative, overriding the v1.6 preservation precedent). Author two new primitives: `cloudfront` (distribution + OAC, stack types `aws:cloudfront:distribution` + `aws:cloudfront:originaccesscontrol`) and `waf` (WAFv2 web ACL, stack type `aws:wafv2:webacl`). Augment the `static-assets` module to a production-ready stack referencing s3 + cloudfront + waf (depth 1, D-049). Expand the Terraform adapter `TYPE_MAP`/`INPUT_MAP`/`OUTPUT_MAP` for the new stack types. Bump `uses:`/`ref:` from `@v1.4` to `@v1.6` (D-056/D-057); create the floating `v1.6` + `v1` git tags pointing at `v1.6.0` so the reference resolves immediately. +- **Status:** active +- **Depends on:** [21] +- **Requirements:** REQ-62, REQ-63, REQ-64 +- **Success Criteria:** + - `grep -R "static-asset[^s]" .` (excluding `.git/`) returns 0 hits; `modules/l2/static-asset/` is renamed to `modules/l2/static-assets/`; `contracts/static-asset.yaml` → `contracts/static-assets.yaml`; registry key renamed; all `.ciagent/` references (incl. verbatim phase descriptions, REQ-25/27/50 text, D-036) rewritten to `static-assets`. + - `modules/l1/cloudfront/` + `modules/l1/waf/` exist with `interface.json` valid against `schemas/stack.schema.json`; registered in `modules/registry.json`. + - `modules/l2/static-assets/composition.json` references s3 + cloudfront + waf (depth 1). + - `adapters/terraform/adapter.py` `TYPE_MAP` covers `aws:cloudfront:distribution`, `aws:cloudfront:originaccesscontrol`, `aws:wafv2:webacl`. + - `contracts/static-assets.yaml` + `.github/workflows/deploy.yml` + `.gitea/workflows/deploy.yml` use `@v1.6`; git tags `v1.6` + `v1` exist pointing at `v1.6.0`. + - `bash scripts/run_ci.sh` exits 0; `python3 -m pytest tests/ -v` passes; `bash scripts/run_platform.sh --check-only` exits 0. + +### Phase 23 — tagging-standards-and-security-adapters +- **Description:** Define a required-tag set (`acdl:owner`, `acdl:contract`, `acdl:environment`, `acdl:cost-center`) in `schemas/tagging-standard.json` (D-054). Author a Checkov custom YAML rule at `adapters/terraform/policy/custom_rules/acdl_tagging.yaml` that fails when required tags are missing on taggable resources. Remove the `_emit_tag_naming_skipped()` placeholder in `checkov_adapter.py` (D-043 closure) and add `ACDL_TAG_NAMING` to `RULE_MAP` as a real rule. Author a Wiz adapter stub (`adapters/wiz/wiz_adapter.py`) translating Wiz API issues → `PolicyCheckResult` records (`engine: "wiz"`), degrading gracefully when unconfigured (D-052). Author a Kyverno K8s-native adapter (`adapters/kyverno/kyverno_adapter.py`) translating Kyverno `PolicyReport` results → `PolicyCheckResult` records (`engine: "kyverno"`), with sample policies as documentation; inactive for Terraform-only stacks, ready for the GitOps reconciler roadmap item (D-053). Add `wiz` + `kyverno` to the `schemas/policy_check_result.schema.json` engine enum. +- **Status:** active +- **Depends on:** [22] +- **Requirements:** REQ-65, REQ-66, REQ-67 +- **Success Criteria:** + - `adapters/terraform/policy/custom_rules/acdl-tagging.yaml` exists; Checkov loads it; `checkov_adapter.py` no longer emits a SKIPPED `ACDL_TAG_NAMING` placeholder (D-043 closed). + - `adapters/wiz/wiz_adapter.py` + `tests/test_wiz_adapter.py` exist; tests pass offline (not-configured graceful degradation). + - `adapters/kyverno/kyverno_adapter.py` + sample policies + `tests/test_kyverno_adapter.py` exist; tests pass offline. + - `schemas/policy_check_result.schema.json` engine enum includes `checkov | kyverno | opa | wiz`. + - `bash scripts/run_ci.sh` exits 0; `python3 -m pytest tests/ -v` passes. + +### Phase 24 — platform-lambda-and-contract-ingestion +- **Description:** Author a platform Lambda (`core/lambda/contract_ingestor.py`) invoked via a Function URL (IAM auth) that accepts `{ consumerRepo, contractId, contract, environment, action }` and writes contracts to a DynamoDB table `acdl-contracts` (PK `consumerRepo`, SK `contractId#submittedAt`, SSE via a customer-managed CMK) (D-051). Define the Terraform (`terraform/platform/main.tf`) for the table, Lambda, Function URL, KMS key, Secrets Manager secret (`acdl/github-token`), and Lambda execution role. Define the cross-account consumer-invoke IAM policy (`terraform/platform/consumer_invoke_policy.json`) granting the consumer's deploy role `lambda:InvokeFunctionUrl` on the Lambda ARN, scoped via ABAC. The `report_error` action (Phase 25) is prepared but not yet implemented. Update `docs/environments/index.md` to document that onboarding now also grants Lambda-invoke permission. +- **Status:** active +- **Depends on:** [23] +- **Requirements:** REQ-68 +- **Success Criteria:** + - `core/lambda/contract_ingestor.py` exists; handler writes contracts to DynamoDB (tested offline with moto). + - `terraform/platform/main.tf` defines `acdl-contracts` DynamoDB table, `acdl-contract-ingestor` Lambda, Function URL (IAM auth), KMS CMK, Secrets Manager secret, Lambda execution role. + - `terraform/platform/consumer_invoke_policy.json` exists (cross-account invoke policy template). + - `tests/test_contract_ingestor.py` passes offline. + - `bash scripts/run_ci.sh` exits 0. + +### Phase 25 — deploy-pipeline-dx-outputs-and-error-reporting +- **Description:** Add a `publish-outputs` step to `scripts/run_platform.sh` (after apply) that writes deploy outputs to SSM Parameter Store as `SecureString` (KMS-encrypted, namespaced `/acdl/{env}/{contractId}/{output_name}`) for runtime-injectable values, and a `comment-outputs` step that posts a structured GitHub PR comment / job summary with human-readable connection strings (D-050). Implement `core/output_publisher.py` (SSM write + GitHub comment formatting). Implement the Lambda `report_error` action (`core/lambda/contract_ingestor.py`) that creates a GitHub issue on the platform repo (`acdl/acdl`) via the GitHub API using a token from Secrets Manager; idempotent (comments on existing open issue rather than duplicating) (D-055). Add an `if: failure()` error-report step to `.github/workflows/deploy.yml` that invokes the Lambda via `aws lambda invoke-function-url` (SigV4-signed). Add a PR comment after every successful pipeline stage (D-055 extension) via `scripts/post_stage_comment.sh` (uses `GITHUB_TOKEN` + `gh api`; no-op when not in a PR context). Update `pipelines/deploy.yaml` + both deploy workflow YAMLs with the new stages (byte-identical). +- **Status:** active +- **Depends on:** [24] +- **Requirements:** REQ-69, REQ-70, REQ-71 +- **Success Criteria:** + - `scripts/run_platform.sh` has a `publish-outputs` step (SSM SecureString, tested offline with moto) + a `comment-outputs` step (GitHub PR comment formatting, tested offline). + - `core/lambda/contract_ingestor.py` `report_error` action creates a GitHub issue (tested with mocked API); idempotent. + - `.github/workflows/deploy.yml` + `.gitea/workflows/deploy.yml` (byte-identical) have an `if: failure()` error-report step invoking the Lambda + stage comments after each successful stage (PR context). + - `pipelines/deploy.yaml` declares the new stages. + - `bash scripts/run_ci.sh` exits 0; `python3 -m pytest tests/ -v` passes. + +### Phase 26 — platform-pipelines-and-release-automation +- **Description:** Author three platform pipelines (D-057): (1) `.github/workflows/platform-test.yml` (PR, lint + unit + integration + schema-validation — replaces `ci.yml` for PRs); (2) `.github/workflows/primitives-plan.yml` (PR, plan-only for all L1 primitives via matrix); (3) `.github/workflows/patterns-plan.yml` (PR, plan-only for all L2 modules via matrix). Author `scripts/run_primitive_plan.sh` + `scripts/run_pattern_plan.sh` (with `--check-only` mode for CI). Author the release job (`.github/workflows/release.yml`) that runs on merge to `main`, computes the next semver (PATCH per phase, MINOR on milestone COMPLETE), creates the MAJOR.MINOR.PATCH tag, force-moves the MAJOR.MINOR + MAJOR floating tags, creates a GitHub release with an auto-generated body. This is the mechanism that lets consumers on `@v1` or `@v1.7` receive updates. +- **Status:** active +- **Depends on:** [25] +- **Requirements:** REQ-72, REQ-73 +- **Success Criteria:** + - `.github/workflows/platform-test.yml` exists, runs lint + unit + integration + schema-validation on PR. + - `.github/workflows/primitives-plan.yml` + `.github/workflows/patterns-plan.yml` exist, run plan-only (matrix) on PR. + - `.github/workflows/release.yml` exists, computes next semver, creates + updates MAJOR.MINOR.PATCH / MAJOR.MINOR / MAJOR tags on merge. + - `scripts/run_primitive_plan.sh` + `scripts/run_pattern_plan.sh` exit 0 in `--check-only` mode. + - `bash scripts/run_ci.sh` exits 0; `python3 -m pytest tests/ -v` passes. + +### Phase 27 — remove-consumer-repos-and-module-documentation-examples +- **Description:** Delete the `consumer-repos/` directory entirely (a v1.2 artifact; references in `.ciagent/` historical narrative are rewritten per D-048). Author a new RDS primitive (`modules/l1/rds/`) with an `engine` input (enum: postgres, mysql, etc.) demonstrating multi-engine variation (D-059). Expand the adapter `TYPE_MAP` for `aws:rds:instance` → `aws_db_instance`. For **each** module (primitives + patterns), add a `modules//examples/` directory with `simple.yaml` + `complex.yaml` (+ variation files) validated against `schemas/contract.schema.json` in the platform-test pipeline (Phase 26 schema-validation stage) (D-058). Each module's `README.md` `## Examples` section references + excerpts the validated files. Update `docs/modules/index.md` + `docs/consumer-guide.md` + `docs/contracts/index.md` with the new module names + examples. +- **Status:** active +- **Depends on:** [26] +- **Requirements:** REQ-74, REQ-75 +- **Success Criteria:** + - `consumer-repos/` does not exist; `grep -R "consumer-repos" .` (excluding `.git/`) returns 0 hits. + - `modules/l1/rds/` exists with `interface.json` (`engine` enum) + `examples/`; registered; adapter emits `aws_db_instance`. + - Every module README has a `## Examples` section; `modules//examples/{simple,complex}.yaml` exist and validate against `schemas/contract.schema.json`. + - `docs/modules/index.md` links to all module READMEs (including cloudfront, waf, rds). + - `bash scripts/run_ci.sh` exits 0; `python3 -m pytest tests/ -v` passes. + +After Phase 27: COMPLETE gate — review → ship `v1.7.0` → audit. \ No newline at end of file diff --git a/.ciagent/config.json b/.ciagent/config.json index 1c8d0dc..d76aed9 100644 --- a/.ciagent/config.json +++ b/.ciagent/config.json @@ -4,7 +4,7 @@ { "slug": "acdl", "name": "Agentic Cloud Delivery Platform", - "milestone": "v1.6", + "milestone": "v1.7", "status": "active" } ],