Populates the PDLC Phase 0 intake format with the absolute ground truth of the system after v1.28 ship (CLI Canonicalization + Identity Layer). Header bumped to v1.28 last-ship. 7 sections: header, architecture state, technical stack, active constraints (D-001..D-231, INV-1..17, CAP-001..038), recent history + quality gates (coverage 73.8% YELLOW — below 80% floor), agent context + assumptions, canonical state references. Unknowns explicit (no new initiative; CodeArtifact/KMS/kj-in-Lambda unverified in-account). ---ci--- project: acdl phase: 0 milestone: v1.28 status: pdlc-intake ---/ci---
44 KiB
Nova — System State (what exists today)
PO-owned catalog of shipped capabilities. Updated at every milestone ship (P final). Additive only — entries are appended, never rewritten, unless a capability is explicitly deprecated (then marked, not deleted). Read by the PO upstream of the PDLC before authoring new REQ-NNN specs, and by CIAgent at SPECIFY for capability awareness.
Authority: this file is descriptive of shipped state, not authoritative for live phase/ship state — that's
CHECKPOINT.json. For why, readNORTH_STAR.md. For how, readARCHITECTURE.md. For what was decided, readPROJECT.mdload-bearing decisions.Last milestone ship: v1.28 (
v1.27.6, 2026-08-19) — CLI Canonicalization + Identity Layer. Feature milestone: Nova CLI installable from CodeArtifact; 15nova <subcommand>subcommands;nova initscaffolding;nova cli-actioncomposite action;core/mode_resolver.py(D-226); Nova-idp identity layer (nova-idp-auth+nova-idp-token-vend+nova-idp-jwksLambdas; Argon2id; KMS-signed OIDC ES256; kyverno-json ABAC fail-closed; PAT lifecycle;nova idp setup;nova auth login/revoke/status). No AWS-managed identity (INV-15). 6 new capabilities (CAP-033..038), 6 new invariants (INV-12..17), 6 decisions (D-226..231). Next update: at v1.29 ship.
How to use this file (PO)
- Before writing a new REQ: search this file for the capability you intend to spec. If it exists, extend it; do not re-spec it under a new REQ-NNN.
- Respect the Invariants below — they are load-bearing and
cross-cutting. A new REQ that violates an invariant requires a
CLARIFYdecision recorded in PROJECT.md. - Anchor each new REQ to a Domain; new domains require a PO decision recorded in CLARIFY.
- When a capability is deprecated (replaced, removed, or
re-architecture), append a
Deprecatedrow marking the milestone + replacement; do not delete the original entry.
Invariants (PO-owned — do not violate in new REQs)
Distilled from
PROJECT.mdload-bearing decisions D-034..D-072 + W1..BA + Q1.3. Cite the decision ID when an REQ touches one.
- INV-1 (Contract surface): The only PDLC→Nova boundary is
schemas/contract.schema.json+schemas/submission-readiness.schema.json(D-133). All consumer intent enters through one of these. Nova never reaches into upstream PDLC. - INV-2 (Confidence inputs): Six canonical inputs — policy (0.30),
validation (0.25), freshness (0.10), source (0.15), history (0.10),
nfrs (0.10). Weights frozen for v1 (D-040).
criticalseverity = hard-block viaPENALTY["critical"]: None(defense-in-depth behind the declarativeblock-on-any-criticalmeta-policy). - INV-3 (HITL gates): dev = autonomous (≥0.50); qa = HITL (≥0.75);
prod = HITL (≥0.90); dr = HITL (≥0.95). Approver identity = Gitea
gitea.actorof theworkflow_dispatch(D-042). Separation-of-duties on prod readsapprover_qafrom the DynamoDB outbox. - INV-4 (Engine is swappable): The policy engine is behind the
PolicyEngineprotocol (core/policy_engine.py, v1.25). Confidence signal + pipeline import only the protocol, never a concrete engine.kyverno-jsonis the v1.25 default;OPA(or other) implements the same 3-method protocol to replace it. - INV-5 (Adapter is stateless):
adapters/terraform/adapter.pyowns no module content — noTYPE_MAP/INPUT_MAP/OUTPUT_MAP(v1.11 rewrite). A new stack type requires a new L1 module (modules/l1/<name>/) +registry.jsonentry, not an adapter change. - INV-6 (Audit stream is immutable): Outbox writes via SQLite hash-chain today (D-083 deferred). S3 Object Lock / JWS tamper- resistant ledger is a future milestone. Current stream is tamper- evident (any tampering breaks the chain).
- INV-7 (PCR schema is the moat):
schemas/policy_check_result.schema.jsonshape is frozen across adapter swaps (v1.25 hard constraint). Theengineenum already includes"kyverno"+"opa"; new engines add no enum value. - INV-8 (Long-lived creds forbidden): §12.5. The D-039/D-047 per-run-
rotated-key waiver satisfies the intent (no persistently long-lived
key). Real OIDC federation is blocked on
go-gitea/gitea#36988. - INV-9 (Two consumer surfaces, one platform): L3A (developer) + L3B (citizen dev) converge on the same contract schema, the same policy envelope, and the same evidence stream.
- INV-10 (Nova is downstream of PDLC): Nova governs infra + delivery only. Product backlog, code authorship, IDE workflows, application business logic are upstream. Integration only via the validated contract boundary (INV-1).
- INV-11 (Pilot scope, v1.26): Equities only (D-200). Single-
validator PoA (D-201). D-083 (Object Lock/JWS) stays deferred. Hot
path deferred (D-126). Multi-cloud deferred. Multi-validator BFT
deferred. The pilot runs
mode: fullfordevonly (D-209); qa/prod/dr stay placeholder (D-208, blocked by the pilot-readiness policy). - INV-12 (Mode observability, v1.28): Every CLI invocation emits a
cli.invocationaudit event containingmode,selection_reason,credential_type,command, andargs. Operators can debug mode selection without reproducing. - INV-13 (Mode resolution determinism, v1.28): Resolution priority
is flag → env (
NOVA_CLIENT_MODE) → credential type →sys.stdin.isatty(). No silent fallbacks. Invalid env values are ignored + warned. Deviations rejected at PR time. - INV-14 (Credential type encodes role, v1.28):
developer_pat/nova_oidc_token+ TTY present →interactive; TTY absent →agent. - INV-15 (No AWS-managed identity in path, v1.28): Nova-idp MUST NOT depend on Cognito, IAM Identity Center, or any AWS-managed identity service. Greenfield constraint (no Cognito existed to "drop").
- INV-16 (Password storage, v1.28): Passwords hashed with Argon2id
(t=3, m=65536 KiB, p=1). Fail-closed on
ImportError(D-228 amended — no pure-Python fallback). Raw passwords never in logs/traces/env/ DynamoDB. - INV-17 (ABAC discipline, v1.28): The token-vend Lambda evaluates
the kyverno-json ABAC policy before signing. Fail-closed on
kjabsence or evaluation error (C-6.1 — never fail open). Allow/deny + policy inputs emitted to the audit stream.policy_version(git SHA, D-231) recorded in every event.
Domains (capability groups)
- Contract surface
- Modules (L1 primitives + L2 patterns)
- Policy engine
- Confidence signal
- Environments & promotion
- Evidence stream & audit
- Telemetry & metrics
- Consumer surfaces (developer + agentic)
- Pilot estate (v1.26)
- Forge / CI runtime
Capabilities (additive — one row per shipped capability)
Tier: local = runs via emulating adapters (no AWS); live-aws = runs against the live AWS account
581513795199; lifecycle-pipeline = verified via themodules-lifecyclepipeline's apply→modify→destroy matrix cell. CAP-NNN IDs cross-reference the regression gate atcore/regression_verify.py(the machine registry). This file is the PO-facing narrative; the machine registry is the source of truth for the gate.
Domain 1 — Contract surface
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| CAP-001 | contract.schema.json validates sample contracts |
v1.1 / v1.2.0 |
schemas/contract.schema.json |
REQ-001, D-... | local | shape: id/name/environment/infrastructure |
| CAP-002 | environment.schema.json validates env files |
v1.9 / v1.9.0 |
schemas/environment.schema.json |
REQ-040 | local | dev/qa/prod/dr env JSONs |
| CAP-006 | Contract interpolation expands ${env.*} / ${contract.*} |
v1.9 / v1.9.0 |
core/contract_resolver.py |
REQ-040 | local | per-env variants |
| — | Submission-readiness gate (superset of contract schema) | v1.18 / v1.18.0 |
schemas/submission-readiness.schema.json, core/submission_readiness.py |
REQ-217, REQ-218, D-133 | local | the only PDLC→Nova boundary (INV-1) |
Domain 2 — Modules (L1 primitives + L2 patterns)
Source:
modules/registry.json(the authoritative module catalog). STATE.md lists the capability of having a registered module; registry.json is the live registry.
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| CAP-003 | contract_resolver resolves static-assets (L2) |
v1.1 / v1.2.0 |
core/contract_resolver.py, modules/l2/static-assets/ |
REQ-003 | local | CloudFront+WAF+S3 pattern |
| CAP-004 | contract_resolver resolves microservice (L2) |
v1.2 / v1.3.0 |
core/contract_resolver.py, modules/l2/microservice/ |
REQ-004 | local | ECS Fargate pattern (6 L1 children) |
| CAP-005 | Terraform adapter compiles resolved stack to .tf |
v1.1 / v1.2.0 |
adapters/terraform/adapter.py |
REQ-005 | local | stateless assembler (v1.11); emits module "<rid>" { source } blocks |
| — | L1 s3 primitive |
v1.1 / v1.2.0 |
modules/l1/s3/ |
REQ-005 | lifecycle | versioning + SSE-KMS by default |
| — | L1 vpc primitive |
v1.1 / v1.2.0 |
modules/l1/vpc/ |
REQ-005 | lifecycle | shared platform VPC (v1.11) |
| — | L1 ecs-cluster primitive |
v1.1 / v1.2.0 |
modules/l1/ecs-cluster/ |
REQ-005 | lifecycle | |
| — | L1 ecs-service primitive |
v1.1 / v1.2.0 |
modules/l1/ecs-service/ |
REQ-005 | lifecycle | execution_role_arn + task_role_arn wired (P4 W1 fix, v1.26) |
| — | L1 iam-role primitive |
v1.1 / v1.2.0 |
modules/l1/iam-role/ |
REQ-005 | lifecycle | |
| — | L1 alb primitive |
v1.1 / v1.2.0 |
modules/l1/alb/ |
REQ-005 | lifecycle | requires SG wire (P4 W1 fix, v1.26) |
| — | L1 ecr primitive |
v1.1 / v1.2.0 |
modules/l1/ecr/ |
REQ-005 | lifecycle | |
| — | L1 cloudfront primitive |
v1.7 / v1.7.0 |
modules/l1/cloudfront/ |
REQ-049, D-049 | lifecycle | OAC + WAF (production edge) |
| — | L1 waf primitive |
v1.7 / v1.7.0 |
modules/l1/waf/ |
REQ-049, D-049 | lifecycle | |
| — | L1 rds primitive |
v1.7 / v1.7.0 |
modules/l1/rds/ |
REQ-059, D-059 | lifecycle | multi-engine input (postgres/mysql/...) |
| — | L1 kms-key primitive |
v1.8 / v1.8.0 |
modules/l1/kms-key/ |
REQ-069, D-069 | lifecycle | per-stack CMK; 90-day rotation |
| — | L1 uptime primitive |
v1.8 / v1.8.0 |
modules/l1/uptime/ |
REQ-066, D-066 | lifecycle | uptime-kuma on ECS Fargate |
| — | L1 dynamodb primitive |
v1.26 / v1.25.2 |
modules/l1/dynamodb/ |
REQ-322 | local | PK + optional SK; PAY_PER_REQUEST; encryption + PITR by default (v1.8 NFRs) |
| CAP-013 | terraform init+validate+plan live AWS (microservice) |
v1.2 / v1.3.0 |
adapters/terraform/adapter.py |
REQ-013 | live-aws | 14 resources; plan saved |
| CAP-014 | terraform init+validate+plan live AWS (static-assets) |
v1.7 / v1.7.0 |
adapters/terraform/adapter.py |
REQ-014 | live-aws | CloudFront+WAF+S3 plan OK |
| CAP-017 | DynamoDB nova-contracts table |
v1.7 / v1.7.0 |
core/lambda/, terraform/ |
REQ-068, D-068 | lifecycle | PK changeRequestId, SK submittedAt (CMDB) |
| CAP-018 | Lambda contract-ingestor | v1.7 / v1.7.0 |
core/lambda/contract_ingestor.py |
REQ-051, D-051 | lifecycle | local stub + lifecycle evidence |
| CAP-019 | ECS cluster + service (L2 microservice) | v1.7 / v1.7.0 |
modules/l2/microservice/ |
REQ-066 | lifecycle | apply/modify/destroy exit 0 |
| CAP-020 | CloudFront + WAF production stack | v1.7 / v1.7.0 |
modules/l2/static-assets/ |
REQ-049 | lifecycle | apply/modify/destroy exit 0 |
| CAP-021 | uptime-kuma monitoring primitive | v1.8 / v1.8.0 |
modules/l1/uptime/ |
REQ-066 | lifecycle | |
| CAP-022 | OIDC role for act_runner | v1.11 / v1.11.0 |
terraform/bootstrap/ |
REQ-116, D-039 | lifecycle | real OIDC blocked on go-gitea/gitea#36988 |
Domain 3 — Policy engine
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| — | PolicyEngine Protocol + PolicyEngineRegistry |
v1.25 / v1.24.1 |
core/policy_engine.py |
REQ-291, REQ-292 | local | selects engine from config.json.policy.engine; NullEngine fallback when key absent |
| — | KyvernoJsonEngine adapter (shells to kj scan) |
v1.25 / v1.24.1 |
adapters/kyverno-json/kyverno_json_engine.py |
REQ-293, REQ-294 | local | is_configured() guards on which kj; SKIPPED PCR when absent |
| — | Contract policies (4) over consumer contract JSON | v1.25 / v1.24.2 |
adapters/kyverno-json/policies/contract/ |
REQ-295, REQ-296 | local | id-pattern, env-enum, infra-min-1, forbid-unknown-fields |
| — | Stack-IR policies (3) over resolved Target Stack IR | v1.25 / v1.24.2 |
adapters/kyverno-json/policies/stack-ir/ |
REQ-297, REQ-298, REQ-299 | local | tagging-standard, public-ingress, encryption-by-default |
| — | Plan-JSON policies (3) over terraform show -json |
v1.25 / v1.24.3 |
adapters/kyverno-json/policies/plan-json/ |
REQ-300, REQ-301, REQ-302 | local | plaintext-secrets, iam-wildcard, kms-reference |
| — | Meta-policies over merged PCR list | v1.25 / v1.24.3 |
adapters/kyverno-json/policies/meta/ |
REQ-303 | local | block-on-any-critical (declarative critical-block); tagging-rules-agree (Checkov↔kj agree) |
| — | Regression-gate policies (3) over capability-inventory JSON | v1.25 / v1.24.4 |
adapters/kyverno-json/policies/regression/ |
REQ-304, REQ-305 | local | declarative mirrors of CAP-013/023/024 imperative checks |
| — | Pilot-readiness policy (no placeholder account) | v1.26 / v1.25.3 |
adapters/kyverno-json/policies/pilot-readiness/no-placeholder-account.json |
REQ-320 | local | fail-closed gate; blocks apply on account_id == "000000000000" |
| — | Settlement-finality policy | v1.26 / v1.25.3 |
adapters/kyverno-json/policies/settlement-finality/all-matches-committed.json |
REQ-315 | local | authored + tested; enforcement deferred to milestone that binds qa/prod/dr (D-208) |
| — | Checkov adapter (raw-finding source) | v1.7 / v1.7.0 |
adapters/terraform/checkov_adapter.py |
REQ-053 | local | feeds meta-policies; NOVA_TAG_NAMING custom rule is the TF-static source of truth |
| — | Wiz adapter (raw-finding source) | v1.7 / v1.7.0 |
adapters/wiz/ |
REQ-053 | local | API findings; is_configured() guard |
| — | K8s Kyverno adapter (documentation-only) | v1.7 / v1.7.0 |
adapters/kyverno/ |
REQ-053, D-053 | local | inactive for Terraform-only stacks; activates when GitOps emits K8s manifests |
Domain 4 — Confidence signal
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| CAP-007 | confidence_signal.compute returns a band |
v1.1 / v1.2.0 |
core/confidence_signal.py |
REQ-007, D-040 | local | 6 inputs (INV-2); band ∈ {pass, block} |
| — | escalation_reason: 'confidence' on band == 'block' |
v1.26 / v1.25.3 |
core/confidence_signal.py |
REQ-318 | local | grounds Human Escalation Frequency numerator |
Domain 5 — Environments & promotion
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| — | env-JSON state_backend wiring |
v1.26 / v1.25.3 |
core/environments/*.json, adapters/terraform/adapter.py |
REQ-319, D-... | local | adapter reads env.state_backend.bucket (fallback to computed name) |
| — | Environment progression (dev autonomous → qa/prod/dr HITL) | v1.1 / v1.2.0 |
core/env_transition.py, core/hitl_gates.py |
REQ-042, D-042 | local | destroy-on-environment-change (v1.24) |
| — | Decommission mode (2-step, HITL SRE gates) | v1.8 / v1.8.0 |
core/env_transition.py, scripts/run_platform.sh |
REQ-070, D-070 | local | mode: decommission requires changeRequestId |
| — | Per-env mandatory metadata (W3.E) | v1.1 / v1.2.0 |
schemas/submission-readiness.schema.json |
W3.E | local | dev=stack+env; qa+=e2e+load; prod+=runbook+dashboard+oncall; dr+=drDrillRef |
Domain 6 — Evidence stream & audit
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| CAP-008 | outbox_writer builds a hash-chained item | v1.1 / v1.2.0 |
core/outbox_writer.py |
REQ-008 | local | tamper-evident (INV-6); tamper-resistant deferred (D-083) |
| CAP-015 | DynamoDB outbox table exists + describable | v1.1 / v1.2.0 |
core/outbox_writer.py |
REQ-015 | live-aws | nova-outbox (post-v1.26 re-bootstrap) |
| CAP-016 | S3 state bucket exists + readable | v1.1 / v1.2.0 |
terraform/bootstrap/ |
REQ-016 | live-aws | nova-tfstate-581513795199-us-east-1 |
| — | Decision Ledger (SQLite hash-chain) | v1.17 / v1.17.0 |
core/metrics/decision_ledger.py |
REQ-185, REQ-186 | local | cold store for metrics; ai.decision.made + attestation.recorded events |
| — | SSM Parameter Store deploy outputs (SecureString, KMS) | v1.7 / v1.7.0 |
core/output_publisher.py |
REQ-050, D-050 | live-aws | /acdl/{env}/{contractId}/{output_name} |
| — | GitHub PR comment / job summary deploy outputs | v1.7 / v1.7.0 |
scripts/run_platform.sh |
REQ-050, D-050 | local | no raw secrets in logs |
| — | Uniform error reporting via Lambda report_error |
v1.7 / v1.7.0 |
core/lambda/contract_ingestor.py |
REQ-055, D-055 | live-aws | GitHub issue on platform repo acdl/acdl; idempotent |
| — | Tagging standard enforcement (4 required tags) | v1.7 / v1.7.0 |
schemas/tagging-standard.json, adapters/terraform/policy/custom_rules/nova_tagging.py |
REQ-054, D-054 | local | nova:owner, nova:contract, nova:environment, nova:cost-center |
| — | Encryption + deletion-protection by default | v1.8 / v1.8.0 |
modules/l1/*/terraform/main.tf |
REQ-062, REQ-069, D-062, D-069, D-072 | local | per-stack CMK; managed KMS fallback for standalone L1 (D-072) |
Domain 7 — Telemetry & metrics
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| CAP-023 | metrics collector runs + emits expected schema | v1.17 / v1.17.0 |
core/metrics/collector.py |
REQ-194 | local | fact_run, fact_decision, fact_attestation dims |
| CAP-024 | unified deck structure (slide count, x3 arc, per-slide benefits) | v1.17 / v1.17.0 |
docs/presentations/nova-autonomous-cloud-delivery-marp.md |
REQ-194 | local | single source-of-truth marp deck |
| — | Outcome backfill (pending → succeeded/failed) |
v1.26 / v1.25.3 |
core/metrics/outcome_backfill.py |
REQ-317 | local | idempotent + terminal; grounds AI Decision Accuracy |
| — | Trust Snapshot | v1.17 / v1.17.0 |
metrics/TRUST_SNAPSHOT.md, core/metrics/trust_snapshot.py |
REQ-194 | local | leadership-ready trust verdict |
| — | PowerBI export (fact/dimension views + 8 placeholder views) | v1.17 / v1.17.0 |
metrics/powerbi/ |
REQ-194 | local | deferred metrics ship as documented-schema placeholders |
| — | Pre-apply Infracost estimate | v1.17 / v1.17.0 |
scripts/run_platform.sh |
REQ-119 | local | nova.cost.estimated; actual-spend CUR reconciliation deferred (D-096) |
| — | Regression gate (scripts/run_regression.sh) |
v1.10 / v1.10.0 |
core/regression_verify.py, scripts/run_regression.sh |
REQ-090, REQ-121 | local | fails closed on any non-Verified CAP; CAP-001..025 |
Domain 8 — Consumer surfaces (developer + agentic)
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| — | Reusable deploy workflow (deploy.yml@v1.25) |
v1.5 / v1.5.0 |
.github/workflows/deploy.yml, .gitea/workflows/deploy.yml |
REQ-105 | local | workflow_call; modes: full/plan-only/check-only/decommission |
| — | Consumer onboarding (developer + citizen-dev paths) | v1.1 / v1.2.0 |
docs/ONBOARDING.md, docs/consumer-guide.md |
BA.E, W3.E | local | both end in a sandbox dev submission that must pass the confidence gate |
| — | Atelier MCP server (agentic validation) | v1.18 / v1.18.0 |
mcp/atelier/server.py |
REQ-221, REQ-222 | local | atelier.validate_against_principles tool |
| — | 9 production-grade engineering skills | v1.18 / v1.18.0 |
skills/{api,security,data,testing,observability,errors,devops,infrastructure-as-code,compliance}.md |
REQ-221, REQ-222, BA.A | local | indexed by docs/skills.md; review/agent-checklist.md gate |
| — | Module examples (validated against contract schema) | v1.7 / v1.7.0 |
modules/<name>/examples/{simple,complex}.yml |
REQ-058, D-058 | local | examples cannot drift from schema silently |
Domain 9 — Pilot estate (v1.26)
The first real consumer estate.
nova-blockchain-exchangerepo (Giteacontinuous-intelligence/nova-blockchain-exchange, local clone/root/nova-blockchain-exchange). Homegrown PoA blockchain, equities only, single validator, T+1 settlement finality = block commit.
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| CAP-026 | PoA blockchain core (block + ledger + validator) | v1.26 / v1.25.1 |
chain/block.py, chain/ledger.py, chain/validator.py |
REQ-310, D-201 | local | single validator; SHA-256 hash chain; deterministic block production |
| CAP-027 | Order-matching engine (limit order book) | v1.26 / v1.25.1 |
engine/order_book.py, engine/order.py |
REQ-311 | local | price-time priority; partial fills |
| CAP-028 | T+1 settlement service | v1.26 / v1.25.1 |
settlement/service.py |
REQ-312 | local | idempotent; finality = block commit |
| CAP-029 | Consumer contract.yaml (blockchain exchange) |
v1.26 / v1.25.2 |
nova-blockchain-exchange/contract.yaml, contracts/*.yml |
REQ-313 | local | per-env variants (dev/qa/prod); validated against contract schema |
| CAP-030 | Consumer deploy via deploy.yml@v1.25 (inline adapter) |
v1.26 / v1.25.2 |
nova-blockchain-exchange/.github/workflows/deploy.yml, .gitea/workflows/deploy.yml |
REQ-314 | local | no cross-repo uses: (SPEC §10 Q1); checkout acdl/acdl @ v1.25 into platform/, run run_platform.sh |
| CAP-025 | Live-pilot-apply regression capability (round-trip) | v1.26 / v1.25.3 |
core/regression_verify.py |
REQ-316 | local | contract→adapter→plan→policy→confidence→attestation→outbox round-trip assertion |
| CAP-031 | Live pilot apply evidence (blkex-pilot-apply-v0.2) |
v1.26 / v1.25.4 |
.ciagent/archive/P4-PILOT-RUN-EVIDENCE-v1.26.md |
REQ-316, REQ-321 | live-aws | confidence 0.800 pass; outcome backfilled; hash chain valid; live apply against 581513795199 |
| CAP-032 | AWS key rotation scheduled workflow | v1.26 / v1.25.3 |
workflows-src/rotate-aws-key.yml |
SPEC §5.9 | local | daily rotation; forge-agnostic token name (REQ-230) |
Domain 10 — Forge / CI runtime
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| CAP-009 | offline pytest suite passes | v1.1 / v1.2.0 |
tests/ |
REQ-009 | local | 844 tests (v1.26 baseline) |
| CAP-010 | run_ci.sh reproduces CI pipeline locally |
v1.4 / v1.4.0 |
scripts/run_ci.sh |
REQ-010 | local | offline; contract→resolver→stack→adapter→structure validated |
| CAP-011 | headline E2E — local tier (microservice) | v1.2 / v1.3.0 |
scripts/run_local_e2e.sh |
REQ-011, D-092 | local | emulating adapters (no AWS) |
| CAP-012 | local E2E — static-assets (no ECS) | v1.1 / v1.2.0 |
scripts/run_local_e2e.sh |
REQ-012 | local | |
| — | platform-test.yml CI workflow |
v1.4 / v1.4.0 |
.github/workflows/platform-test.yml |
REQ-010 | local | platform repo only (consumer CI is per-consumer) |
| — | modules-lifecycle pipeline (apply→modify→destroy matrix) |
v1.11 / v1.11.0 |
.github/workflows/modules-lifecycle.yml |
REQ-121, D-096 | live-aws | per-module lifecycle cell; ci-vpc-destroy always runs |
| — | release.yml (semver + floating tag maintenance) |
v1.7 / v1.7.0 |
.github/workflows/release.yml |
REQ-... | local | v1.25 + v1 floating tags force-moved on merge to main |
| — | IAM policy baseline (acdl-spike-runner-policy) |
v1.11 / v1.11.0 |
terraform/bootstrap/spike_runner_policy.json, .ciagent/IAM_POLICY.md |
REQ-116, D-095 | live-aws | regression-tested by tests/test_iam_policy_baseline.py; OIDC role acdl-act-runner-role (CAP-022) |
| — | Local emulating adapters (no AWS) | v1.10 / v1.10.0 |
core/local_lambda_stub.py, scripts/run_local_e2e.sh |
D-092 | local | proves runtime behavior without live AWS |
Domain 11 — CLI + Identity Layer (v1.28)
| ID | Capability | Shipped | Files | Controlling | Tier | Notes |
|---|---|---|---|---|---|---|
| CAP-033 | CLI subcommand surface exists | v1.28 / v1.27.1 |
nova/cli.py, nova/<module>.py (15 subcommands) |
REQ-324 | local | nova --help lists a subcommand for every core/ module; argparse-only, auto-discovered |
| CAP-034 | Subcommand delegates to core/ |
v1.28 / v1.27.1 |
nova/<module>.py |
REQ-324 | local | ≤50 lines, ≤3 FunctionDef, all calls resolve to core.* imports; AST-scanned in tests/test_cli_subcommands.py |
| CAP-035 | Layer matches wheel | v1.28 / v1.27.1 |
.github/workflows/publish.yml, .gitea/workflows/publish.yml, SSM /nova/layer/nova-cli/version |
REQ-323 | local | wheel + Lambda layer co-published with identical version; SSM mapping; CodeArtifact + fallback |
| CAP-036 | Nova-idp auth flow works | v1.28 / v1.27.3 |
core/lambda/nova_idp_auth.py, tests/test_idp_auth.py |
REQ-333 | local | sign-up → sign-in → session E2E; Argon2id t=3 m=65536 p=1; fail-closed D-228; moto locally, real DDB in CI |
| CAP-037 | Token-vend signs via KMS | v1.28 / v1.27.4 |
core/lambda/nova_idp_token_vend.py, core/kms_signing.py, tests/test_kms_roundtrip.py |
REQ-337 | local | ECDSA P-256 / ES256; DER→raw conversion; KMS round-trip test; mock KMS locally, real KMS in CI |
| CAP-038 | PAT issuance + revocation | v1.28 / v1.27.4 |
core/pat_lifecycle.py, tests/test_pat_revocation.py |
REQ-342 | local | issue → vend → revoke → 403 within 60s P95; strong-read DDB (D-229); verified <1s locally |
| — | nova init scaffolds .nova/ |
v1.28 / v1.27.1 |
nova/init.py, core/init_scaffold.py |
REQ-325 | local | .nova/, .nova/contract.yml.attestations/, .gitignore (secrets excluded) |
| — | nova cli-action composite action |
v1.28 / v1.27.1 |
.github/actions/nova-cli/action.yml |
REQ-326 | local | byte-identical GitHub + Gitea; Python 3.12 pinned; NFR-11 |
| — | mode_resolver (flag→env→cred→TTY) |
v1.28 / v1.27.1 |
core/mode_resolver.py |
REQ-327, D-226 | local | sys.stdin.isatty() (not stdout); hypothesis property tests |
| — | Dual-use Lambda/CLI import | v1.28 / v1.27.2 |
core/lambda/contract_ingestor.py |
REQ-329 | local | shared dispatch_action(); ≥80% code share; NFR-7 |
| — | Local env synthesizer | v1.28 / v1.27.2 |
core/env.py (synthesize_local_env) |
REQ-330 | local | nova apply --local; no cloud provisioning |
| — | JWS-from-PAT (HKDF-SHA256, HS256) | v1.28 / v1.27.2 |
core/jws_attestation.py |
REQ-332, C-5.2 | local | symmetric; verification key derived from PAT via same KDF |
| — | JWKS endpoint (function URL) | v1.28 / v1.27.4 |
core/lambda/nova_idp_jwks.py |
REQ-338, D-230 | local | AuthType: NONE; Cache-Control: max-age=3600; optional CloudFront/WAF |
| — | kyverno-json ABAC token-vend policy | v1.28 / v1.27.4 |
platform/abac/token-vend.policy, core/abac_evaluator.py |
REQ-339, D-227 | local | fail-closed (C-6.1, 7 tests); policy_version git SHA (D-231) |
| — | nova idp setup --check/--apply/--verify |
v1.28 / v1.27.4 |
nova/idp/setup.py, core/lambda/nova_idp_setup.py, core/lambda/nova_idp_cfn.py |
REQ-340, REQ-341 | local | CloudFormation template review (NFR-10); IAM policy delta; KMS round-trip verify |
| — | nova auth login/revoke/status |
v1.28 / v1.27.4 |
nova/auth/{login,revoke,status}.py, core/auth_store.py |
REQ-344, C-7.3 | local | ~/.nova/credentials.json 0600 stores OIDC token + metadata (NOT raw PAT) |
| — | E2E integration test | v1.28 / v1.27.5 |
tests/test_e2e_idp.py |
REQ-348 | local | sign-up → sign-in → token-vend → apply → audit chain |
| — | Identity-layer threat model | v1.28 / v1.27.5 |
docs/threat-model.md |
REQ-347 | local | 8 threats + C-9.2 INV-18..21 compression audit |
| — | Operator guide | v1.28 / v1.27.5 |
docs/operator-guide-idp.md |
REQ-345 | local | nova idp setup + KMS rotation + layer update + PITR restore + emergency PAT revocation |
| — | Developer guide | v1.28 / v1.27.5 |
docs/developer-guide-auth.md |
REQ-346 | local | quickstart + mode resolution + JWS KDF + service-account PATs |
Archive pointers
- v1.0–v1.24 capability narrative + the 2026-07-27 re-verification sweep:
.ciagent/archive/CAPABILITY_INVENTORY-v1.10.md(moved from.ciagent/CAPABILITY_INVENTORY.mdat v1.27). CAP-NNN IDs in this file cross-reference the regression gate atcore/regression_verify.py. - v1.0–v1.24 milestone narrative:
.ciagent/archive/PROJECT-v1.0-v1.24.md. - v1.0–v1.24 requirements (REQ-01..REQ-290):
.ciagent/archive/REQUIREMENTS-v1.0-v1.24.md. - v1.0–v1.24 phase breakdowns:
.ciagent/archive/ROADMAP-v1.0-v1.24.md. - v1.0–v1.24 architecture history:
.ciagent/archive/ARCHITECTURE-v1.0-v1.24.md. - v1.26 pre-execution artifacts (CLARIFY, GRILL, IDEATE, RESEARCH):
.ciagent/archive/{CLARIFY,GRILL,IDEATE,RESEARCH}-v1.26.md(decisions D-200..D-213 folded intoPROJECT.mdload-bearing decisions + PLAN.md binding revisions at v1.27 archive time). - v1.26 phase verifications:
.ciagent/archive/{VERIFY-P03,VERIFY-P04,REVIEW-AUDIT-P05}.md. - v1.26 live pilot run evidence:
.ciagent/archive/P4-PILOT-RUN-EVIDENCE-v1.26.md. - v1.21 autonomy thesis (folded into NORTH_STAR.md Vision):
.ciagent/archive/AUTONOMY_THESIS-v1.21.md. - v1.14 AWS cost report (predates v1.26 live pilot):
.ciagent/archive/COST-v1.14.md.
Update discipline
This file is updated once per milestone, at the P-final milestone-ship
wave (Wave 3 "milestone ship" in PLAN.md), alongside
ROADMAP.md/NORTH_STAR.md/REQUIREMENTS.md:
- Append new capability entries for each shipped REQ (one row per capability; group by domain).
- Mark any deprecated capability with a
Deprecatedrow citing the milestone + replacement. - Bump the "Last milestone ship" header.
- Do not rewrite existing entries (additive only).
Enforcement: convention (the P-final ship step names this file). A
drift-check gate (assert every REQ marked complete in
REQUIREMENTS.md traceability appears in STATE.md) is a future option
if the convention drifts.
PDLC Phase 0 Intake (current ground truth — 2026-08-19)
Single-pass discovery for the next PDLC cycle. Populated from the live repo state after v1.28 ship. No aspirational items — state is what is, not what should be. Unknowns are explicit.
1. Header (mandatory)
Project: Nova — The New Dawn of DevSecOps
Initiative: UNKNOWN — needs investigation (no new initiative specified; v1.28 just shipped, next milestone not yet scoped)
Initiator: Product Owner / Manager (PDLC Phase 0 trigger)
Date (UTC): 2026-08-19
Current Version: v1.28 complete (tag v1.27.6, merged to main 2026-08-19); all 7 phases shipped; no phase in progress
System Health: YELLOW — coverage 73.8% is below the 80% release-gate floor (NFR/quality debt); CodeArtifact not provisioned (P1 Wave 0 gate unresolved — fallback documented); KMS asymmetric key unverified in-account (C-1.1 documented as CI gate, not verified locally)
Raw Idea (≤ 3 sentences):
UNKNOWN — needs investigation (no raw idea provided; the PDLC trigger is the post-v1.28 state intake, not a new initiative).
Trigger: v1.28 milestone completion (CLI Canonicalization + Identity Layer shipped 2026-08-19).
Desired outcome: UNKNOWN — the PO defines the next initiative from this intake.
2. Architecture State
Active Layers (which exist and are stable):
[x] Core Primitives — core/ (27 modules): abac_evaluator, attestation_matrix, auth_store, confidence_signal, contract_resolver, decommission_transform, env, env_transition, environment_check, hitl_gates, init_scaffold, jws_attestation, kms_signing, local_emulators, mode_resolver, onboarding, outbox_writer, output_publisher, pat_lifecycle, policy_engine, regression_verify, separation_of_duties, submission_readiness + core/lambda/ (6 modules) + core/metrics/ (decision ledger)
[x] Domain Modules — adapters/terraform/ (stateless adapter), adapters/kyverno-json/ (unified policy engine, INV-4 swappable), adapters/wiz/, adapters/kyverno/ (K8s, inactive for Terraform — D-053)
[x] API/Dev Surface — nova/ CLI package (15 subcommands, argparse-only, [project.scripts] nova = "nova.cli:main"); nova auth {login,revoke,status}; nova idp setup; nova init; nova apply --local; nova cli-action composite action (GitHub + Gitea)
[x] UI/Agent Surface — N/A (no UI; CLI + JSON endpoints only; JWKS serves application/json)
Compute Topology (per environment):
local: abstract (local emulators via core/local_emulators.py:LocalLambdaStub; nova apply --local synthesizes env via core/env.synthesize_local_env(); no cloud provisioning)
dev: abstract (env JSON core/environments/dev.json; pilot ran mode: full against live AWS 581513795199 at v1.26; Nova-idp Lambdas deploy via nova idp setup but not yet live-verified in dev)
staging: N/A (no staging environment JSON; environments are dev/qa/prod/dr)
prod: UNKNOWN — needs investigation (env JSON core/environments/prod.json exists; live-apply not run against prod; pilot was dev-only per D-209)
dr: placeholder (env JSON core/environments/dr.json exists; blocked by pilot-readiness policy D-208; not activated)
Identity Stack in Force:
auth: Custom IDP — Nova-idp (nova-idp-auth Lambda, v1.28): sign-up/sign-in/session; Argon2id (t=3, m=65536, p=1); DynamoDB nova-users/nova-sessions/nova-password-resets. NOT live-deployed (code + tests complete; nova idp setup ready; deployment pending operator action + AWS creds).
token-vend: Nova-idp (nova-idp-token-vend Lambda, v1.28): accepts PAT/session → KMS-signed OIDC token (ECDSA P-256 / ES256); kyverno-json ABAC fail-closed (INV-17, C-6.1); nova-pats DynamoDB (strong-read revocation, D-229, 60s SLO). NOT live-deployed.
signing: KMS asymmetric — alias/nova-oidc-signing (ECC_NIST_P256, SIGN_VERIFY). Code complete; key NOT yet created in-account (C-1.1 documented as CI gate — aws kms create-key --key-spec ECC_NIST_P256 --key-usage SIGN_VERIFY unverified).
session: DynamoDB — nova-sessions table (PK session_id, TTL expires_at, 24h). Cookie/local-file: ~/.nova/credentials.json (0600, OIDC token + PAT metadata, NOT raw PAT — C-7.3).
Audit Stream:
source of truth: DynamoDB outbox → S3 Object Lock (7-yr) → GitHub/Gitea audit repo (hot index). The Decision Ledger (SQLite hash-chain, D-121, core/metrics/decision_ledger.py) is the cold store for ai.decision.made + attestation.recorded events.
in-repo fallback: yes (SQLite hash-chain outbox_writer, core/outbox_writer.py, INV-6 tamper-evident; tamper-resistant deferred — D-083 S3 Object Lock/JWS not yet enabled)
retention policy: 7 years (S3 Object Lock target; not yet enabled — D-083 deferred)
3. Technical Stack (concrete, not aspirational)
Language(s) and runtime(s): Python 3.12 (requires-python >=3.12; Lambda Python 3.12 runtime on Amazon Linux 2023)
Build / packaging: setuptools (pyproject.toml, build-backend setuptools.build_meta); wheel via python -m build --wheel; Lambda layer via pip install --target layer/python/ + zip; publish to CodeArtifact (NOT yet provisioned — fallback: Gitea wheel index / private PyPI via NOVA_WHEEL_INDEX)
CI / CD: Gitea Actions (.gitea/workflows/) + GitHub Actions (.github/workflows/, byte-identical); publish.yml (wheel + layer co-publish, REQ-323, CAP-035); ci.yml (test/lint); deploy.yml@v1.25 (consumer deploy); nova cli-action composite action (.github/actions/nova-cli/action.yml); OIDC to AWS (id-token: write)
Infrastructure: AWS account 581513795199 (single-region us-east-1); S3 (state files); DynamoDB (locking + outbox + identity tables); Lambda (contract ingestor + Nova-idp 3 Lambdas); KMS (per-stack CMK + alias/nova-oidc-signing); CloudFront/WAF/ACM (optional, --public-jwks-domain); no VMs/bare metal/OS (Anti-Goal)
Data stores: DynamoDB — nova-contracts, nova-change-requests (v1.7); nova-users, nova-sessions, nova-password-resets, nova-pats (v1.28); SQLite — Decision Ledger (core/metrics/decision_ledger.py, local cold store); S3 — Terraform state + audit Object Lock (target, D-083 deferred)
Secrets / KMS: KMS per-stack CMK (D-069, 90-day rotation); alias/nova-oidc-signing (ECC_NIST_P256, 90-day rotation target — code complete, key not yet created); nova-spike-runner IAM user (static key, daily rotation via workflows-src/rotate-aws-key.yml, REQ-230 forge-agnostic); Secrets Manager (nova/github-token); NOVA_GITEA_TOKEN in .env (not shell-env, per bash_allowlist)
External integrations in scope: CodeArtifact (internal PyPI — NOT yet provisioned); Gitea (git.cloudinit.dev/continuous-intelligence/acdl — primary forge); GitHub (mirror, byte-identical workflows); AWS (account 581513795199 — pilot + identity stack); kj / kyverno-json v0.0.3 (Go binary, pinned SHA256, bundled in Lambda layer — platform/abac/kj-version.txt)
4. Active Constraints (the load-bearing ones)
Locked Decisions: D-001..D-231 (full ledger in PROJECT.md + CLARIFY history). Load-bearing for new work: D-022 (contract schema), D-039/D-047 (per-run creds), D-051 (Lambda Function URL), D-069 (per-stack CMK), D-083 (S3 Object Lock — deferred), D-092 (local emulators), D-096 (live pilot — lifted v1.26), D-121 (Decision Ledger), D-133 (submission-readiness gate), D-200..D-213 (v1.26 pilot), D-214..D-225 (v1.27), D-226..D-231 (v1.28 — mode resolution, kyverno-json ABAC, Argon2id fail-closed, PAT revocation strong-read, JWKS function URL, ABAC policy git-SHA versioning)
Active Invariants: INV-1..INV-17 (full text above). New in v1.28: INV-12 (mode observability), INV-13 (mode determinism), INV-14 (credential type encodes role), INV-15 (no AWS-managed identity), INV-16 (Argon2id password storage), INV-17 (ABAC discipline fail-closed)
Standing Capability Gate: CAP-001..CAP-038 — all Verified (32 from v1.0..v1.27 + 6 from v1.28). Gate enforced by core/regression_verify.py + CI merge gates. CAP-033..038 added v1.28 (CLI surface, delegation AST, layer/wheel match, auth flow, KMS sign, PAT revocation).
Anti-Goals Touched: docs/vision.md §7 / NORTH_STAR.md §Anti-Goals — (1) not an upstream dev platform; (2) not a general-purpose AI; (3) not a legacy infra bridge; (4) not a permissive delivery highway; (5) not a mutable audit log. v1.28 honored all 5 (no PDLC reach, narrow CLI autonomy, no VMs, ABAC fail-closed + HITL gates intact, immutable outbox).
Out-of-Scope (hard): MFA/TOTP enforcement (v1.21+); WebAuthn/FIDO2 (v1.23+); upstream IdP federation (v1.23+); Lambda layer auto-update on core/ changes (v1.19); password breach detection (v1.23+); session refresh token rotation (v1.22); S3 Object Lock / JWS tamper-resistance (D-083, deferred); multi-cloud (Azure/GCP); ML forecasting; bonds/derivatives/options (D-200 equities-only); multi-validator BFT (D-201 single-validator PoA)
5. Recent History & Quality Gates (last 1-2 milestones)
Last Shipped: v1.28 (tag v1.27.6, 2026-08-19) — CLI Canonicalization + Identity Layer. 31 REQs (REQ-323..353), 6 CAPs (CAP-033..038), 6 INV (INV-12..17), 6 decisions (D-226..231). 7 phases (P0 + P1..P5 + P6 final). 1000 tests passing. Grill PROCEED 0.76 (3 critical + 16 tracked conditions resolved). Merged to main c0cb188.
In Progress: N/A (no phase in progress; v1.28 complete; next milestone not yet scoped)
Coverage Floor: 73.8% (3119/4227 lines covered) — BELOW the 80% release-gate floor. v1.28 new modules (nova/, core/mode_resolver.py, core/lambda/nova_idp_*.py, core/kms_signing.py, core/abac_evaluator.py, core/jws_attestation.py, core/pat_lifecycle.py) have high unit-test coverage but the overall floor is dragged by older uncovered code paths. Quality debt to address in a future NFR milestone.
Recent Incidents: none (no incidents in v1.27 or v1.28; no hotfix/rollback/outage commits in recent history)
Known Tensions: (1) CodeArtifact not provisioned — the publish pipeline (REQ-323) has a documented Gitea wheel-index fallback (NOVA_WHEEL_INDEX) but the primary path is unverified. (2) KMS asymmetric key unverified in-account (C-1.1) — the token-vend Lambda code + tests are complete but aws kms create-key --key-spec ECC_NIST_P256 has not been run against 581513795199. (3) kj Go binary in Lambda layer — pinned + locally verified, but AL2023 Lambda-runtime compatibility is a P2 spike that was not live-verified (D-227 risk; Fargate fallback documented). (4) Coverage 73.8% < 80% floor — the release gate was satisfied by phase-level coverage on new modules, but the overall floor is in debt. (5) pyproject.toml version is 1.14.0 (stale — not bumped through v1.15..v1.28; the milestone tags are authoritative, not the pyproject version).
6. Agent Context & Assumptions (Agent Initiators Only)
Missing Context: (1) The next initiative / raw idea — no new PDLC work was specified; this intake is the post-v1.28 state snapshot. (2) Live AWS verification of Nova-idp — CodeArtifact, KMS asymmetric key, and kj-in-Lambda-layer were not live-verified (no AWS creds in the build environment); all have documented fallbacks + CI gates. (3) Prod/dr environment activation status — env JSONs exist but live-apply was dev-only (D-209).
Agent Assumptions: (1) The PDLC trigger is the post-v1.28 state intake (not a new initiative) — the PO will define the next initiative from this snapshot. (2) Coverage 73.8% is reported as YELLOW system health (below 80% floor) but is not a blocker for the intake — it's quality debt for a future NFR milestone. (3) The 3 unverified-in-account items (CodeArtifact, KMS, kj-in-Lambda) are reported as tensions, not blockers — they have fallbacks + CI gates documented. (4) pyproject.toml version 1.14.0 is stale but not load-bearing (milestone tags are authoritative); flagged for a future chore.
7. Canonical State References (Version/Hash)
Vision/Strategy doc: docs/vision.md v0.2 (referenced in PROJECT.md; not version-tagged separately)
Architecture document: .ciagent/ARCHITECTURE.md §12.1..§12.10 (v1.28-appended §12.10 Nova-idp); commit c0cb188 (main HEAD)
Last approved SPEC: v1.28 (REQ-323..353, REQUIREMENTS.md §v1.28); commit c0cb188
Decision log: D-001..D-231 (PROJECT.md load-bearing + CLARIFY.md history); last synced commit c0cb188
Invariants catalog: INV-1..INV-17 (STATE.md §Invariants); commit c0cb188
Capability catalog: CAP-001..CAP-038 (STATE.md §Domains 1..11); commit c0cb188
Ground rules compliance
- No prose paragraphs inside sections — field structure used throughout. ✓
- No aspirational items — state is what is (CodeArtifact "NOT yet provisioned", KMS "NOT yet created", prod "UNKNOWN"). ✓
- No restated decisions — referenced D-/INV-/CAP-* IDs only. ✓
- Unknowns explicit — "UNKNOWN — needs investigation" used for initiative, prod state, raw idea. ✓
- One file, one format — appended to STATE.md as §PDLC Phase 0 Intake. ✓
- Full shipping workflow + merge to forge upstream, NO release — branch + merge + push only (release skipped per instruction). ✓