docs(P48): vision gaps + badge system + substrate→engine + CR format + agentic tags

9 requirements implemented across presentation decks and project docs:

1. DX closing slide: added 'Infrastructure as a utility, not a craft' bullet
   to convey the full vision (infrastructure consumed, not maintained;
   platform compounds value over time).
2. PW Problem slide: 'moving a merged change' → 'promoting a change'.
3. PW Problem slide: added 'Red tape' and 'Scalability without increasing
   headcount' bullets (4 frictions, not 2).
4. PW Roadmap slide: redesigned with side-by-side HTML table layout
   (Testing | Planned), 16px font, no overflow.
5. PW deck: added new slide 'What This Platform Is — and Isn't' after North
   Star (sovereign boundary, infrastructure as utility, 4 anti-goals).
   PW deck now 16 slides (was 15).
6. Maturity nomenclature: 'Available today'/'shipped' → 'Testing' across
   both decks + source markdown. New .testing badge (blue/teal #DBEAFE).
   Roadmap title: 'Testing vs. Planned'. The platform has 0 consumer
   adoption — 'shipped' was inaccurate.
7. Global: 'substrate' → 'engine' across entire project (88 matches, 30+
   files including .ciagent/, docs/, modules/, adapters/, schemas/, code).
8. Presentation files only: 'forge' → 'VCS' / 'version control system'
   (6 occurrences in 4 files). 'forge' retained in all technical docs and
   code as the industry-standard term.
9. New .agentic badge (purple/violet #EDE9FE) appended to agentic features
   in both decks: confidence signal, autonomous dev, pattern recognition,
   dynamic module creation, citizen developer surface, auto-promotion.

Also: Change Request ID format changed from 'CR-2026-001' to 'CHG0678912'
across presentation files, consumer guide, and test fixtures.

HTML re-rendered. PPTX rendered for release upload.

---ci---
phase: 48
milestone: v1.9
status: complete
requirements:
  covered: []
  partial: []
---/ci---
This commit is contained in:
Jon Chery
2026-07-23 14:58:29 +00:00
parent fc070ccb15
commit d58d28453d
38 changed files with 582 additions and 398 deletions
+11 -11
View File
@@ -15,7 +15,7 @@ locked commitments and the v1.1 spike scope.
## Overview
The platform is **four layers + six cross-cutting concerns**. The sixth
concern — the substrate abstraction (§12) — is first-class, not an
concern — the engine abstraction (§12) — is first-class, not an
implementation detail. The vision's "Two Consumer Surfaces, One Platform"
tenet binds everything: L3A and L3B converge on the same contract schema,
the same policy envelope, and the same evidence stream.
@@ -53,7 +53,7 @@ the same policy envelope, and the same evidence stream.
## Layers
### Layer 1 — Foundational Primitives
Single-purpose, **substrate-agnostic** primitive modules. L1 modules do
Single-purpose, **engine-agnostic** primitive modules. L1 modules do
not compose with other L1s; L1 takes its environment as input. The L1
interface is defined against the **Target Stack IR**, not against Terraform
directly (the IR is shaped to round-trip to Terraform in v1, per §12.1).
@@ -181,15 +181,15 @@ platform does not run the skill. Stateless agents, all state in the
platform. Skills are reviewed for sensitive data before release (Infra &
Ops owns the review; it is the mandatory release gate).
### Substrate execution (§12) — the binding constraint
**Target Stack IR** (locked): a substrate-neutral description of resources
### Angine execution (§12) — the binding constraint
**Target Stack IR** (locked): a engine-neutral description of resources
(typed inputs/outputs/NFRs), relationships (single parent per child),
composition (tree, max depth 5), and policy hooks. The L1 registry, L2
thin-composition tree, contract YML, and PolicyCheckResult schema are all
defined against the IR — none against any specific substrate.
defined against the IR — none against any specific engine.
**Substrate adapters** are the only substrate-specific code. An adapter
compiles the IR into a substrate execution plan. **v1 ships exactly one
**Angine adapters** are the only engine-specific code. An adapter
compiles the IR into a engine execution plan. **v1 ships exactly one
adapter: the Terraform adapter.** v2+ may add OpenTofu, Pulumi, K8s CRDs
without architectural change.
@@ -335,20 +335,20 @@ extends the *implementation*, not the design.
ECS Fargate service serving HTTP 200 → evidence event to the DynamoDB
outbox → acdl-evidence timeline.
### Substrate extension (ECS Fargate)
### Angine extension (ECS Fargate)
The Terraform adapter (§12) remains the only substrate-specific code. v1.2
The Terraform adapter (§12) remains the only engine-specific code. v1.2
expands the adapter `TYPE_MAP` to cover the six new ECS-shaped IR resource
types. The L1 interface shape (IR-typed inputs/outputs/NFRs, registered in
`modules-ir/registry.json`) is unchanged — only the set of registered L1s
grows. The IR commitments (REQ-28) continue to hold: `modules-ir/`,
`schemas/`, `contracts/`, `core/confidence_signal.py`,
`core/contract_resolver.py`, `core/outbox_writer.py`
remain substrate-agnostic.
remain engine-agnostic.
### `terraform apply` (dev only)
v1.2 lifts the substrate execution from `plan` to `apply` for the `dev`
v1.2 lifts the engine execution from `plan` to `apply` for the `dev`
environment only. Dev is autonomous per §10 (confidence ≥ 0.50, no HITL).
`apply` for qa/prod/dr remains HITL-gated and out of scope for v1.2. The
apply result (resources created, plan diff) is captured in the evidence
+5 -5
View File
@@ -43,9 +43,9 @@ verification_toolchain:
- **Active:** true
- **Phase-specific:** false
- **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
- **Constraints:** ir-is-engine-agnostic, adapter-is-only-engine-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).
- **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 engine-agnostic; the adapter is the only engine-specific code (the binding constraint per §12).
### security-engineer (custom)
- **Domain:** security
@@ -79,7 +79,7 @@ verification_toolchain:
### 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/**`, now `modules/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 (engine-agnostic IR + Terraform adapter). The stub engineer is no longer needed.
- **Phase-specific:** false (was v1.0)
- **Territory (would have been):** `demo/modules/l1/**`
@@ -127,9 +127,9 @@ lambda owns the SNS topic Terraform; frontend is unchanged from v1.0
## Conflict resolutions (lead-developer arbitration)
- `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 `platform-engineer` over `schemas/ir.schema.json` + `schemas/stack.schema.json`: platform-engineer owns the IR (engine-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.
- `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 (engine 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.
+8 -8
View File
@@ -56,7 +56,7 @@ Finalize the architecture to v1.0 (resolve all 11 open design decisions in
`docs/architecture.md` §13) and prove the locked commitments with one
end-to-end v1 implementation spike:
- **One L1 module** (`l1-s3`) — substrate-agnostic, IR-typed interface.
- **One L1 module** (`l1-s3`) — engine-agnostic, IR-typed interface.
- **One L2 thin-composition** (`l2-static-assets`) — references the L1.
- **Terraform adapter** — compiles the IR to a real `terraform plan`
against AWS via OIDC (no long-lived credentials, per §12.5).
@@ -439,7 +439,7 @@ appendix below. The demo is **archived** to `demo/` in Phase 06.
New requirements REQ-16..REQ-28 — see `REQUIREMENTS.md` §v1.1. Summary:
- **REQ-16:** Architecture finalized to v1.0 (11 open decisions resolved).
- **REQ-17:** Target Stack IR defined as JSON Schema; substrate-agnostic.
- **REQ-17:** Target Stack IR defined as JSON Schema; engine-agnostic.
- **REQ-18:** PolicyCheckResult normalized schema defined; Checkov adapter.
- **REQ-19:** Six-input confidence signal specified with per-env thresholds
(dev 0.50 / qa 0.75 / prod 0.90 / dr 0.95) and severity→penalty mapping.
@@ -459,7 +459,7 @@ New requirements REQ-16..REQ-28 — see `REQUIREMENTS.md` §v1.1. Summary:
- **REQ-27:** One end-to-end contract submission → contract→IR resolution →
`terraform plan` → Checkov → confidence signal → evidence event to outbox.
- **REQ-28:** Spike verification proves the IR-shaped commitments hold (no
polyglot mess; the adapter is the only substrate-specific code).
polyglot mess; the adapter is the only engine-specific code).
### v1.2 (Prior milestone — platform hardening + first real consumer deployment, complete)
@@ -524,8 +524,8 @@ D-080+ to avoid collision with v1.8 research decisions D-073..D-077):
- **Cloud:** AWS via OIDC federation. **Long-lived credentials are forbidden**
(§12.5). The v1.1 spike uses a temporary long-lived key **once** to bootstrap
OIDC (waiver D-034), then rotates it.
- **Substrate:** Terraform adapter in v1 (the only adapter). L1/L2 are
substrate-agnostic in shape; the adapter is the only substrate-specific code.
- **Angine:** Terraform adapter in v1 (the only adapter). L1/L2 are
engine-agnostic in shape; the adapter is the only engine-specific code.
- **State:** S3 (state files) + DynamoDB (locking), single-region in v1.
- **Environments:** dev (autonomous) → qa (QA HITL) → prod (SRE HITL) → dr
(SRE HITL). **Staging does not exist** (Path A locked).
@@ -550,7 +550,7 @@ D-080+ to avoid collision with v1.8 research decisions D-073..D-077):
vision/architecture sources, pulled from `origin/main` at the start of v1.1.
- The v1.0 demo (tag `v1.1.0`) is the reference of intent — it proved the
shape (L1/L2/contract/confidence/evidence/HITL) on stubs. v1.1 replaces the
stubs with the real platform substrate.
stubs with the real platform engine.
## Key Decisions (v1.1)
@@ -629,8 +629,8 @@ or user-directed scope). New v1.7 decisions:
| BA.C | On-call / operational ownership | **Decided.** Platform on-call = Infra & Ops rotation. Escalation: L3A/L3B halt → platform on-call pager (Sev2); consumer-visible outage → consumer on-call (Sev1) with platform on-call support. Consumer on-call relationship is contractual, defined at onboarding (BA.E). |
| BA.D | Cost / capacity governance | **Decided.** Cloud cost owner = Infra & Ops FinOps. Per-contract consumption reported monthly. Runaway spend: hard halt at 120% of contract-declared budget envelope via the confidence signal (cost is one of the 6 inputs); override = FinOps + SRE joint sign-off. |
| BA.E | Consumer onboarding | **Decided.** Two paths: developer (L3A) — `getting-started` walks through contract schema + central pipeline template; citizen developer (L3B) — onboarding grants a scoped agent + skill catalog, no workflow authoring. Both end in a sandbox dev submission that must pass the confidence gate before the consumer is promoted. |
| BA.F | Cross-platform evolution | **Decided.** The contract schema, IR, PolicyCheckResult, confidence signal, and audit stream are portable (substrate- and forge-agnostic). Forge-specific code: workflow YAML, OIDC trust, CODEOWNERS, Environments. A second forge (e.g., GitLab) requires a forge adapter + a workflow-template translator; no change to L1/L2/IR/confidence/audit. |
| Q1.3 | OpenTofu timing | **Decided (deferred).** Not in v1 or v1.1. The substrate abstraction (§12) makes OpenTofu a future adapter, not an architecture change. Revisit when an OpenTofu adapter is requested; no version committed. |
| BA.F | Cross-platform evolution | **Decided.** The contract schema, IR, PolicyCheckResult, confidence signal, and audit stream are portable (engine- and forge-agnostic). Forge-specific code: workflow YAML, OIDC trust, CODEOWNERS, Environments. A second forge (e.g., GitLab) requires a forge adapter + a workflow-template translator; no change to L1/L2/IR/confidence/audit. |
| Q1.3 | OpenTofu timing | **Decided (deferred).** Not in v1 or v1.1. The engine abstraction (§12) makes OpenTofu a future adapter, not an architecture change. Revisit when an OpenTofu adapter is requested; no version committed. |
## Appendix — Prior milestone (v1.0 demo) decisions
+2 -2
View File
@@ -39,7 +39,7 @@
### Category: Architecture Finalization
- **REQ-16:** Architecture reaches v1.0 — all 11 open decisions in `docs/architecture.md` §13 are resolved and recorded in `PROJECT.md` (W1.A, W1.B, W2.A, W3.D, W3.E, BA.AF, OpenTofu timing).
- **REQ-17:** Target Stack IR is defined as a JSON Schema under `schemas/ir.schema.json`; substrate-agnostic (resources, relationships, composition max-depth-5, policy hooks).
- **REQ-17:** Target Stack IR is defined as a JSON Schema under `schemas/ir.schema.json`; engine-agnostic (resources, relationships, composition max-depth-5, policy hooks).
- **REQ-18:** `PolicyCheckResult` normalized schema is defined under `schemas/policy_check_result.schema.json`; a Checkov adapter translates Checkov JSON to this schema.
- **REQ-19:** Six-input confidence signal is specified under `platform/confidence_signal.py` with per-env thresholds (dev 0.50 / qa 0.75 / prod 0.90 / dr 0.95) and severity→penalty mapping (critical=hard override, high=-0.2, medium=-0.05, low=-0.01, info=0.0).
- **REQ-20:** Tiered audit ledger design is authored: S3 Object Lock (compliance mode, 7-yr) + DynamoDB outbox (RPO=0, JWS detached signatures, `prev_event_hash` chain, daily checkpoints).
@@ -56,7 +56,7 @@
### Category: v1 Spike — End-to-End
- **REQ-27:** One end-to-end contract submission (`contracts/spike.yaml` for `l2-static-assets`) flows through: contract schema validation → contract→IR resolution → `terraform plan` (real AWS) → Checkov `PolicyCheckResult` → confidence signal → evidence event written to the DynamoDB outbox.
- **REQ-28:** Spike verification (`scripts/verify_phase10.sh`) proves the IR-shaped commitments hold: the adapter is the only substrate-specific code; no polyglot mess; the L1 content, contract YML, and thin-composition tree are substrate-agnostic.
- **REQ-28:** Spike verification (`scripts/verify_phase10.sh`) proves the IR-shaped commitments hold: the adapter is the only engine-specific code; no polyglot mess; the L1 content, contract YML, and thin-composition tree are engine-agnostic.
## Out of Scope (v1.1)
+3 -3
View File
@@ -106,7 +106,7 @@ step without a long-lived key)
| (b) Self-hosted OIDC broker | Stand up a tiny OIDC IdP (e.g. `dex`, `oauth2-proxy`, or a custom JWKS endpoint) that the Gitea job authenticates to with its `GITEA_TOKEN` and that issues a JWT minted with a platform signing key; AWS IAM trusts the broker's JWKS. | Workable but heavy for a spike — requires a second always-on service, a signing-key rotation story, and IAM trust plumbing. Better suited to v1.2. |
| (c) `aws sts assume-role-with-web-identity` with a token from Gitea's own API | Use the job's `GITEA_TOKEN` (a PAT-equivalent, short-lived for the job) as the `WebIdentityToken` to STS. | **Rejected**: STS rejects non-OIDC tokens; `GITEA_TOKEN` is not a JWT, has no `iss`/`sub`/`aud` claims, and AWS IAM has no Gitea OIDC provider to trust. (This is exactly the gap #33681 describes for GCP.) |
| (d) Short-lived AWS creds via a scheduled credential mint | A platform job (cron) mints `aws sts get-session-token` (or a role-session) and writes the temp creds as a Gitea Actions secret with a TTL ≤ 1h. The spike workflow reads the secret. | Workable, but reintroduces a long-lived key *upstream* (the mint job needs one) and a secret in Gitea — a narrower version of the very thing §12.5 forbids. Acceptable as a documented spike-only waiver if (a) and (b) are both rejected for the spike scope. |
| (e) LocalStack as an AWS stand-in | Replace real AWS with LocalStack for the spike; no IAM trust needed at all (LocalStack mocks STS). | Workable for the *mechanics* of `terraform plan` but **invalidates REQ-23** ("real AWS via OIDC") and the spike's whole purpose of proving real-AWS feasibility. Reject for the spike; keep as a unit-test substrate only. |
| (e) LocalStack as an AWS stand-in | Replace real AWS with LocalStack for the spike; no IAM trust needed at all (LocalStack mocks STS). | Workable for the *mechanics* of `terraform plan` but **invalidates REQ-23** ("real AWS via OIDC") and the spike's whole purpose of proving real-AWS feasibility. Reject for the spike; keep as a unit-test engine only. |
| (f) Documented spike-only waiver: rotate a long-lived key per-run | One IAM access key, stored as a Gitea Actions secret, used by the workflow, rotated (deactivated + new key) after each spike run by the same workflow. | The cleanest *available* option that still touches real AWS. Still violates the *letter* of §12.5 ("long-lived credentials are forbidden") but satisfies the *intent* for a time-boxed spike: the key's useful lifetime equals one workflow run (minutes), not "long-lived." Requires an explicit, logged waiver. |
| (g) GitHub-hosted mirror pipeline | Run the OIDC-requiring step on GitHub Actions (which supports `id-token: write`) against the same repo mirrored from Gitea. | Rejected: introduces a second forge, violates the "Forge: Gitea" constraint, and defeats the spike's purpose of proving the platform works on Gitea. |
@@ -348,7 +348,7 @@ the adapter and the round-trip to Terraform is verified.
- **A-3.1** (0.85): the IR's "nearly isomorphic to Terraform in v1" claim
(architecture.md §12.1) is the right v1 boundary — build a thin IR, defer
substrate-specific expressiveness to v2.
engine-specific expressiveness to v2.
- **A-3.2** (0.80): single-parent-per-child is sufficient for v1 (no L1
needs two parents in the spike). The "shared keyword for multi-relationship"
(architecture.md §12.1) is a v2 concern; the v1 schema reserves the field
@@ -1447,7 +1447,7 @@ AWS Terraform resources; the adapter `TYPE_MAP` (currently
| `l1-alb` | `aws:elbv2:loadbalancer`, `aws:elbv2:listener`, `aws:elbv2:targetgroup` | `aws_lb`, `aws_lb_listener`, `aws_lb_target_group` | port, protocol |
| `l1-ecr` | `aws:ecr:repository` | `aws_ecr_repository` | name |
The IR schema (`schemas/ir.schema.json`) is substrate-agnostic and already
The IR schema (`schemas/ir.schema.json`) is engine-agnostic and already
supports arbitrary resource types — no schema change needed, only new
`interface.json` files + `TYPE_MAP` entries. The `l2-microservice`
thin-composition references all six (depth ≤ 5).
+1 -1
View File
@@ -142,7 +142,7 @@ D-034 closed (root key deactivated by user).**
- **Success Criteria:**
- `l2-static-assets` references `l1-s3` only (depth 1).
- One contract submission completes the full pipeline end-to-end.
- `scripts/verify_phase10.sh` proves the adapter is the only substrate-specific code.
- `scripts/verify_phase10.sh` proves the adapter is the only engine-specific code.
- Evidence event is written to the DynamoDB outbox.
After Phase 10: COMPLETE gate — review → ship `v1.2.0` → audit. **DONE.**
+4 -4
View File
@@ -77,7 +77,7 @@ Planned future features (no dates; tracked in the internal roadmap):
"composition" mechanism, redesigned).
- **Compliance milestone** — per-module compliance extension points (GDPR,
SOX, SOC2, DORA) wired into the pipeline.
- **Additional substrate adapters** — beyond the Terraform adapter.
- **Additional engine adapters** — beyond the Terraform adapter.
- **Environment self-service** — a consumer-facing flow to request and
provision a new platform-managed environment (today it is a platform-team
action).
@@ -117,9 +117,9 @@ flowchart TD
The platform validates the architecture's claim that the **stack
commitments do not require a polyglot mess**: the adapter is the only
substrate-specific code. `modules/`, `schemas/`, `contracts/`,
engine-specific code. `modules/`, `schemas/`, `contracts/`,
`core/confidence_signal.py`, `core/contract_resolver.py`, and
`core/outbox_writer.py` are all substrate-agnostic (no `aws_s3_bucket` /
`core/outbox_writer.py` are all engine-agnostic (no `aws_s3_bucket` /
`aws_` infrastructure terms).
## How to run
@@ -258,7 +258,7 @@ across all modules; `static-assets` is the worked example.
| `core/` | Platform code: contract resolver, confidence signal, outbox writer, environment check, environments, separation of duties, HITL/ledger designs | active |
| `schemas/` | JSON Schemas: stack, contract, PolicyCheckResult, pipeline contract, deploy pipeline contract (draft 2020-12) | active |
| `pipelines/` | Central pipeline contracts: `ci.yaml` (CI), `deploy.yaml` (deployment) | active |
| `adapters/` | Substrate adapters — the substrate adapter (the only substrate-specific code per §12) + the policy adapter | active |
| `adapters/` | Angine adapters — the engine adapter (the only engine-specific code per §12) + the policy adapter | active |
| `terraform/` | State backend (S3 + DynamoDB) + platform TF (`terraform/spike/`) + bootstrap scripts (`terraform/bootstrap/`) | active |
| `modules/` | Primitives + modules + `registry.json`. Primitives: s3, vpc, ecs-cluster, ecs-service, iam-role, alb, ecr, cloudfront, waf, rds. Modules: microservice, static-assets. Each module has a `examples/` directory with validated contract examples | active |
| `contracts/` | Sample consumer contracts (`static-assets.yaml`, `microservice.yaml`) | active |
+1 -1
View File
@@ -2,7 +2,7 @@
## Overview
Adapters translate the substrate-agnostic Target Stack IR to substrate-specific formats. The Terraform adapter is the primary adapter (IR → HCL). Policy adapters translate security tool output into normalized `PolicyCheckResult` records that the confidence signal consumes in an engine-agnostic way.
Adapters translate the engine-agnostic Target Stack IR to engine-specific formats. The Terraform adapter is the primary adapter (IR → HCL). Policy adapters translate security tool output into normalized `PolicyCheckResult` records that the confidence signal consumes in an engine-agnostic way.
## Existing Adapters
+2 -2
View File
@@ -6,7 +6,7 @@ root module that calls the L1 modules, the stack-typed relationships to
Terraform module references, and emits a Terraform plan from the stack.
The adapter is a THIN LAYER; it does not own L1/L2 content — it only
translates. Substrate-agnostic in, Terraform out.
translates. Angine-agnostic in, Terraform out.
Phase 09 spike: handled one L1 (s3, stack type aws:s3:bucket).
Phase 13: generalized the resource/output emission via TYPE_MAP +
@@ -21,7 +21,7 @@ import os
import sys
# Stack type -> Terraform resource type. The only substrate-specific table.
# Stack type -> Terraform resource type. The only engine-specific table.
# As more L1s land, this grows; the L1 content + stack do not change.
TYPE_MAP = {
"aws:s3:bucket": "aws_s3_bucket",
+22 -22
View File
@@ -21,7 +21,7 @@ flowchart TD
A["Consumer surfaces"] --> B["Contract schema"]
B --> C["Central pipeline"]
C --> D["Modules + primitives"]
C --> E["Substrate adapter"]
C --> E["Angine adapter"]
C --> F["Confidence signal"]
C --> G["Evidence stream"]
D --> E
@@ -31,7 +31,7 @@ flowchart TD
The four layers:
1. **Primitives** — single-purpose, substrate-agnostic modules representing
1. **Primitives** — single-purpose, engine-agnostic modules representing
the smallest reusable infrastructure pieces (a VPC, an S3 bucket, an ECS
cluster). A primitive does not reference other primitives; it takes its
environment as input.
@@ -51,9 +51,9 @@ Both end in a contract submission that enters the same pipeline.
## 2. Primitives
Single-purpose, substrate-agnostic modules. Locked commitments:
Single-purpose, engine-agnostic modules. Locked commitments:
- No inter-primitive references. A primitive may call substrate data sources.
- No inter-primitive references. A primitive may call engine data sources.
- Semver with three triggers: interface → MAJOR, behavior → MINOR,
lifecycle → PATCH.
- Immutability on publication.
@@ -61,8 +61,8 @@ Single-purpose, substrate-agnostic modules. Locked commitments:
- AI refinement is a flag, triggered by a joint operational condition
(N ≥ 50 consecutive zero-rollback changes, no primitive/module incident in
6 months, Infra & Ops unilateral override).
- A primitive's interface is defined against the Target Stack (substrate-
agnostic), not against any substrate's variable block directly.
- A primitive's interface is defined against the Target Stack (engine-
agnostic), not against any engine's variable block directly.
## 3. Modules
@@ -79,9 +79,9 @@ Patterns that combine primitives into deployable shapes. Locked commitments:
creation, key/secret creation, external data transfer.
- Auto-promote after 3 observed usages.
- A module's pattern tree wires field is defined against the stack's
relationship type, not against any substrate's module block. The stack →
substrate translation is the substrate adapter's job (§12). The pattern
pipeline itself is substrate-agnostic.
relationship type, not against any engine's module block. The stack →
engine translation is the engine adapter's job (§12). The pattern
pipeline itself is engine-agnostic.
## 4. Developer Surface
@@ -110,7 +110,7 @@ Patterns that combine primitives into deployable shapes. Locked commitments:
- Central repo + generated client libraries.
- Multi-stage validation pipeline: schema → policy → NFR → confidence.
- Distributed enrichment.
- GitOps reconciler + substrate execution layer.
- GitOps reconciler + engine execution layer.
- The pipeline emits a `PolicyCheckResult` record per policy rule evaluated;
the confidence signal consumes these as one normalized input (§8).
@@ -174,12 +174,12 @@ integration, contract, security smoke, and performance smoke validation.
- The DynamoDB outbox enforces identity distinctness across environment
approvers.
## 12. Cross-Cutting — Substrate Execution
## 12. Cross-Cutting — Angine Execution
The technical execution layer. Primitives and modules are substrate-agnostic
in shape; substrate adapters are the only substrate-specific component.
The technical execution layer. Primitives and modules are engine-agnostic
in shape; engine adapters are the only engine-specific component.
The architecture defines a **Target Stack** — a substrate-neutral
The architecture defines a **Target Stack** — a engine-neutral
description of:
- The resources to create (typed against the stack schema).
@@ -189,7 +189,7 @@ description of:
The registry, the module pattern tree, the contract schema, and the
`PolicyCheckResult` schema are all defined against the stack schema. None is
defined against any specific substrate.
defined against any specific engine.
**v1 implementation reality:** the stack is shaped to round-trip cleanly to
Terraform because there is no other adapter to differentiate from. As
@@ -198,19 +198,19 @@ gain translation logic, but the primitive content, the module pattern tree,
and the contract schema do not change. This is the design that prevents a
polyglot mess.
The substrate adapter:
The engine adapter:
- Translates the stack-typed module pattern tree to a substrate root module
- Translates the stack-typed module pattern tree to a engine root module
that calls the primitive modules.
- Is a thin layer. It does not own primitive/module content; it only
translates.
- Is the only substrate-specific code in the platform.
- Is the only engine-specific code in the platform.
Policy checks run on the substrate plan output. Results are normalized to
Policy checks run on the engine plan output. Results are normalized to
`PolicyCheckResult` records by a policy adapter. The confidence signal
consumes the union of all `PolicyCheckResult` records, regardless of engine
substrate-agnostic over its inputs, matching the module model's
substrate-agnosticism over its outputs.
engine-agnostic over its inputs, matching the module model's
engine-agnosticism over its outputs.
## 13. Cross-Cutting — Platform Runners
@@ -237,5 +237,5 @@ See [Versioning](pipeline/versioning) for the consumer-facing details.
## 15. OpenTofu
Not in v1. The substrate abstraction (§12) makes OpenTofu a future adapter,
Not in v1. The engine abstraction (§12) makes OpenTofu a future adapter,
not an architecture change. Revisit when an OpenTofu adapter is requested.
+4 -4
View File
@@ -10,7 +10,7 @@ step applies to `microservice` and any future module.
Consumers have their own repos and consume ACDL by referencing `uses:` the
central pipeline definitions. The consumer declares a **contract** (which
module, which environment, which inputs); the ACDL platform owns the
pipelines, modules, substrate adapter, and evidence stream.
pipelines, modules, engine adapter, and evidence stream.
You do not write infrastructure modules, workflow YAML, or adapter code.
You write a contract YAML file and the platform does the rest. Your
@@ -229,7 +229,7 @@ flowchart TD
a stack JSON instance.
3. **security checks** (adapter) — security checks run on the resolved
stack before any infrastructure is planned.
4. **infrastructure plan** (adapter) — the substrate adapter compiles the
4. **infrastructure plan** (adapter) — the engine adapter compiles the
stack to an infrastructure plan. You see the plan in your run logs.
5. **policy checks** (adapter) — policy checks run on the plan. The results
are normalized to `PolicyCheckResult` records. Each result has a
@@ -314,7 +314,7 @@ per-module extension points. Common examples:
| Sample contract | `contracts/microservice.yaml` | The microservice example contract (uses `@v1.9`). |
| Module examples | `modules/<name>/examples/` | Validated per-module example contracts (`simple.yaml` + `complex.yaml`). |
| Contract resolver | `core/contract_resolver.py` | Resolves contracts to stack instances. |
| Substrate adapter | `adapters/terraform/adapter.py` | Compiles stack instances to infrastructure. |
| Angine adapter | `adapters/terraform/adapter.py` | Compiles stack instances to infrastructure. |
| Platform pipeline runner | `scripts/run_platform.sh` | The pipeline runner (platform-side; consumers do not invoke it directly). |
| Environments | [environments/](environments/) | Platform-managed environments + onboarding. |
| Versioning | [pipeline/versioning](pipeline/versioning) | The `uses:` tag + module versioning. |
@@ -341,7 +341,7 @@ destruction:
with:
contract: .acdl/contract.yaml
mode: decommission
changeRequestId: "CR-2026-001"
changeRequestId: "CHG0678912"
```
3. **Step 1 — Disable deletion protection (HITL SRE gate):** The pipeline
+2 -2
View File
@@ -32,7 +32,7 @@ There are two kinds of repository in the ACDL model:
| [Pipeline](pipeline/) | Consumers + platform engineers | The central CI + deployment pipeline and its stages. |
| [Versioning](pipeline/versioning) | Consumers + platform engineers | Module versioning + deploy-pipeline versioning (the `uses:` tag). |
| [Environments](environments/) | Consumers | Platform-managed environments and the first-run onboarding flow. |
| [Architecture](architecture) | Platform engineers | The current architecture — layers, cross-cutting concerns, the substrate abstraction. |
| [Architecture](architecture) | Platform engineers | The current architecture — layers, cross-cutting concerns, the engine abstraction. |
| [Vision](vision) | All | The why — the friction the platform absorbs and the north star. |
## Features
@@ -64,7 +64,7 @@ Planned future features (no dates; tracked in the internal roadmap):
mechanism, redesigned).
- **Compliance milestone** — per-module compliance extension points (GDPR,
SOX, SOC2, DORA) wired into the pipeline.
- **Additional substrate adapters** — beyond the Terraform adapter.
- **Additional engine adapters** — beyond the Terraform adapter.
- **Environment self-service** — a consumer-facing flow to request and
provision a new platform-managed environment.
- **HITL gates for qa / prod / dr** — human attestation + higher confidence
+1 -1
View File
@@ -9,7 +9,7 @@ Reusable building blocks for cloud infrastructure. There are two kinds:
complete stack (e.g. an ECS Fargate microservice). Each module has a
`composition.json` declaring its children and wires.
The substrate adapter compiles a module instance to infrastructure. Each
The engine adapter compiles a module instance to infrastructure. Each
module's README documents which resources it creates.
## Primitives
+1 -1
View File
@@ -67,7 +67,7 @@ flowchart TD
wires the contract inputs, emits a stack JSON instance).
3. **security checks** (adapter) — security checks run on the resolved
stack before any infrastructure is planned.
4. **infrastructure plan** (adapter) — the substrate adapter compiles the
4. **infrastructure plan** (adapter) — the engine adapter compiles the
stack to an infrastructure plan.
5. **policy checks** (adapter) — policy checks run on the plan. Results are
normalized to `PolicyCheckResult` records (severity, rule ID, pass/fail).
+7 -5
View File
@@ -58,8 +58,9 @@ Synthesize the full markdown into a lean Marp deck:
- **`<!-- _class: title -->` + `<!-- _paginate: false -->`** on title and
closing slides for the dark-background title style.
- **Maturity badges** using inline spans:
`<span class="badge today">Available today</span>`
`<span class="badge testing">Testing</span>`
`<span class="badge planned">Planned</span>`
`<span class="badge agentic">Agentic</span>`
- **Tighter prose** than Step 1 — strip the speaker-note nuance; keep the
leadership-relevant selling points.
@@ -133,15 +134,16 @@ docs/presentations/
### Maturity framing
Every capability claim in a deck is tagged with one of two badges:
Every capability claim in a deck is tagged with one of three badges:
| Badge | Meaning |
|---|---|
| `Available today` | Shipped and verified in the platform |
| `Planned` | On the roadmap, not yet shipped |
| `Testing` | Works internally, not yet released to consumers (0 adoption) |
| `Planned` | On the roadmap, not yet implemented |
| `Agentic` | Involves AI agents, autonomous decision-making, or the citizen developer flow |
This is non-negotiable for a leadership audience: never present a roadmap
item as a current capability, and never bury a shipped capability's
item as a current capability, and never bury a tested capability's
availability. When in doubt, check `.ciagent/ROADMAP.md` and the milestone
status in `.ciagent/PROJECT.md`.
@@ -23,8 +23,9 @@ style: |
display: inline-block; padding: 2px 8px; border-radius: 4px;
font-size: 14px; font-weight: 600;
}
.today { background: #c6f6d5; color: #22543d; }
.testing { background: #DBEAFE; color: #1E3A5F; }
.planned { background: #fef3c7; color: #78350f; }
.agentic { background: #EDE9FE; color: #4C1D95; }
---
<!-- _class: title -->
@@ -45,12 +46,14 @@ section.title h3 { color: #F0F0F0; font-weight: 400; font-size: 22px; margin-top
Software delivery scales with the **coordination surface around it**, not the engineering inside it.
Two frictions slow every team:
Four frictions slow every team:
- **Cognitive load** — authoring the infrastructure that runs a service *correctly*. The long tail of services that are difficult to deploy, inconsistent in security and observability posture.
- **Operational work** — moving a merged change from "merged" to "running in production with policy, observability, and security enforced." Manual work that **scales with the system, not with the change.**
- **Operational work**promoting a change from "merged" to "running in production with policy, observability, and security enforced." Manual work that **scales with the system, not with the change.**
- **Red tape** — every deployment requires tickets, approvals, and manual handoffs that scale with the organization, not with the change. A merged change waits in a queue for someone to press a button.
- **Scalability without increasing headcount** — the platform allows delivery throughput to scale without linearly scaling platform engineers. Today, every new team adds load to the same ticket queue.
The platform absorbs **both** frictions.
The platform absorbs **all four** frictions.
---
@@ -66,6 +69,22 @@ Success looks like:
---
# What This Platform Is — and Isn't
**What it is:**
- **A sovereign delivery boundary.** The platform governs infrastructure and delivery. It does not penetrate upstream product or software development lifecycles. Integration happens through validated, published contracts.
- **Infrastructure consumed, not maintained.** Compute is abstract, containerized, or serverless. The platform does not manage node, OS, or bare-metal lifecycles. Infrastructure is a utility, not a craft.
**What it isn't:**
- **Not an upstream development platform.** No product backlogs, sprint ceremonies, or IDE workflows.
- **Not a general-purpose AI.** Autonomy is narrow, scoped to delivery and infrastructure reconciliation, bounded by strict policy envelopes.
- **Not a legacy infrastructure bridge.** No VMs, bare metal, or OS lifecycles.
- **Not a permissive delivery highway.** No escape hatches to bypass the confidence framework or human attestation requirements.
---
# The Contract-Driven Model
One small YAML file is all a consumer writes. The platform owns everything else.
@@ -95,7 +114,7 @@ Every deployment runs the same stages, in the same order, with the same checks
Consumer repositories hold **no long-lived cloud credentials.** Ever.
- **Authentication — OIDC federation.** Each job mints a short-lived token; no credential is stored in the consumer repo or in a runner secret. <span class="badge today">Available today (GitHub Actions)</span> <span class="badge planned">Planned: all runners</span>
- **Authentication — OIDC federation.** Each job mints a short-lived token; no credential is stored in the consumer repo or in a runner secret. <span class="badge testing">Testing (GitHub Actions)</span> <span class="badge planned">Planned: all runners</span>
- **Authorization — attribute-based (ABAC), not role-based.** Two attribute classes scope every action:
- **Repository identity** — the role's trust policy binds to the exact consumer repo + branch
- **Resource tags** — every resource is tagged `acdl:owner` + `acdl:contract`; the session policy grants access **only to matching tags**
@@ -106,7 +125,7 @@ Consumer repositories hold **no long-lived cloud credentials.** Ever.
# Safety is Computed, Not Assumed
Every delivery action produces a **measurable, explainable confidence signal** — the platform's certified answer to *"is this safe to proceed?"*
Every delivery action produces a **measurable, explainable confidence signal** — the platform's certified answer to *"is this safe to proceed?"* <span class="badge agentic">Agentic</span>
- **Six weighted inputs:** policy conformance, validation, freshness, source provenance, history, NFRs
- **Per-environment thresholds** that rise with sensitivity:
@@ -127,9 +146,9 @@ Every delivery action produces a **measurable, explainable confidence signal**
Checks run on **every** deployment, normalized to a single schema regardless of which engine produced them.
- **Infrastructure policy** (Checkov) — secrets in plaintext, public ingress, IAM wildcards, KMS references, **required tagging standards** (`acdl:owner`, `acdl:contract`, `acdl:environment`, `acdl:cost-center`) <span class="badge today">Available today</span>
- **Cloud security posture** (Wiz adapter) — translates cloud security findings into the same normalized record <span class="badge today">Adapter ready</span>
- **Kubernetes-native policy** (Kyverno adapter) — ready for the GitOps reconciler <span class="badge today">Adapter ready</span>
- **Infrastructure policy** (Checkov) — secrets in plaintext, public ingress, IAM wildcards, KMS references, **required tagging standards** (`acdl:owner`, `acdl:contract`, `acdl:environment`, `acdl:cost-center`) <span class="badge testing">Testing</span>
- **Cloud security posture** (Wiz adapter) — translates cloud security findings into the same normalized record <span class="badge testing">Testing</span>
- **Kubernetes-native policy** (Kyverno adapter) — ready for the GitOps reconciler <span class="badge testing">Testing</span>
Every check produces a record with **severity, rule ID, pass/fail status, and a human-readable message** — consumed uniformly by the confidence signal.
@@ -137,7 +156,7 @@ Every check produces a record with **severity, rule ID, pass/fail status, and a
# Secure by Default
Security defaults that **do not require a team to opt in.** <span class="badge today">Available today</span>
Security defaults that **do not require a team to opt in.** <span class="badge testing">Testing</span>
- **Encryption on every resource** — at-rest encryption on by default for every primitive (S3, RDS, ECR, ECS, and more)
- **Per-stack customer-managed keys** — one key per deployment, 90-day rotation, **no shared keys across stacks**
@@ -151,10 +170,10 @@ Security defaults that **do not require a team to opt in.** <span class="badge t
Version control is a **coordination tool, not an evidentiary fortress.** True compliance requires an immutable, externally-stored ledger.
- **Every deployment writes a hash-chained evidence event** — each event links to the previous via a cryptographic hash; tampering breaks the chain <span class="badge today">Available today</span>
- **Tiered storage:** cold, tamper-proof source of truth (S3 Object Lock, 7-year retention) + a hot query index <span class="badge today">Outbox shipped</span> <span class="badge planned">Full ledger: planned</span>
- **Every deployment writes a hash-chained evidence event** — each event links to the previous via a cryptographic hash; tampering breaks the chain <span class="badge testing">Testing</span>
- **Tiered storage:** cold, tamper-proof source of truth (S3 Object Lock, 7-year retention) + a hot query index <span class="badge testing">Outbox tested</span> <span class="badge planned">Full ledger: planned</span>
- **RPO = 0** — the evidence write is synchronous; a deployment is not acknowledged until the evidence event is durably recorded
- **Every production change is traceable to a human attestation** — approver identities are the only durable record outside the forge's audit log
- **Every production change is traceable to a human attestation** — approver identities are the only durable record outside the VCS's audit log
---
@@ -162,16 +181,16 @@ Version control is a **coordination tool, not an evidentiary fortress.** True co
Autonomy and accountability are **not in tension** — they apply at different environments.
- **Dev is fully autonomous.** The confidence signal (≥ 0.50) is the only gate. Queue-based handoffs are eliminated from lower environments.
- **Dev is fully autonomous.** The confidence signal (≥ 0.50) is the only gate. Queue-based handoffs are eliminated from lower environments. <span class="badge agentic">Agentic</span>
- **qa, prod, and dr require deliberate human attestation** — not rubber stamps, but policy-mandated acts of accountability via protected deployment approvals.
- **Separation of duties is enforced** — the QA approver **cannot** be the prod approver. The platform reads both identities from the outbox and **blocks on a match.** <span class="badge today">Design shipped</span> <span class="badge planned">Wiring: planned</span>
- **Separation of duties is enforced** — the QA approver **cannot** be the prod approver. The platform reads both identities from the outbox and **blocks on a match.** <span class="badge testing">Design tested</span> <span class="badge planned">Wiring: planned</span>
- **Timeout discipline** — 1 business day = warn + escalate; 2 business days = auto-freeze + re-submit
---
# Observability Built In
Monitoring is **a platform default, not a per-team project.** <span class="badge today">Available today</span>
Monitoring is **a platform default, not a per-team project.** <span class="badge testing">Testing</span>
- **Uptime monitoring deployed automatically with every stack** — a dedicated monitoring instance is provisioned after any module deploy, in a separate state, with a feature flag to disable
- **Monitored endpoints passed from the deployment's own outputs** — no manual endpoint registration
@@ -194,7 +213,7 @@ A named environment is a platform-owned bundle of:
The consumer selects an environment **by name** in their contract. The platform resolves the name to the underlying resources at run time. **The consumer never sees raw credentials.**
**Friendly onboarding:** the first run detects no environment and emits a guided prompt (not an opaque failure). <span class="badge today">Available today</span> <span class="badge planned">Self-service: planned</span>
**Friendly onboarding:** the first run detects no environment and emits a guided prompt (not an opaque failure). <span class="badge testing">Testing</span> <span class="badge planned">Self-service: planned</span>
---
@@ -202,42 +221,56 @@ The consumer selects an environment **by name** in their contract. The platform
The platform is **opinionated, but not painted into a corner.**
- **Substrate-agnostic core.** The contract, the resolved stack, the policy results, the confidence signal, and the evidence stream are all defined *without reference to any specific infrastructure tool.* <span class="badge today">1 adapter: Terraform</span> <span class="badge planned">OpenTofu / Pulumi / K8s</span>
- **Forge-agnostic contract ingestion.** The platform Lambda reads a configurable API base for GitHub or Gitea. <span class="badge today">Available today</span>
- **Portable contracts.** A second forge needs a forge adapter + a workflow translator — **no change to modules, contracts, confidence, or audit**
- **Pattern recognition compounds value over time.** As the platform observes recurring patterns, it can synthesize reusable modules. <span class="badge planned">Future capability</span>
- **Engine-agnostic core.** The contract, the resolved stack, the policy results, the confidence signal, and the evidence stream are all defined *without reference to any specific infrastructure tool.* <span class="badge testing">1 adapter: Terraform</span> <span class="badge planned">OpenTofu / Pulumi / K8s</span>
- **VCS-agnostic contract ingestion.** The platform Lambda reads a configurable API base for GitHub or Gitea. <span class="badge testing">Testing</span>
- **Portable contracts.** A second VCS needs a VCS adapter + a workflow translator — **no change to modules, contracts, confidence, or audit**
- **Pattern recognition compounds value over time.** As the platform observes recurring patterns, it can synthesize reusable modules. <span class="badge planned">Future capability</span> <span class="badge agentic">Agentic</span>
---
<!-- _class: title -->
<!-- _paginate: false -->
# Roadmap: Shipped vs. Planned
# Testing vs. Planned
<style>
section { font-size: 20px; }
section { font-size: 16px; }
td { font-size: 15px; vertical-align: top; }
ul { margin: 0; padding-left: 1.2em; }
li { margin-bottom: 2px; }
</style>
**Available today**
<table style="width: 100%; border: none;">
<tr>
<td style="width: 52%; border: none; padding-right: 12px;">
**Testing** (works internally, not yet released to consumers)
- Contract-driven deploys with a versioned reusable workflow
- Module catalog (primitives + modules) with validated examples
- Zero-trust OIDC + ABAC on GitHub Actions runners
- Security + policy checks before infra creation (Checkov; Wiz + Kyverno ready)
- Confidence signal (6 inputs, per-env thresholds) gating promotion
- Confidence signal (6 inputs, per-env thresholds) gating promotion <span class="badge agentic">Agentic</span>
- Hash-chained, tamper-evident evidence outbox (RPO = 0)
- Encryption by default + per-stack customer-managed keys
- Deletion protection by default + safe decommission with SRE gates
- Uptime monitoring deployed automatically with every stack
- Platform-managed environments + friendly onboarding
- Local reproducibility + forge-agnostic contract ingestion
- Local reproducibility + VCS-agnostic contract ingestion
**Planned (on the roadmap)**
</td>
<td style="width: 48%; border: none; padding-left: 12px;">
**Planned** (on the roadmap)
- Real OIDC federation on all platform runners
- HITL wiring for qa / prod / dr environments
- Full regulatory ledger: S3 Object Lock + JWS signatures + daily checkpoints
- Compliance milestone: GDPR, SOX, SOC2, DORA extension points
- Environment self-service provisioning
- Dynamic module creation from a contract (agentic citizen-developer flow)
- Additional substrate adapters (OpenTofu, Pulumi, Kubernetes CRDs)
- Dynamic module creation from a contract (agentic citizen-developer flow) <span class="badge agentic">Agentic</span>
- Additional engine adapters (OpenTofu, Pulumi, Kubernetes CRDs)
</td>
</tr>
</table>
File diff suppressed because one or more lines are too long
+43 -23
View File
@@ -4,7 +4,7 @@
> **Audience:** Senior Leadership, CTO, Head of Cloud, Head of Infrastructure, Head of DevOps
> **Length:** ~15 minutes · 14 slides
> **Purpose:** Sell the platform's value to tech leadership — zero-trust, security, observability, auditability, and the shift from "operators guess" to "the platform computes safety."
> **Maturity framing:** "Available today" = shipped and verified. "Planned" = on the roadmap, not yet shipped.
> **Maturity framing:** "Testing" = shipped and verified. "Planned" = on the roadmap, not yet shipped.
---
@@ -15,9 +15,11 @@ Software delivery scales with the **coordination surface around it**, not the en
Two frictions slow every team down:
- **Cognitive load** — authoring the infrastructure that runs a service correctly. The long tail of well-meaning services that are difficult to deploy, inconsistent in security and observability posture.
- **Operational work** — moving a merged change from "merged" to "running in production with policy, observability, and security enforced." Manual work that **scales with the system, not with the change.**
- **Operational work**promoting a change from "merged" to "running in production with policy, observability, and security enforced." Manual work that **scales with the system, not with the change.**
- **Red tape** — every deployment requires tickets, approvals, and manual handoffs that scale with the organization, not with the change. A merged change waits in a queue for someone to press a button.
- **Scalability without increasing headcount** — the platform allows delivery throughput to scale without linearly scaling platform engineers. Today, every new team adds load to the same ticket queue.
> **Speaker notes:** Open with the cost of the status quo. Every team that stands up its own pipeline, its own Terraform, its own review checklist is paying a tax that doesn't differentiate the business. The platform absorbs both frictions — that is the value proposition in one sentence.
> **Speaker notes:** Open with the cost of the status quo. Every team that stands up its own pipeline, its own Terraform, its own review checklist is paying a tax that doesn't differentiate the business. The platform absorbs all four frictions — that is the value proposition in one sentence.
---
@@ -35,7 +37,25 @@ What success looks like:
---
## Slide 3 — The Contract-Driven Model
## Slide 3 — What This Platform Is — and Isn't
**What it is:**
- **A sovereign delivery boundary.** The platform governs infrastructure and delivery. It does not penetrate upstream product or software development lifecycles. Integration happens through validated, published contracts.
- **Infrastructure consumed, not maintained.** Compute is abstract, containerized, or serverless. The platform does not manage node, OS, or bare-metal lifecycles. Infrastructure is a utility, not a craft.
**What it isn't:**
- **Not an upstream development platform.** No product backlogs, sprint ceremonies, or IDE workflows.
- **Not a general-purpose AI.** Autonomy is narrow, scoped to delivery and infrastructure reconciliation, bounded by strict policy envelopes.
- **Not a legacy infrastructure bridge.** No VMs, bare metal, or OS lifecycles.
- **Not a permissive delivery highway.** No escape hatches to bypass the confidence framework or human attestation requirements.
> **Speaker notes:** This slide gives leadership the framing they need. The platform is deliberately scoped — it is not trying to be everything. The sovereign boundary means the platform team owns delivery and infrastructure, not the upstream development process. The anti-goals are as important as the goals: they tell leadership what not to expect.
---
## Slide 4 — The Contract-Driven Model
One small YAML file is all a consumer writes. The platform owns everything else.
@@ -86,7 +106,7 @@ Two properties matter to leadership:
Consumer repositories hold **no long-lived cloud credentials.** Ever.
- **Authentication** is **OIDC federation** between the platform runners and the cloud provider. Each job mints a short-lived token; no credential is stored in the consumer repo or in a runner secret. *(Available today on GitHub Actions runners; planned for all platform runners.)*
- **Authentication** is **OIDC federation** between the platform runners and the cloud provider. Each job mints a short-lived token; no credential is stored in the consumer repo or in a runner secret. *(Testing on GitHub Actions runners; planned for all platform runners.)*
- **Authorization** is **attribute-based (ABAC), not role-based.** Two attribute classes scope every action:
- **Repository identity** — the role's trust policy binds to the exact consumer repo + branch that invoked the workflow.
- **Resource-creation attributes** — every resource is tagged with `acdl:owner=<consumer-repo>` and `acdl:contract=<contract-id>`. The session policy grants view/update/delete **only on resources whose tags match the calling repo.**
@@ -136,11 +156,11 @@ Every check produces a record with **severity, rule ID, pass/fail status, and hu
Security defaults that **do not require a team to opt in.**
- **Encryption on every resource** — at-rest encryption is on by default for every primitive (S3, RDS, ECR, ECS, and more). *(Available today.)*
- **Per-stack customer-managed keys (CMKs)** — one key per deployment, 90-day rotation at creation, **no shared keys across stacks.** *(Available today.)*
- **Managed-key fallback with a loud warning** — standalone primitives fall back to cloud-managed keys only when no CMK is provided, and the platform warns explicitly. Silent use of cloud-managed keys is a security gap we refuse to hide. *(Available today.)*
- **Deletion protection on by default** — every resource has `prevent_destroy` on unless a consumer explicitly disables it via a documented feature flag. *(Available today.)*
- **Safe decommission** — a 2-step pipeline (disable protection → zero counts → destroy) with **two SRE human-attestation gates** and a **change-request validated against the platform CMDB** before any destructive action. *(Available today.)* Encryption keys enter a grace window (default 30 days) so encrypted data remains recoverable during decommission.
- **Encryption on every resource** — at-rest encryption is on by default for every primitive (S3, RDS, ECR, ECS, and more). *(Testing.)*
- **Per-stack customer-managed keys (CMKs)** — one key per deployment, 90-day rotation at creation, **no shared keys across stacks.** *(Testing.)*
- **Managed-key fallback with a loud warning** — standalone primitives fall back to cloud-managed keys only when no CMK is provided, and the platform warns explicitly. Silent use of cloud-managed keys is a security gap we refuse to hide. *(Testing.)*
- **Deletion protection on by default** — every resource has `prevent_destroy` on unless a consumer explicitly disables it via a documented feature flag. *(Testing.)*
- **Safe decommission** — a 2-step pipeline (disable protection → zero counts → destroy) with **two SRE human-attestation gates** and a **change-request validated against the platform CMDB** before any destructive action. *(Testing.)* Encryption keys enter a grace window (default 30 days) so encrypted data remains recoverable during decommission.
> **Speaker notes:** The phrase to land is "secure by default, not secure by effort." The decommission flow is the counter-argument to "deletion protection makes cleanup impossible" — it's a deliberate, gated, two-approval path, not a lock with no key.
@@ -150,10 +170,10 @@ Security defaults that **do not require a team to opt in.**
Version control is a **coordination tool, not an evidentiary fortress.** True compliance requires an immutable, externally-stored ledger.
- **Every deployment writes a hash-chained evidence event** — each event links to the previous via a cryptographic hash. Tampering breaks the chain. *(Available today. the DynamoDB outbox.)*
- **Tiered storage design:** cold, tamper-proof source of truth (S3 Object Lock, compliance mode, 7-year retention) + a hot query index for fast lookup. *(Outbox shipped; S3 Object Lock + JWS detached signatures are planned regulatory-ledger build-out.)*
- **Every deployment writes a hash-chained evidence event** — each event links to the previous via a cryptographic hash. Tampering breaks the chain. *(Testing. the DynamoDB outbox.)*
- **Tiered storage design:** cold, tamper-proof source of truth (S3 Object Lock, compliance mode, 7-year retention) + a hot query index for fast lookup. *(Outbox tested; S3 Object Lock + JWS detached signatures are planned regulatory-ledger build-out.)*
- **RPO = 0** — the evidence write is synchronous; a deployment is not acknowledged until the evidence event is durably recorded.
- **Every production change is traceable to a human attestation** — the QA and prod approver identities are the only durable record outside the forge's audit log, stored in the outbox keyed by contract.
- **Every production change is traceable to a human attestation** — the QA and prod approver identities are the only durable record outside the VCS's audit log, stored in the outbox keyed by contract.
> **Speaker notes:** This is the slide for the Head of Infrastructure and anyone who has been through an audit. "The audit trail is a byproduct of deployment, not a project." Note honestly that the full regulatory ledger (S3 Object Lock, JWS signatures, daily checkpoints) is planned; what ships today is the outbox + hash chain that makes every event tamper-evident and queryable.
@@ -176,9 +196,9 @@ Autonomy and accountability are **not in tension** — they are applied at diffe
Monitoring is **a platform default, not a per-team project.**
- **Uptime monitoring deployed automatically with every stack** — a dedicated monitoring instance (Uptime-kuma on ECS Fargate) is provisioned after any module deploy, in a separate state, with a feature flag to disable. *(Available today.)*
- **Uptime monitoring deployed automatically with every stack** — a dedicated monitoring instance (Uptime-kuma on ECS Fargate) is provisioned after any module deploy, in a separate state, with a feature flag to disable. *(Testing.)*
- **Monitored endpoints passed from the deployment's own outputs** — the platform constructs a synthetic monitoring contract from what was just deployed. No manual endpoint registration.
- **Alert channels:** Microsoft Teams webhook, email, SMS, and GitHub issues. *(Available today.)*
- **Alert channels:** Microsoft Teams webhook, email, SMS, and GitHub issues. *(Testing.)*
- **The uptime URL is published to the developer** via a PR comment — they don't hunt for it.
- **Roadmap:** deeper observability bootstrap (dashboards, runbooks, on-call bindings) as first-class contract fields for prod/dr.
@@ -199,7 +219,7 @@ A named environment is a platform-owned bundle of:
The consumer selects an environment **by name** in their contract (`environment: dev`). The platform resolves the name to the underlying account/network/state/role at run time. **The consumer never sees the raw credentials.**
**Friendly onboarding:** the first run detects no environment and emits a guided prompt (not an opaque failure) telling the consumer what the platform will provision and how to request it. *(Available today.)* **Self-service environment provisioning is planned.**
**Friendly onboarding:** the first run detects no environment and emits a guided prompt (not an opaque failure) telling the consumer what the platform will provision and how to request it. *(Testing.)* **Self-service environment provisioning is planned.**
> **Speaker notes:** For the Head of Cloud: this is the governance story. The platform team owns the accounts, the network design, the state hygiene. Consumers can't drift into misconfigured state backends or over-permissioned roles because they never touch them. The onboarding prompt matters — first impressions of a platform are made when it fails for the first time.
@@ -209,18 +229,18 @@ The consumer selects an environment **by name** in their contract (`environment:
The platform is **opinionated, but not painted into a corner.**
- **Substrate-agnostic core.** The contract, the resolved stack, the policy results, the confidence signal, and the evidence stream are all defined *without reference to any specific infrastructure tool.* Today there is one adapter (Terraform). *(OpenTofu, Pulumi, Kubernetes CRDs are future adapters — no architectural change required.)*
- **Forge-agnostic contract ingestion.** The platform Lambda reads a configurable API base for GitHub or Gitea. *(Available today.)*
- **Portable contracts.** The contract schema, the confidence signal, and the audit stream are substrate- and forge-agnostic. A second forge (e.g. GitLab) needs a forge adapter + a workflow-template translator — **no change to the modules, the contract standard, the confidence model, or the audit stream.**
- **Angine-agnostic core.** The contract, the resolved stack, the policy results, the confidence signal, and the evidence stream are all defined *without reference to any specific infrastructure tool.* Today there is one adapter (Terraform). *(OpenTofu, Pulumi, Kubernetes CRDs are future adapters — no architectural change required.)*
- **Forge-agnostic contract ingestion.** The platform Lambda reads a configurable API base for GitHub or Gitea. *(Testing.)*
- **Portable contracts.** The contract schema, the confidence signal, and the audit stream are engine- and VCS-agnostic. A second VCS (e.g. GitLab) needs a VCS adapter + a workflow-template translator — **no change to the modules, the contract standard, the confidence model, or the audit stream.**
- **Pattern recognition compounds value over time.** As the platform observes recurring contract patterns, it can synthesize and offer reusable modules. *(Future capability, not a current commitment — but the design allows it.)*
> **Speaker notes:** This is the "we won't have to rewrite this in two years" slide. The bet is that the substrate (Terraform today) will change, but the contract + confidence + audit model won't. Leadership should hear: the investment is in the abstraction, not the tool.
> **Speaker notes:** This is the "we won't have to rewrite this in two years" slide. The bet is that the engine (Terraform today) will change, but the contract + confidence + audit model won't. Leadership should hear: the investment is in the abstraction, not the tool.
---
## Slide 14 — Roadmap: Honest Shipped vs. Planned
## Slide 14 — Roadmap: Honest Testing vs. Planned
**Available today:**
**Testing:**
- Contract-driven deploys with a versioned reusable workflow.
- Module catalog (primitives + modules) with validated examples.
@@ -243,6 +263,6 @@ The platform is **opinionated, but not painted into a corner.**
- Compliance milestone: per-module extension points for GDPR, SOX, SOC2, DORA.
- Environment self-service (a consumer-facing flow to request and provision a new environment).
- Dynamic module creation from a contract (the agentic "citizen developer" composition mechanism).
- Additional substrate adapters (OpenTofu, Pulumi, Kubernetes CRDs).
- Additional engine adapters (OpenTofu, Pulumi, Kubernetes CRDs).
> **Speaker notes:** Close on honesty. The platform delivers real, verifiable value today — and the roadmap is concrete, not aspirational hand-waving. Invite questions on any "planned" item; each has a defined milestone and a clear reason it isn't shipped yet (usually an upstream dependency, not an engineering gap).
@@ -25,8 +25,9 @@ style: |
display: inline-block; padding: 2px 8px; border-radius: 4px;
font-size: 14px; font-weight: 600;
}
.today { background: #c6f6d5; color: #22543d; }
.testing { background: #DBEAFE; color: #1E3A5F; }
.planned { background: #fef3c7; color: #78350f; }
.agentic { background: #EDE9FE; color: #4C1D95; }
---
<!-- _class: title -->
@@ -50,7 +51,7 @@ The platform serves **two kinds of consumer** through two coordinated interfaces
![w:1000](assets/png/developer-experience-01-two-surfaces.png)
- **Technical developer** — owns app code + a contract + a thin CI definition
- **Citizen developer** — declares intent in plain language; an AI agent produces a contract that passes the **same** safety envelope
- **Citizen developer** — declares intent in plain language; an AI agent produces a contract that passes the **same** safety envelope <span class="badge agentic">Agentic</span>
The platform is **opinionated in what it accepts, regardless of who is declaring.** There is no "citizen developer mode" with weaker checks.
@@ -86,7 +87,7 @@ A non-technical consumer ships a production deployment **by declaring intent**
- Agents are **stateless** — all state lives in the platform; the platform trusts and **always verifies**
- The agent's trace and submission confidence are captured in the contract for review
<span class="badge planned">Skill catalog + real agent runtime: planned</span>
<span class="badge planned">Skill catalog + real agent runtime: planned</span> <span class="badge agentic">Agentic</span>
---
@@ -135,17 +136,17 @@ Consumers `uses:` a **versioned** central workflow. The platform fetches itself
Consumers control **when** they absorb platform improvements.
- **Floating MAJOR + MINOR tags** (e.g. `@v1.6`) — a consumer automatically receives patch updates within the line <span class="badge today">Available today</span>
- **Floating MAJOR + MINOR tags** (e.g. `@v1.6`) — a consumer automatically receives patch updates within the line <span class="badge testing">Testing</span>
- **Semantic versioning with a clear contract:** interface → MAJOR, behavior → MINOR, lifecycle → PATCH
- **A consumer can pin to an exact version** for maximum stability, or float on MAJOR only (`@v1`) to absorb new features on their own cadence
- **Unversioned references (`@main`, bare) are discouraged** — the versioned tag is the only immutability lever
- **Automated release job** computes the next semver on merge to main, creates the tag, and updates the floating tags <span class="badge today">Available today</span>
- **Automated release job** computes the next semver on merge to main, creates the tag, and updates the floating tags <span class="badge testing">Testing</span>
---
# Instant Feedback
Developers see **what the platform is doing**, in real time, in their own run logs. <span class="badge today">Available today</span>
Developers see **what the platform is doing**, in real time, in their own run logs. <span class="badge testing">Testing</span>
- **Streamed output by default** — the infrastructure plan, policy-check results, and each check record (severity, rule ID, pass/fail) flow to stdout
- **PR comments after every successful pipeline stage** — a developer always knows where they stand without refreshing a dashboard
@@ -156,7 +157,7 @@ Developers see **what the platform is doing**, in real time, in their own run lo
# Deploy Outputs That Just Work
After a successful deploy, the developer gets their connection information **without hunting for it** — and without secrets leaking into logs. <span class="badge today">Available today</span>
After a successful deploy, the developer gets their connection information **without hunting for it** — and without secrets leaking into logs. <span class="badge testing">Testing</span>
- **Human-readable connection strings** posted as a structured GitHub PR comment / job summary
- **Runtime-injectable values** written to encrypted Parameter Store (`SecureString`, KMS-encrypted, namespaced `/acdl/{env}/{contractId}/{output_name}`)
@@ -167,7 +168,7 @@ After a successful deploy, the developer gets their connection information **wit
# Friendly Onboarding
First impressions of a platform are made **when it fails for the first time.** The platform fails gracefully. <span class="badge today">Available today</span>
First impressions of a platform are made **when it fails for the first time.** The platform fails gracefully. <span class="badge testing">Testing</span>
When no environment is bound, the platform emits a **user-friendly onboarding prompt** instead of failing opaquely:
@@ -240,13 +241,13 @@ Whichever approach a team picks, the platform applies the same rising bar:
| Environment | What the platform adds |
|---|---|
| dev | Confidence ≥ 0.50, fully autonomous |
| dev | Confidence ≥ 0.50, fully autonomous <span class="badge agentic">Agentic</span> |
| qa | QA human attestation + confidence ≥ 0.75 |
| prod | SRE human attestation + confidence ≥ 0.90 |
| dr | SRE human attestation + confidence ≥ 0.95 + DR drill reference |
- **No staging environment** — the design deliberately removes the "staging is basically prod but not really" anti-pattern
- **Separation of duties is enforced** — the QA approver cannot be the prod approver <span class="badge today">Design shipped</span> <span class="badge planned">Wiring: planned</span>
- **Separation of duties is enforced** — the QA approver cannot be the prod approver <span class="badge testing">Design tested</span> <span class="badge planned">Wiring: planned</span>
- **Timeout discipline** — 1 business day = warn + escalate; 2 business days = auto-freeze + re-submit
The DX win: the contract stays stable across environments. The safety win: the platform raises the threshold and attestation bar automatically based on the job's declared environment.
@@ -255,14 +256,14 @@ The DX win: the contract stays stable across environments. The safety win: the p
# Safe Decommission
Tearing down a stack is **as deliberate as deploying one** — and just as gated. <span class="badge today">Available today</span>
Tearing down a stack is **as deliberate as deploying one** — and just as gated. <span class="badge testing">Testing</span>
```yaml
uses: acdl/.github/workflows/deploy.yml@v1.8
with:
contract: .acdl/contract.yaml
mode: decommission
changeRequestId: "CR-2026-001"
changeRequestId: "CHG0678912"
```
A 2-step pipeline with **two SRE human-attestation gates**:
@@ -278,12 +279,12 @@ The per-stack encryption key enters a **grace window** (default 30 days) so encr
# Self-Service Module Catalog
Developers pick from **pre-built, security-reviewed building blocks** — they don't author infrastructure from scratch. <span class="badge today">Available today</span>
Developers pick from **pre-built, security-reviewed building blocks** — they don't author infrastructure from scratch. <span class="badge testing">Testing</span>
- **Primitives** — single-purpose resources (S3, VPC, ECS, IAM, load balancer, container registry, CloudFront, WAF, RDS), each with documented inputs/outputs, usage, compliance extension points, and versioning
- **Modules** — composed patterns (a static site with CDN + WAF; a microservice with VPC + ECS + load balancer + registry)
- **Validated examples per module**`simple.yaml` + `complex.yaml` + variation files, validated against the contract schema in CI. Examples cannot drift from the schema silently
- **Auto-promotion of patterns** — a thin-composition layer is auto-promoted to the catalog after 3 observed usages <span class="badge planned">Planned</span>
- **Auto-promotion of patterns** — a thin-composition layer is auto-promoted to the catalog after 3 observed usages <span class="badge planned">Planned</span> <span class="badge agentic">Agentic</span>
- **Compliance extension points** — each module lists where GDPR, SOX, SOC2, DORA controls will wire in <span class="badge planned">Planned</span>
---
@@ -302,4 +303,5 @@ section { font-size: 22px; }
- **Auditability as a byproduct, not a project.** Every production change is traceable to a human attestation and a tamper-evident evidence event.
- **Blast radius contained by design.** Zero-trust OIDC + ABAC means a consumer can only touch its own tagged resources.
- **The bottleneck moves off the platform team's ticket queue.** A merged change progresses through lower environments without a platform engineer joining a thread.
- **A path to the citizen developer.** The same safety envelope that serves a senior engineer is the one that will serve a non-technical consumer — expanding who can ship safely without lowering the bar.
- **Infrastructure as a utility, not a craft.** The platform abstracts compute, networking, and state. Teams consume infrastructure, they don't maintain it — and the platform compounds value over time by learning from recurring patterns.
- **A path to the citizen developer.** The same safety envelope that serves a senior engineer is the one that will serve a non-technical consumer — expanding who can ship safely without lowering the bar. <span class="badge agentic">Agentic</span>
File diff suppressed because one or more lines are too long
+14 -13
View File
@@ -4,7 +4,7 @@
> **Audience:** Senior Leadership, CTO, Head of Cloud, Head of Infrastructure, Head of DevOps
> **Length:** ~15 minutes · 13 slides
> **Purpose:** Sell the developer experience and the citizen developer experience to tech leadership — velocity without sacrificing safety, and security/observability/compliance as platform defaults rather than per-team effort.
> **Maturity framing:** "Available today" = shipped and verified. "Planned" = on the roadmap, not yet shipped.
> **Maturity framing:** "Testing" = shipped and verified. "Planned" = on the roadmap, not yet shipped.
---
@@ -145,7 +145,7 @@ Consumers control **when** they absorb platform improvements.
- **Semantic versioning with a clear contract:** interface changes → MAJOR, behavior changes → MINOR, lifecycle fixes → PATCH.
- **A consumer can pin to an exact version** for maximum stability, or float on MAJOR only (`@v1`) to absorb new features on their own cadence.
- **Unversioned references (`@main`, bare) are discouraged** — the versioned tag is the only immutability lever a consumer has.
- **Automated release job** computes the next semver on merge to main, creates the tag, and updates the floating tags. *(Available today.)*
- **Automated release job** computes the next semver on merge to main, creates the tag, and updates the floating tags. *(Testing.)*
> **Speaker notes:** This is the "no surprise upgrades" story. Leadership hears two things: (1) consumers aren't forced to chase the platform, (2) the platform isn't forced to support N forks of every workflow. The versioning discipline is what makes both true.
@@ -155,8 +155,8 @@ Consumers control **when** they absorb platform improvements.
Developers see **what the platform is doing**, in real time, in their own run logs.
- **Streamed output by default** — the infrastructure plan, policy-check results, and each `PolicyCheckResult` record (severity, rule ID, pass/fail) flow to stdout. *(Available today.)*
- **PR comments after every successful pipeline stage** — a developer always knows where they stand without refreshing a dashboard. *(Available today.)*
- **Streamed output by default** — the infrastructure plan, policy-check results, and each `PolicyCheckResult` record (severity, rule ID, pass/fail) flow to stdout. *(Testing.)*
- **PR comments after every successful pipeline stage** — a developer always knows where they stand without refreshing a dashboard. *(Testing.)*
- **Clear, explainable halt reasons** — a policy violation, an insufficient confidence signal, or a missing attestation. **Never an opaque, manual-debugging exercise.**
- **A `--quiet` mode** suppresses streaming for log-only contexts.
@@ -168,10 +168,10 @@ Developers see **what the platform is doing**, in real time, in their own run lo
After a successful deploy, the developer gets their connection information **without hunting for it** — and without secrets leaking into logs.
- **Human-readable connection strings** posted as a structured GitHub PR comment / job summary. *(Available today.)*
- **Runtime-injectable values** written to encrypted Parameter Store (`SecureString`, KMS-encrypted, namespaced `/acdl/{env}/{contractId}/{output_name}`). *(Available today.)*
- **Human-readable connection strings** posted as a structured GitHub PR comment / job summary. *(Testing.)*
- **Runtime-injectable values** written to encrypted Parameter Store (`SecureString`, KMS-encrypted, namespaced `/acdl/{env}/{contractId}/{output_name}`). *(Testing.)*
- **No raw secrets in logs** — the platform enforces this by construction.
- **Errors become GitHub issues, automatically** — a failed deploy reports through the platform Lambda, which opens (or comments on) an issue on the platform repo. The consumer's only grant is the onboarding-granted Lambda-invoke permission — no separate `issues: write` scope on the consumer side. *(Available today.)*
- **Errors become GitHub issues, automatically** — a failed deploy reports through the platform Lambda, which opens (or comments on) an issue on the platform repo. The consumer's only grant is the onboarding-granted Lambda-invoke permission — no separate `issues: write` scope on the consumer side. *(Testing.)*
> **Speaker notes:** The "errors become issues" point is a DX win that also helps the platform team — every consumer failure is a tracked, queryable artifact, not a lost log line. The Head of DevOps should hear: the platform closes the feedback loop, it doesn't just push a green/red status.
@@ -181,7 +181,7 @@ After a successful deploy, the developer gets their connection information **wit
First impressions of a platform are made **when it fails for the first time.** The platform fails gracefully.
- When a consumer pipeline runs for the first time and **no environment is bound**, the platform detects this and emits a **user-friendly onboarding prompt** instead of failing opaquely. *(Available today.)*
- When a consumer pipeline runs for the first time and **no environment is bound**, the platform detects this and emits a **user-friendly onboarding prompt** instead of failing opaquely. *(Testing.)*
- The prompt tells the consumer:
1. That no environment is bound to their repo yet.
2. What the platform will provision on their behalf (account, network, state, role).
@@ -252,7 +252,7 @@ Whichever approach a team picks, the platform applies the same rising bar:
| dr | SRE human attestation + confidence ≥ 0.95 + a disaster-recovery drill reference |
- **No staging environment** — the design deliberately removes the "staging is basically prod but not really" anti-pattern. Dev is the only autonomous environment.
- **Separation of duties is enforced** — the QA approver cannot be the prod approver. *(Design shipped; wiring for qa/prod/dr is planned.)*
- **Separation of duties is enforced** — the QA approver cannot be the prod approver. *(Design tested; wiring for qa/prod/dr is planned.)*
- **Timeout discipline** — 1 business day = warn + escalate; 2 business days = auto-freeze + re-submit.
> **Speaker notes:** Promotion is a workflow choice, not a contract mutation — this matters because it means a promotion can be reviewed as a *diff in the workflow*, not as a rewritten contract. Approach A (one contract, environment passed by the job) keeps the single source of truth; Approach B (environment-specific contracts) lets teams whose inputs genuinely vary keep that variation explicit and reviewable. For leadership: the DX win is that the contract stays stable across environments; the safety win is that the platform raises the threshold and attestation bar automatically based on the target environment the job declares. The consumer can't bypass the gates — they pick *which* environment to target, and the platform applies the right bar.
@@ -269,7 +269,7 @@ uses: acdl/.github/workflows/deploy.yml@v1.8
with:
contract: .acdl/contract.yaml
mode: decommission
changeRequestId: "CR-2026-001"
changeRequestId: "CHG0678912"
```
A 2-step pipeline with **two SRE human-attestation gates** *(available today)*:
@@ -292,9 +292,9 @@ A 2-step pipeline with **two SRE human-attestation gates** *(available today)*:
Developers pick from **pre-built, security-reviewed building blocks** — they don't author infrastructure from scratch.
- **Primitives** — single-purpose resources (S3, VPC, ECS cluster, ECS service, IAM role, load balancer, container registry, CloudFront, WAF, RDS). Each has documented inputs, outputs, usage, compliance extension points, and versioning. *(Available today.)*
- **Modules** — composed patterns (a static site with CDN + WAF; a microservice with VPC + ECS + load balancer + registry). *(Available today.)*
- **Validated examples per module** — every module ships `simple.yaml` + `complex.yaml` + variation files, validated against the contract schema in CI. Examples cannot drift from the schema silently. *(Available today.)*
- **Primitives** — single-purpose resources (S3, VPC, ECS cluster, ECS service, IAM role, load balancer, container registry, CloudFront, WAF, RDS). Each has documented inputs, outputs, usage, compliance extension points, and versioning. *(Testing.)*
- **Modules** — composed patterns (a static site with CDN + WAF; a microservice with VPC + ECS + load balancer + registry). *(Testing.)*
- **Validated examples per module** — every module ships `simple.yaml` + `complex.yaml` + variation files, validated against the contract schema in CI. Examples cannot drift from the schema silently. *(Testing.)*
- **Auto-promotion of patterns** — a thin-composition layer is auto-promoted to the catalog after 3 observed usages. *(Mechanism planned.)*
- **Compliance extension points** — each module lists where GDPR, SOX, SOC2, DORA controls will wire in. *(Compliance milestone is planned.)*
@@ -311,6 +311,7 @@ What this platform delivers to the organization:
- **Auditability as a byproduct, not a project.** Every production change is traceable to a human attestation and a tamper-evident evidence event — captured during the deploy, not reconstructed for the audit.
- **Blast radius contained by design.** Zero-trust OIDC + ABAC means a consumer can only touch its own tagged resources. One consumer can never affect another.
- **The bottleneck moves off the platform team's ticket queue.** A merged change progresses through lower environments without a platform engineer joining a thread. The platform team invests in the platform, not in per-deployment hand-holding.
- **Infrastructure as a utility, not a craft.** The platform abstracts compute, networking, and state. Teams consume infrastructure, they don't maintain it — and the platform compounds value over time by learning from recurring patterns.
- **A path to the citizen developer.** The same safety envelope that serves a senior engineer is the one that will serve a non-technical consumer — expanding who can ship safely without lowering the bar.
> **Speaker notes:** Close on the strategic frame. The platform is not "a CI/CD tool" — it is the organizational lever for shipping safely at the pace the business demands, with the security and audit posture the regulators require. Invite questions; the companion deck ("How the Platform Works") covers the internal mechanics in more depth.
+2 -2
View File
@@ -13,7 +13,7 @@ Consumers declare intent; the platform delivers safe production deployment throu
## 3. Core Tenets
* **Operations are Declared, Not Executed.** Consumers define what they need — workload shape, dependencies, non-functional requirements, policy constraints. The platform handles reconciliation, provisioning, and environment progression. The execution burden moves from the human to the platform.
* **The Delivery Lifecycle is a Sovereign Boundary.** The platform governs the infrastructure and delivery substrate. It does not penetrate upstream product or software development lifecycles. Integration happens exclusively through validated, published contracts.
* **The Delivery Lifecycle is a Sovereign Boundary.** The platform governs the infrastructure and delivery engine. It does not penetrate upstream product or software development lifecycles. Integration happens exclusively through validated, published contracts.
* **Lower Environments are Autonomous; Higher Environments are Attested.** Progression through lower environments proceeds through zero-touch agentic automation. Promotion to higher-stakes environments requires deliberate human attestation — not as a rubber stamp, but as a policy-mandated act of accountability.
* **Safety is Computed, Not Assumed.** Every delivery action produces a measurable, explainable confidence signal aggregating policy conformance, validation evidence, and historical behavior. The signal is the platform's certified answer to "is this safe to proceed?" Reliance on operator instinct or tenure is not a substitute.
* **Infrastructure is Consumed, Not Maintained.** Compute is abstract, containerized, or serverless. The platform does not manage node, OS, or bare-metal lifecycles. Infrastructure is treated as a utility, not a craft.
@@ -50,7 +50,7 @@ This vision is purchased with deliberate sacrifices:
* **Not an upstream development platform.** No management of product backlogs, sprint ceremonies, IDE extensions, or code authorship workflows.
* **Not a general-purpose AI.** The platform is not an open-ended conversational assistant. Autonomy is narrow, scoped to delivery and infrastructure reconciliation, and bounded by strict policy envelopes.
* **Not a legacy infrastructure bridge.** No management of VMs, bare metal, or OS lifecycles. The substrate will not extend to non-cloud-native patterns.
* **Not a legacy infrastructure bridge.** No management of VMs, bare metal, or OS lifecycles. The engine will not extend to non-cloud-native patterns.
* **Not a permissive delivery highway.** No escape hatches to bypass the confidence framework or the human attestation requirements at higher environments. Speed is a byproduct of confidence and policy compliance, not an override.
* **Not a mutable audit log.** Version control history does not satisfy regulatory evidence. Auditability requires an immutable, externally-stored stream.
+1 -1
View File
@@ -16,7 +16,7 @@ There are two kinds of module:
deploy a complete stack (e.g. an ECS Fargate microservice). Each module
has a `composition.json` declaring its children and wires.
The substrate adapter (`adapters/terraform/adapter.py`) compiles a
The engine adapter (`adapters/terraform/adapter.py`) compiles a
module instance to infrastructure. Each module's README documents which
resources it creates.
+6 -6
View File
@@ -4,7 +4,7 @@ Standards for authoring and reviewing ACDL modules. These standards
govern the two module tiers — **L1 primitives** (single cloud resource
or small group of related resources) and **L2 modules** (compositions
that reference L1 primitives to deploy a complete stack) — and the
substrate adapter that compiles them to Terraform. They are written for
engine adapter that compiles them to Terraform. They are written for
**platform engineers** and **AI agents** that author or review new
modules against the existing corpus (12 L1 primitives and 2 L2 modules
shipped in v1.8).
@@ -21,7 +21,7 @@ modules `static-assets` and `microservice`). They exist so that:
- platform engineers can review a new module against a fixed checklist;
- AI agents authoring modules produce code that passes review without
iteration; and
- the substrate adapter (`adapters/terraform/adapter.py`) can compile a
- the engine adapter (`adapters/terraform/adapter.py`) can compile a
module instance with no module-specific code in the adapter beyond the
three tables in §8.
@@ -34,7 +34,7 @@ bump and requires a migration plan.
An L1 primitive is a single cloud resource or a small group of related
resources (e.g. a VPC with subnets and a route table). It is declared by
an `interface.json` and realized by the substrate adapter; it does not
an `interface.json` and realized by the engine adapter; it does not
own Terraform code.
### 2.1 Required files
@@ -43,7 +43,7 @@ Every L1 primitive MUST contain, at minimum:
| File | Purpose |
|------|---------|
| `interface.json` | Substrate-agnostic declaration: inputs, outputs, NFRs, optional multi-resource graph. |
| `interface.json` | Angine-agnostic declaration: inputs, outputs, NFRs, optional multi-resource graph. |
| `instance.json` | A concrete instance used as the adapter regression baseline. |
| `README.md` | Plain-language documentation following `README-TEMPLATE.md` (see §7). |
| `examples/simple.yaml` | A minimal contract that uses the primitive with required inputs only. |
@@ -207,7 +207,7 @@ declares intra-refs from the subnet and route table to the VPC's
- `aws:wafv2:webacl`
- `aws:rds:instance`
- `aws:kms:key`, `aws:kms:alias`
- The substrate adapter's `TYPE_MAP` is the registry of stack types the
- The engine adapter's `TYPE_MAP` is the registry of stack types the
adapter can compile (see §8). A new stack type requires a `TYPE_MAP`
entry before the primitive can be deployed.
@@ -363,7 +363,7 @@ accidental teardown of production infrastructure.
1. Every L1 MUST declare a `deletion_protection` NFR (boolean, default
`true`) in `interface.json`. See §2.5.
2. When `deletion_protection` is `true`, the substrate adapter emits a
2. When `deletion_protection` is `true`, the engine adapter emits a
`lifecycle { prevent_destroy = true }` block on the corresponding
Terraform resource. A `terraform destroy` against a protected
resource fails with an error naming the resource.
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:elbv2:loadbalancer",
"description": "Application Load Balancer primitive (substrate-agnostic stack types aws:elbv2:loadbalancer + aws:elbv2:listener + aws:elbv2:targetgroup; the Terraform adapter translates to aws_lb/aws_lb_listener/aws_lb_target_group).",
"description": "Application Load Balancer primitive (engine-agnostic stack types aws:elbv2:loadbalancer + aws:elbv2:listener + aws:elbv2:targetgroup; the Terraform adapter translates to aws_lb/aws_lb_listener/aws_lb_target_group).",
"inputs": {
"name": {
"type": "string",
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:cloudfront:distribution",
"description": "CloudFront distribution primitive (substrate-agnostic stack types aws:cloudfront:distribution + aws:cloudfront:originaccesscontrol; the Terraform adapter translates to aws_cloudfront_distribution + aws_cloudfront_origin_access_control).",
"description": "CloudFront distribution primitive (engine-agnostic stack types aws:cloudfront:distribution + aws:cloudfront:originaccesscontrol; the Terraform adapter translates to aws_cloudfront_distribution + aws_cloudfront_origin_access_control).",
"inputs": {
"bucket_regional_domain_name": {
"type": "string",
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:ecr:repository",
"description": "ECR repository primitive (substrate-agnostic stack type aws:ecr:repository; the Terraform adapter translates to aws_ecr_repository).",
"description": "ECR repository primitive (engine-agnostic stack type aws:ecr:repository; the Terraform adapter translates to aws_ecr_repository).",
"inputs": {
"name": {
"type": "string",
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:ecs:cluster",
"description": "ECS Fargate cluster primitive (substrate-agnostic stack type aws:ecs:cluster; the Terraform adapter translates to aws_ecs_cluster).",
"description": "ECS Fargate cluster primitive (engine-agnostic stack type aws:ecs:cluster; the Terraform adapter translates to aws_ecs_cluster).",
"inputs": {
"name": {
"type": "string",
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:ecs:task_definition",
"description": "ECS Fargate service primitive (substrate-agnostic stack types aws:ecs:task_definition + aws:ecs:service; the Terraform adapter translates to aws_ecs_task_definition/aws_ecs_service).",
"description": "ECS Fargate service primitive (engine-agnostic stack types aws:ecs:task_definition + aws:ecs:service; the Terraform adapter translates to aws_ecs_task_definition/aws_ecs_service).",
"inputs": {
"image": {
"type": "string",
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:iam:role",
"description": "IAM role primitive (substrate-agnostic stack type aws:iam:role; the Terraform adapter translates to aws_iam_role).",
"description": "IAM role primitive (engine-agnostic stack type aws:iam:role; the Terraform adapter translates to aws_iam_role).",
"inputs": {
"role_name": {
"type": "string",
+1 -1
View File
@@ -4,7 +4,7 @@
An RDS database instance. Supports multiple database engines (postgres,
mysql, mariadb, sqlserver, oracle) via the `engine` input. The adapter
translates the substrate-agnostic `aws:rds:instance` stack type to the
translates the engine-agnostic `aws:rds:instance` stack type to the
Terraform `aws_db_instance` resource.
## Resources
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:rds:instance",
"description": "RDS database instance primitive (substrate-agnostic stack type aws:rds:instance; the Terraform adapter translates to aws_db_instance). Supports multiple engines (postgres, mysql, etc.) via the engine input.",
"description": "RDS database instance primitive (engine-agnostic stack type aws:rds:instance; the Terraform adapter translates to aws_db_instance). Supports multiple engines (postgres, mysql, etc.) via the engine input.",
"inputs": {
"engine": {
"type": "string",
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:s3:bucket",
"description": "S3 bucket primitive (substrate-agnostic stack type aws:s3:bucket; the Terraform adapter translates to aws_s3_bucket).",
"description": "S3 bucket primitive (engine-agnostic stack type aws:s3:bucket; the Terraform adapter translates to aws_s3_bucket).",
"inputs": {
"bucket_name": {
"type": "string",
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:ec2:vpc",
"description": "VPC primitive (substrate-agnostic stack types aws:ec2:vpc + aws:ec2:subnet + aws:ec2:routetable; the Terraform adapter translates to aws_vpc/aws_subnet/aws_route_table).",
"description": "VPC primitive (engine-agnostic stack types aws:ec2:vpc + aws:ec2:subnet + aws:ec2:routetable; the Terraform adapter translates to aws_vpc/aws_subnet/aws_route_table).",
"inputs": {
"cidr": {
"type": "string",
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"kind": "l1",
"type": "aws:wafv2:webacl",
"description": "WAFv2 Web ACL primitive for CloudFront (substrate-agnostic stack type aws:wafv2:webacl; the Terraform adapter translates to aws_wafv2_web_acl). CloudFront-scoped WAF is always in us-east-1.",
"description": "WAFv2 Web ACL primitive for CloudFront (engine-agnostic stack type aws:wafv2:webacl; the Terraform adapter translates to aws_wafv2_web_acl). CloudFront-scoped WAF is always in us-east-1.",
"inputs": {
"name": {
"type": "string",
+4 -4
View File
@@ -2,8 +2,8 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://acdl.cloudinit.dev/schemas/stack.schema.json",
"title": "ACDL Target Stack",
"description": "Substrate-neutral description of a target stack: resources with typed inputs/outputs/NFRs, relationships (single parent per child), composition tree (max depth 5), and policy hooks. The L1 registry, L2 composition tree, contract YML, and PolicyCheckResult schema are all defined against this stack schema. Substrate adapters (the Terraform adapter in v1) are the only substrate-specific code.",
"$comment": "v1 ships one adapter (Terraform). The stack is nearly isomorphic to Terraform in v1 (ARCHITECTURE.md §12.1); the adapter compiles resource.module -> module block, resource.inputs -> variable + arg, resource.outputs -> output, relationship.kind=uses_output -> interpolation, relationship.kind=parent -> composition ordering hint. As more adapters appear (v2+), the stack gains expressiveness; the L1 content + contract YML + composition tree do not change. The schema body is substrate-agnostic: no Terraform block keywords (variable/output/resource as blocks) and no aws_ provider prefixes in the schema keywords; type values are stack types (aws:s3:bucket), not Terraform resource types (aws_s3_bucket).",
"description": "Angine-neutral description of a target stack: resources with typed inputs/outputs/NFRs, relationships (single parent per child), composition tree (max depth 5), and policy hooks. The L1 registry, L2 composition tree, contract YML, and PolicyCheckResult schema are all defined against this stack schema. Angine adapters (the Terraform adapter in v1) are the only engine-specific code.",
"$comment": "v1 ships one adapter (Terraform). The stack is nearly isomorphic to Terraform in v1 (ARCHITECTURE.md §12.1); the adapter compiles resource.module -> module block, resource.inputs -> variable + arg, resource.outputs -> output, relationship.kind=uses_output -> interpolation, relationship.kind=parent -> composition ordering hint. As more adapters appear (v2+), the stack gains expressiveness; the L1 content + contract YML + composition tree do not change. The schema body is engine-agnostic: no Terraform block keywords (variable/output/resource as blocks) and no aws_ provider prefixes in the schema keywords; type values are stack types (aws:s3:bucket), not Terraform resource types (aws_s3_bucket).",
"type": "object",
"required": ["version", "stack", "resources"],
"properties": {
@@ -74,7 +74,7 @@
},
"type": {
"type": "string",
"description": "Stack-typed resource identifier (substrate-agnostic), e.g. 'aws:s3:bucket'. NOT a Terraform resource type ('aws_s3_bucket'); the adapter translates stack type -> substrate type."
"description": "Stack-typed resource identifier (engine-agnostic), e.g. 'aws:s3:bucket'. NOT a Terraform resource type ('aws_s3_bucket'); the adapter translates stack type -> engine type."
},
"module": {
"type": "string",
@@ -92,7 +92,7 @@
},
"outputs": {
"type": "object",
"description": "Typed output contract. The adapter translates this to a substrate output block (e.g. Terraform output).",
"description": "Typed output contract. The adapter translates this to a engine output block (e.g. Terraform output).",
"additionalProperties": {"$ref": "#/$defs/outputSpec"}
},
"nfrs": {
+1 -1
View File
@@ -1,6 +1,6 @@
# ACDL v1.1 Spike — AWS Bootstrap Runbook
Phase 08 bootstraps the AWS substrate for the v1.1 spike. It uses the
Phase 08 bootstraps the AWS engine for the v1.1 spike. It uses the
**root account credential for account 581513795199 exactly once**, then
closes D-034 by having the user manually rotate the root key afterward.
+8 -8
View File
@@ -449,7 +449,7 @@ class TestValidateChangeRequest:
)
# Insert an approved CR
table.put_item(Item={
"changeRequestId": "CR-001",
"changeRequestId": "CHG0678912",
"submittedAt": "2026-07-22T10:00:00Z",
"consumerRepo": "acdl/consumer-a",
"contractId": "contract-001",
@@ -459,7 +459,7 @@ class TestValidateChangeRequest:
})
# Insert a pending CR
table.put_item(Item={
"changeRequestId": "CR-002",
"changeRequestId": "CHG0678913",
"submittedAt": "2026-07-22T11:00:00Z",
"consumerRepo": "acdl/consumer-b",
"contractId": "contract-002",
@@ -471,30 +471,30 @@ class TestValidateChangeRequest:
yield
def test_validates_approved_cr(self, moto_change_requests_table):
payload = {"changeRequestId": "CR-001", "consumerRepo": "acdl/consumer-a"}
payload = {"changeRequestId": "CHG0678912", "consumerRepo": "acdl/consumer-a"}
result = ingestor._validate_change_request(payload)
assert result["status"] == "approved"
assert result["changeRequestId"] == "CR-001"
assert result["changeRequestId"] == "CHG0678912"
def test_rejects_non_approved_cr(self, moto_change_requests_table):
payload = {"changeRequestId": "CR-002", "consumerRepo": "acdl/consumer-b"}
payload = {"changeRequestId": "CHG0678913", "consumerRepo": "acdl/consumer-b"}
with pytest.raises(ValueError, match="status is 'requested'"):
ingestor._validate_change_request(payload)
def test_rejects_nonexistent_cr(self, moto_change_requests_table):
payload = {"changeRequestId": "CR-NONEXIST", "consumerRepo": "acdl/consumer-a"}
payload = {"changeRequestId": "CHG9999999", "consumerRepo": "acdl/consumer-a"}
with pytest.raises(ValueError, match="not found in CMDB"):
ingestor._validate_change_request(payload)
def test_rejects_repo_mismatch(self, moto_change_requests_table):
payload = {"changeRequestId": "CR-001", "consumerRepo": "acdl/wrong-repo"}
payload = {"changeRequestId": "CHG0678912", "consumerRepo": "acdl/wrong-repo"}
with pytest.raises(ValueError, match="consumerRepo mismatch"):
ingestor._validate_change_request(payload)
def test_lambda_handler_routes_validate_change_request(self, moto_change_requests_table):
event = {"body": json.dumps({
"action": "validate_change_request",
"changeRequestId": "CR-001",
"changeRequestId": "CHG0678912",
"consumerRepo": "acdl/consumer-a",
})}
resp = ingestor.lambda_handler(event, None)