Add two leadership-facing presentation decks for senior leadership
(CTO, Head of Cloud, Head of Infrastructure, Head of DevOps):
1. How the Platform Works — 14 slides covering the contract-driven model,
zero-trust, computed safety, policy enforcement, secure-by-default,
immutable audit, HITL, observability, platform-managed environments,
portability, and an honest shipped-vs-planned roadmap.
2. The Developer Experience — 14 slides covering two consumer surfaces,
the 5-line contract, no platform code, versioned releases, instant
feedback, deploy outputs, local reproducibility, friendly onboarding,
safe promotion (one contract + per-env CI jobs), safe decommission,
self-service module catalog, and the leadership outcome.
Each deck has two forms:
- Full markdown (source of truth) with speaker notes + mermaid code blocks
- Marp deck (lean, no speaker notes, embedded PNG diagrams) for presentation
Includes a README documenting the 3-step slide creation process:
(full markdown → Marp synthesis → PPTX export) with conventions, build
commands, and maturity framing rules.
---ci---
phase: 44
milestone: v1.9
status: complete
requirements:
covered: []
partial: []
---/ci---
---ci---
project: acdl
phase: 36
milestone: v1.8
status: execute
---/ci---
- schemas/README.md: how to write schemas, wire into platform, test in
CI, dependencies, existing catalog, adding a new schema.
- pipelines/README.md: how to write pipeline contracts, wire into
workflows, test, dependencies, existing catalog, adding a new pipeline.
- adapters/README.md: how to write adapters (Terraform + policy patterns),
wire into platform, test, dependencies, existing catalog, adding a new
adapter.
- tests/test_docs_coverage.py: 6 tests validating all 3 READMEs exist
with required sections.
Tests: +6 (344 -> 350). All pass.
---ci---
project: acdl
phase: 32
milestone: v1.8
status: execute
---/ci---
- All 11 L1 primitives now have deletion_protection NFR (boolean, default true).
- Adapter emits `lifecycle { prevent_destroy = true }` when NFR is true;
omits it when false. Default is true when NFR is absent.
- L2 composition resolver propagates inputs.deletion_protection to all
children NFRs. When false, all resources get deletion_protection=false.
- Stack schema updated with optional features object (deletion_protection,
uptime_enabled).
- Contract schema description updated to document deletion_protection
and uptime_enabled inputs.
Tests: +5 (307 -> 312). All pass.
---ci---
project: acdl
phase: 31
milestone: v1.8
status: execute
---/ci---
- New kms-key L1 primitive (aws:kms:key) with enable_key_rotation=true
(AWS-managed annual rotation, D-075). Registered in registry.json.
- Adapter TYPE_MAP expanded for aws:kms:key + aws:kms:alias.
- Adapter emits enable_key_rotation from NFR.
- S3 adapter emits server_side_encryption_configuration with KMS when
kms_key_arn provided; managed KMS fallback with stderr warning when not.
- All 10 existing L1 primitives now have encryption_enabled NFR (default true).
- s3, rds, ecr, ecs-service, ecs-cluster have kms_key_arn input.
- Both L2 compositions (static-assets, microservice) now include a kms-key
child + wires connecting kms_key_arn to children.
- L2 stack outputs include kms_key_arn.
Tests: +7 (300 -> 307). All pass. run_platform.sh --check-only green
(static-assets now resolves to 5 resources with the CMK).
---ci---
project: acdl
phase: 30
milestone: v1.8
status: execute
---/ci---
P1-8: run_platform.sh now emits adapter output to $WORK/tf (per-run temp
dir), not the committed terraform/spike/ directory. The committed
terraform/spike/*.tf files are removed — they were scratch artifacts.
Deploy workflow artifact upload path updated to /tmp/acdl_platform_run_v18/tf/.
P1-9: contract_ingestor.py now reads GITHUB_API_BASE env for forge-agnostic
API URLs. _forge_type() detects GitHub vs Gitea. Search URL is branched
(GitHub uses /search/issues, Gitea uses /repos/{owner}/{repo}/issues).
S1: Deploy workflow configure-aws-credentials step restructured as a single
conditional step. OIDC when no static key (role-to-assume), static-key
when ACDL_AWS_ACCESS_KEY_ID present (access-key-id/secret-access-key inputs).
Both deploy workflows remain byte-identical.
Tests: +8 (292 -> 300). All pass. run_platform.sh --check-only green.
---ci---
project: acdl
phase: 29
milestone: v1.8
status: execute
---/ci---
P1-3: SSM publisher now raises RuntimeError when ACDL_KMS_KEY_ID is
unset. ACDL_ALLOW_DEFAULT_KMS=1 escape hatch for local testing.
P1-6: consumer_invoke_policy.json now uses ${account_id} and ${region}
placeholders. Terraform renders them via data.aws_caller_identity +
data.aws_region + replace() at apply time. No more hardcoded 000000000000.
Tests: +7 (285 -> 292). All pass.
---ci---
project: acdl
phase: 0
milestone: v1.7
status: audit
---/ci---
v1.7 audit: all checks pass.
Reconstruction: PASS — 122 ---ci--- blocks parsed; v1.7 state
(specify → clarify D-048..D-059 → research → execute P22-27 → complete
REQ-62..75 → verify) matches .ciagent/ files exactly.
.ciagent/ File Discipline: PASS — config.json valid, PROJECT.md has
all required sections + D-048..D-060, ROADMAP.md has 6 phases marked
complete, REQUIREMENTS.md traceability complete (14/14 v1.7 reqs),
ARCHITECTURE.md components match code, PERSONAS.md has lambda-engineer.
Branch Hygiene: 2 stale branches (phase/21-docs-restructure from v1.6,
milestone/v1.0-initial from v1.0) — non-blocking prior-milestone
artifacts. All v1.7 work committed directly to main (v1.1-v1.6 precedent).
Commit Discipline: PASS — 18/18 v1.7 commits have ---ci--- blocks.
0 unresolved escalations (2 prior audit commits have 'escalation' in
subject but are resolved audit actions).
Stale References: 0 stale references outside .ciagent/ (historical
narrative in .ciagent/ records pre-v1.6 dir structure acdl_platform/
modules-ir/ — these are verbatim historical records, not stale in v1.7
scope). Fixed 1 cosmetic temp dir name (acdl_platform_run →
acdl_platform_run_v17 in run_platform.sh).
Tests: 275 passed. CI pipeline green.
The --check-only mode hardcoded static-assets-specific assertions
(stack name == 'static-assets', 'aws_s3_bucket' in main.tf, 'acdl-spike-bucket'
in main.tf). The platform-test.yml integration-test stage runs check-only for
every contracts/*.yaml, so contracts/microservice.yaml would fail the
AssertionError. Replace with generic structural checks valid for any contract.
verify(P0): code review — correctness
---ci---
phase: 26
milestone: v1.7
status: verify
lessons:
- P0 fix applied: run_platform.sh check-only hardcoded static-assets assertions broke for non-static-assets contracts (microservice); generalized to structural checks
---/ci---
Each module README (10 primitives + 2 patterns) now has a ## Examples
section before ## Versioning, referencing and excerpting the validated
simple.yaml + complex.yaml (+ mysql.yaml for RDS) example contracts. The
RDS README includes a Multi-engine variation subsection (D-059).
---ci---
project: acdl
phase: 27
milestone: v1.7
status: execute
---/ci---
Add modules/<name>/examples/ directories with simple.yaml + complex.yaml
(+ mysql.yaml for RDS) for every primitive and module pattern. All 25
example contracts validate against schemas/contract.schema.json. Update
the contract schema to allow object/array input values (for env vars).
Fix the platform-test schema-validation glob to modules/*/*/examples/*.yaml
to match the nested l1/l2 path structure. Update the microservice sample
contract note (env objects now permitted by the schema).
---ci---
project: acdl
phase: 27
milestone: v1.7
status: execute
---/ci---
Delete the consumer-repos/ directory (v1.2 artifact removed in v1.7).
Rewrite all .ciagent/ historical narrative references per D-048 to
describe the removal rather than referencing the directory as existing.
---ci---
project: acdl
phase: 27
milestone: v1.7
status: execute
---/ci---
---ci---
project: acdl
phase: 26
milestone: v1.7
status: execute
---/ci---
The microservice pattern (and any L2 referencing multi-resource L1s like
vpc) failed at the adapter stage because the resolver emitted refs using
the child id (e.g. 'vpc') instead of the expanded sub-resource id (e.g.
'vpc-subnet'). The adapter's type_by_id table only knows the sub-resource
ids, so ref:vpc.subnet_ids was an unknown resource id.
Fix:
- contract_resolver.py: child_outputs now maps {outputName -> resourceId}
instead of just the interface outputs dict. For multi-resource L1s, the
ref uses the sub-resource id that produces the output. For single-resource
L1s, the resourceId == childId (unchanged behavior).
- vpc interface.json: the subnet sub-resource output is 'subnet_ids'
(matching the interface-level output name) instead of 'subnet_id'.
- adapter.py OUTPUT_MAP: aws:ec2:subnet now maps both 'subnet_ids' and
'subnet_id' to 'id'.
Verification:
- microservice pattern check-only: PASS (11 resources)
- static-assets pattern check-only: PASS (4 resources)
- platform check-only: PASS
- full test suite: 266 passed
Phase 26 — platform-pipelines-and-release-automation:
- platform-test.yml: PR pipeline (lint + unit-test + integration-test +
schema-validation) replacing ci.yml for PRs; integration-test runs
run_platform.sh --check-only for every contracts/*.yaml
- primitives-plan.yml: PR pipeline with matrix over all 9 L1 primitives
(s3, vpc, ecs-cluster, ecs-service, iam-role, alb, ecr, cloudfront, waf)
- patterns-plan.yml: PR pipeline with matrix over all 2 L2 modules
(static-assets, microservice)
- release.yml: push-to-main pipeline computing next semver tag (PATCH for
regular phases, MINOR for milestone completions), updating floating
MAJOR.MINOR + MAJOR tags, and creating GitHub releases
- run_primitive_plan.sh: plan-only/check-only runner for a single L1
primitive (adapter compile + structure validation offline)
- run_pattern_plan.sh: plan-only/check-only runner for a single L2 pattern
(environment check + contract validate + resolve + adapter + structure
validation offline)
- contracts/microservice.yaml: sample consumer contract for the
microservice L2 module (schema-compliant scalar inputs)
- instance.json for 8 L1 primitives (vpc, ecs-cluster, ecs-service,
iam-role, alb, ecr, cloudfront, waf) so the primitives-plan matrix can
run the adapter offline; s3 already had one
- tests/test_release_logic.py: unit test for semver computation
(PATCH bump, MINOR bump on milestone, floating tag format)
- tests/test_pipeline_contract.py: 19 new tests validating the 4 platform
workflows exist and conform (stages, matrices, triggers, permissions)
DEVIATION: The microservice pattern (run_pattern_plan.sh --check-only
microservice + run_platform.sh --check-only contracts/microservice.yaml)
fails at the adapter stage due to a pre-existing resolver ref-id mismatch
for multi-resource L1s (resolver emits ref:vpc.subnet_ids but the expanded
resource id is vpc-subnet). This predates Phase 26 and is out of scope for
pipeline automation; the static-assets pattern passes end-to-end. The
microservice contract is schema-valid and resolves correctly (11
resources); only the adapter compilation of multi-resource L1 refs fails.
VERIFICATION:
- bash scripts/run_ci.sh: PASS (lint + test + check-only)
- python3 -m pytest tests/ -v: 266 passed
- bash scripts/run_primitive_plan.sh --check-only s3: PASS
- bash scripts/run_pattern_plan.sh --check-only static-assets: PASS
- All 9 primitives pass run_primitive_plan.sh --check-only
- All instance.json validate against stack.schema.json
---ci---
project: acdl
phase: 26
milestone: v1.7
status: execute
---/ci---
Phase 24 — platform-lambda-and-contract-ingestion.
- core/lambda/contract_ingestor.py: AWS Lambda handler invoked via Function
URL (IAM auth). Parses JSON body, validates required fields, writes the
contract to DynamoDB table acdl-contracts (PK consumerRepo, SK
contractId#submittedAt, status submitted, ISO-8601 submittedAt). report_error
action is a stub returning "error_report_prepared"; GitHub issue creation is
wired in Phase 25. Returns 400 on missing fields / unknown action, 500 on
error. Table name + GitHub-token secret ID come from env (set by Terraform).
- core/lambda/__init__.py: empty package marker.
- terraform/platform/main.tf: DynamoDB acdl-contracts (PITR, SSE via CMK),
KMS customer-managed key with alias/acdl-platform, Secrets Manager secret
acdl/github-token, IAM execution role (DynamoDB write + Secrets Manager read +
KMS decrypt + CloudWatch logs), Lambda acdl-contract-ingestor (Python 3.12,
handler contract_ingestor.lambda_handler), Function URL with AWS_IAM auth.
State key platform/terraform.tfstate (distinct from spike/microservice).
- terraform/platform/README.md: documents what it deploys, the state key, how
to apply, and the cross-account invocation model.
- terraform/platform/consumer_invoke_policy.json: ABAC-scoped policy template
applied to consumer deploy roles during onboarding; grants
lambda:InvokeFunctionUrl conditioned on aws:PrincipalTag/acdl:owner ==
consumerRepo.
- tests/test_contract_ingestor.py: 11 tests (moto-backed DynamoDB mock) covering
submit_contract put_item shape, report_error stub, missing-field 400, unknown
action 400, the lambda_handler wrapper with a Function-URL-style event, dict
body, default action, and internal-error 500.
- docs/environments/index.md: new section documenting the cross-account
contract-ingestion grant (one-way consumer→platform, D-051) and that
onboarding now also grants the consumer deploy role InvokeFunctionUrl.
- scripts/run_ci.sh, pipelines/ci.yaml, .gitea/workflows/ci.yml,
.github/workflows/ci.yml: add core/lambda/contract_ingestor.py to the lint
py_compile list. The two workflow YAMLs remain byte-identical.
Verification: scripts/run_ci.sh passes all 3 stages (lint/test/check-only);
python3 -m pytest tests/ -v passes all 213 tests (11 new + 202 existing).
---ci---
project: acdl
phase: 24
milestone: v1.7
status: execute
---/ci---