docs(init): validate v1.9 specification
---ci---
project: acdl
phase: 0
milestone: v1.9
status: specify
---/ci---
v1.9 scope (user-directed, 2026-07-23):
- Design doc refresh (hitl_matrix_design.md + audit_ledger_design.md)
- Contract interpolation (${env.<field>} + ${contract.<field>})
- Per-environment CI jobs (no environment field editing for promotion)
- Stub implementation (SoD, HITL gates, attestation matrix, Wiz, Kyverno)
- P1-1 adapter parameterization remediation
Requirements REQ-100..REQ-111 added to REQUIREMENTS.md.
PROJECT.md v1.9 objective + phase table (39-43) appended.
config.json milestone bumped to v1.9 (active).
This commit is contained in:
@@ -296,6 +296,74 @@ and test each.
|
|||||||
Milestone COMPLETE gate: review → ship `v1.8.0` (feature milestone, next
|
Milestone COMPLETE gate: review → ship `v1.8.0` (feature milestone, next
|
||||||
minor per run.md — v1.7 shipped `v1.7.0`) → audit.
|
minor per run.md — v1.7 shipped `v1.7.0`) → audit.
|
||||||
|
|
||||||
|
## Objective for Milestone v1.9 (active)
|
||||||
|
|
||||||
|
Production-grade progression: contract interpolation, per-environment
|
||||||
|
promotion without field editing, stub implementation, and P1-1
|
||||||
|
remediation. The v1.8 milestone shipped encryption/deletion-protection by
|
||||||
|
default, uptime, decommission, and engineering standards but left four
|
||||||
|
gaps that v1.9 closes (user-directed, 2026-07-23):
|
||||||
|
|
||||||
|
1. **Design doc refresh.** `core/hitl_matrix_design.md` and
|
||||||
|
`core/audit_ledger_design.md` are stale — both still describe the
|
||||||
|
v1.1 spike scope ("dev-only; HITL not exercised"; "spike scope =
|
||||||
|
hash chain + outbox write; Object Lock + JWS are v1.2"). v1.9 brings
|
||||||
|
them up to date with the shipped v1.8 platform and the v1.9 wiring.
|
||||||
|
2. **Contract interpolation (variable expansion).** Contracts cannot
|
||||||
|
reference environment onboarding values today — bucket names, account
|
||||||
|
IDs, regions are hardcoded literals. v1.9 adds `${env.<field>}` and
|
||||||
|
`${contract.<field>}` expansion in the resolver, sourced from the
|
||||||
|
environment onboarding JSON. Naming patterns like
|
||||||
|
`acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}`
|
||||||
|
become expressible. The S3 bucket naming-pattern requirement is the
|
||||||
|
binding example.
|
||||||
|
3. **Per-environment CI jobs (no field editing for promotion).** Today a
|
||||||
|
promotion dev → qa requires editing the `environment:` field in the
|
||||||
|
contract YAML. v1.9 ships a hybrid model: (a) per-environment contract
|
||||||
|
files (`.acdl/static-assets.dev.yaml`, `...qa.yaml`, etc.) and (b) an
|
||||||
|
`environment` `workflow_call` input on the reusable deploy workflow
|
||||||
|
that overrides the contract's environment at load time. There is one
|
||||||
|
CI job per environment, each pointing at its respective contract (or
|
||||||
|
the same contract + the env input). Promotion = running the matching
|
||||||
|
job; no field editing.
|
||||||
|
4. **Stub implementation.** Identify and implement the stubbed
|
||||||
|
functionality: `separation_of_duties.route_halt_artifact` (logs only →
|
||||||
|
real SNS + outbox event); HITL qa/prod/dr pre-execution attestation
|
||||||
|
gates (only decommission SRE gates are wired today); the full
|
||||||
|
8-concern attestation matrix (offline-testable subset implemented;
|
||||||
|
operator-supplied concerns accept signed evidence artifacts); the Wiz
|
||||||
|
adapter (stub → real API client with graceful degrade); the Kyverno
|
||||||
|
adapter (fleshed out translator, still inactive for Terraform-only
|
||||||
|
stacks). The audit-ledger S3 Object Lock + JWS + async worker + DLQ +
|
||||||
|
daily checkpoints build-out is **deferred** to a future milestone
|
||||||
|
(D-076) — it requires non-offline-testable AWS infra (Object Lock
|
||||||
|
bucket, KMS signing key, SQS DLQ, Lambda worker).
|
||||||
|
5. **Post-hoc requirement from previous milestones.** P1-1 from the v1.2
|
||||||
|
review (adapter ECS/ALB/VPC hardcoded defaults — `desired_count = 1`,
|
||||||
|
`launch_type = "FARGATE"`, `target_type = "ip"`,
|
||||||
|
`load_balancer_type = "application"`, `family = "app"`, `Name = ...`
|
||||||
|
— should be parameterized via the L1 interfaces, deferred to v1.3,
|
||||||
|
never implemented) is closed. The adapter becomes a thin translator;
|
||||||
|
the defaults move into `interface.json` inputs.
|
||||||
|
|
||||||
|
The milestone also reconstructs `.ciagent/REVIEW.md`, which still holds
|
||||||
|
v1.2 review content (v1.3–v1.8 reviews were not persisted). The v1.9
|
||||||
|
review overwrites it with current milestone content; a note records the
|
||||||
|
historical gap (no git-history rewrite).
|
||||||
|
|
||||||
|
## Milestone v1.9 Phases
|
||||||
|
|
||||||
|
| Phase | Name | Goal |
|
||||||
|
|-------|------|------|
|
||||||
|
| 39 | design-doc-refresh-and-p1-1-parameterization | Refresh `hitl_matrix_design.md` + `audit_ledger_design.md` to current. Move adapter ECS/ALB/VPC hardcoded defaults into L1 `interface.json` inputs (P1-1 closure). |
|
||||||
|
| 40 | contract-interpolation | `${env.<field>}` + `${contract.<field>}` resolver expansion from environment onboarding JSON. Environment JSON schema. Sample contracts use naming patterns (region + account id + environment). |
|
||||||
|
| 41 | per-environment-ci-jobs | Per-env contract files + `environment` workflow_call input on the deploy workflow. 1 CI job per environment (dev/qa/prod/dr), each pointing at its respective contract. HITL attestation gate structure wired (qa/prod/dr). |
|
||||||
|
| 42 | stub-implementation | `route_halt_artifact` real (SNS + outbox). HITL qa/prod/dr attestation gates. 8-concern attestation matrix (offline-testable subset). Wiz real client. Kyverno translator fleshed out. |
|
||||||
|
| 43 | verify-review-audit-complete | 4-layer verify. Multi-persona review. Audit. Complete v1.9 (tag `v1.9.0`, floating tags, `uses:` bump `@v1.6` → `@v1.9`). |
|
||||||
|
|
||||||
|
Milestone COMPLETE gate: review → ship `v1.9.0` (feature milestone, next
|
||||||
|
minor per run.md — v1.8 shipped `v1.8.0`) → audit.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
### v1.0 (Prior milestone — the demo)
|
### v1.0 (Prior milestone — the demo)
|
||||||
|
|||||||
@@ -240,6 +240,38 @@
|
|||||||
| Adversarial tamper-proofing of evidence | Hash chain is demonstrative; not cryptographically secure against a determined attacker. |
|
| Adversarial tamper-proofing of evidence | Hash chain is demonstrative; not cryptographically secure against a determined attacker. |
|
||||||
| Multi-tenant isolation | Out of demo scope. |
|
| Multi-tenant isolation | Out of demo scope. |
|
||||||
|
|
||||||
|
## v1.9 (Active — design doc refresh + contract interpolation + per-env CI jobs + stub implementation + P1-1 remediation)
|
||||||
|
|
||||||
|
### Category: Design Doc Refresh
|
||||||
|
- **REQ-100:** `core/hitl_matrix_design.md` is up to date: the "dev-only spike" framing is replaced with the v1.9 wired-gates reality (qa/prod/dr `workflow_dispatch` approval gates + CODEOWNERS routing + outbox-based SoD); the 8-concern attestation matrix is marked implemented (offline-testable subset) with operator-supplied concerns noted; the spike-scope note is updated. No stale "v1.2 wires the gates" language remains.
|
||||||
|
- **REQ-101:** `core/audit_ledger_design.md` is up to date: the hash-chain + DynamoDB-outbox path is marked shipped + production (since v1.8); the S3 Object Lock + JWS + async worker + DLQ + daily checkpoints build-out is clearly labeled "Deferred to a future milestone" (D-076); the RPO/RTO table reflects the v1.9 state.
|
||||||
|
|
||||||
|
### Category: P1-1 Remediation
|
||||||
|
- **REQ-102:** The adapter (`adapters/terraform/adapter.py`) contains no resource-type-specific hardcoded defaults for ECS/ALB/VPC resources — `desired_count`, `launch_type`, `target_type`, `load_balancer_type`, `family`, and `Name` tag values are read from L1 `interface.json` inputs (with defaults declared in the interface). The adapter is a thin translator. An L1 with an overridden `desired_count: 3` emits `desired_count = 3`; the default emits `desired_count = 1` via the interface default, not an adapter hardcode (P1-1 closed).
|
||||||
|
|
||||||
|
### Category: Contract Interpolation
|
||||||
|
- **REQ-103:** The contract resolver (`core/contract_resolver.py`) expands `${env.<field>}` and `${contract.<field>}` tokens in contract string values (including dotted paths like `${env.state_backend.bucket}`) after schema validation and before IR resolution. The `env` context is the loaded `core/environments/<contract.environment>.json`; the `contract` context is the contract dict. Unresolved tokens raise `ValueError` (fail loud). Sample contracts use naming patterns that include region, account id, and environment (e.g. `acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}`).
|
||||||
|
- **REQ-104:** An environment JSON schema `schemas/environment.schema.json` (draft 2020-12) defines the environment file shape (`name`, `account_id`, `region`, `state_backend`, `network`, `runner_role_arn`, `autonomy`, `confidence_threshold`). `core/environments/dev.json` validates against it. `qa.json`, `prod.json`, `dr.json` placeholder bindings exist (autonomy `attested`, thresholds 0.75/0.90/0.95).
|
||||||
|
|
||||||
|
### Category: Per-Environment CI Jobs
|
||||||
|
- **REQ-105:** Per-environment contract files exist for each sample module (`contracts/static-assets.{dev,qa,prod,dr}.yaml` and `contracts/microservice.{dev,qa,prod,dr}.yaml`), each setting `environment:` to its own name and using interpolation for env-specific values. The existing `contracts/static-assets.yaml` + `contracts/microservice.yaml` remain as the dev default for backwards compatibility.
|
||||||
|
- **REQ-106:** The reusable deploy workflow (`.github/workflows/deploy.yml` + `.gitea/workflows/deploy.yml`, byte-identical) declares an `environment` `workflow_call` input (enum dev/qa/prod/dr, default empty). When non-empty, `scripts/run_platform.sh --environment <name>` overrides the contract's `environment` field at load time (before interpolation). A consumer repo's caller workflow has one job per environment, each pointing at its respective contract (or the same contract + the env input). Promotion = running the matching job; no `environment:` field editing. `docs/CONSUMER_GUIDE.md` documents the per-env caller workflow pattern.
|
||||||
|
|
||||||
|
### Category: Stub Implementation
|
||||||
|
- **REQ-107:** `core/separation_of_duties.py` `route_halt_artifact` is a real implementation: publishes to an SNS topic `acdl-sod-halt` (ARN from `ACDL_SOD_HALT_TOPIC_ARN`); when unset, falls back to a structured stderr emission + a `SEPARATION_OF_DUTIES_VIOLATION` event write to the DynamoDB outbox via `outbox_writer.write_event`. No silent print-only stub. The SNS topic is defined in `terraform/platform/main.tf`.
|
||||||
|
- **REQ-108:** HITL qa/prod/dr pre-execution attestation gates are wired via `core/hitl_gates.py` (`attest(contract_id, env, approver, evidence)`). The gate records the approver (`gitea.actor` / `github.actor`) to the outbox (`approver_qa` / `approver_prod` / `approver_dr` attributes per `audit_ledger_design.md`), runs the separation-of-duties check on prod, and returns `(ok, reason)`. `scripts/run_platform.sh` calls `hitl_gates.attest` before apply for qa/prod/dr (dev skips). The workflow's `workflow_dispatch` approval input is the trigger.
|
||||||
|
- **REQ-109:** The full 8-concern attestation matrix from `hitl_matrix_design.md` §10.4 is implemented in `core/attestation_matrix.py`. Offline-testable concerns (contract NFRs, schema validity, policy pass) run for real; operator-supplied concerns (k6 load test, DR drill, FinOps forecast) accept an uploaded signed evidence artifact validated for freshness + schema, failing loud if missing/expired for prod/dr. `hitl_gates.attest` invokes the matrix for the target env and blocks on any failing concern.
|
||||||
|
- **REQ-110:** The Wiz adapter (`adapters/wiz/wiz_adapter.py`) is a real API client: a `WizClient` queries the Wiz GraphQL API (`WIZ_API_TOKEN` + `WIZ_API_URL`) and translates issues → `PolicyCheckResult` records. It degrades gracefully (existing `WIZ_NOT_CONFIGURED` SKIPPED record) when env unset. Offline tests use a recorded GraphQL fixture.
|
||||||
|
- **REQ-111:** The Kyverno adapter (`adapters/kyverno/kyverno_adapter.py`) translator is fleshed out: full `PolicyReport` → `PolicyCheckResult` mapping with severity + skip handling. It remains inactive for Terraform-only stacks (guard preserved); a `--kube-version` stub is added for future GitOps. Sample policies already exist.
|
||||||
|
|
||||||
|
## Out of Scope (v1.9)
|
||||||
|
|
||||||
|
| Feature | Reason |
|
||||||
|
|---------|--------|
|
||||||
|
| S3 Object Lock + JWS + async worker + DLQ + daily checkpoints (audit ledger build-out) | Requires non-offline-testable AWS infra (Object Lock bucket, KMS signing key, SQS DLQ, Lambda worker). Deferred to a future milestone (D-076). The hash-chain + DynamoDB-outbox path remains the v1.9 production audit record. |
|
||||||
|
| Live k6/Gatling load test execution, live DR drill, live FinOps forecast | Operator-supplied evidence artifacts (signed blobs) are accepted + validated; the platform does not run these inline. |
|
||||||
|
| Self-service environment provisioning | Adding an environment remains a platform-team action (per `core/environments/README.md`). v1.9 adds the env files + schema, not self-service provisioning. |
|
||||||
|
|
||||||
## Traceability
|
## Traceability
|
||||||
|
|
||||||
### v1.0 (prior — demo)
|
### v1.0 (prior — demo)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
{
|
{
|
||||||
"slug": "acdl",
|
"slug": "acdl",
|
||||||
"name": "Agentic Cloud Delivery Platform",
|
"name": "Agentic Cloud Delivery Platform",
|
||||||
"milestone": "v1.8",
|
"milestone": "v1.9",
|
||||||
"status": "complete"
|
"status": "active"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"active_project": "acdl",
|
"active_project": "acdl",
|
||||||
|
|||||||
Reference in New Issue
Block a user