---ci---
project: acdl
phase: 9
milestone: v1.1
status: verify
verdict: VERIFIED
---/ci---
Four-layer verification of Phase 09 (v1-spike-ir-and-l1-and-adapter):
- Layer 1 Structural: PASS (9/9 deliverables; interface/instance/registry/adapter/TF/gitignore/tags/history all correct)
- Layer 2 Behavioral: PASS (verify_phase09.sh exit 0; typecheck; adapter reproducible; IR schema validates; unsupported IR type -> ValueError; terraform validate)
- Layer 3 Security: PASS (no secret pairs leaked; spike key gitignored + holds spike user key not root; no creds in TF/adapter; plan-only no apply)
- Layer 4 Quality: PASS (README layout accurate; all P09 commits carry ---ci--- blocks; ROADMAP/REQUIREMENTS traceability updated; D-P09-1..4 respected; versioning warning non-blocking)
P0: none. P1: (P1-1) two AWS access key IDs (public identifiers, not secret pairs) appear in the Phase 08 verify narrative at .ciagent/VERIFY.md commit 6d27dad which falls in the v1.1.3..v1.1.4 range — recommend redacting to placeholders in a future hygiene pass (the Phase 09 gate's AKIA scan correctly excludes .ciagent/). P1-2: terraform/spike/.terraform.lock.hcl is untracked and NOT covered by .gitignore (the PLAN's gitignore list missed it) — recommend adding it to .gitignore in a future hygiene pass.
Real terraform plan against AWS succeeded (rotated spike key, plan-only, -lock=false per D-P09-1).
---ci---
project: acdl
phase: 9
milestone: v1.1
status: plan-as-execute
persona: platform-engineer
task: [T-9.5, T-9.6, T-9.7, T-9.9]
requirements.covered: [REQ-26]
---/ci---
Waves 2+3: Terraform adapter + generated spike TF + run script.
- T-9.5: adapters/terraform/adapter.py - compiles an IR instance to a
Terraform root module. TYPE_MAP {aws:s3:bucket -> aws_s3_bucket}. Thin
layer; does not own L1 content. Emits main.tf (resource + outputs) +
terraform.tf (required_version/providers + S3 backend, NO
dynamodb_table per D-P09-1) + providers.tf (aws provider region from
the IR). CLI: adapter.py <ir_instance.json> <out_dir>.
- T-9.6: terraform/spike/{main.tf,terraform.tf,providers.tf} - generated
by running the adapter against modules-ir/l1/l1-s3/spike_instance.json.
Committed so verify_phase09.sh can validate/plan without regenerating
(D-P09-4); the verify script will regenerate + diff to prove
reproducibility.
- T-9.7: scripts/run_spike_plan.sh - loads rotated spike key from
gitignored .env.secrets, exports AWS env vars, cd terraform/spike,
terraform init -lock=false, terraform validate, terraform plan
-lock=false -out=tfplan. Plan-only; no apply.
- T-9.9: .gitignore - add terraform/spike/.terraform/ + tfplan +
*.tfstate*.
EXECUTE: ran scripts/run_spike_plan.sh against real AWS via the rotated
spike key (D-039). terraform plan succeeded: 1 to add (the S3 bucket),
outputs computed. One non-blocking deprecation warning (aws_s3_bucket
versioning block -> use aws_s3_bucket_versioning in v1.2). No long-lived
credential in the workflow (key loaded from .env.secrets at runtime).
---ci---
project: acdl
phase: 8
milestone: v1.1
status: plan-as-execute
persona: lead-developer
task: T-8.8
requirements.covered: [REQ-23]
---/ci---
Wave 5: execute the bootstrap against real AWS + fix verify script.
- Created S3 bucket acdl-tfstate-581513795199-us-east-1 (versioning
enabled) + DynamoDB table acdl-outbox (PAY_PER_REQUEST, PK contractId,
SK eventType#eventTs) via create_state_backend.py.
- Created IAM user acdl-spike-runner + scoped inline policy
(DenyEverythingElse) + initial key via create_iam_user.py.
- Rotated the spike key via rotate_spike_key.sh: old key deleted, new
key in gitignored .env.secrets (chmod 600).
- verify_phase08.sh fixes: (a) heredoc python instead of -c to avoid
bash quoting issues; (b) Check 4 uses the bootstrap root key to
inspect IAM (the spike key is least-privilege and cannot iam:GetUser
- that itself confirms the policy denies non-granted actions); (c)
get_user_policy returns PolicyDocument as a dict, not a URL-encoded
string in this boto3 version - handle both.
- VERIFIED: caller identity is acdl-spike-runner (not root), S3 + DDB +
IAM user + Deny-everything-else policy all present, .env.secrets +
.bootstrap_state.json gitignored.
D-034 closure: user must manually rotate the root key in the AWS IAM
console now (the bootstrap root key has served its one-shot purpose).
---ci---
project: acdl
phase: 8
milestone: v1.1
status: plan-as-execute
persona: security-engineer+platform-engineer
task: [T-8.1, T-8.2, T-8.3, T-8.4]
requirements.covered: [REQ-23]
---/ci---
Waves 1+2: IAM policy + state backend + IAM user creation scripts.
- T-8.1 (security): terraform/bootstrap/spike_runner_policy.json —
least-privilege IAM policy: Allow S3 r/w on the state bucket, DynamoDB
r/w on the outbox table, sts:GetCallerIdentity; final Deny statement
(Action *, NotResource = the above ARNs) enforcing least privilege. No
terraform apply permission (plan-only spike).
- T-8.2/T-8.3 (platform): terraform/bootstrap/create_state_backend.py —
boto3, idempotent: creates S3 bucket acdl-tfstate-581513795199-us-east-1
(versioning enabled) + DynamoDB table acdl-outbox (PAY_PER_REQUEST, PK
contractId, SK eventType#eventTs per D-P08-1 one table for both lock
+ outbox). Writes .bootstrap_state.json marker.
- T-8.4 (platform + security review): terraform/bootstrap/create_iam_user.py
— boto3, idempotent: creates IAM user acdl-spike-runner, attaches the
inline policy from spike_runner_policy.json, creates an initial access
key if none active exists (prints to stdout for the orchestrator to
capture; NEVER committed).
py_compile + policy JSON valid.
---ci---
project: acdl
phase: 6
milestone: v1.1
status: verify
verdict: VERIFIED
---ci---
All four verification layers pass for Phase 06 (v1.1.1):
- Structural: demo/ contains the full v1.0 demo (history preserved via
git mv); new v1.1 top-level dirs scaffolded with .gitkeep; no stray
v1.0 dirs at root; v1.0.1..v1.0.5 + v1.1.0 + v1.1.1 tags present.
- Behavioral: typecheck gate green; scripts/verify_phase06.sh exits 0
with "Phase 06: ALL CHECKS PASS"; demo/scripts/run_demo.sh --no-upload
produces a non-empty, hash-chained audit.json in /tmp/acdl_demo_run/.
- Security: no .env/tfstate/_key/secret files in v1.1.0..v1.1.1 diff;
the only content authored in the phase was the move commit, README,
.gitignore, and the verify script. LSP error on
demo/scripts/finalize_evidence.py:46 is pre-existing v1.0 demo code
(authored at v1.0.4, Phase 06 only git-mv'd it) — not a regression.
- Quality: all README link targets exist (docs/vision.md,
docs/architecture.md, .ciagent/{PROJECT,ARCHITECTURE,ROADMAP}.md,
demo/ACDL_DEMO.md); every phase commit carries a ---ci--- block with
the required fields; ROADMAP §Phase 06 status = complete (v1.1.1).
P1 (post-hoc, non-blocking): scripts/verify_phase06.sh does not
programmatically assert runner-data/ is in .gitignore. The must-have
is satisfied structurally (file content verified); only the assertion
is missing. Recommend adding `grep -q '^runner-data/$' .gitignore` in
a future touch-up.
No P0 issues. Phase 06 has no new REQ (repo hygiene).
---ci---
project: acdl
phase: 6
milestone: v1.1
status: plan-as-execute
persona: lead-developer
tasks: [T-6.1, T-6.2, T-6.3, T-6.4]
---/ci---
Archive the v1.0 demo under demo/ (D-037) and reorient the repo to the
real platform. Wave 1 of the Phase 06 plan.
- T-6.1: git mv modules/, scripts/, evidence-ui/, contracts/,
contracts-repo/, .gitea/ -> demo/; mv ACDL_DEMO.md + runner-data/ -> demo/
- T-6.2: scaffold new v1.1 top-level dirs (platform/, schemas/, adapters/,
terraform/, modules-ir/) with .gitkeep
- T-6.3: create top-level scripts/verify_phase06.sh (v1.1 verify scripts
live at top-level, NOT demo/scripts/ which holds the v1.0 demo verify
scripts)
- T-6.4: rewrite README.md to reflect the real platform (vision +
architecture links, new layout, status v1.1 active); add runner-data/
to .gitignore
All moves via git mv (history preserved). Repo root now contains only
README.md, demo/, docs/, .ciagent/, and the new empty v1.1 dirs.
---ci---
project: acdl
phase: 0
milestone: v1.1
status: research
research_targets: 10
top_finding:
- TARGET 1 (conf 0.95): Gitea Actions does NOT support id-token: write / OIDC.
Real OIDC deferred to v1.2 (blocked on go-gitea/gitea#36988).
Spike adopts D-039: per-run-rotated long-lived key waiver.
decisions_adopted: [D-039, D-040, D-041, D-042, D-043, D-044, D-045, D-046]
risks:
- R-1 (highest): OIDC gap -> key-rotation waiver (mitigated by D-039)
- R-2: Checkov terraform_plan edge cases (mitigated by ACDL_TAG_NAMING skipped record)
- R-3: 6 confidence inputs are a recommendation (D-040 adopted in PROJECT.md)
---/ci---
RESEARCH.md (1330 lines) authored by ci-researcher. Key findings:
- TARGET 1: Gitea Actions does NOT support emitting an OIDC id-token
(Gitea docs list id-token as unsupported; go-gitea/gitea#33681 open;
draft PR #36988 unmerged; Gitea's own CI still uses long-lived keys
per #37980). Real-AWS OIDC is unachievable in this environment for v1.1.
- TARGETS 2-10: Terraform/Checkov install steps, IR prior art, Checkov
adapter, DynamoDB outbox, 6-input confidence signal, tiered ledger
(Object Lock deferred), HITL/SoD, contract schema, archive strategy
— all resolved with concrete sketches in RESEARCH.md.
Adopted D-039..D-046 in PROJECT.md. Re-scoped Phase 08 (ROADMAP) and
REQ-23 (REQUIREMENTS) to reflect the OIDC blocker: the spike uses a
per-run-rotated long-lived key (D-039) instead of OIDC; real OIDC is a
v1.2 deliverable. ARCHITECTURE.md Gitea API surface table updated with
the OIDC verdict.
---ci---
project: acdl
phase: 0
milestone: v1.1
status: clarify
clarifications:
resolved: 12 operational parameters (AWS region, state bucket/lock names, OIDC role + trust subject, spike L1/L2/contract inputs, terraform command scope, Checkov ruleset, tag preservation, next ship tag)
mode: accept-recommendations + decide-rest (D-038)
deferred_to_research: [gitea/act_runner OIDC support, terraform/checkov runner availability, configure-aws-credentials action availability]
user_blocking_questions: 0
---/ci---
At full autonomy, the 11 architecture open decisions were already
recorded in PROJECT.md during SPECIFY (D-038). CLARIFY resolves the 12
operational parameters needed to unblock planning (AWS region, state
backend names, OIDC role, spike L1/L2/contract inputs, terraform command
scope, Checkov ruleset). The one genuinely unknown item — Gitea/act_runner
OIDC support — is not a clarification (no user preference can resolve it);
it is the highest-priority RESEARCH target.
---ci---
phase: 0
milestone: v1.0
status: complete
audit:
reconstruction: PASS (git-log phase statuses match ROADMAP.md; all 5 phases complete; 33 decisions in PROJECT.md; SEC-001 mitigated)
branch_hygiene: PASS (all 5 phase branches merged + deleted; main + milestone/v1.0-initial only; tags v1.0.1..v1.0.5 + v1.1.0 monotonic; all 5 PRs merged)
commit_discipline: PASS-WITH-CAVEAT (all per-task commits had ---ci--- blocks on phase branches; the 5 squash-merge commits on main lack ---ci--- blocks because Gitea's squash-merge API compresses the phase branch into a single summary commit — the per-task blocks were on the deleted phase branches)
security_findings:
- SEC-001 (Phase 01): mitigated (token rotated to env var)
- P0-001 (Phase 04): fixed inline (URLError catch in finalize_evidence.py)
- P0-002 (Phase 04): fixed inline (shell injection in issue body -> env var)
- P1-001 (this audit): fixed (remote URL in .git/config stripped of token; future pushes use 'git -c http.https://<host>/.extraHeader=Authorization: token <token>' or a credential helper)
escalation_count: 0
lessons_count: 13 (across 5 verify_phaseNN.sh commits)
---/ci---
Audit PASS. Reconstruction test confirms git-log state matches .ciagent/
files. Branch hygiene clean (no orphan phase branches; tags monotonic;
PRs merged). Commit discipline passes with the documented caveat that
Gitea's squash-merge API strips per-task ---ci--- blocks from the
squashed commit body (the per-task blocks existed on the now-deleted
phase branches and are recoverable via git reflog if needed).
P1-001 (token in .git/config remote URL — deferred from Phase 01 verify)
is now FIXED: the remote URL is tokenless; future pushes use a one-shot
'git -c http.<host>/.extraHeader=Authorization: token <token>' or a
credential helper. This was the last open finding from the milestone.
The ACDL milestone v1.0 is complete and audited. Tag v1.1.0 is the
feature-milestone release (next minor per ship.md). The demo is live at
https://git.cloudinit.dev/continuous-intelligence/acdl-evidence/raw/branch/main/index.html
Squash merge of phase/05-evidence-ui-and-demo-dry-run; evidence-ui/index.html + run_demo.sh 4-act simulation + verify_phase05.sh; demo live at acdl-evidence raw URL.