Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d199204367 | |||
| 6a64b2b337 | |||
| 9274b4b87f | |||
| 25ddc894c2 | |||
| 156431c80a | |||
| 631244458f | |||
| 81b731ed17 | |||
| cc6071ee53 | |||
| d1ff6934c6 | |||
| ccbccb02ac | |||
| 574e6cb189 | |||
| 358aa62c3a | |||
| ff416777f9 | |||
| 94891af6ee | |||
| 072ac83ef6 | |||
| c6036ca433 | |||
| 38eb01d266 | |||
| 0404988465 | |||
| dbca694f55 | |||
| 71f0f1a05d | |||
| ce751313a7 | |||
| 5b5e24d535 | |||
| 85c500e45a | |||
| 301aa2c8d8 | |||
| 707a7dbe9b | |||
| e7866fda84 | |||
| 2efed26bb6 | |||
| 5c07e29b90 | |||
| aa868c97ef | |||
| e4a9915891 | |||
| 0ca383dae6 | |||
| ed5ea90654 | |||
| 2273009b95 | |||
| 0d2cbdb423 | |||
| b418d429b5 | |||
| dcba380b52 | |||
| f0bc3be92c | |||
| 0b79b16715 | |||
| 90624be63f | |||
| be51fc15fa | |||
| e3f4ce17d4 | |||
| e0d01ad2ef | |||
| a4c5f332f6 | |||
| 9e20b7ba95 | |||
| 6da538c936 | |||
| 4e03817ea6 | |||
| 951ad56576 | |||
| d882cf0c6e | |||
| 564d4a4ca3 | |||
| c524ad731e | |||
| 8bcf7296d5 | |||
| 81c7a22ddd | |||
| 2c08c778a9 | |||
| 6ffcbe8283 | |||
| 5775a97388 | |||
| b3c75ccec1 | |||
| e891496163 | |||
| 382944c055 | |||
| 71b6a4fa91 | |||
| 0f677641ee | |||
| e3ebbc4978 | |||
| 37b6b6fc14 | |||
| d61a3d1a2f | |||
| 4c8b2b77fc | |||
| 1daae0ac0a | |||
| d048460abf | |||
| 0ad6a88c4b | |||
| eb5b24b88d | |||
| cb1a7071a7 | |||
| e4adb3f09e | |||
| 9415afc739 | |||
| d9b402c283 | |||
| b1cf24873b | |||
| eb43e08367 | |||
| a9c5d67301 | |||
| b054849a99 | |||
| 942185c85b | |||
| 3a7604dec0 |
@@ -0,0 +1,66 @@
|
|||||||
|
# Nova — The Autonomous Cloud Delivery Platform: Autonomy Defensibility Brief
|
||||||
|
|
||||||
|
> Strategic direction, leadership metrics & unified story
|
||||||
|
> Last refined: v1.21 — reframe from "no-humans" to "autonomous operations"
|
||||||
|
|
||||||
|
## The thesis
|
||||||
|
|
||||||
|
Nova is the autonomous infrastructure layer that lets product teams
|
||||||
|
ship without engaging an operator, and lets executives trust the
|
||||||
|
platform not because it never fails but because every decision is
|
||||||
|
captured, scored, and accountable.
|
||||||
|
|
||||||
|
**Autonomy in operations; human at stage gates.** Normal operations —
|
||||||
|
provisioning, healing, remediation — run without an operator in the
|
||||||
|
loop. Human attestation remains required at stage gates: QA signs off
|
||||||
|
for production, SRE greenlights based on operational readiness. The
|
||||||
|
absence of an operator in the loop is never the absence of a record.
|
||||||
|
|
||||||
|
## Grounded proof (measurable today)
|
||||||
|
|
||||||
|
| Proof | Source | Status |
|
||||||
|
|-------|--------|--------|
|
||||||
|
| Capabilities verified, none broken (live-AWS caps honestly skipped, resources torn down to zero-cost steady state) | regression report | grounded |
|
||||||
|
| Decision Ledger captures 100% of automated decisions with outcome backfill | decision ledger store | grounded |
|
||||||
|
| Attestation coverage: 100% of prod/dr promotions attested by a human | attestation gates + outbox | grounded |
|
||||||
|
| Confidence-gated policy engine (deterministic, not an LLM) — weighted inputs, band outcome | confidence signal | grounded |
|
||||||
|
| Attestation matrix with separation-of-duties on prod | attestation matrix + separation-of-duties | grounded |
|
||||||
|
| Pre-apply cost estimates (offline) | cost adapter | grounded |
|
||||||
|
| Test suite passes | test results | grounded |
|
||||||
|
|
||||||
|
## Deferred proof (measurable when blocking work lifts)
|
||||||
|
|
||||||
|
| Proof | Blocking work | Unblock requirement |
|
||||||
|
|-------|----------------|---------------------|
|
||||||
|
| Touchless resolution rate across production estates | 0 consumers today | Pilot estate activation |
|
||||||
|
| Live infrastructure health (ECS, ALB, RPS) | Live AWS torn down | Live AWS re-provisioning |
|
||||||
|
| Onboarding funnel: requested → granted | Auto-grant not built | Auto-grant implementation |
|
||||||
|
| Drift auto-reversal rate | No drift scheduler | Drift detection scheduler |
|
||||||
|
| Predictive vs reactive ratio | No emitter | ML anomaly-forecasting service |
|
||||||
|
| Tamper-evident ledger checkpoints (S3 Object Lock + JWS) | Audit ledger build-out | Audit ledger build-out |
|
||||||
|
|
||||||
|
## Anti-claims (what Nova is NOT)
|
||||||
|
|
||||||
|
1. **Nova's decisions are NOT made by an LLM.** They are made by a
|
||||||
|
confidence-gated policy engine: deterministic scripts calculate a
|
||||||
|
score, and a band outcome gates the action. The platform functions
|
||||||
|
without AI. The Decision Ledger captures this real decision path —
|
||||||
|
not a fabricated "AI agent." When an LLM planner is added, it will
|
||||||
|
emit richer `alternatives_considered` without schema breakage.
|
||||||
|
2. **Nova does NOT remove humans from accountability.** Only from
|
||||||
|
normal operations. Every stage-gate promotion (qa/prod/dr) requires
|
||||||
|
a human attestation recorded with approver identity,
|
||||||
|
separation-of-duties check, and the evidence matrix.
|
||||||
|
3. **Nova is NOT for legacy, untagged, or freeform infrastructure.** It
|
||||||
|
requires Terraform-managed, policy-aligned, fully-tagged inputs.
|
||||||
|
4. **Nova does NOT fabricate metrics.** Every metric is grounded (cites
|
||||||
|
a source), derived (documented formula), or deferred (cites the
|
||||||
|
blocking work). No fabricated numbers in any deck slide or metrics
|
||||||
|
entry (the "no fabrication" hard constraint).
|
||||||
|
|
||||||
|
## What "won" looks like
|
||||||
|
|
||||||
|
By month 18, Nova is the layer enterprise leadership points to when
|
||||||
|
they say *"we don't have an infrastructure ops team anymore, and the
|
||||||
|
audit trail is stronger than it ever was"* — and it is the layer their
|
||||||
|
AI engineering teams reach for first when an agent needs to deploy.
|
||||||
@@ -1,13 +1,28 @@
|
|||||||
{
|
{
|
||||||
"phase": 0,
|
"phase": 6,
|
||||||
"stage": "complete",
|
"stage": "complete",
|
||||||
"milestone": "v1.17",
|
"milestone": "v1.22",
|
||||||
"phase_role": "pre_execution",
|
"phase_role": "final",
|
||||||
"attempts": 0,
|
"attempts": 0,
|
||||||
"updated_at": "2026-08-04T21:30:00Z",
|
"updated_at": "2026-08-11T15:30:00Z",
|
||||||
"milestone_complete": false,
|
"milestone_complete": true,
|
||||||
"tag": "v1.16.0",
|
"tag": "v1.21.6",
|
||||||
"release_id": 441,
|
"requirements": ["REQ-254","REQ-255","REQ-256","REQ-257","REQ-258","REQ-259","REQ-260","REQ-261","REQ-262"],
|
||||||
"requirements": ["REQ-185"],
|
"release": {
|
||||||
"notes": "Phase 0 complete. NORTH_STAR.md authored. 29 requirements (REQ-185..213). Telemetry reference architecture + metric scorecard. Deck rebuild plan (18 slides). Interactive GRILL: 12 binding decisions applied. Tag v1.16.0 pushed. Gitea release 441 created. Ready for execution phases P1..P7 + final P8."
|
"forge": "gitea",
|
||||||
|
"releases_created": true,
|
||||||
|
"release_ids": {
|
||||||
|
"v1.21.0": 621,
|
||||||
|
"v1.21.1": 622,
|
||||||
|
"v1.21.2": 623,
|
||||||
|
"v1.21.3": 624,
|
||||||
|
"v1.21.4": 625,
|
||||||
|
"v1.21.5": 626,
|
||||||
|
"v1.21.6": 627
|
||||||
|
},
|
||||||
|
"milestone_release_id": 627,
|
||||||
|
"pptx_asset_id": 98,
|
||||||
|
"pptx_download_url": "https://git.cloudinit.dev/attachments/fe691962-4f4e-4321-ab5d-c2bb8c3fd6ad"
|
||||||
|
},
|
||||||
|
"notes": "v1.22 milestone complete. Tag v1.21.6 (milestone release). Merged to main + pushed to origin. All 7 Gitea releases created (ids 621-627). PPTX attached to milestone release (asset id 98). All milestone branches deleted. 9 requirements complete (REQ-254..262). 32 slide tests pass (23 original + 9 new). 94 key-file tests pass. Pipeline check exit 0. Next milestone starts fresh."
|
||||||
}
|
}
|
||||||
+57
-36
@@ -1,7 +1,7 @@
|
|||||||
# NORTH_STAR — Nova
|
# NORTH_STAR — Nova
|
||||||
|
|
||||||
> **Status:** Draft (pending interactive GRILL → final)
|
> **Status:** Draft (pending interactive GRILL → final)
|
||||||
> **Milestone:** v1.17 — Strategic Direction, Leadership Metrics & Unified Story
|
> **Milestone:** v1.21 — Nova Deck Refinement & Pipeline Hardening
|
||||||
> **Owner:** Product Owner
|
> **Owner:** Product Owner
|
||||||
> **Purpose:** Durable strategic intent. Read by CIAgent in every future
|
> **Purpose:** Durable strategic intent. Read by CIAgent in every future
|
||||||
> `/ci-run` so the platform's direction survives across milestones. This
|
> `/ci-run` so the platform's direction survives across milestones. This
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
## Vision
|
## Vision
|
||||||
|
|
||||||
> **Infrastructure operations become invisible. Every environment
|
> **Infrastructure operations become visible. Every environment
|
||||||
> provisioned, every incident healed, every risk remediated — by an
|
> provisioned, every incident healed, every risk remediated — by an
|
||||||
> autonomous system whose trustworthiness is provable, not promised.
|
> autonomous system whose trustworthiness is provable, not promised.
|
||||||
> Human attestation remains required at stage gates — QA signs off for
|
> Human attestation remains required at stage gates — QA signs off for
|
||||||
@@ -22,9 +22,12 @@
|
|||||||
> operator is never in the loop of normal operations.**
|
> operator is never in the loop of normal operations.**
|
||||||
|
|
||||||
Nova is the autonomous infrastructure layer that lets product teams ship
|
Nova is the autonomous infrastructure layer that lets product teams ship
|
||||||
without engaging an operator, and lets executives trust the AI not because
|
without engaging an operator, and lets executives trust the platform not
|
||||||
it never fails but because every decision is captured, scored, and
|
because it never fails but because every decision is captured, scored,
|
||||||
accountable.
|
and accountable. The recurring theme across the platform is that
|
||||||
|
**infrastructure operations become visible** — security posture,
|
||||||
|
remediation velocity, reliability, and lead time are surfaced as
|
||||||
|
queryable signals rather than hidden in tribal knowledge.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -38,46 +41,64 @@ human by design; operational escalations (AI confidence too low to
|
|||||||
proceed) are the failure mode we drive toward zero. Everything else
|
proceed) are the failure mode we drive toward zero. Everything else
|
||||||
collapses if autonomy isn't real.
|
collapses if autonomy isn't real.
|
||||||
|
|
||||||
**2. Establish provable trust in AI decisions.**
|
**2. Establish provable trust in automated decisions.**
|
||||||
Build the audit substrate — Decision Ledger, confidence scoring, circuit
|
Trust is established by deterministic scripts that calculate a score and
|
||||||
breakers, blast-radius controls — that turns "autonomous" from a
|
a band outcome that gates the action — the platform functions without AI.
|
||||||
marketing claim into a defensible one. Trust is the moat. Features can be
|
"AI decisions" are really automated decisions. The audit substrate —
|
||||||
copied; an immutable, queryable decision history cannot.
|
Decision Ledger, confidence scoring, circuit breakers, blast-radius
|
||||||
|
controls — turns "autonomous" from a marketing claim into a defensible
|
||||||
|
one. Trust is the moat. Features can be copied; an immutable, queryable
|
||||||
|
decision history cannot.
|
||||||
|
|
||||||
**3. Deliver compounding, quantifiable ROI for customers.**
|
**3. Deliver compounding, quantifiable ROI for customers.**
|
||||||
Each quarter on Nova must reduce cloud spend, free engineering hours, and
|
Each quarter on Nova must show measurable improvement on four CTO-grade
|
||||||
avoid downtime measurably. If the CFO can't point to a number that
|
metrics, all of which flow into PowerBI views and are captured by the
|
||||||
improves quarter-over-quarter, Nova fails its commercial test, regardless
|
telemetry pipeline:
|
||||||
of how clever the AI is.
|
|
||||||
|
|
||||||
**4. Become the default substrate for agentic infrastructure consumption.**
|
- **Lead Time** — from PR merge to production deployment (downward trend).
|
||||||
AI agents are already becoming the largest consumers of cloud
|
- **Infrastructure Vulnerability Count** — open findings on deployed
|
||||||
infrastructure. Nova must be the platform through which those agents
|
resources (downward trend, demonstrating that proactive scanning +
|
||||||
declare, deploy, and verify infrastructure — not a vendor scrambling into
|
remediation keeps up with the AI-era 0-day pace).
|
||||||
that market two quarters late.
|
- **MTTR** — for platform-detected and platform-remediated incidents.
|
||||||
|
- **Cloud Spend Reduction** — on pilot estates vs. the pre-Nova
|
||||||
|
baseline.
|
||||||
|
|
||||||
|
If leadership cannot point to a number that improves quarter-over-quarter
|
||||||
|
on these four axes, Nova fails its commercial test, regardless of how
|
||||||
|
clever the automation is.
|
||||||
|
|
||||||
|
**4. Integrate with externally owned development platforms — regardless of source.**
|
||||||
|
Nova integrates with externally owned PDLC, SDLC, Agentic, and Citizen
|
||||||
|
Developer platforms with no regard for the source of the intent. Nova
|
||||||
|
provides a set of skills and MCP endpoints that help the developer or AI
|
||||||
|
agent make their application production-grade. Regardless of the source,
|
||||||
|
all intents to deploy to production go through the same rigorous
|
||||||
|
controls, quality gates, attestation, and evidence stream. Nova is the
|
||||||
|
layer any of those platforms reach for first when an agent needs to
|
||||||
|
deploy — not a vendor arriving late to that market.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Anti-Goals (5 — what Nova is fundamentally NOT)
|
## Anti-Goals (4 — what Nova is fundamentally NOT)
|
||||||
|
|
||||||
1. **Not a Terraform, Kubernetes, or hyperscaler competitor.** We
|
1. **Not a general-purpose AI agent platform.** We are purpose-built for
|
||||||
orchestrate them. Replacing them is the most expensive possible
|
|
||||||
distraction from the value we create.
|
|
||||||
2. **Not a general-purpose AI agent platform.** We are purpose-built for
|
|
||||||
infrastructure operations. Breadth here produces shallow tools; depth
|
infrastructure operations. Breadth here produces shallow tools; depth
|
||||||
here wins the category.
|
here wins the category.
|
||||||
3. **Not a system that removes humans from accountability.** Only from
|
2. **Not a system that removes humans from accountability.** Only from
|
||||||
operations. Every AI decision lands in an immutable ledger. Every
|
normal operations. Every automated decision lands in an immutable
|
||||||
stage-gate promotion (qa/prod/dr) requires a human attestation recorded
|
ledger. Every stage-gate promotion (qa/prod/dr) requires a human
|
||||||
with approver identity, separation-of-duties check, and the 8-concern
|
attestation recorded with approver identity, separation-of-duties
|
||||||
evidence matrix. The absence of an operator is never the absence of a
|
check, and the evidence matrix. The absence of an operator in the
|
||||||
record.
|
loop is never the absence of a record.
|
||||||
4. **Not for legacy, untagged, or freeform infrastructure.** Nova requires
|
3. **Not an upstream development platform.** Nova does not own the
|
||||||
Terraform-managed, policy-aligned, fully-tagged inputs. We optimize for
|
product backlog, IDE workflows, code authorship, or application
|
||||||
the disciplined 95%, not the chaotic 5%.
|
business logic. The PDLC is upstream; Nova integrates with it through
|
||||||
5. **Not sold to operators.** Nova is sold to leadership on outcomes —
|
a validated contract boundary — Nova never penetrates it.
|
||||||
cost, velocity, risk. Selling to operators inverts the incentive and
|
4. **Not a replacement for the Product Development Lifecycle (PDLC).**
|
||||||
breaks the autonomy thesis.
|
Nova governs infrastructure + delivery only. Product lifecycle
|
||||||
|
decisions (what to build, when to ship, for whom) remain with the
|
||||||
|
product team. Nova makes their intent production-grade; it does not
|
||||||
|
own the intent.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+198
-351
@@ -1,385 +1,232 @@
|
|||||||
---
|
---
|
||||||
project: acdl
|
project: acdl
|
||||||
milestone: v1.17
|
milestone: v1.22
|
||||||
generated_at: 2026-08-04
|
generated_at: 2026-08-11
|
||||||
generator: lead-developer
|
generator: lead-developer
|
||||||
verification_toolchain:
|
verification_toolchain:
|
||||||
typecheck: "terraform validate && python3 -m py_compile core/**/*.py && python3 -m jsonschema schemas/*.schema.json"
|
typecheck: "python3 -m py_compile tests/test_slides_pipeline.py"
|
||||||
test: "bash scripts/run_regression.sh # 22-capability gate (D-091/D-118) + CAP-023/024 (v1.17)"
|
test: "pytest tests/test_slides_pipeline.py # REQ-254..262"
|
||||||
build: "bash scripts/run_ci.sh # full local CI reproduction (lint+test+check-only)"
|
build: "bash scripts/render_slides.sh nova-autonomous-cloud-delivery # HTML + PPTX"
|
||||||
note: |
|
note: |
|
||||||
v1.17 adds a telemetry/observability layer (metrics emitters, SQLite
|
v1.22 is the Nova Deck Layout Fix — a docs-only NFR milestone. Two
|
||||||
cold store, PowerBI export, Decision Ledger) + a unified narrative
|
active personas: lead-developer (theme CSS + deck markdown + talking
|
||||||
deck + a durable NORTH_STAR.md. Three active personas: lead-developer
|
points + README + .ciagent metadata), backend-engineer (render scripts
|
||||||
(coordination + deck narrative co-author), backend-engineer (event
|
+ tests). frontend-engineer stays deactivated (decks are markdown =
|
||||||
emitters, outbox_writer extension, Infracost adapter), data-engineer
|
lead-developer territory, per v1.17/v1.18 precedent). No data-engineer
|
||||||
(SQLite store, schemas, PowerBI views, metrics collector). frontend-
|
(no schema/DB changes). No new personas (the work is CSS + bash +
|
||||||
engineer stays deactivated (no Nova web UI — dashboards are PowerBI,
|
markdown + pytest, all within the two active personas' range).
|
||||||
not a Nova-built frontend; decks are markdown = lead-developer
|
|
||||||
territory). No new custom personas needed — the metrics domain maps
|
|
||||||
cleanly to data-engineer (schema/store/export) + backend-engineer
|
|
||||||
(emitters/instrumentation).
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# ACDL — Persona Roster (project-level, v1.11 RESTART)
|
# ACDL — Persona Roster (v1.22 Nova Deck Layout Fix)
|
||||||
|
|
||||||
> v1.11 is a restart (D-097). The v1.9 roster is superseded. Three
|
> v1.22 roster. Two active personas + one deactivated. This is a docs-
|
||||||
> structural corrections: (1) stateless adapter (D-098), (2) terraform
|
> only NFR milestone: the work is theme CSS, render scripts, mermaid
|
||||||
> owns lifecycle (D-101), (3) pipeline-driven testing (D-102). The roster
|
> diagrams, deck markdown, and tests. frontend-engineer stays
|
||||||
> is simplified to the three active domains: data (terraform foundation),
|
> deactivated (decks are markdown = lead-developer territory, per
|
||||||
> backend (adapter/resolver), general (pipelines/workflows).
|
> v1.17/v1.18 precedent). No data-engineer (no schema/DB changes).
|
||||||
|
|
||||||
## Active personas
|
## Active personas
|
||||||
|
|
||||||
|
### lead-developer
|
||||||
|
- **Domain:** coordination + deck content
|
||||||
|
- **Active:** true
|
||||||
|
- **Phase-specific:** false
|
||||||
|
- **Frameworks:** [] (no framework — owns process + narrative + CSS + markdown)
|
||||||
|
- **Constraints:** ["pragmatic", "battle-tested defaults", "no fabrication (NORTH_STAR honesty model)", "do not change the 4-beat arc", "do not re-introduce badges/version/internal citations"]
|
||||||
|
- **Territory:**
|
||||||
|
- `docs/presentations/assets/nova-sp-theme.css` (REQ-254,255,256 — theme CSS)
|
||||||
|
- `docs/presentations/nova-autonomous-cloud-delivery-marp.md` (REQ-261 — deck content)
|
||||||
|
- `docs/presentations/nova-autonomous-cloud-delivery.md` (REQ-261 — source of truth)
|
||||||
|
- `docs/presentations/nova-autonomous-cloud-delivery-talking-points.md` (REQ-261)
|
||||||
|
- `docs/presentations/README.md` (REQ-261 — slide-count convention)
|
||||||
|
- `docs/presentations/assets/mmd/*.mmd` (REQ-259,260 — mermaid re-layout)
|
||||||
|
- `.ciagent/**` (PROJECT, ROADMAP, REQUIREMENTS, RESEARCH, PLAN, GRILL, PERSONAS, REVIEW, CHECKPOINT)
|
||||||
|
- **Reason:** Owns the theme CSS (the root cause), the deck markdown
|
||||||
|
(trim/split overflowing slides), the mermaid re-layout, the talking
|
||||||
|
points, the README, and all CIAgent metadata. Is the only persona
|
||||||
|
that touches `.ciagent/**` and the deck markdown/CSS.
|
||||||
|
- **Phase-specific flag:** none (active for all of P0–P6).
|
||||||
|
|
||||||
|
### backend-engineer
|
||||||
|
- **Domain:** render scripts + tests
|
||||||
|
- **Active:** true
|
||||||
|
- **Phase-specific:** false
|
||||||
|
- **Frameworks:** ["bash", "pytest", "marp-cli", "mermaid-cli"]
|
||||||
|
- **Constraints:** ["pin CLI versions (no @latest)", "2x scale + transparent bg for mermaid", "tests must catch layout regressions", "no raw curl with shell-env tokens"]
|
||||||
|
- **Territory:**
|
||||||
|
- `scripts/render_slides.sh` (REQ-257,258 — pin versions, 2x scale)
|
||||||
|
- `scripts/render_deck.sh` (REQ-257 — DELETE)
|
||||||
|
- `tests/test_slides_pipeline.py` (REQ-262 — layout/aspect-ratio/theme-structural tests)
|
||||||
|
- `.github/workflows/slides.yml` (if references to render_deck.sh need removal)
|
||||||
|
- **Reason:** Owns the render pipeline (bash scripts) and the test
|
||||||
|
suite. The layout/aspect-ratio/theme-structural tests (REQ-262) are
|
||||||
|
the gap that let this regression through — backend-engineer owns
|
||||||
|
closing that gap. Pinning CLI versions and adding 2x scale are
|
||||||
|
backend/scripting tasks.
|
||||||
|
- **Phase-specific flag:** none (active for P2, P5; light touch on P0/P6).
|
||||||
|
|
||||||
|
## Deactivated personas
|
||||||
|
|
||||||
|
### frontend-engineer
|
||||||
|
- **Active:** false
|
||||||
|
- **Domain:** frontend
|
||||||
|
- **Frameworks:** ["react", "next.js"] (inert — no territory)
|
||||||
|
- **Constraints:** ["component-first", "server-components", "minimal-client-js"] (inert)
|
||||||
|
- **Territory:** [] (no territory in v1.22)
|
||||||
|
- **Reason:** v1.22 has no frontend; decks are markdown (lead-developer
|
||||||
|
territory); deactivated per PERSONAS.md v1.17/v1.18 precedent. The
|
||||||
|
theme CSS is a Marp stylesheet, not a React/Next.js component system
|
||||||
|
— it stays lead-developer territory. No reactivation trigger.
|
||||||
|
|
||||||
|
### data-engineer
|
||||||
|
- **Active:** false
|
||||||
|
- **Domain:** data
|
||||||
|
- **Frameworks:** [] (inert)
|
||||||
|
- **Constraints:** [] (inert)
|
||||||
|
- **Territory:** [] (no territory in v1.22)
|
||||||
|
- **Reason:** v1.22 has no schema/DB/ORM changes. The milestone is
|
||||||
|
docs + scripts + tests only. No reactivation trigger.
|
||||||
|
|
||||||
|
## Roster decisions
|
||||||
|
|
||||||
|
### D-148 (0.95): Theme CSS is lead-developer territory, not frontend-engineer
|
||||||
|
The `nova-sp-theme.css` is a Marp stylesheet (CSS for a markdown-to-
|
||||||
|
slide renderer), not a React/Next.js component system. The v1.17/v1.18
|
||||||
|
precedent (decks are markdown = lead-developer territory) extends to
|
||||||
|
the deck's CSS theme. frontend-engineer's frameworks (react, next.js)
|
||||||
|
are irrelevant to Marp CSS. **Decision:** theme CSS stays lead-developer
|
||||||
|
territory. Confidence 0.95 — the only counter-argument is that CSS is
|
||||||
|
"frontend," but Marp CSS is a static stylesheet, not a component system.
|
||||||
|
|
||||||
|
### D-149 (0.9): No new personas for v1.22
|
||||||
|
The work is CSS + bash + markdown + mermaid + pytest. All of this is
|
||||||
|
within the two active personas' range (lead-developer: CSS + markdown +
|
||||||
|
mermaid; backend-engineer: bash + pytest). Creating a separate "css-
|
||||||
|
engineer" or "slides-engineer" persona would fragment ownership of the
|
||||||
|
theme CSS + deck markdown (both lead-developer) and the render scripts
|
||||||
|
+ tests (both backend-engineer). **Decision:** no new personas.
|
||||||
|
Confidence 0.9.
|
||||||
|
|
||||||
|
### Territory-overlap resolution (co-ownership)
|
||||||
|
|
||||||
|
| Path | Primary | Co-owner | Why |
|
||||||
|
|------|---------|----------|-----|
|
||||||
|
| `docs/presentations/assets/mmd/*.mmd` | lead-developer (mermaid re-layout) | backend-engineer (re-render via render_slides.sh) | The .mmd content is lead-developer (diagram narrative); the PNG re-render is backend-engineer (script invocation). |
|
||||||
|
| `tests/test_slides_pipeline.py` | backend-engineer (test code) | lead-developer (assertions reflect deck structure) | The test code is backend; the assertions (slide count, theme rules, aspect ratios) reflect lead-developer's deck/theme decisions. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Historical rosters
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>v1.18 roster (Citizen Developer & Production-Grade Guidance) — superseded by v1.22</summary>
|
||||||
|
|
||||||
|
### Active personas (v1.18)
|
||||||
|
|
||||||
### lead-developer
|
### lead-developer
|
||||||
- **Domain:** coordination
|
- **Domain:** coordination
|
||||||
- **Active:** true
|
- **Active:** true
|
||||||
- **Phase-specific:** false
|
- **Phase-specific:** false
|
||||||
- **Reason:** Owns CIAgent metadata, cross-phase verification scripts, the v1.11 phase orchestration (D-107: P56a + P56b split), and arbitrates persona conflicts. Resolves the milestone decomposition and the STANDARDS.md §8 rewrite (the adapter extension pattern is replaced by the per-module terraform subdir pattern).
|
- **Frameworks:** [] (no framework — owns process + narrative, not code)
|
||||||
|
- **Constraints:** ["pragmatic", "battle-tested defaults", "no fabrication (NORTH_STAR honesty model)"]
|
||||||
|
- **Territory:**
|
||||||
|
- `docs/presentations/**` (Step 1/2/4 markdown + the deck automation trigger)
|
||||||
|
- `.ciagent/**` (PROJECT, ROADMAP, REQUIREMENTS, RESEARCH, PLAN, GRILL, PERSONAS, REVIEW, CHECKPOINT)
|
||||||
|
- `PROJECT.md` (RACI matrix + PDLC-scope statement, REQ-215/216)
|
||||||
|
- `ROADMAP.md`
|
||||||
|
- `REQUIREMENTS.md`
|
||||||
|
- `docs/raci.md` (REQ-215)
|
||||||
|
- `docs/scope.md` (REQ-216)
|
||||||
|
- `docs/skills.md` (REQ-222 — the index page, not the skill files themselves)
|
||||||
|
- `docs/submission-readiness.md` (REQ-219 — citizen-developer-facing copy; co-owned with backend-engineer for the reason-code catalog)
|
||||||
|
- **Reason:** Owns CIAgent metadata, the milestone narrative, the RACI +
|
||||||
|
PDLC-scope statements (REQ-215/216), the deck (21 slides, S&P theme
|
||||||
|
regression check vs P1, CAP-024), the skills index page (REQ-222), and
|
||||||
|
the citizen-developer-facing submission-readiness doc (REQ-219). Is
|
||||||
|
the only persona that touches `.ciagent/**` and the deck markdown.
|
||||||
|
- **Phase-specific flag:** none (active for all of P0–P7).
|
||||||
|
|
||||||
### backend-engineer
|
### backend-engineer
|
||||||
- **Domain:** backend
|
- **Domain:** backend
|
||||||
- **Active:** true
|
- **Active:** true
|
||||||
- **Phase-specific:** false
|
- **Phase-specific:** false
|
||||||
- **Reason:** Owns the adapter rewrite (D-098: stateless assembler — deletes TYPE_MAP/INPUT_MAP/OUTPUT_MAP + 39 type-specific branches, becomes a ~80-line assembler that emits `module "x" { source = "..." ... }` blocks) and the contract resolver env-aware state keys (D-106: `spike/{id}/{env}/terraform.tfstate`). The adapter holds no module content; the engine binding lives in the per-module `terraform/` subdir. Co-authoring expected on the adapter + `run_platform.sh` boundary (general adds `--apply`/`--destroy` modes that invoke the adapter).
|
- **Frameworks:** ["mcp (Python SDK v2)", "pydantic", "jsonschema", "urllib"]
|
||||||
- **Territory:** `adapters/terraform/adapter.py` (rewrite to stateless assembler), `core/contract_resolver.py` (env-aware state keys, deterministic composition), `schemas/stack.schema.json` (if the stack instance shape changes), `tests/test_adapter*.py` (regression baseline — the s3 instance.json round-trip must still pass).
|
- **Constraints:** ["api-first", "strict-typing", "plugin-registry extensible (D-140)", "stdio now / HTTP-ready (D-135)", "no stack traces to citizen developers (REQ-218)"]
|
||||||
|
- **Territory:**
|
||||||
|
- `mcp/atelier/server.py` (REQ-223)
|
||||||
|
- `mcp/atelier/plugins/**/*.py` (REQ-223 — principles.py, validation.py)
|
||||||
|
- `mcp/atelier/vendor/**` (REQ-224 — vendored Atelier snapshot)
|
||||||
|
- `mcp/atelier/VERSION.md` + `mcp/atelier/README.md` (REQ-224)
|
||||||
|
- `scripts/update_atelier_vendor.sh` (REQ-224)
|
||||||
|
- `core/submission_readiness.py` (REQ-218 — the validator, invoked as `contract_ingestor.py --check-readiness`)
|
||||||
|
- `scripts/render_deck.sh` (REQ-228 — HTML + PPTX render)
|
||||||
|
- `scripts/attach_release_asset.py` (REQ-228 — Gitea release asset upload)
|
||||||
|
- `tests/test_atelier_mcp.py` (REQ-225)
|
||||||
|
- `tests/test_submission_readiness.py` (REQ-220)
|
||||||
|
- `docs/submission-readiness.md` (REQ-219 — reason-code catalog section; co-owned with lead-developer for the narrative)
|
||||||
|
- **Reason:** Owns the MCP server (plugin-registry, stdio, vendored
|
||||||
|
Atelier), the submission-readiness validator (extends
|
||||||
|
`contract_ingestor.py --check-readiness`, D-133), the render/attach
|
||||||
|
scripts (D-142 trigger), and the two new test files. The MCP
|
||||||
|
plugin-registry (D-140) is a backend pattern — no separate
|
||||||
|
mcp-engineer persona is created; backend-engineer owns it.
|
||||||
|
- **Phase-specific flag:** none (active for P1 deck-render, P3 validator,
|
||||||
|
P5 MCP server, P6 scripts).
|
||||||
|
|
||||||
### data-engineer
|
### data-engineer
|
||||||
- **Domain:** data
|
- **Domain:** data
|
||||||
- **Active:** true
|
- **Active:** true
|
||||||
- **Phase-specific:** false
|
- **Phase-specific:** false
|
||||||
- **Reason:** Reactivated for v1.11. Owns the heaviest territory: the per-module `terraform/` subdirs (D-098/D-099/D-100 — the engine binding) for all 12 L1 modules, plus the single platform VPC (D-105: `terraform/platform` owns ONE VPC; the microservice composition drops its `vpc` child and references the platform VPC via data source). Each L1 module ships a real terraform module dir (versions/variables/locals/main/outputs.tf) owning its resource shape, nested blocks, and defaults. `locals.tf` is used heavily to centralize default interpolation (D-099). Multi-resource modules get the full 5-file split; trivial single-resource modules may inline locals in main.tf. This is the binding constraint — the stateless adapter cannot be written until the reference s3 module exists (D-107: P56a proves the design with s3 first).
|
- **Frameworks:** ["jsonschema", "dynamodb (item shape)"]
|
||||||
- **Territory:** `terraform/` (platform VPC, D-105), `modules/l1/*/terraform/` (per-module terraform subdirs — the engine binding), `modules/l1/*/interface.json` (defaults move from adapter to interface inputs), `modules/registry.json` (terraform_dir field), `modules/l2/microservice/composition.json` (drop the vpc child, D-105), `modules/STANDARDS.md` §8 (rewrite the adapter extension pattern → per-module terraform subdir pattern).
|
- **Constraints:** ["schema-first", "superset-gate NOT duplicate (PROJECT.md hard constraint)", "W3.E per-env mandatory table is the source of truth"]
|
||||||
|
- **Territory:**
|
||||||
|
- `schemas/**` (REQ-217 — `submission-readiness.schema.json` is the new schema; existing schemas untouched)
|
||||||
|
- `core/lambda/contract_ingestor.py` (the `--check-readiness` subcommand wiring, D-133 — the validator is in `core/submission_readiness.py` but the ingestor dispatches to it; co-owned with backend-engineer)
|
||||||
|
- **Reason:** Owns the submission-readiness JSON Schema (REQ-217) — it
|
||||||
|
is a schema artifact, data-engineer territory. The schema is a
|
||||||
|
*superset gate above* `contract.schema.json`, not a duplicate (it
|
||||||
|
references contract fields, does not redefine them). The
|
||||||
|
per-env-mandatory table comes from W3.E (the locked decision). The
|
||||||
|
ingestor wiring is co-owned with backend-engineer (the dispatch point
|
||||||
|
is backend; the schema it validates against is data).
|
||||||
|
- **Phase-specific flag:** none (active for P3 schema + ingestor wiring).
|
||||||
|
|
||||||
### general (lead-developer + backend-engineer pipeline work)
|
### Deactivated personas (v1.18)
|
||||||
- **Domain:** coordination + pipelines
|
|
||||||
- **Active:** true
|
|
||||||
- **Phase-specific:** false
|
|
||||||
- **Reason:** Owns the pipeline-driven testing (D-102/D-103/D-104) and the terraform lifecycle modes (D-101). The modules-lifecycle pipeline (Gitea + GitHub, byte-identical) matrix-runs each L1 module's `examples/{simple,complex}.yml` contracts through apply→modify→destroy against live AWS. `run_platform.sh` gains `--apply` and `--destroy` modes; Python never runs terraform. `verify_deploy_microservice.py` is deleted (D-101). Co-authoring expected on the `run_platform.sh` boundary (backend-engineer rewrites the adapter that `run_platform.sh` invokes).
|
|
||||||
- **Territory:** `pipelines/modules-lifecycle.yml`, `.gitea/workflows/modules-lifecycle.yml` + `.github/workflows/modules-lifecycle.yml` (byte-identical, D-102), `scripts/run_platform.sh` (`--apply`/`--destroy` modes, D-101), `scripts/run_primitive_plan.sh` (if extended for lifecycle), `scripts/run_pattern_plan.sh` (if extended), `pipelines/README.md` (document the new pipeline), `schemas/deploy-pipeline.schema.json` (if the lifecycle stages are added to the contract).
|
|
||||||
|
|
||||||
## Deactivated personas
|
|
||||||
|
|
||||||
### lambda-engineer (custom, v1.9 — deactivated for v1.11)
|
|
||||||
- **Domain:** serverless
|
|
||||||
- **Active:** false
|
|
||||||
- **Phase-specific:** false
|
|
||||||
- **Reason:** No per-module Python this milestone (D-102: testing is pipeline-driven, not pytest). The v1.9 Lambda (`core/lambda/contract_ingestor.py`) and the `terraform/platform/main.tf` Lambda/DynamoDB/KMS/Secrets definitions persist from v1.9 but are not touched in v1.11. The `acdl-sod-halt` SNS topic and the attestation matrix are out of scope. Removed from the roster for v1.11; reactivates if a future milestone touches the Lambda.
|
|
||||||
|
|
||||||
### platform-engineer (custom, v1.9 — folded into data-engineer for v1.11)
|
|
||||||
- **Domain:** infra
|
|
||||||
- **Active:** false
|
|
||||||
- **Phase-specific:** false
|
|
||||||
- **Reason:** The v1.11 scope (D-097..D-107) is terraform module authoring + adapter rewrite + pipelines — not the v1.9-era L1/L2 IR-typed module authoring or the AWS OIDC bootstrap. The platform-engineer's v1.9 territory (`adapters/terraform/**`, `modules/**`, `terraform/**`) is split: the adapter goes to backend-engineer (rewrite), the per-module terraform subdirs + platform VPC go to data-engineer (the heaviest v1.11 work). Folded into data-engineer for v1.11; reactivates if a future milestone does IR-shaped module authoring or OIDC bootstrap work.
|
|
||||||
|
|
||||||
### security-engineer (custom, v1.9 — deactivated for v1.11)
|
|
||||||
- **Domain:** security
|
|
||||||
- **Active:** false
|
|
||||||
- **Phase-specific:** false
|
|
||||||
- **Reason:** The v1.11 scope does not touch Wiz/Kyverno/Checkov adapters, the HITL matrix, separation-of-duties, or the audit ledger. The security-engineer's v1.9 territory persists but is not touched. Removed from the roster for v1.11; reactivates if a future milestone touches security adapters or HITL gates.
|
|
||||||
|
|
||||||
### frontend-engineer
|
### frontend-engineer
|
||||||
|
- **Active:** false
|
||||||
- **Domain:** frontend
|
- **Domain:** frontend
|
||||||
- **Active:** false
|
- **Frameworks:** ["react", "next.js"] (inert — no territory)
|
||||||
- **Phase-specific:** false
|
- **Constraints:** ["component-first", "server-components", "minimal-client-js"] (inert)
|
||||||
- **Reason:** The evidence timeline UI (`evidence-ui/**`) is unchanged from v1.0 and not touched in v1.11. Removed from the active roster; reactivates if a future milestone touches the timeline UI.
|
- **Territory:** [] (no territory in v1.18)
|
||||||
|
- **Reason:** v1.18 has no frontend; decks are markdown (lead-developer
|
||||||
|
territory); deactivated per PERSONAS.md v1.17 precedent. v1.18's
|
||||||
|
observability stays PowerBI / external (Out of Scope: "A Nova-built
|
||||||
|
frontend / dashboard"). The MCP server exposes tools to an AI agent,
|
||||||
|
not a web UI. No reactivation trigger in this milestone.
|
||||||
|
|
||||||
### data-engineer (v1.9 — was deactivated, reactivated for v1.11)
|
### Roster decisions (v1.18)
|
||||||
- **Domain:** data
|
|
||||||
- **Active:** true (reactivated)
|
|
||||||
- **Phase-specific:** false
|
|
||||||
- **Reason:** See the active `data-engineer` entry above. The v1.9 deactivation rationale ("No ORM/persistence framework") no longer applies — v1.11's data-engineer owns terraform module authoring, not a data persistence layer.
|
|
||||||
|
|
||||||
### infra-stub-engineer (custom, v1.0 only)
|
### D-143 (0.90): Fold mcp-engineer into backend-engineer
|
||||||
- **Domain:** backend
|
The MCP plugin-registry (D-140: `plugins/<name>.py register(mcp)`) is a
|
||||||
- **Active:** false
|
backend code pattern — Python modules, type hints, stdio transport,
|
||||||
- **Reason:** Owned L1 stub modules in the v1.0 demo. The demo is archived to `demo/`; real L1 modules are owned by data-engineer (v1.11). Not reactivated.
|
urllib for the Gitea asset API. It shares nothing with the data domain
|
||||||
|
(schemas/DynamoDB) and is not a new engineering discipline. Creating a
|
||||||
|
separate `mcp-engineer` persona would fragment ownership of the server +
|
||||||
|
its tests + the render/attach scripts (all backend). **Decision:** fold
|
||||||
|
into backend-engineer. backend-engineer's `frameworks` list gains
|
||||||
|
`mcp (Python SDK v2)`. Confidence 0.90 — the only counter-argument is
|
||||||
|
that MCP is a distinct protocol skill, but the SDK v2 API surface
|
||||||
|
(`@mcp.tool()` + type hints) is small and well within backend-engineer's
|
||||||
|
range (it's the same Pydantic/FastAPI-style pattern the persona already
|
||||||
|
knows).
|
||||||
|
|
||||||
## Phase-specific overrides
|
### Territory-overlap resolution (v1.18)
|
||||||
|
|
||||||
| Phase | Personas active | Notes |
|
| Path | Primary | Co-owner | Why |
|
||||||
|-------|------------------|-------|
|
|------|---------|----------|-----|
|
||||||
| 56a adapter-rewrite-and-s3-reference-module | data-engineer (lead: s3 reference terraform module — proves the design), backend-engineer (lead: stateless adapter rewrite — emits module blocks for s3), general (run_platform.sh --apply/--destroy skeleton) | security/lambda/frontend idle |
|
| `docs/submission-readiness.md` | lead-developer (narrative + examples) | backend-engineer (reason-code catalog, REQ-218 codes) | The doc is citizen-developer-facing copy (lead) but the reason-code catalog (MISSING_TAGS, ENV_MISSING_MANDATORY, AGENTIC_MISSING_INTENT, MISSING_APP_SOURCE, POLICY_PRECONDITION_MISSING) is backend (it mirrors the validator's return codes). |
|
||||||
| 56b remaining-11-l1-module-terraform-subdirs | data-engineer (lead: author 11 L1 module terraform subdirs — vpc, ecs-cluster, ecs-service, iam-role, alb, ecr, cloudfront, waf, rds, kms-key, uptime), backend-engineer (adapter: confirm each module round-trips through the assembler), general (modules-lifecycle pipeline wiring) | security/lambda/frontend idle |
|
| `core/lambda/contract_ingestor.py` | backend-engineer (dispatch wiring) | data-engineer (the schema it validates against) | D-133 places the `--check-readiness` subcommand on the ingestor (backend dispatch), but the readiness schema it loads is data-engineer territory. |
|
||||||
| (modules-lifecycle pipeline) | general (lead: byte-identical Gitea+GitHub workflow + matrix apply→modify→destroy), data-engineer (examples/{simple,complex}.yml contracts as the modify variants), backend-engineer (adapter confirms the lifecycle cells resolve) | security/lambda/frontend idle |
|
| `schemas/submission-readiness.schema.json` | data-engineer (schema artifact) | backend-engineer (the validator must match it) | The schema is data-engineer's; the validator (REQ-218) is backend-engineer's and must stay in sync with it. |
|
||||||
| (platform VPC + composition drop) | data-engineer (lead: terraform/platform VPC + microservice composition drops vpc child, D-105), backend-engineer (resolver: env-aware state keys, D-106) | general/security/lambda/frontend idle |
|
|
||||||
| verify | lead-developer (lead: 4-layer verification), all active personas (review their territory) | — |
|
|
||||||
| review-audit-complete | lead-developer (lead: review + audit + milestone completion), all active personas (review participation) | — |
|
|
||||||
|
|
||||||
## Domain priority (used by TaskDecomposer)
|
</details>
|
||||||
|
|
||||||
`data → backend → general`
|
|
||||||
|
|
||||||
Rationale: in v1.11, the terraform foundation (per-module `terraform/`
|
|
||||||
subdirs + platform VPC) is the binding constraint — the stateless adapter
|
|
||||||
cannot be written until the reference s3 module exists (D-107: P56a
|
|
||||||
proves the design with s3 first). Backend (adapter/resolver) follows once
|
|
||||||
the module shape is proven. General (pipelines/workflows) wires the
|
|
||||||
lifecycle modes last, once the adapter + modules produce valid terraform.
|
|
||||||
|
|
||||||
## Conflict resolutions (lead-developer arbitration)
|
|
||||||
|
|
||||||
- `backend-engineer` vs `data-engineer` over `modules/l1/*/interface.json`:
|
|
||||||
data-engineer owns the interface defaults (defaults move from the
|
|
||||||
adapter to the interface inputs, D-100); backend-engineer owns the
|
|
||||||
adapter that reads them. Co-authoring is expected; conflict goes to
|
|
||||||
lead-developer.
|
|
||||||
- `backend-engineer` vs `general` over `scripts/run_platform.sh`:
|
|
||||||
backend-engineer rewrites the adapter that `run_platform.sh` invokes;
|
|
||||||
general adds the `--apply`/`--destroy` modes. The interface (the CLI
|
|
||||||
flags + the adapter invocation) is co-authored; conflicts go to
|
|
||||||
lead-developer.
|
|
||||||
- `data-engineer` vs `general` over `modules/l1/*/examples/`:
|
|
||||||
data-engineer owns the example contracts (the modify variants,
|
|
||||||
D-103); general owns the pipeline that matrix-runs them. Co-authoring
|
|
||||||
is expected; conflicts go to lead-developer.
|
|
||||||
- `lead-developer` vs any: lead-developer owns `.ciagent/**` + `docs/**`
|
|
||||||
meta + verification scripts + `modules/STANDARDS.md` §8 rewrite; persona
|
|
||||||
engineers do not edit CIAgent metadata or the vision/architecture
|
|
||||||
source docs.
|
|
||||||
|
|
||||||
## Territory enforcement mode
|
|
||||||
|
|
||||||
`warn` — config.json has no `personas.territory_enforcement` field, so the
|
|
||||||
default per execute.md is `warn`. Cross-territory edits are logged in the
|
|
||||||
commit message but do not fail the task. v1.11's scope means co-authoring
|
|
||||||
across territories is likely (e.g. backend + general on the adapter +
|
|
||||||
`run_platform.sh` boundary; data + general on the examples + pipeline
|
|
||||||
boundary); `warn` keeps it frictionless.
|
|
||||||
---
|
|
||||||
|
|
||||||
## v1.15 Persona Addendum — Nova Rebrand (2026-07-30)
|
|
||||||
|
|
||||||
**Milestone:** v1.15-Nova. The roster carries forward from v1.11/v1.14
|
|
||||||
unchanged — the rebrand touches existing territories, no new domains.
|
|
||||||
**frontend-engineer** remains deactivated (no UI; decks are markdown =
|
|
||||||
lead-developer territory). No **security-engineer** persona is activated
|
|
||||||
— the ABAC session-policy + tag-key migration (REQ-162) is data-engineer
|
|
||||||
territory (terraform IAM) with lead-developer review.
|
|
||||||
|
|
||||||
### v1.15 territory assignments
|
|
||||||
|
|
||||||
| Phase | Lead | Contributors | Territory |
|
|
||||||
|-------|------|---------------|-----------|
|
|
||||||
| P1 docs-decks-prose | lead-developer | — | `README.md`, `docs/**`, `.ciagent/*.md`, deck `.md`/`-marp.md`/`-talking-points.md`/`.html`, `docs/presentations/assets/mmd/*.mmd` (+ PNG re-export), `pyproject.toml`, `schemas/*.schema.json` `$id` (D-110), `docs/NOVA_MIGRATION.md`, `.github/workflows/release.yml` title, `modules/STANDARDS.md` |
|
|
||||||
| P2 code-envvars-consumer-path | backend-engineer | lead-developer (docs/runbook) | `core/env.py` (NEW dual-read helper, D-108), `core/*.py` (call-site migration), `scripts/*.py` + `*.sh`, `adapters/**`, `tests/**`, `.gitea/workflows/**` + `.github/workflows/**`, `.env` + `.env.secrets` (key rename), `schemas/tagging-standard.json`, `adapters/terraform/policy/custom_rules/acdl_tagging.py` → `nova_tagging.py` (D-109: warn mode) |
|
|
||||||
| P3 ssm-tagkeys | data-engineer | backend-engineer (readers) | `core/output_publisher.py` (SSM path `/nova/`), `core/contract_resolver.py` (SSM reads), `scripts/migrate_ssm_paths.py` (NEW), `terraform/**` (tag keys `nova:*`), `adapters/terraform/policy/custom_rules/nova_tagging.py` (D-109: hard mode), ABAC session-policy terraform |
|
|
||||||
| P4 aws-resource-migration | data-engineer | lead-developer (runbook) | `terraform/platform/main.tf`, `terraform/microservice/main.tf`, `terraform/ci-vpc/main.tf`, `terraform/bootstrap/**`, `modules/l1/alb/instance.json`, `scripts/migrate_dynamodb_data.py` (NEW), `docs/NOVA_AWS_MIGRATION.md` (NEW runbook), `core/lambda/contract_ingestor.py` (default table names → `nova-*`, D-111) |
|
|
||||||
| P5 final-review-ship | lead-developer | all active (review) | `.ciagent/**` (REQUIREMENTS/ROADMAP/PROJECT complete), `core/env.py` (remove dual-read fallback), `nova_tagging.py` (hard-fail `acdl:*`), review + audit |
|
|
||||||
|
|
||||||
### v1.15 domain priority
|
|
||||||
|
|
||||||
`lead → backend → data` (inverted from v1.11)
|
|
||||||
|
|
||||||
Rationale: the rebrand is docs/prose-first (P1 establishes the
|
|
||||||
vocabulary, no runtime impact), then code/env-vars/consumer-path (P2),
|
|
||||||
then SSM/tag-keys (P3), then the heavy terraform/AWS migration (P4).
|
|
||||||
Lead-developer owns the docs + runbooks + verification + final ship;
|
|
||||||
backend-engineer owns the dual-read helper + call-site migration +
|
|
||||||
contract resolver; data-engineer owns the terraform resource/tag/SSM
|
|
||||||
migration (the heaviest terraform territory). Co-authoring expected at:
|
|
||||||
`core/env.py` + `core/*.py` boundary (backend + lead on the helper
|
|
||||||
design), `nova_tagging.py` + `schemas/tagging-standard.json` boundary
|
|
||||||
(backend authors the rule, data-engineer owns the tag-key schema),
|
|
||||||
`core/output_publisher.py` SSM path + `terraform` outputs boundary
|
|
||||||
(backend writes the reader, data-engineer owns the terraform that
|
|
||||||
produces the outputs).
|
|
||||||
|
|
||||||
### v1.15 verification toolchain (unchanged from v1.14)
|
|
||||||
|
|
||||||
```
|
|
||||||
typecheck: terraform validate && python3 -m py_compile core/**/*.py adapters/**/*.py
|
|
||||||
test: bash scripts/run_regression.sh # 16-capability gate
|
|
||||||
build: bash scripts/run_ci.sh # full local CI reproduction
|
|
||||||
```
|
|
||||||
|
|
||||||
The regression gate (CAP-001..CAP-016) must stay **16/16 Verified**
|
|
||||||
throughout the rebrand — the rebrand must not regress any capability.
|
|
||||||
P2/P3/P4 update test fixtures that reference `ACDL`/`acdl` so the gate
|
|
||||||
stays green.
|
|
||||||
|
|
||||||
## v1.16 Persona Addendum — Nova Simplification (2026-07-30)
|
|
||||||
|
|
||||||
**Milestone:** v1.16-Nova-Simplification (NFR). Roster carries forward
|
|
||||||
unchanged — NFR work touches existing territories, no new domains. The
|
|
||||||
onboarding request-path (P18–P20) is backend-engineer (Lambda action +
|
|
||||||
onboarding.py) + data-engineer (cross-account Terraform) territory.
|
|
||||||
**frontend-engineer** remains deactivated. No **security-engineer**
|
|
||||||
persona — the ingestor defense-in-depth (P10) is backend-engineer with
|
|
||||||
lead-developer review; IAM/ABAC (P20) is data-engineer territory.
|
|
||||||
|
|
||||||
### v1.16 territory assignments
|
|
||||||
|
|
||||||
| Phase | Lead | Contributors | Territory |
|
|
||||||
|-------|------|---------------|-----------|
|
|
||||||
| P1 state-bucket+kyverno fix | backend-engineer | data-engineer (kyverno policy) | `adapters/terraform/adapter.py:117`, `adapters/kyverno/policies/require-resource-labels.yml` |
|
|
||||||
| P2 user-facing brand sweep | lead-developer | backend-engineer | `core/environment_check.py`, `core/lambda/contract_ingestor.py`, `scripts/post_stage_comment.sh`, `scripts/run_ci.sh`, module docstrings, `adapters/README.md` |
|
|
||||||
| P3 dead-code+stale-prefix | lead-developer | — | `scripts/run_platform.sh`, `core/local_emulators.py`, `core/regression_verify.py`, lifecycle scripts |
|
|
||||||
| P4 migrate-ssm except | backend-engineer | — | `scripts/migrate_ssm_paths.py` |
|
|
||||||
| P5 regression-verify dedup | backend-engineer | — | `core/regression_verify.py` |
|
|
||||||
| P6 run-platform deadcode+hitl-fn | lead-developer | — | `scripts/run_platform.sh` |
|
|
||||||
| P7 contract-resolver envloader+kind | backend-engineer | — | `core/contract_resolver.py`, `modules/registry.json` |
|
|
||||||
| P8 workflow generator | lead-developer | backend-engineer (test) | `scripts/sync_workflows.py` (NEW), `tests/test_pipeline_contract.py`, `.gitea/workflows/**`, `.github/workflows/**` |
|
|
||||||
| P9 run-platform split | lead-developer | — | `scripts/run_platform.sh`, `scripts/run_decommission.sh` (NEW), `scripts/run_uptime.sh` (NEW) |
|
|
||||||
| P10 ingestor defense-in-depth | backend-engineer | lead-developer (review) | `core/lambda/contract_ingestor.py`, `core/environments/` |
|
|
||||||
| P11 ingestor payload validation | backend-engineer | — | `core/lambda/contract_ingestor.py` |
|
|
||||||
| P12 split contract-resolver | backend-engineer | — | `core/contract_resolver.py` → `core/contract_resolve.py` + `core/decommission_transform.py` + `core/contract_resolver_cli.py` |
|
|
||||||
| P13 split regression-verify | backend-engineer | — | `core/regression_verify.py` → split modules |
|
|
||||||
| P14 schema-driven outputs+cache | backend-engineer | data-engineer (interface.json) | `core/output_publisher.py`, `core/contract_resolver.py`, `modules/l1/*/interface.json` |
|
|
||||||
| P15 run-platform --help+flags | lead-developer | — | `scripts/run_platform.sh`, `README.md` |
|
|
||||||
| P16 workflows README catalog | lead-developer | — | `.github/workflows/README.md` (NEW) |
|
|
||||||
| P17 getting-started consolidation | lead-developer | — | `README.md` |
|
|
||||||
| P18 onboarding schema+lambda | backend-engineer | lead-developer (schema) | `schemas/onboarding.schema.json` (NEW), `core/lambda/contract_ingestor.py` |
|
|
||||||
| P19 onboarding envfile autogen | backend-engineer | lead-developer (docs) | `core/onboarding.py` (NEW), `core/environment_check.py`, `core/environments/README.md` |
|
|
||||||
| P20 cross-account role offline | data-engineer | backend-engineer (ABAC) | `terraform/onboarding/` (NEW), `terraform/platform/main.tf` |
|
|
||||||
| P21 final-review-ship | lead-developer | all active (review) | `.ciagent/**`, review + audit + ship |
|
|
||||||
|
|
||||||
### v1.16 domain priority
|
|
||||||
|
|
||||||
`backend → lead → data` (the simplification + security + ingestor work
|
|
||||||
is backend-heavy; lead-developer owns docs/DX/splits; data-engineer owns
|
|
||||||
the P20 cross-account Terraform only).
|
|
||||||
|
|
||||||
### v1.16 verification toolchain
|
|
||||||
|
|
||||||
```
|
|
||||||
typecheck: terraform validate && python3 -m py_compile core/**/*.py adapters/**/*.py
|
|
||||||
test: bash scripts/run_regression.sh # 22-capability gate (D-118: P9 + P21)
|
|
||||||
build: bash scripts/run_ci.sh # full local CI reproduction
|
|
||||||
```
|
|
||||||
|
|
||||||
The regression gate (22 capabilities) must stay **22/22 Verified**
|
|
||||||
throughout v1.16 — simplification must not regress any capability
|
|
||||||
(D-118). P9 (end of Wave 2) and P21 (milestone complete) run the gate;
|
|
||||||
P14 (end of Wave 3) is an offline mid-milestone checkpoint.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# v1.17 Persona Roster — Strategic Direction, Leadership Metrics & Unified Story
|
|
||||||
|
|
||||||
> v1.17 adds a telemetry/observability layer (P1–P3), a metrics catalog
|
|
||||||
> + NORTH_STAR integration (P4), a unified narrative deck (P5), a
|
|
||||||
> regression capability (P6), and a final review/ship (P7). Three
|
|
||||||
> active personas; frontend-engineer stays deactivated (no Nova web UI
|
|
||||||
> — dashboards are PowerBI, not a Nova-built frontend).
|
|
||||||
|
|
||||||
## Active personas
|
|
||||||
|
|
||||||
### lead-developer
|
|
||||||
- **Domain:** coordination + deck narrative
|
|
||||||
- **Active:** true
|
|
||||||
- **Phase-specific:** false
|
|
||||||
- **Reason:** Owns CIAgent metadata, the NORTH_STAR.md authoring
|
|
||||||
process (P0), the milestone decomposition, the unified narrative deck
|
|
||||||
co-authoring (P5 — the deck is markdown, which is lead-developer
|
|
||||||
territory per the established convention), and the final review/ship
|
|
||||||
(P7). Arbitrates persona conflicts (e.g., backend vs data on the
|
|
||||||
emitter/store boundary).
|
|
||||||
- **Territory:** `.ciagent/NORTH_STAR.md`, `.ciagent/PROJECT.md`,
|
|
||||||
`.ciagent/REQUIREMENTS.md`, `.ciagent/PLAN.md`, `.ciagent/RESEARCH.md`,
|
|
||||||
`.ciagent/ARCHITECTURE.md`, `docs/presentations/nova-no-humans-platform.md`
|
|
||||||
(NEW — unified deck source of truth), `docs/presentations/nova-no-humans-platform-marp.md`,
|
|
||||||
`docs/presentations/nova-no-humans-platform-talking-points.md`,
|
|
||||||
`docs/METRICS.md`, `docs/metrics/*.md` (per-KPI definition docs).
|
|
||||||
|
|
||||||
### backend-engineer
|
|
||||||
- **Domain:** backend (event emitters + instrumentation)
|
|
||||||
- **Active:** true
|
|
||||||
- **Phase-specific:** false
|
|
||||||
- **Reason:** Owns the event emitters (P1): the CloudEvents envelope,
|
|
||||||
the per-run manifest writer, the `outbox_writer.py` extension to the
|
|
||||||
SQLite Decision Ledger, the Infracost post-processor, the
|
|
||||||
`hitl_gates.py` attestation event emission, the `confidence_signal.py`
|
|
||||||
decision event emission, the `checkov_adapter.py` policy event
|
|
||||||
emission, and the pytest `--junitxml` addopts change. Also owns the
|
|
||||||
`regression_verify.py` CAP-023/024 additions (P6). The emitter work
|
|
||||||
is the bridge between existing Nova components and the new metrics
|
|
||||||
layer — it touches the code paths that already exist.
|
|
||||||
- **Territory:** `core/metrics/event_envelope.py` (NEW),
|
|
||||||
`core/metrics/run_manifest.py` (NEW),
|
|
||||||
`core/metrics/infracost_adapter.py` (NEW),
|
|
||||||
`core/metrics/decision_ledger.py` (NEW — extends outbox_writer),
|
|
||||||
`core/outbox_writer.py` (extend to SQLite),
|
|
||||||
`core/hitl_gates.py` (emit attestation.recorded),
|
|
||||||
`core/confidence_signal.py` (emit ai.decision.made),
|
|
||||||
`adapters/terraform/policy/checkov_adapter.py` (emit policy.evaluated),
|
|
||||||
`scripts/run_platform.sh` (invoke manifest writer + Infracost),
|
|
||||||
`core/regression_verify.py` (CAP-023/024),
|
|
||||||
`pyproject.toml` (addopts --junitxml),
|
|
||||||
`tests/test_metrics_emitters.py` (NEW),
|
|
||||||
`tests/test_decision_ledger.py` (NEW).
|
|
||||||
|
|
||||||
### data-engineer
|
|
||||||
- **Domain:** data (schema, SQLite store, PowerBI export)
|
|
||||||
- **Active:** true
|
|
||||||
- **Phase-specific:** false
|
|
||||||
- **Reason:** Reactivated with a new territory for v1.17: the metrics
|
|
||||||
collector (P2) and the PowerBI export (P3). Owns the schema design
|
|
||||||
(metrics_*.schema.json), the SQLite cold store (nova_metrics.db), the
|
|
||||||
fact/dimension table design, the 8 deferred placeholder views, and
|
|
||||||
the CSV/JSON export. The data-engineer's schema-first constraint
|
|
||||||
applies: all event types and fact/dim tables have JSON Schema
|
|
||||||
definitions before any code is written. The collector reads files +
|
|
||||||
events → SQLite; the export reads SQLite → CSV/JSON. This is the
|
|
||||||
heaviest data-territory work since v1.11's terraform modules.
|
|
||||||
- **Territory:** `core/metrics/collector.py` (NEW),
|
|
||||||
`core/metrics/powerbi_export.py` (NEW),
|
|
||||||
`schemas/metrics_*.schema.json` (NEW — event + fact/dim schemas),
|
|
||||||
`metrics/nova_metrics.db` (NEW — SQLite cold store),
|
|
||||||
`metrics/powerbi/` (NEW — CSV/JSON export dir),
|
|
||||||
`docs/METRICS_VIEWS.md` (NEW — schema doc for PowerBI views),
|
|
||||||
`tests/test_metrics_collector.py` (NEW),
|
|
||||||
`tests/test_powerbi_export.py` (NEW).
|
|
||||||
|
|
||||||
## Deactivated personas
|
|
||||||
|
|
||||||
### frontend-engineer
|
|
||||||
- **Domain:** frontend
|
|
||||||
- **Active:** false
|
|
||||||
- **Phase-specific:** false
|
|
||||||
- **Reason:** v1.17 has no Nova web UI. The leadership dashboards are
|
|
||||||
PowerBI (an external tool that ingests CSV/JSON files), not a
|
|
||||||
Nova-built frontend. The decks are markdown (lead-developer
|
|
||||||
territory). frontend-engineer stays deactivated, consistent with
|
|
||||||
v1.11–v1.16. Reactivates if a future milestone builds a Nova web UI.
|
|
||||||
|
|
||||||
### lambda-engineer, platform-engineer, security-engineer
|
|
||||||
- **Active:** false (carried forward from v1.11)
|
|
||||||
- **Reason:** v1.17 does not touch the Lambda (beyond emitting events
|
|
||||||
from the existing hitl_gates/attestation_matrix), does not do IR-
|
|
||||||
shaped module authoring, and does not touch security adapters beyond
|
|
||||||
emitting policy.evaluated events. The existing components are
|
|
||||||
instrumented, not rewritten.
|
|
||||||
|
|
||||||
## v1.17 phase assignment
|
|
||||||
|
|
||||||
| Phase | Primary persona | Supporting | Territory |
|
|
||||||
|-------|----------------|------------|-----------|
|
|
||||||
| P0 pre-execution | lead-developer | — | `.ciagent/NORTH_STAR.md`, `PROJECT.md`, `REQUIREMENTS.md`, `RESEARCH.md`, `ARCHITECTURE.md`, `PERSONAS.md`, `PLAN.md` |
|
|
||||||
| P1 event-emitters | backend-engineer | data-engineer (schemas) | `core/metrics/event_envelope.py`, `run_manifest.py`, `decision_ledger.py`, `infracost_adapter.py`, `outbox_writer.py`, `hitl_gates.py`, `confidence_signal.py`, `checkov_adapter.py`, `run_platform.sh`, `pyproject.toml` |
|
|
||||||
| P2 metrics-collector | data-engineer | backend-engineer (event formats) | `core/metrics/collector.py`, `schemas/metrics_*.schema.json`, `metrics/nova_metrics.db` |
|
|
||||||
| P3 powerbi-export | data-engineer | — | `core/metrics/powerbi_export.py`, `metrics/powerbi/`, `docs/METRICS_VIEWS.md` |
|
|
||||||
| P4 metrics-catalog + north-star-integration | lead-developer | data-engineer (metric definitions) | `docs/METRICS.md`, `docs/metrics/*.md`, `PROJECT.md`, `ARCHITECTURE.md`, `config.json` |
|
|
||||||
| P5 deck-rebuild | lead-developer | — | `docs/presentations/nova-no-humans-platform*.md`, retire old decks |
|
|
||||||
| P6 regression-capability | backend-engineer | data-engineer (CAP-023 schema) | `core/regression_verify.py` (CAP-023, CAP-024) |
|
|
||||||
| P7 final-review-ship | lead-developer | all active (review) | `.ciagent/**`, review + audit + ship |
|
|
||||||
|
|
||||||
## v1.17 domain priority
|
|
||||||
|
|
||||||
`backend → data → lead` (the emitter work in P1 is the foundation;
|
|
||||||
data-engineer's collector + export in P2–P3 depends on P1's event
|
|
||||||
formats; lead-developer's catalog + deck in P4–P5 depends on the
|
|
||||||
metrics being grounded).
|
|
||||||
|
|
||||||
## v1.17 verification toolchain
|
|
||||||
|
|
||||||
```
|
|
||||||
typecheck: terraform validate && python3 -m py_compile core/**/*.py adapters/**/*.py
|
|
||||||
test: bash scripts/run_regression.sh # 22-capability gate + CAP-023/024 (v1.17)
|
|
||||||
build: bash scripts/run_ci.sh # full local CI reproduction
|
|
||||||
```
|
|
||||||
|
|
||||||
The regression gate (22 capabilities + CAP-023 metrics collector +
|
|
||||||
CAP-024 deck structure) must pass at P6 and P7. CAP-009 (offline pytest
|
|
||||||
suite) must remain Verified after the `--junitxml` addopts change
|
|
||||||
(assumption A5).
|
|
||||||
+1324
-1049
File diff suppressed because it is too large
Load Diff
+405
-7
@@ -58,6 +58,103 @@ traceable to a human attestation and an immutable evidence stream.
|
|||||||
boundary. The platform validates, enriches with operational standards,
|
boundary. The platform validates, enriches with operational standards,
|
||||||
and reconciles the target state.
|
and reconciles the target state.
|
||||||
|
|
||||||
|
## Scope: Nova is Downstream of PDLC
|
||||||
|
|
||||||
|
> **Promoted from Core Tenet #2 + Anti-Goal #1 (v1.18, REQ-216).** This
|
||||||
|
> is the unmissable scope statement — the PDLC is upstream, Nova is
|
||||||
|
> downstream.
|
||||||
|
|
||||||
|
The **Product Development Lifecycle (PDLC)** — product backlog, code
|
||||||
|
authorship, IDE workflows, sprint planning, application business logic —
|
||||||
|
is **upstream** of Nova. Nova never penetrates the PDLC. Nova's domain is
|
||||||
|
**infrastructure + delivery only**: environment progression, cloud
|
||||||
|
resource lifecycle, operational security/observability NFRs, policy
|
||||||
|
enforcement, immutable audit lineage, and the two consumer surfaces
|
||||||
|
(technical developer + agentic).
|
||||||
|
|
||||||
|
Integration between the PDLC and Nova is **only** through the validated,
|
||||||
|
published contract boundary (`schemas/contract.schema.json` +
|
||||||
|
`schemas/submission-readiness.schema.json`). The citizen developer's AI
|
||||||
|
coding agent, an upstream agentic SDLC platform, or any upstream
|
||||||
|
development platform may all produce submissions — the source does not
|
||||||
|
matter because all are subject to the same compliance standards (the
|
||||||
|
submission-readiness gate, D-133). Nova validates, enriches with
|
||||||
|
operational standards, and reconciles the target state. Nova never
|
||||||
|
authors application code, manages product backlogs, or provides IDE
|
||||||
|
workflows.
|
||||||
|
|
||||||
|
```
|
||||||
|
PDLC (upstream) Nova (downstream)
|
||||||
|
───────────────── ─────────────────
|
||||||
|
product backlog contract ingestion
|
||||||
|
code authorship (AI agent / IDE / SDLC) → submission-readiness gate
|
||||||
|
sprint planning → policy enforcement
|
||||||
|
application business logic → cloud resource lifecycle
|
||||||
|
→ environment progression (dev→qa→prod→dr)
|
||||||
|
→ immutable audit + attestation
|
||||||
|
```
|
||||||
|
|
||||||
|
## RACI Matrix
|
||||||
|
|
||||||
|
> **Source of truth (v1.18, REQ-215, D-139).** Three roles clarify who
|
||||||
|
> owns what across the Nova delivery lifecycle. The matrix is the
|
||||||
|
> authoritative version; `docs/raci.md` is the citizen-developer-facing
|
||||||
|
> copy.
|
||||||
|
|
||||||
|
### Roles
|
||||||
|
|
||||||
|
- **Citizen Developer (CD)** — the consumer (technical developer L3A or
|
||||||
|
non-technical L3B). Responsible for all **Functional Requirements (FRs)**
|
||||||
|
and **User Acceptance Testing (UAT)**. The FRs + UAT are produced via
|
||||||
|
the citizen developer's AI coding agent, an upstream agentic SDLC, or
|
||||||
|
an upstream development platform — **the source does not matter as all
|
||||||
|
are subject to the same compliance standards** (the submission-readiness
|
||||||
|
gate, D-133).
|
||||||
|
- **Platform** — Nova. Responsible for all **Non-Functional Requirements
|
||||||
|
(NFRs)**, **Infrastructure** (cloud resource lifecycle, state, IAM),
|
||||||
|
**QA** (the platform-side quality checks: policy, confidence, schema),
|
||||||
|
and **Production deployments to cloud** (the apply path, the pipeline,
|
||||||
|
the release).
|
||||||
|
- **Release Management (RM)** — **co-owned**. QA + SRE attestations are
|
||||||
|
required by the actual release. The attestations are performed
|
||||||
|
agentically (the platform runs the checks), but the release is
|
||||||
|
**overseen and triggered by the Citizen Developer** — the human
|
||||||
|
attestation at the stage gate (D-042, hitl_gates.py). The platform
|
||||||
|
performs; the citizen developer authorizes.
|
||||||
|
|
||||||
|
### Matrix
|
||||||
|
|
||||||
|
| Work Category | Citizen Developer | Platform | Release Management |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **Functional Requirements (FRs)** | **R/A** | C | I |
|
||||||
|
| **User Acceptance Testing (UAT)** | **R/A** | C | I |
|
||||||
|
| **Non-Functional Requirements (NFRs)** | I | **R/A** | C |
|
||||||
|
| **Infrastructure (cloud, state, IAM)** | I | **R/A** | C |
|
||||||
|
| **QA (policy, confidence, schema checks)** | C | **R/A** | I |
|
||||||
|
| **Production deployment to cloud** | I | **R/A** | C |
|
||||||
|
| **Release attestation (QA + SRE sign-off)** | **A** | R | **R** |
|
||||||
|
|
||||||
|
**Key: R** = Responsible (does the work) · **A** = Accountable (owns the
|
||||||
|
outcome, sign-off) · **C** = Consulted · **I** = Informed.
|
||||||
|
|
||||||
|
**Compliance-standard equivalence note:** the citizen developer's FRs +
|
||||||
|
UAT may originate from any upstream source — an AI coding agent, an
|
||||||
|
agentic SDLC platform, or a traditional development platform. All are
|
||||||
|
subject to the same compliance standards: the submission-readiness gate
|
||||||
|
(`schemas/submission-readiness.schema.json`), the contract schema, the
|
||||||
|
policy envelope, and the immutable audit stream. The platform does not
|
||||||
|
differentiate by upstream source; it validates the submission, not the
|
||||||
|
author.
|
||||||
|
|
||||||
|
**Co-ownership of Release Management:** the release is co-owned. The
|
||||||
|
platform performs the QA + SRE attestations agentically (confidence signal,
|
||||||
|
policy checks, separation-of-duties). The citizen developer oversees and
|
||||||
|
triggers the actual release — the human attestation at the stage gate is
|
||||||
|
the citizen developer's authorization, recorded with approver identity
|
||||||
|
(D-042). The platform runs the checks; the citizen developer authorizes
|
||||||
|
the promotion. This is the "autonomy in operations, human at stage gates"
|
||||||
|
model from the NORTH_STAR.
|
||||||
|
|
||||||
## Capability Status (Re-Verified 2026-07-27)
|
## Capability Status (Re-Verified 2026-07-27)
|
||||||
|
|
||||||
> Source of truth: `.ciagent/CAPABILITY_INVENTORY.md` (Phase 54, D-093).
|
> Source of truth: `.ciagent/CAPABILITY_INVENTORY.md` (Phase 54, D-093).
|
||||||
@@ -592,12 +689,97 @@ DX: 16 total). Key changes:
|
|||||||
10. Old two-surfaces diagram replaced by scope boundary diagram.
|
10. Old two-surfaces diagram replaced by scope boundary diagram.
|
||||||
|
|
||||||
Source markdown, talking points, and README all updated to mirror the new
|
Source markdown, talking points, and README all updated to mirror the new
|
||||||
structure. Also includes scripts/sync_to_gl.sh (GitLab mirror sync
|
structure. Also includes scripts/sync_to_nova.sh (manual-only "2nd release"
|
||||||
utility, unrelated to presentations).
|
into ~/nova — a separate GitLab consumer-facing repo with its own history;
|
||||||
|
domain-based conventional commits, never triggered by CI; REQ-229).
|
||||||
|
|
||||||
No code changes; 494 tests pass; `run_ci.sh` + `run_platform.sh --check-only`
|
No code changes; 494 tests pass; `run_ci.sh` + `run_platform.sh --check-only`
|
||||||
green. PPTX files uploaded to Gitea release.
|
green. PPTX files uploaded to Gitea release.
|
||||||
|
|
||||||
|
## Objective for Milestone v1.18 (active — Citizen Developer & Production-Grade Guidance)
|
||||||
|
|
||||||
|
v1.18 advances Nova from a platform that governs infrastructure delivery
|
||||||
|
to one that **instructs the citizen developer on production-grade
|
||||||
|
engineering** and defines a **clear, machine-checkable contract for what
|
||||||
|
is acceptable to start**. Five user-directed inputs drive the milestone:
|
||||||
|
|
||||||
|
1. **S&P Global theme restoration.** The v1.17 P5 deck rebuild consolidated
|
||||||
|
two decks into one unified narrative deck but lost the S&P Global Energy
|
||||||
|
brand visual identity (introduced v1.9.2 / P45, commit `ae0cb58`). The
|
||||||
|
Marp `style:` block (red-core `#D6002A`, grey-90 `#1B1B1B`, Akkurat Pro
|
||||||
|
font, 8px top accent bar) is restored to the unified deck. The mermaid
|
||||||
|
`sp-theme.json` survived; only the Marp CSS theme was lost.
|
||||||
|
|
||||||
|
2. **PDLC-upstream scope made explicit.** Core Tenet #2 already states the
|
||||||
|
platform "does not penetrate upstream product/SDLC" and Anti-Goal #1 says
|
||||||
|
"Not an upstream development platform." v1.18 promotes this from a
|
||||||
|
buried tenet to a dedicated, unmissable scope statement in PROJECT.md +
|
||||||
|
`docs/scope.md` + a deck slide: **the PDLC (Product Development
|
||||||
|
Lifecycle — product backlog, code authorship, IDE) is upstream of Nova;
|
||||||
|
Nova governs infra + delivery only; integration is through the validated
|
||||||
|
contract boundary.**
|
||||||
|
|
||||||
|
3. **RACI matrix.** A three-role responsibility matrix clarifies who owns
|
||||||
|
what: **Citizen Developer** (Responsible for all Functional Requirements
|
||||||
|
+ User Acceptance Testing, via their AI coding agent / upstream agentic
|
||||||
|
SDLC / upstream development platform — the source does not matter as all
|
||||||
|
are subject to the same compliance standards), **Platform** (Responsible
|
||||||
|
for all NFRs + Infrastructure + QA + Production deployments to cloud),
|
||||||
|
**Release Management** (co-owned: QA + SRE attestations required by the
|
||||||
|
actual release, performed agentically but overseen & triggered by the
|
||||||
|
Citizen Developer). Source of truth in PROJECT.md + `docs/raci.md` + a
|
||||||
|
deck slide.
|
||||||
|
|
||||||
|
4. **Nova input contract — "what is acceptable to start."** A JSON Schema
|
||||||
|
(`schemas/submission-readiness.schema.json`) defines the
|
||||||
|
acceptable-to-start gate as a superset *above* contract-schema validity:
|
||||||
|
schema-valid contract + required Nova tags + per-env mandatory metadata
|
||||||
|
(per W3.E) + declared policy preconditions + (for L3B) `profile:agentic`
|
||||||
|
markers + `appSource` pointer. A validator (`core/submission_readiness.py`,
|
||||||
|
invoked as `contract_ingestor.py --check-readiness`) returns a structured
|
||||||
|
`ReadinessResult` with reason codes. On fail → citizen-developer-facing
|
||||||
|
error (not a stack trace); on pass → proceeds to existing ingestion.
|
||||||
|
|
||||||
|
5. **Atelier integration — production-grade guidance + agentic validation.**
|
||||||
|
Nova consumes `coreci/atelier` (a first-principles docs-as-code
|
||||||
|
engineering framework — 8 core principles, 19 domains, 190 P-rules) via
|
||||||
|
two surfaces: **skills** (markdown files under `skills/` keyed to Atelier
|
||||||
|
domain paths, surfaced to the citizen developer's AI agent, extending the
|
||||||
|
BA.A 5-skill catalog) and an **MCP server** (`mcp/atelier/server.py`,
|
||||||
|
plugin-registry architecture, stdio transport, vendored Atelier snapshot
|
||||||
|
for audit reproducibility) exposing tools for principle-lookup,
|
||||||
|
domain-listing, matrix-lookup, and agentic validation against the
|
||||||
|
Atelier agent-checklist — validation that goes beyond deterministic
|
||||||
|
scanners (Wiz/Checkmarx/Mend) by catching correctness/clarity/simplicity/
|
||||||
|
observability gaps.
|
||||||
|
|
||||||
|
**Deck automation (cross-cutting):** any phase modifying
|
||||||
|
`docs/presentations/*-marp.md` or `docs/presentations/assets/` MUST
|
||||||
|
re-render HTML + PPTX, **commit the PPTX to git** (binary, no LFS), and
|
||||||
|
attach it to the phase's Gitea release. New scripts:
|
||||||
|
`scripts/render_deck.sh` (HTML + PPTX render) and
|
||||||
|
`scripts/attach_release_asset.py` (Gitea release asset upload).
|
||||||
|
|
||||||
|
**Milestone type:** Feature (P1 S&P theme restoration + P3 readiness
|
||||||
|
schema/validator + P5 MCP server are new code/features). Tags run on the
|
||||||
|
**v1.17.x** patch line (previous minor per branch-strategy): `v1.17.0` (P0)
|
||||||
|
→ `v1.17.1..v1.17.6` (P1–P6) → `v1.17.7` (P7 final = milestone release).
|
||||||
|
|
||||||
|
**Phase count:** 8 (P0 pre-execution + 6 execution + 1 final).
|
||||||
|
|
||||||
|
**Hard constraints:**
|
||||||
|
- DO NOT make anything up (NORTH_STAR.md honesty model).
|
||||||
|
- The submission-readiness schema is a superset gate above
|
||||||
|
`contract.schema.json`, NOT a duplicate — it references but does not
|
||||||
|
redefine contract fields.
|
||||||
|
- The MCP server is plugin-registry extensible (future capabilities drop
|
||||||
|
in as new plugin files, no `server.py` edits).
|
||||||
|
- Atelier is vendored (pinned tag) for audit reproducibility — an agentic
|
||||||
|
validation result must be replayable against the exact principles that
|
||||||
|
produced it.
|
||||||
|
- PPTX is a first-class artifact: committed (history) + attached (download)
|
||||||
|
— both always, not optional.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
### v1.0 (Prior milestone — the demo)
|
### v1.0 (Prior milestone — the demo)
|
||||||
@@ -799,7 +981,7 @@ or user-directed scope). New v1.7 decisions:
|
|||||||
| W1.A | AI-refinement trigger | **Accept recommendation.** Joint condition: N ≥ 50 consecutive changes with zero rollbacks AND no L1/L2 incident in last 6 months AND Infra & Ops unilateral override. |
|
| W1.A | AI-refinement trigger | **Accept recommendation.** Joint condition: N ≥ 50 consecutive changes with zero rollbacks AND no L1/L2 incident in last 6 months AND Infra & Ops unilateral override. |
|
||||||
| W1.B | Multi-stack edge case rule | **Accept recommendation.** Permitted only for (a) DR-region mirror, (b) time-boxed experimental stack with TTL ≤ 30d, (c) explicit Infra & Ops approval with `multiStack.justification`. |
|
| W1.B | Multi-stack edge case rule | **Accept recommendation.** Permitted only for (a) DR-region mirror, (b) time-boxed experimental stack with TTL ≤ 30d, (c) explicit Infra & Ops approval with `multiStack.justification`. |
|
||||||
| W2.A | Tag mutability for prod | **Accept recommendation (Path B).** Tag for dev/qa, SHA for prod. Platform CLI resolves tag→SHA for prod-bound workflows. Justified by the "Audit truth lives outside the repository" bet. |
|
| W2.A | Tag mutability for prod | **Accept recommendation (Path B).** Tag for dev/qa, SHA for prod. Platform CLI resolves tag→SHA for prod-bound workflows. Justified by the "Audit truth lives outside the repository" bet. |
|
||||||
| BA.A | Initial L3B skill catalog | **Accept recommendation.** 5 skills: web API, worker, scheduled job, static asset, basic observability bootstrap. Addition criteria: (a) reviewable for sensitive data, (b) expressible as a single contract submission, (c) documented use case. |
|
| BA.A | Initial L3B skill catalog | **Accept recommendation.** 5 skills: web API, worker, scheduled job, static asset, basic observability bootstrap. Addition criteria: (a) reviewable for sensitive data, (b) expressible as a single contract submission, (c) documented use case. **Extended v1.18 (REQ-221/222):** the BA.A 5-skill catalog is extended with 9 Atelier-derived production-grade engineering skills under `skills/` (api, security, data, testing, observability, errors, devops, infrastructure-as-code, compliance), indexed by `docs/skills.md`. The Atelier skills extend, not replace, the BA.A catalog. |
|
||||||
| W3.D | L1/L2 standard versioning | **Decided.** Semver: interface → MAJOR, behavior → MINOR, lifecycle → PATCH (same as the v1.0 demo D-rule, lifted to the real platform). Pin model: L2 contracts pin L1 by `name@semver`; the resolver picks the highest compatible. Evolution: MAJOR bumps require a new registry entry (immutable publication); old entry enters a 12-month deprecation window. |
|
| W3.D | L1/L2 standard versioning | **Decided.** Semver: interface → MAJOR, behavior → MINOR, lifecycle → PATCH (same as the v1.0 demo D-rule, lifted to the real platform). Pin model: L2 contracts pin L1 by `name@semver`; the resolver picks the highest compatible. Evolution: MAJOR bumps require a new registry entry (immutable publication); old entry enters a 12-month deprecation window. |
|
||||||
| W3.E | Schema mandatory vs optional inputs | **Decided.** Per-env mandatory table: dev requires `stack` + `environment`; qa adds `validation.e2eSuite` + `validation.loadTest`; prod adds `runbook` + `dashboard` + `oncall`; dr adds `drDrillRef`. `inputs` map is always optional. `profile: agentic` fields (`naturalLanguageIntent`, `confidenceAtSubmission`, `agentTrace`) optional everywhere. |
|
| W3.E | Schema mandatory vs optional inputs | **Decided.** Per-env mandatory table: dev requires `stack` + `environment`; qa adds `validation.e2eSuite` + `validation.loadTest`; prod adds `runbook` + `dashboard` + `oncall`; dr adds `drDrillRef`. `inputs` map is always optional. `profile: agentic` fields (`naturalLanguageIntent`, `confidenceAtSubmission`, `agentTrace`) optional everywhere. |
|
||||||
| BA.B | Confidence threshold tuning | **Decided.** Starting thresholds frozen for v1. Tuning begins in v1.2: track FP/FN per environment quarterly; override authority = Infra & Ops + SRE joint sign-off; any override is itself a confidence-event in the audit stream. |
|
| BA.B | Confidence threshold tuning | **Decided.** Starting thresholds frozen for v1. Tuning begins in v1.2: track FP/FN per environment quarterly; override authority = Infra & Ops + SRE joint sign-off; any override is itself a confidence-event in the audit stream. |
|
||||||
@@ -1084,16 +1266,29 @@ P7 review+audit+ship). Tags on the v1.16.x line: `v1.16.0` (P0) →
|
|||||||
|
|
||||||
- **Pillar A — Strategic Direction.** A durable, PO-authored
|
- **Pillar A — Strategic Direction.** A durable, PO-authored
|
||||||
`.ciagent/NORTH_STAR.md` encodes the platform's vision, 4 strategic
|
`.ciagent/NORTH_STAR.md` encodes the platform's vision, 4 strategic
|
||||||
objectives, 5 anti-goals, v1.17 non-goals, 12–18mo targets (with a
|
objectives, anti-goals, v1.17 non-goals, 12–18mo targets (with a
|
||||||
grounding column), and success criteria. CIAgent reads it in every
|
grounding column), and success criteria. CIAgent reads it in every
|
||||||
future `/ci-run` so the direction survives across milestones. The
|
future `/ci-run` so the direction survives across milestones. The
|
||||||
attestation clarification is reflected: human attestation required at
|
attestation clarification is reflected: human attestation required at
|
||||||
stage gates (QA for production, SRE for operational readiness); autonomy
|
stage gates (QA for production, SRE for operational readiness); autonomy
|
||||||
in operations, not in accountability.
|
in operations, not in accountability. **v1.21 refinement:** Strategic
|
||||||
|
Objective #4 reframed from "default substrate for agentic consumption" to
|
||||||
|
integrating with externally owned PDLC/SDLC/Agentic/Citizen Developer
|
||||||
|
platforms regardless of source (Nova provides skills + MCP endpoints;
|
||||||
|
all prod intents go through the same controls). Objective #2 reworded:
|
||||||
|
trust is established by deterministic scripts that calculate a score —
|
||||||
|
the platform functions without AI. Objective #3 reworded with four
|
||||||
|
CTO-grade metrics (Lead Time PR→Prod, Infrastructure Vulnerability
|
||||||
|
Count trend, MTTR, Cloud Spend Reduction) all flowing into PowerBI.
|
||||||
|
Anti-goals #1, #4, #5 removed; replaced with "not an upstream
|
||||||
|
development platform" and "not a replacement for the PDLC".
|
||||||
|
|
||||||
- **Pillar B — Leadership Metrics + PowerBI.** Instrument Nova to
|
- **Pillar B — Leadership Metrics + PowerBI.** Instrument Nova to
|
||||||
collect, aggregate, and surface leadership-grade metrics that prove the
|
collect, aggregate, and surface leadership-grade metrics that prove the
|
||||||
"no-humans" autonomous-infrastructure value proposition. Nova-native
|
"no-humans" autonomous-infrastructure value proposition (reframed in
|
||||||
|
v1.21 to "autonomous cloud delivery" — professional framing; the
|
||||||
|
platform delivers safe production deployment without an operator in
|
||||||
|
the loop of normal operations). Nova-native
|
||||||
minimal tech (CloudEvents 1.0 envelope, JSONL event log, SQLite cold
|
minimal tech (CloudEvents 1.0 envelope, JSONL event log, SQLite cold
|
||||||
store, hash-chained Decision Ledger via `outbox_writer.py` extension)
|
store, hash-chained Decision Ledger via `outbox_writer.py` extension)
|
||||||
+ Infracost for pre-apply cost estimates. Hybrid model: existing
|
+ Infracost for pre-apply cost estimates. Hybrid model: existing
|
||||||
@@ -1133,4 +1328,207 @@ P7 review+audit+ship). Tags on the v1.16.x line: `v1.16.0` (P0) →
|
|||||||
| D-129 | PowerBI delivery = CSV/JSON files, folder connector. | Nova is offline-first; no live connector to a running service. PowerBI ingests via the folder connector. | P3 emits CSV/JSON to metrics/powerbi/. |
|
| D-129 | PowerBI delivery = CSV/JSON files, folder connector. | Nova is offline-first; no live connector to a running service. PowerBI ingests via the folder connector. | P3 emits CSV/JSON to metrics/powerbi/. |
|
||||||
| D-130 | Deck arc = Problem → Vision → How → Proof → Roadmap. | The unified narrative deck's 5-act structure. x3 arc at deck + slide level. Per-slide benefit callouts. Fluid transitions. Both old decks retired. | P5 builds the unified deck; old decks deleted. |
|
| D-130 | Deck arc = Problem → Vision → How → Proof → Roadmap. | The unified narrative deck's 5-act structure. x3 arc at deck + slide level. Per-slide benefit callouts. Fluid transitions. Both old decks retired. | P5 builds the unified deck; old decks deleted. |
|
||||||
| D-131 | MTTR scope = platform-run MTTR. | The <60s MTTR target refers to platform-run failures (apply.failed → successful retry), not infra-incident MTTR (no incident detection system). Infra-incident MTTR deferred. | P4 grounds platform-run MTTR. |
|
| D-131 | MTTR scope = platform-run MTTR. | The <60s MTTR target refers to platform-run failures (apply.failed → successful retry), not infra-incident MTTR (no incident detection system). Infra-incident MTTR deferred. | P4 grounds platform-run MTTR. |
|
||||||
| D-132 | Attestation instrumentation = emit attestation.recorded events. | The attestation system (hitl_gates.py + attestation_matrix.py + separation_of_duties.py) already exists. Instrument it: emit attestation.recorded events into the Decision Ledger + PowerBI. Attestation Coverage = 100% target grounded from outbox approver_* attributes. | P1 emits attestation events; P4 grounds Attestation Coverage. |
|
| D-132 | Attestation instrumentation = emit attestation.recorded events. | The attestation system (hitl_gates.py + attestation_matrix.py + separation_of_duties.py) already exists. Instrument it: emit attestation.recorded events into the Decision Ledger + PowerBI. Attestation Coverage = 100% target grounded from outbox approver_* attributes. | P1 emits attestation events; P4 grounds Attestation Coverage. |
|
||||||
|
|
||||||
|
## Key Decisions (v1.18)
|
||||||
|
|
||||||
|
Resolved at the CLARIFY stage (full autonomy — all within locked
|
||||||
|
constraints or user-directed scope). New v1.18 decisions:
|
||||||
|
|
||||||
|
| ID | Decision | Rationale | Outcome |
|
||||||
|
|----|----------|-----------|---------|
|
||||||
|
| D-133 | Submission-readiness validator location = extend `contract_ingestor.py --check-readiness`. | Adding a new CLI binary is unnecessary; the ingestor is the existing entry point for contract submission. The validator is a subcommand that runs before ingestion proceeds. No new binary, no new entry point to maintain. | P3 implements the subcommand; no new CLI binary. |
|
||||||
|
| D-134 | Deck slide budget = 18 → 21 slides (no act restructure). | The 3 new slides (scope/RACI/atelier) are leadership-relevant and append after the existing 18. The 5-act arc (D-130) is preserved; the new slides are append-only context, not a new act. | P6 appends 3 slides → 21 total. |
|
||||||
|
| D-135 | Atelier MCP transport = stdio now; HTTP-ready (same server object). | stdio is the local-agent transport (the citizen developer's AI agent spawns the server as a subprocess). The MCP Python SDK v2 supports Streamable HTTP on the same `MCPServer` object, so adding HTTP later is a transport-only change in `server.py`, not a rewrite. | P5 ships stdio; HTTP deferred (documented in README). |
|
||||||
|
| D-136 | Atelier source = vendor pinned tag under `mcp/atelier/vendor/`. | An agentic validation result is only reproducible if the principles that produced it are pinned. Live-fetch breaks replayability (Atelier `main` drifts). Vendoring matches the v1.16 P15 offline-first precedent and the Nova thesis (provable trust). `mcp/atelier/vendor/VERSION.md` records the pinned tag; `scripts/update_atelier_vendor.sh` is the intentional upgrade path. | P5 vendors Atelier; live-fetch not implemented. |
|
||||||
|
| D-137 | MCP server language = Python (MCP Python SDK v2, `modelcontextprotocol/python-sdk`). | Nova's `core/` is Python. The MCP Python SDK v2 (23.9k stars, MIT, stable) matches the codebase; type hints become JSON Schema automatically (`@mcp.tool()` decorator). | P5 uses Python SDK v2. |
|
||||||
|
| D-138 | Skill catalog format = markdown files under `skills/` keyed to Atelier domain paths. | Markdown is the established Nova docs format (Jekyll Pages, 4-step deck process). Each skill file names the Atelier source path, distills the first-principles, links to agent-checklist triggers, and maps to the BA.A catalog. | P4 authors 9 markdown skill files. |
|
||||||
|
| D-139 | RACI role names = Citizen Developer / Platform / Release Management (co-owned). | User-specified. The 3 roles are the columns of the RACI table. Release Management is co-owned: QA + SRE attestations are required by the actual release (performed agentically, overseen & triggered by the Citizen Developer). | P2 authors the RACI with these 3 roles. |
|
||||||
|
| D-140 | MCP server extensibility = plugin-registry (`plugins/<name>.py` implementing `register(mcp)`). | Future capabilities (new scanners, policy evaluators, cost tools) drop in as new plugin files — no `server.py` edits. `server.py` scans `plugins/` and calls `register` on each. This is the extensibility insurance: plugins are decoupled from the server entrypoint. | P5 implements the plugin-registry; initial plugins are `principles.py` + `validation.py`. |
|
||||||
|
| D-141 | PPTX storage = commit binary directly to `docs/presentations/` (no LFS). | Decks are small (~1-5 MiB); git handles binary blobs. LFS requires server-side support (unverified for git.cloudinit.dev) + client config. Committing directly is simplest and works without any repo/server config. Binary diffs are not delta-friendly, but deck changes are infrequent. | P1/P2/P6 commit .pptx directly. |
|
||||||
|
| D-142 | Deck render trigger = any phase modifying `docs/presentations/*-marp.md` or `docs/presentations/assets/` must re-render HTML + PPTX, commit PPTX, and attach to the Gitea release. | PPTX was previously manual + release-only (not committed). v1.18 makes it a first-class artifact: committed (history) + attached (download), both always, not optional. Automated via `scripts/render_deck.sh` + `scripts/attach_release_asset.py`. | P1/P2/P6 run the render+commit+attach pipeline. |
|
||||||
|
## Objective for Milestone v1.19 (complete — Nova 2nd-Release Sync)
|
||||||
|
|
||||||
|
> **NFR-only chore milestone.** Ships a patch on the v1.18.x line (tag
|
||||||
|
> `v1.18.0`). Single execution phase. Establishes the manual-only "2nd
|
||||||
|
> release" pipeline from `~/acdl` (CIAgent-managed source of truth, full audit
|
||||||
|
> trail) into `~/nova` (GitLab `jonathanchery/nova` — separate repo, separate
|
||||||
|
> history, consumer / platform-team audience).
|
||||||
|
|
||||||
|
### Why
|
||||||
|
|
||||||
|
`~/acdl` is the engineering source of truth and carries the full CIAgent
|
||||||
|
audit trail (`.ciagent/`, milestone branches, `---ci---` blocks, Gitea
|
||||||
|
releases). Consumers and the platform team should consume a clean,
|
||||||
|
conventional-commit-shaped tree without the CIAgent plumbing. The old
|
||||||
|
`scripts/sync_to_gl.sh` mirrored `~/acdl → ~/gl/acdl` with a single
|
||||||
|
kitchen-sink `chore: sync from source mirror <ts>` commit — wrong audience,
|
||||||
|
wrong commit standard, wrong repo.
|
||||||
|
|
||||||
|
### What
|
||||||
|
|
||||||
|
- **`scripts/sync_to_nova.sh`** replaces `scripts/sync_to_gl.sh`.
|
||||||
|
- **Manual-only gate**: refuses without `--release` / `RELEASE_CONFIRMED=1`
|
||||||
|
(exit 2). Never triggerable by CI.
|
||||||
|
- **Consumer subset only**: excludes `.ciagent/`, `.gitea/`, `.env*`,
|
||||||
|
`terraform/`, `demo/`, runtime metrics artifacts, and internal-only scripts
|
||||||
|
(the `EXCLUDE_SCRIPTS` list — CIAgent/ops/release plumbing). Keeps
|
||||||
|
consumer-facing runbooks (`run_ci.sh`, `run_platform.sh`, etc.) and the
|
||||||
|
metrics export views (`metrics/README.md`, `powerbi/`, `TRUST_SNAPSHOT.md`).
|
||||||
|
- **Destination history protected**: rsync `--filter=P .git` ensures
|
||||||
|
`~/nova/.git` is never touched.
|
||||||
|
- **Domain-based commits**: 13 fixed-order domains (config → core → adapters
|
||||||
|
→ modules → contracts → schemas → pipelines → mcp → skills → scripts →
|
||||||
|
tests → docs → workflows). Each changed domain gets its own conventional
|
||||||
|
commit, supplied positionally via repeated `-m` flags. No kitchen-sink.
|
||||||
|
- **Conventional-commit validation**: regex-enforced
|
||||||
|
(`feat|fix|docs|chore|refactor|perf|test|build|ci|style|revert`); bypass via
|
||||||
|
`--no-verify-format`.
|
||||||
|
- **Modes**: `--list-domains` (print order), `--dry-run` (preview rsync +
|
||||||
|
messages), `--no-push` (commit without pushing), `-v` (verbose).
|
||||||
|
|
||||||
|
### Out of Scope
|
||||||
|
|
||||||
|
- **coreci / Atelier review gate on the synced tree** — deferred. A future
|
||||||
|
milestone may run a vendored-Atelier review pass before commit and block on
|
||||||
|
P0 findings.
|
||||||
|
- **Tagging releases on the `~/nova` side** — could add `--tag <semver>`
|
||||||
|
later.
|
||||||
|
- **Deleting `~/gl`** — the old mirror dir is left on disk; only the sync
|
||||||
|
script targeting it is removed.
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
- **REQ-229** — `scripts/sync_to_nova.sh` replaces `sync_to_gl.sh` with the
|
||||||
|
manual-only, consumer-subset, domain-committed 2nd-release pipeline
|
||||||
|
described above. (Phase P1)
|
||||||
|
|
||||||
|
### Phase Plan
|
||||||
|
|
||||||
|
| Phase | Name | Status |
|
||||||
|
|-------|------|--------|
|
||||||
|
| P1 | nova-sync-script | complete |
|
||||||
|
| P2 | final-review-ship | pending |
|
||||||
|
|
||||||
|
### Decisions
|
||||||
|
|
||||||
|
| ID | Decision | Rationale | Outcome |
|
||||||
|
|----|----------|-----------|---------|
|
||||||
|
| D-143 | 2nd release target = `~/nova` (separate GitLab repo), not `~/gl/acdl`. | `~/nova` is consumer/platform-team-facing with its own history; `~/gl/acdl` was an internal mirror with a kitchen-sink commit standard. Separate audience → separate repo → separate commit standard. | `sync_to_nova.sh` targets `~/nova`; `sync_to_gl.sh` removed. |
|
||||||
|
| D-144 | Commit standard for `~/nova` = real conventional commits per domain (not the `---ci---` audit blocks used in `~/acdl`). | `~/acdl` commits carry CIAgent audit metadata (`---ci---` blocks) for the ciagent auditing workflow; that's noise for platform consumers. `~/nova` gets clean `feat/fix/docs/chore(scope): subject` commits grouped by domain. | Script validates conventional format; domain-based commits via positional `-m`. |
|
||||||
|
| D-145 | Trigger = manual-only (`--release` / `RELEASE_CONFIRMED=1`). | The 2nd release is a deliberate human action, not a CI side-effect. The gate guarantees it can never fire from Gitea Actions, GitHub Actions, or accidental invocation. | Script exits 2 without `--release`. |
|
||||||
|
| D-146 | Domain grouping = 13 fixed-order domains by path prefix; messages map positionally over CHANGED domains only. | Avoids the kitchen-sink commit; gives `~/nova` a reviewable, conventional history tailored to platform consumers. Positional-over-changed mapping lets the human supply exactly the messages needed, in domain order, without padding for unchanged domains. | `--list-domains` prints order; `--dry-run` previews; count-mismatch errors clearly. |
|
||||||
|
| D-147 | coreci / Atelier review gate = deferred this milestone. | The vendored Atelier (`mcp/atelier/vendor`) could review the synced tree before commit and block on P0, but that's an additive hardening step, not part of establishing the pipeline. Deferred to a future milestone. | Sync ships consumer contents as-is; no review gate. |
|
||||||
|
|
||||||
|
### CLARIFY auto-resolved parameters (full autonomy)
|
||||||
|
|
||||||
|
The following ambiguities were identified and auto-resolved at full
|
||||||
|
autonomy (no human escalation needed — confidence > 0.6 threshold):
|
||||||
|
|
||||||
|
1. **Fix scope** — comprehensive (theme CSS + render scripts + mermaid
|
||||||
|
re-layout + deck content + tests) vs. minimal. **Resolved: comprehensive.**
|
||||||
|
The root cause spans all four layers; a theme-only fix would leave
|
||||||
|
the extreme-aspect-ratio diagrams and the stale `render_deck.sh`
|
||||||
|
unfixed. Confidence: 0.95.
|
||||||
|
|
||||||
|
2. **Pipeline depth** — full pipeline (SPECIFY→CLARIFY→RESEARCH→PLAN→
|
||||||
|
GRILL→EXECUTE→VERIFY→SHIP) vs. lighter path. **Resolved: full pipeline.**
|
||||||
|
This is a new milestone (v1.22); the full pipeline ensures the plan
|
||||||
|
is grilled and the audit trail is complete. Confidence: 0.9.
|
||||||
|
|
||||||
|
3. **Mermaid diagram fixes** — re-layout to LR + re-render vs. CSS-only
|
||||||
|
fix. **Resolved: re-layout to LR + re-render at 2x transparent.**
|
||||||
|
The `telemetry-live-ops.mmd` uses `flowchart TB` (produced a 1024×1628
|
||||||
|
PNG — aspect 0.63); the README (line 168) explicitly says to use
|
||||||
|
horizontal layouts for wide diagrams. CSS-only cannot fix the aspect
|
||||||
|
ratio. Confidence: 0.95.
|
||||||
|
|
||||||
|
4. **`render_deck.sh` disposition** — fix (add `--theme`) vs. delete.
|
||||||
|
**Resolved: delete.** The README already documents `render_slides.sh`
|
||||||
|
as canonical; `render_deck.sh` is unreferenced by the build-commands
|
||||||
|
section and is a footgun (produces unthemed output). Confidence: 0.9.
|
||||||
|
|
||||||
|
5. **Slide count change** — keep 18 main + 1 appendix vs. split
|
||||||
|
overflowing slides. **Resolved: split slides 3 and 8** (18 → 20 main
|
||||||
|
+ 1 appendix). The `test_marp_deck_slide_count` test + README
|
||||||
|
convention are updated to match. Confidence: 0.85.
|
||||||
|
|
||||||
|
No human escalation. All decisions logged with confidence scores above
|
||||||
|
the 0.6 threshold.
|
||||||
|
|
||||||
|
## Objective for Milestone v1.22 (active — Nova Deck Layout Fix)
|
||||||
|
|
||||||
|
v1.22 fixes the systemic layout/formatting problems in the Nova
|
||||||
|
presentation deck that made every slide look "out of whack" after the
|
||||||
|
v1.21 P5 re-render. A full investigation determined the root cause is
|
||||||
|
**not a P5 regression** — the `nova-sp-theme.css` has had zero `section`
|
||||||
|
padding since it was authored (it declares `/* @theme nova-sp */` as a
|
||||||
|
comment, not the `@theme` directive, and does not `@import` Marp's
|
||||||
|
default theme, so Marp's default `section { padding: 56px 64px }` never
|
||||||
|
applies). Combined with `overflow:hidden` (silent clip), a blunt
|
||||||
|
`img { max-height: 320px }` rule, header+footer chrome on every slide,
|
||||||
|
and two new P5 diagrams with extreme aspect ratios (13.52× and 0.63×),
|
||||||
|
8 of 19 slides overflow and the rest look jammed against the edges.
|
||||||
|
|
||||||
|
This milestone is a **comprehensive fix** across four layers: (1) the
|
||||||
|
theme CSS (padding, overflow handling, aspect-ratio-aware image rules,
|
||||||
|
title-slide chrome suppression, paragraph/list/table spacing); (2) the
|
||||||
|
render scripts (delete the stale unthemed `render_deck.sh`, pin
|
||||||
|
marp-cli/mermaid-cli versions, add 2x scale + transparent bg to
|
||||||
|
mermaid); (3) the two problematic mermaid diagrams (re-layout to LR +
|
||||||
|
2-row wrap); (4) the deck content (trim/split the 8 overflowing slides,
|
||||||
|
remove the redundant `header:` from frontmatter). It also adds the
|
||||||
|
**layout/aspect-ratio/theme-structural tests** that were missing — the
|
||||||
|
gap that let this regression through undetected.
|
||||||
|
|
||||||
|
**Milestone type:** NFR (all phases are fix/docs/test — no feat/breaking).
|
||||||
|
Tags run on the **v1.21.x** patch line (previous minor per
|
||||||
|
branch-strategy): `v1.21.0` (P0) → `v1.21.1..v1.21.5` (P1–P5) →
|
||||||
|
`v1.21.6` (P6 final = milestone release).
|
||||||
|
|
||||||
|
**Phase count:** 7 (P0 pre-execution + 5 execution + 1 final).
|
||||||
|
|
||||||
|
**Wave ordering:**
|
||||||
|
- Wave 1 (P1 + P2, parallel): theme CSS + render scripts — no
|
||||||
|
interdependency. P1 establishes the padding/overflow/image budget that
|
||||||
|
P4's content trimming relies on; P2 fixes the render pipeline that P3's
|
||||||
|
PNG re-render depends on.
|
||||||
|
- Wave 2 (P3 + P4, parallel): mermaid re-layout + deck content. P3
|
||||||
|
depends on P2 (2x scale flag); P4 depends on P1 (padding budget).
|
||||||
|
- Wave 3 (P5): re-render HTML + PPTX + add tests. Depends on all above.
|
||||||
|
- Wave 4 (P6): final review + audit + milestone ship.
|
||||||
|
|
||||||
|
**Hard constraints:**
|
||||||
|
- DO NOT change the deck narrative or the 4-beat arc (Problem → Solution
|
||||||
|
→ Proof → Roadmap + Ask) — only fix layout/formatting.
|
||||||
|
- DO NOT re-introduce badges, version strings, or internal citations
|
||||||
|
(D-###/REQ-###/.py paths) that v1.21 removed.
|
||||||
|
- The slide count may change from 18 main + 1 appendix to 20 main + 1
|
||||||
|
appendix (splitting slides 3 and 8 to relieve overflow). The
|
||||||
|
`test_marp_deck_slide_count` test + README "18 main + 1 appendix"
|
||||||
|
convention must be updated to match.
|
||||||
|
- PPTX remains a first-class committed artifact + release attachment.
|
||||||
|
- No code changes outside `docs/presentations/`, `scripts/render*.sh`,
|
||||||
|
and `tests/test_slides_pipeline.py`.
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
New requirements REQ-254..REQ-262 — see `REQUIREMENTS.md` §v1.22. Summary:
|
||||||
|
|
||||||
|
- **REQ-254:** Theme CSS — add `section` padding + overflow handling.
|
||||||
|
- **REQ-255:** Theme CSS — aspect-ratio-aware image rules (replace blunt
|
||||||
|
`max-height:320px`).
|
||||||
|
- **REQ-256:** Theme CSS — title-slide chrome suppression + paragraph/
|
||||||
|
list/table spacing tightening.
|
||||||
|
- **REQ-257:** Render scripts — delete `render_deck.sh` (or fix `--theme`);
|
||||||
|
pin marp-cli/mermaid-cli versions.
|
||||||
|
- **REQ-258:** `render_slides.sh` — add `-s 2 -b transparent` to mermaid-cli
|
||||||
|
(README spec).
|
||||||
|
- **REQ-259:** Re-layout `telemetry-live-ops.mmd` from `flowchart TB` →
|
||||||
|
`flowchart LR`; re-render PNG at 2x transparent.
|
||||||
|
- **REQ-260:** Re-layout `platform-pipeline.mmd` to 2-row subgraph wrap;
|
||||||
|
re-render PNG at 2x transparent.
|
||||||
|
- **REQ-261:** Trim/split 8 overflowing slides (3, 5, 6, 8, 9, 12, 15,
|
||||||
|
A1) + remove redundant `header:` from frontmatter.
|
||||||
|
- **REQ-262:** Re-render HTML + PPTX + add layout/aspect-ratio/theme-
|
||||||
|
structural tests.
|
||||||
|
|||||||
+753
-29
@@ -1132,35 +1132,35 @@ with documented schemas.
|
|||||||
|
|
||||||
| Requirement | Phase | Status |
|
| Requirement | Phase | Status |
|
||||||
|-------------|-------|--------|
|
|-------------|-------|--------|
|
||||||
| REQ-185 | P0 | in_progress |
|
| REQ-185 | P0 | complete |
|
||||||
| REQ-186 | P4 | pending |
|
| REQ-186 | P4 | complete |
|
||||||
| REQ-187 | P1 | pending |
|
| REQ-187 | P1 | complete |
|
||||||
| REQ-188 | P1 | pending |
|
| REQ-188 | P1 | complete |
|
||||||
| REQ-189 | P2 | pending |
|
| REQ-189 | P2 | complete |
|
||||||
| REQ-190 | P3 | pending |
|
| REQ-190 | P3 | complete |
|
||||||
| REQ-191 | P4 | pending |
|
| REQ-191 | P4 | complete |
|
||||||
| REQ-192 | P4 | pending |
|
| REQ-192 | P4 | complete |
|
||||||
| REQ-193 | P4 | pending |
|
| REQ-193 | P4 | complete |
|
||||||
| REQ-194 | P4 | pending |
|
| REQ-194 | P4 | complete |
|
||||||
| REQ-195 | P4 | pending |
|
| REQ-195 | P4 | complete |
|
||||||
| REQ-196 | P5 | pending |
|
| REQ-196 | P5 | complete |
|
||||||
| REQ-197 | P5 | pending |
|
| REQ-197 | P5 | complete |
|
||||||
| REQ-198 | P6 | pending |
|
| REQ-198 | P6 | complete |
|
||||||
| REQ-199 | P3 | pending |
|
| REQ-199 | P3 | complete |
|
||||||
| REQ-200 | P2 | pending |
|
| REQ-200 | P2 | complete |
|
||||||
| REQ-201 | P2 | pending |
|
| REQ-201 | P2 | complete |
|
||||||
| REQ-202 | P5 | pending |
|
| REQ-202 | P5 | complete |
|
||||||
| REQ-203 | P5 | pending |
|
| REQ-203 | P5 | complete |
|
||||||
| REQ-204 | P4 | pending |
|
| REQ-204 | P4 | complete |
|
||||||
| REQ-205 | P1+P2+P3 | pending |
|
| REQ-205 | P1+P2+P3 | complete |
|
||||||
| REQ-206 | P1+P2 | pending |
|
| REQ-206 | P1+P2 | complete |
|
||||||
| REQ-207 | P2 | pending |
|
| REQ-207 | P2 | complete |
|
||||||
| REQ-208 | P3 | pending |
|
| REQ-208 | P3 | complete |
|
||||||
| REQ-209 | P3/P4 | pending |
|
| REQ-209 | P3/P4 | complete |
|
||||||
| REQ-210 | P4 | pending |
|
| REQ-210 | P4 | complete |
|
||||||
| REQ-211 | P4 | pending |
|
| REQ-211 | P4 | complete |
|
||||||
| REQ-212 | P4 | pending |
|
| REQ-212 | P4 | complete |
|
||||||
| REQ-213 | P4/P5 | pending |
|
| REQ-213 | P4/P5 | complete |
|
||||||
|
|
||||||
### Out of Scope (v1.17)
|
### Out of Scope (v1.17)
|
||||||
|
|
||||||
@@ -1180,3 +1180,727 @@ with documented schemas.
|
|||||||
- A third deck — the two existing decks merge into one; no new
|
- A third deck — the two existing decks merge into one; no new
|
||||||
standalone metrics deck.
|
standalone metrics deck.
|
||||||
- A Nova web UI — dashboards are PowerBI, not a Nova-built frontend.
|
- A Nova web UI — dashboards are PowerBI, not a Nova-built frontend.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.18 — Citizen Developer & Production-Grade Guidance
|
||||||
|
|
||||||
|
> **Milestone type:** Feature. Tags run on the v1.17.x patch line (previous
|
||||||
|
> minor per branch-strategy). `v1.17.0` (P0) → `v1.17.1..v1.17.6` (P1–P6) →
|
||||||
|
> `v1.17.7` (P7 final = milestone release).
|
||||||
|
> **Active milestone:** v1.18. **Branch:**
|
||||||
|
> `milestone/v1.18-citizen-developer-guidance`.
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
- **REQ-214** — S&P Global Energy Marp theme restored in the unified deck
|
||||||
|
(`docs/presentations/nova-no-humans-platform-marp.md`). The `style:` block
|
||||||
|
from commit `ae0cb58` (v1.9.2 / P45) is ported: H1/H2 `#D6002A`
|
||||||
|
(S&P red-core), title-slide bg `#1B1B1B` (grey-90) with 8px `#D6002A` top
|
||||||
|
accent bar, body text `#1B1B1B`, blockquote border `#D6002A`,
|
||||||
|
table headers `#F0F0F0`, font `'Akkurat Pro'` with web-safe fallbacks. The
|
||||||
|
current Nova header/footer text is preserved (rebrand is not touched —
|
||||||
|
only the visual theme is restored). HTML re-rendered with the S&P theme.
|
||||||
|
|
||||||
|
- **REQ-215** — RACI matrix authored in `PROJECT.md` (new `## RACI Matrix`
|
||||||
|
section) and `docs/raci.md` (citizen-developer-facing copy). Three roles:
|
||||||
|
**Citizen Developer** (Responsible for all Functional Requirements + User
|
||||||
|
Acceptance Testing — via their AI coding agent / upstream agentic SDLC /
|
||||||
|
upstream development platform; the source does not matter as all are
|
||||||
|
subject to the same compliance standards), **Platform** (Responsible for
|
||||||
|
all NFRs + Infrastructure + QA + Production deployments to cloud),
|
||||||
|
**Release Management** (co-owned: QA + SRE attestations required by the
|
||||||
|
actual release, performed agentically but overseen & triggered by the
|
||||||
|
Citizen Developer). Rendered as a table: rows = work categories (FRs, UAT,
|
||||||
|
NFRs, Infra, QA, Prod deploy, Release attestation), columns = R/A/C/I per
|
||||||
|
role. Includes the compliance-standard-equivalence note.
|
||||||
|
|
||||||
|
- **REQ-216** — PDLC-upstream scope statement made explicit in `PROJECT.md`
|
||||||
|
(new `## Scope: Nova is Downstream of PDLC` subsection under Domain
|
||||||
|
Boundaries) and `docs/scope.md`. States that the PDLC (Product Development
|
||||||
|
Lifecycle — product backlog, code authorship, IDE) is upstream of Nova;
|
||||||
|
Nova governs infra + delivery only; integration is through the validated
|
||||||
|
contract boundary. Promotes Core Tenet #2 + Anti-Goal #1 from buried
|
||||||
|
tenets to a dedicated, unmissable scope statement.
|
||||||
|
|
||||||
|
- **REQ-217** — `schemas/submission-readiness.schema.json` (JSON Schema
|
||||||
|
draft 2020-12) defines what is acceptable to start — a superset gate
|
||||||
|
*above* `contract.schema.json` validity. Required fields: `contractId`
|
||||||
|
(non-empty), `environment` (dev/qa/prod/dr) with the W3.E per-env mandatory
|
||||||
|
table enforced (dev: stack+environment; qa: +validation.e2eSuite
|
||||||
|
+validation.loadTest; prod: +runbook+dashboard+oncall; dr: +drDrillRef),
|
||||||
|
`tags` (the 5 required Nova tags per D-054: `nova:owner`, `nova:contract`,
|
||||||
|
`nova:environment`, `nova:cost-center`, `nova:ref`), `policyPreconditions`
|
||||||
|
(declared policy expectations the platform will enforce, e.g.,
|
||||||
|
`public-ingress: false`), `profile` (`developer` or `agentic`; if
|
||||||
|
`agentic`, requires `naturalLanguageIntent`, `confidenceAtSubmission`,
|
||||||
|
`agentTrace` per REQ-22 / W3.E), `appSource` (repo + ref pointer for
|
||||||
|
runtime fetch).
|
||||||
|
|
||||||
|
- **REQ-218** — `core/submission_readiness.py` validator, invoked as
|
||||||
|
`contract_ingestor.py --check-readiness` subcommand (decision D-133). Returns
|
||||||
|
a structured `ReadinessResult` (pass/fail per check, with reason codes).
|
||||||
|
On fail → the ingestor rejects with a citizen-developer-facing error
|
||||||
|
(not a stack trace). On pass → proceeds to existing contract ingestion.
|
||||||
|
Calls `contract.schema.json` validation first, then the readiness checks.
|
||||||
|
Reason codes: `MISSING_TAGS`, `ENV_MISSING_MANDATORY:<env>:<field>`,
|
||||||
|
`AGENTIC_MISSING_INTENT`, `MISSING_APP_SOURCE`, `POLICY_PRECONDITION_MISSING`.
|
||||||
|
|
||||||
|
- **REQ-219** — `docs/submission-readiness.md` citizen-developer-facing doc
|
||||||
|
explaining what is acceptable to start, with good + rejected examples and
|
||||||
|
the reason-code catalog. References `schemas/submission-readiness.schema.json`
|
||||||
|
as the source of truth.
|
||||||
|
|
||||||
|
- **REQ-220** — `tests/test_submission_readiness.py` covers: good contract
|
||||||
|
passes; missing tags fail with `MISSING_TAGS`; missing env mandatory fails
|
||||||
|
with `ENV_MISSING_MANDATORY:<env>:<field>`; agentic profile missing intent
|
||||||
|
fails with `AGENTIC_MISSING_INTENT`; missing appSource fails with
|
||||||
|
`MISSING_APP_SOURCE`.
|
||||||
|
|
||||||
|
- **REQ-221** — `skills/` directory with 9 Atelier-derived skill files mapped
|
||||||
|
to the BA.A citizen-developer catalog: `skills/api.md` (domains/api/),
|
||||||
|
`skills/security.md` (domains/security/), `skills/data.md` (domains/data/),
|
||||||
|
`skills/testing.md` (domains/testing/), `skills/observability.md`
|
||||||
|
(domains/observability/), `skills/errors.md` (domains/errors/),
|
||||||
|
`skills/devops.md` (domains/devops/), `skills/infrastructure-as-code.md`
|
||||||
|
(domains/infrastructure-as-code/), `skills/compliance.md`
|
||||||
|
(domains/compliance/). Each names the Atelier source path, distills the
|
||||||
|
first-principles to the citizen-developer-relevant subset, links to
|
||||||
|
agent-checklist triggers, and maps to the BA.A 5-skill catalog (web API,
|
||||||
|
worker, scheduled job, static asset, basic observability bootstrap).
|
||||||
|
|
||||||
|
- **REQ-222** — `docs/skills.md` index page listing the skill catalog, the
|
||||||
|
Atelier provenance, and how the citizen developer's AI agent consumes them
|
||||||
|
(read before completing a task; run `review/agent-checklist.md` before
|
||||||
|
finishing). `PROJECT.md` BA.A decision extended with the Atelier-derived
|
||||||
|
skill catalog reference.
|
||||||
|
|
||||||
|
- **REQ-223** — `mcp/atelier/server.py` MCP server (stdio transport,
|
||||||
|
decision D-135) with a **plugin-registry architecture** (decision D-140):
|
||||||
|
`plugins/<name>.py` modules each expose `register(mcp: MCPServer) -> None`
|
||||||
|
and call `@mcp.tool()` for their tools; `server.py` scans `plugins/` and
|
||||||
|
calls `register` on each. Initial plugins: `principles.py`
|
||||||
|
(`atelier.lookup_principle`, `atelier.list_domains`, `atelier.matrix_lookup`)
|
||||||
|
and `validation.py` (`atelier.validate_against_principles` — agentic
|
||||||
|
validation against the Atelier agent-checklist, beyond Wiz/Checkmarx/Mend).
|
||||||
|
Uses the MCP Python SDK v2 (`modelcontextprotocol/python-sdk`).
|
||||||
|
|
||||||
|
- **REQ-224** — `mcp/atelier/vendor/` vendored Atelier snapshot (pinned tag,
|
||||||
|
decision D-136) for audit reproducibility. `mcp/atelier/vendor/VERSION.md`
|
||||||
|
records the pinned tag + a `scripts/update_atelier_vendor.sh` helper for
|
||||||
|
intentional upgrades. `mcp/atelier/README.md` documents the server: how to
|
||||||
|
run, transport, tool catalog, plugin-authoring guide, vendoring policy.
|
||||||
|
|
||||||
|
- **REQ-225** — `tests/test_atelier_mcp.py` covers: tool registration (all 4
|
||||||
|
tools discoverable via `tools/list`), `atelier.lookup_principle` returns
|
||||||
|
the principle text + core C-rule, `atelier.validate_against_principles`
|
||||||
|
catches a planted C1 (correctness) + C7 (observability) violation in a
|
||||||
|
known-bad snippet and passes a known-good snippet, `atelier.matrix_lookup`
|
||||||
|
returns the domain→core mapping, plugin discovery loads all plugins in
|
||||||
|
`plugins/`.
|
||||||
|
|
||||||
|
- **REQ-226** — 3 new deck slides added to the unified deck
|
||||||
|
(`docs/presentations/nova-no-humans-platform-marp.md`) → 21 slides total:
|
||||||
|
Slide 19 "Scope: Downstream of PDLC", Slide 20 "RACI: Who Owns What",
|
||||||
|
Slide 21 "Production-Grade Guidance via Atelier". Arc Preview slide
|
||||||
|
updated to reflect 21-slide count. Talking points
|
||||||
|
(`nova-no-humans-platform-talking-points.md`) synced for the 3 new slides.
|
||||||
|
S&P theme preserved (regression check vs P1). CAP-024 deck structure
|
||||||
|
regression passes.
|
||||||
|
|
||||||
|
- **REQ-227** — `docs/presentations/README.md` slide count + deck table
|
||||||
|
updated to reflect 21 slides + the 3 new slide titles.
|
||||||
|
|
||||||
|
- **REQ-228** — `scripts/render_deck.sh` (renders HTML + PPTX from a Marp
|
||||||
|
deck, commits both to git) and `scripts/attach_release_asset.py` (uploads
|
||||||
|
a file to a Gitea release via the API). Any phase modifying
|
||||||
|
`docs/presentations/*-marp.md` or `docs/presentations/assets/` MUST
|
||||||
|
re-render HTML + PPTX, commit the PPTX binary to `docs/presentations/`,
|
||||||
|
and attach it to the phase's Gitea release. PPTX is stored as a committed
|
||||||
|
binary (no LFS, decision D-141).
|
||||||
|
|
||||||
|
### Out of Scope (v1.18)
|
||||||
|
|
||||||
|
- **Streamable HTTP transport for the MCP server** — stdio ships now; HTTP
|
||||||
|
is a future milestone (the SDK supports it on the same server object, so
|
||||||
|
adding it later is a transport-only change, not a rewrite).
|
||||||
|
- **A Nova-built frontend / dashboard** — observability stays PowerBI /
|
||||||
|
external; no Nova web UI.
|
||||||
|
- **Replacing the existing BA.A 5-skill catalog** — the Atelier-derived
|
||||||
|
skills extend it, not replace it.
|
||||||
|
- **Live AWS re-provisioning** (D-096, still deferred) — submission-readiness
|
||||||
|
validates the contract shape, not a live AWS deployment.
|
||||||
|
- **A second forge adapter** (GitLab) — BA.F cross-platform evolution is
|
||||||
|
future work.
|
||||||
|
- **Atelier live-fetch mode** — vendoring is the only mode this milestone;
|
||||||
|
live-fetch (with its reproducibility trade-offs) is not implemented.
|
||||||
|
|
||||||
|
### v1.18 Traceability
|
||||||
|
|
||||||
|
| REQ | Phase | Status |
|
||||||
|
|-----|-------|--------|
|
||||||
|
| REQ-214 | P1 | complete |
|
||||||
|
| REQ-215 | P2 | complete |
|
||||||
|
| REQ-216 | P2 | complete |
|
||||||
|
| REQ-217 | P3 | complete |
|
||||||
|
| REQ-218 | P3 | complete |
|
||||||
|
| REQ-219 | P3 | complete |
|
||||||
|
| REQ-220 | P3 | complete |
|
||||||
|
| REQ-221 | P4 | complete |
|
||||||
|
| REQ-222 | P4 | complete |
|
||||||
|
| REQ-223 | P5 | complete |
|
||||||
|
| REQ-224 | P5 | complete |
|
||||||
|
| REQ-225 | P5 | complete |
|
||||||
|
| REQ-226 | P6 | complete |
|
||||||
|
| REQ-227 | P6 | complete |
|
||||||
|
| REQ-228 | P1/P2/P6 | complete |
|
||||||
|
|
||||||
|
## v1.19 — Nova 2nd-Release Sync (GitLab consumer mirror)
|
||||||
|
|
||||||
|
> **NFR-only chore milestone.** A single execution phase shipping a patch on
|
||||||
|
> the v1.18.x line (tag `v1.18.0`). Establishes the manual-only "2nd release"
|
||||||
|
> pipeline from `~/acdl` (CIAgent-managed source of truth) into `~/nova`
|
||||||
|
> (GitLab `jonathanchery/nova` — a separate repo, separate history, consumer /
|
||||||
|
> platform-team audience). `~/acdl` retains the full CIAgent audit trail;
|
||||||
|
> `~/nova` receives only the consumer subset, committed with real
|
||||||
|
> conventional commits per domain (no kitchen-sink "sync from source mirror").
|
||||||
|
|
||||||
|
- **REQ-229** — `scripts/sync_to_nova.sh` replaces `scripts/sync_to_gl.sh`.
|
||||||
|
The script: (1) refuses to run without `--release` / `RELEASE_CONFIRMED=1`
|
||||||
|
(manual-only — never triggerable by CI); (2) rsyncs the consumer subset of
|
||||||
|
`~/acdl` into `~/nova`, excluding `.ciagent/`, `.gitea/`, `.env*`, `terraform/`,
|
||||||
|
`demo/`, runtime metrics artifacts, and internal-only scripts (full list in
|
||||||
|
`EXCLUDE_SCRIPTS`), while protecting `~/nova/.git` history via rsync
|
||||||
|
`--filter=P .git`; (3) commits changes domain-by-domain in a fixed order
|
||||||
|
(config → core → adapters → modules → contracts → schemas → pipelines →
|
||||||
|
mcp → skills → scripts → tests → docs → workflows) using one
|
||||||
|
conventional-commit message per changed domain passed via repeated `-m`
|
||||||
|
flags (positional mapping over changed domains only — no kitchen-sink
|
||||||
|
commit); (4) validates conventional-commit format (`feat|fix|docs|chore|…`)
|
||||||
|
unless `--no-verify-format`; (5) pushes to the branch upstream unless
|
||||||
|
`--no-push`. `--list-domains`, `--dry-run`, `-v` supported. The old
|
||||||
|
`sync_to_gl.sh` is removed. (Phase P1)
|
||||||
|
|
||||||
|
### Out of Scope (v1.19)
|
||||||
|
|
||||||
|
- **coreci / Atelier review gate on the synced tree** — deferred; the sync
|
||||||
|
ships consumer contents as-is. A future milestone may run a vendored-Atelier
|
||||||
|
review pass before commit and block on P0 findings.
|
||||||
|
- **Tagging releases on the `~/nova` side** — could add `--tag <semver>` later.
|
||||||
|
- **Deleting `~/gl`** — the old GitLab `acdl` mirror is left on disk; only the
|
||||||
|
sync script targeting it is removed.
|
||||||
|
|
||||||
|
### v1.19 Traceability
|
||||||
|
|
||||||
|
| REQ | Phase | Status |
|
||||||
|
|-----|-------|--------|
|
||||||
|
| REQ-229 | P1 | complete |
|
||||||
|
|
||||||
|
## v1.20 — Consumer Cleanup + Transparent Terraform + Slide Pipeline
|
||||||
|
|
||||||
|
> **Multi-concern milestone.** Four user-directed inputs spanning consumer
|
||||||
|
> cleanup, infrastructure transparency, and presentation automation. Tags
|
||||||
|
> run on the v1.19.x line (milestone v1.20 → tags v1.19.0, v1.19.1, …).
|
||||||
|
>
|
||||||
|
> **Input 1 — Gitea/GitLab removal:** Remove all mentions of `gitea` / `gitlab`
|
||||||
|
> (case-insensitive) from every file synced to `~/nova`. The platform team
|
||||||
|
> (consumer of `~/nova`) must never know about the dev forge or the GitLab
|
||||||
|
> mirror. Genericize forge-detection code to `forge` / `generic_forge`.
|
||||||
|
>
|
||||||
|
> **Input 2 — Documentation simplification:** Radically simplify all synced
|
||||||
|
> documentation. Anything the CIAgent needs to reference for itself lives in
|
||||||
|
> `.ciagent/`. Everything else is tailored to the Platform Team audience.
|
||||||
|
> Strip ciagent-internal provenance (REQ-/D-/P-/CAP- IDs, milestone headers,
|
||||||
|
> `.ciagent/PROJECT.md` citations) from synced docs. Delete completed
|
||||||
|
> migration guides. Move internal artifacts to `.ciagent/`.
|
||||||
|
>
|
||||||
|
> **Input 3 — Transparent terraform:** Move terraform `init` / `validate` /
|
||||||
|
> `plan` / `apply` / `output` into native workflow steps (transparent, visible
|
||||||
|
> in CI logs). Split `run_platform.sh` into `run_codegen.sh` (pre-TF) +
|
||||||
|
> `run_postapply.sh` (post-TF). Add `var.enabled` feature flags to every L1
|
||||||
|
> module + L2 composition toggles. Wire forge repo variables as per-client
|
||||||
|
> feature flags — different clients test different functionality without
|
||||||
|
> version upgrades.
|
||||||
|
>
|
||||||
|
> **Input 4 — Slide pipeline + product roadmap:** The slides have not adopted
|
||||||
|
> the S&P Global theme fully. Create a dedicated render pipeline that builds
|
||||||
|
> the slides (mermaid PNGs + Marp HTML/PPTX) with the S&P theme applied to all
|
||||||
|
> slide chrome. Add a 12-month product roadmap (high-level, product-oriented
|
||||||
|
> vs the technical roadmap in `.ciagent/ROADMAP.md`) to the deck.
|
||||||
|
|
||||||
|
- **REQ-230** — No `gitea` / `gitlab` string literal (case-insensitive) appears
|
||||||
|
in any file synced to `~/nova`. Verified by
|
||||||
|
`tests/test_no_forge_mentions.py` which scans the synced subset (same
|
||||||
|
path rules as `sync_to_nova.sh`'s `DOMAINS` / `EXCLUDES`). Forge-detection
|
||||||
|
code (`contract_ingestor.py`, `hitl_gates.py`, `run_platform.sh`) is
|
||||||
|
genericized: `gitea` → `forge` / `generic_forge`, `GITEA_ACTOR` →
|
||||||
|
`FORGE_ACTOR` (with `GITHUB_ACTOR` primary). (Phase P1)
|
||||||
|
|
||||||
|
- **REQ-231** — Synced documentation is tailored to the Platform Team
|
||||||
|
audience. Ciagent-internal provenance (`v1.XX — Strategic Direction` headers,
|
||||||
|
`REQ-NNN` / `D-NNN` / `P-NNN` / `CAP-NNN` IDs, `.ciagent/PROJECT.md`
|
||||||
|
"source of truth" citations) is stripped from synced docs. (Phase P1)
|
||||||
|
|
||||||
|
- **REQ-232** — Completed/historical migration docs
|
||||||
|
(`docs/NOVA_MIGRATION.md`, `docs/NOVA_AWS_MIGRATION.md`) removed from the
|
||||||
|
synced tree. `docs/NO_HUMANS_THESIS.md` moved to `.ciagent/` (internal
|
||||||
|
thesis-defense artifact). (Phase P1)
|
||||||
|
|
||||||
|
- **REQ-233** — Terraform `init` / `validate` / `plan` / `apply` / `output`
|
||||||
|
run as native workflow steps in `deploy.yml` (transparent, named steps
|
||||||
|
visible in CI logs), not buried inside `run_platform.sh`. (Phase P4)
|
||||||
|
|
||||||
|
- **REQ-234** — `run_platform.sh` is split: `run_codegen.sh` (pre-TF: env
|
||||||
|
check, validate, resolve, adapt) + `run_postapply.sh` (post-TF: Checkov,
|
||||||
|
confidence, HITL, outbox, SSM, comment, uptime). A thin `run_platform.sh`
|
||||||
|
shim preserves backward compat for local-dev usage. (Phase P4)
|
||||||
|
|
||||||
|
- **REQ-235** — Every L1 module has `variable "enabled" { type = bool,
|
||||||
|
default = true }` + `count = var.enabled ? 1 : 0` on its primary
|
||||||
|
resource(s); declared in `interface.json`. The `uptime` module's
|
||||||
|
`feature_flag_enabled` is renamed to `enabled` (with backward-compat alias).
|
||||||
|
(Phase P4)
|
||||||
|
|
||||||
|
- **REQ-236** — L2 `composition.json` supports per-child `enabled` toggles
|
||||||
|
driven by contract `inputs.enable_<child>`. The resolver skips children
|
||||||
|
with `enabled: false`. (Phase P4)
|
||||||
|
|
||||||
|
- **REQ-237** — `deploy.yml` reads feature flags from forge repository
|
||||||
|
variables (`vars.ENABLE_*`) and passes them as `-var` flags to terraform,
|
||||||
|
enabling per-client feature toggles without version upgrades. (Phase P4)
|
||||||
|
|
||||||
|
- **REQ-238** — Stale artifact path `/tmp/acdl_platform_run_v18` in
|
||||||
|
`deploy.yml` fixed to use `NOVA_WORK_DIR`. (Phase P4)
|
||||||
|
|
||||||
|
- **REQ-239** — A dedicated S&P Global theme CSS file
|
||||||
|
(`docs/presentations/assets/nova-sp-theme.css`) is the Marp theme for all
|
||||||
|
Nova presentation decks. The theme applies the S&P Red/Black/White palette
|
||||||
|
(`#D6002A`, `#1B1B1B`, `#FFFFFF`) to all slide chrome (background,
|
||||||
|
header/footer, pagination, tables, blockquotes), not just headings. (Phase P2)
|
||||||
|
|
||||||
|
- **REQ-240** — A dedicated render pipeline (`scripts/render_slides.sh`)
|
||||||
|
builds the presentation deck end-to-end: (1) renders all
|
||||||
|
`assets/mmd/*.mmd` → `assets/png/*.png` via `mermaid-cli --configFile
|
||||||
|
sp-theme.json`; (2) renders the Marp deck → HTML + PPTX via `marp-cli`;
|
||||||
|
(3) stages all rendered artifacts to git. Supersedes `render_deck.sh`.
|
||||||
|
(Phase P2)
|
||||||
|
|
||||||
|
- **REQ-241** — A CI workflow (`workflows-src/slides.yml` +
|
||||||
|
`.github/workflows/slides.yml`) runs `render_slides.sh` on any change to
|
||||||
|
`docs/presentations/**` and commits the rendered HTML/PPTX/PNGs back. No
|
||||||
|
manual re-render step; no artifact drift. (Phase P2)
|
||||||
|
|
||||||
|
- **REQ-242** — `tests/test_slides_pipeline.py` validates: (1) the Marp
|
||||||
|
deck frontmatter references `nova-sp-theme.css`; (2) the CSS contains the
|
||||||
|
S&P colors; (3) every `.mmd` has a corresponding `.png`; (4) the HTML
|
||||||
|
exists and is newer than the Marp `.md`. (Phase P2)
|
||||||
|
|
||||||
|
- **REQ-243** — `docs/presentations/README.md` directory layout is updated
|
||||||
|
to remove retired decks (`how-the-platform-works-*`,
|
||||||
|
`the-developer-experience-*`) and document the render pipeline + theme CSS.
|
||||||
|
(Phase P2)
|
||||||
|
|
||||||
|
- **REQ-244** — A 12-month product roadmap (4 quarters, product-outcome
|
||||||
|
oriented, grounded in NORTH_STAR strategic objectives + deferred-metric
|
||||||
|
candidate milestones) is added to the presentation deck as Slide 20 +
|
||||||
|
Slide 21. The roadmap is distinct from Slide 15's deferred-metric unblock
|
||||||
|
paths. A matching talking-points section is added. (Phase P3)
|
||||||
|
|
||||||
|
### Out of Scope (v1.20)
|
||||||
|
|
||||||
|
- **Multi-cloud (Azure/GCP) implementation** — deferred; only the product
|
||||||
|
roadmap references it as a Q4 aspiration.
|
||||||
|
- **ML anomaly-forecasting service** — deferred; only the product roadmap
|
||||||
|
references it as a Q4 aspiration.
|
||||||
|
- **Actual pilot estate activation** — deferred (requires live AWS
|
||||||
|
re-provisioning, D-096 lift); the product roadmap references it as Q1.
|
||||||
|
- **Token rotation for `NOVA_GITEA_TOKEN`** — out of scope; the `.env` files
|
||||||
|
are correctly excluded from sync. Flagged for awareness only.
|
||||||
|
|
||||||
|
### v1.20 Traceability
|
||||||
|
|
||||||
|
| REQ | Phase | Status |
|
||||||
|
|-----|-------|--------|
|
||||||
|
| REQ-230 | P1 | complete |
|
||||||
|
| REQ-231 | P1 | complete |
|
||||||
|
| REQ-232 | P1 | complete |
|
||||||
|
| REQ-233 | P4 | complete |
|
||||||
|
| REQ-234 | P4 | complete |
|
||||||
|
| REQ-235 | P4 | complete |
|
||||||
|
| REQ-236 | P4 | complete |
|
||||||
|
| REQ-237 | P4 | complete |
|
||||||
|
| REQ-238 | P4 | complete |
|
||||||
|
| REQ-239 | P2 | complete |
|
||||||
|
| REQ-240 | P2 | complete |
|
||||||
|
| REQ-241 | P2 | complete |
|
||||||
|
| REQ-242 | P2 | complete |
|
||||||
|
| REQ-243 | P2 | complete |
|
||||||
|
| REQ-244 | P3 | complete |
|
||||||
|
|
||||||
|
## v1.21 — Nova Deck Refinement & Pipeline Hardening
|
||||||
|
|
||||||
|
> Leadership-deck refinement based on 33 review notes on the v1.20 deck
|
||||||
|
> (v1.20 shipped as `nova-no-humans-platform*`). This milestone renames the
|
||||||
|
> deck to the professional "Autonomous Cloud Delivery Platform" framing,
|
||||||
|
> restructures the narrative (Problem → Solution → Proof → Roadmap + Ask),
|
||||||
|
> removes internal provenance from audience-facing slides, hardens the
|
||||||
|
> policy pipeline (Checkov before plan, Wiz-or-Checkov on plan), and moves
|
||||||
|
> the strategic integration objective into the North Star.
|
||||||
|
>
|
||||||
|
> Tags run on the v1.20.x line (milestone v1.21 → tags v1.20.0, v1.20.1, …).
|
||||||
|
|
||||||
|
### REQ-245 — Deck rename + restructure
|
||||||
|
|
||||||
|
The deck files are renamed from `nova-no-humans-platform*` to
|
||||||
|
`nova-autonomous-cloud-delivery*` across all five artifacts
|
||||||
|
(source `.md`, `-marp.md`, `.html`, `.pptx`, `-talking-points.md`).
|
||||||
|
The in-deck title becomes "Nova — The Autonomous Cloud Delivery Platform"
|
||||||
|
(professional, conveys autonomy without the provocative "no-humans"
|
||||||
|
wording). The narrative restructures to 18 main + 1 appendix slides:
|
||||||
|
|
||||||
|
1. The Problem (merged old 1+2; broader problem framing; no "arc"; no
|
||||||
|
"18 capabilities verified"; not "humans are the problem"; add tribal
|
||||||
|
knowledge / rockstar-operator framing)
|
||||||
|
2. Nova's Vision
|
||||||
|
3. Strategic Objectives + Anti-Goals
|
||||||
|
4. Scope: Downstream of PDLC (moved up)
|
||||||
|
5. RACI: Who Owns What (moved up)
|
||||||
|
6. The Platform Pipeline
|
||||||
|
7. The Decision Ledger
|
||||||
|
8. The Attestation Matrix
|
||||||
|
9. Telemetry & Live Ops
|
||||||
|
10. Decision Ledger + Attestation Coverage
|
||||||
|
11. Cost & ROI
|
||||||
|
12. What's Deferred — and Why
|
||||||
|
13. Roadmap to the North Star
|
||||||
|
14. 12-Month Product Roadmap
|
||||||
|
15. Quarter-by-Quarter Outcomes
|
||||||
|
16. Production-Grade Guidance via Atelier (1/2)
|
||||||
|
17. Production-Grade Guidance via Atelier (2/2)
|
||||||
|
18. Recap + Ask
|
||||||
|
A1. Metrics Glossary
|
||||||
|
|
||||||
|
Removed: old Slide 10 (Capability Health), old Slide 12 (Zero-Touch
|
||||||
|
Efficiency), old Appendix A2 (Operating Model & Cost). Slide 5's first
|
||||||
|
table removed.
|
||||||
|
|
||||||
|
### REQ-246 — Thesis rename + reframe
|
||||||
|
|
||||||
|
`.ciagent/NO_HUMANS_THESIS.md` is renamed (git mv) to
|
||||||
|
`.ciagent/AUTONOMY_THESIS.md`. Content reframes from "removing humans" to
|
||||||
|
"autonomy in operations, human at stage gates" — professional, not
|
||||||
|
provocative. The operator-bottleneck framing is softened; the attestation
|
||||||
|
model + provable trust are emphasized. Anti-claims are retained and
|
||||||
|
reworded for a tech-leadership audience. All references across the repo
|
||||||
|
are updated to the new filename + framing.
|
||||||
|
|
||||||
|
### REQ-247 — Strategic-docs sync (NORTH_STAR + PROJECT)
|
||||||
|
|
||||||
|
`NORTH_STAR.md` is updated:
|
||||||
|
- Vision polished for a technical audience concerned about security,
|
||||||
|
security remediation velocity, and reliability; "infrastructure
|
||||||
|
operations become visible" is preserved as a recurring theme.
|
||||||
|
- Strategic Objective #2 (provable trust) is reworded: trust is
|
||||||
|
established by deterministic scripts that calculate a score, not by
|
||||||
|
AI. The platform functions without AI. "AI decisions" are really
|
||||||
|
automated decisions.
|
||||||
|
- Strategic Objective #3 (ROI) is reworded with four CTO-grade metrics:
|
||||||
|
Lead Time (PR → Production), Infrastructure Vulnerability Count
|
||||||
|
(downward trend), MTTR, Cloud Spend Reduction. All flow into PowerBI
|
||||||
|
views and are captured by the telemetry pipeline.
|
||||||
|
- Strategic Objective #4 is replaced: integrate with externally owned
|
||||||
|
PDLC, SDLC, Agentic, and Citizen Developer platforms regardless of
|
||||||
|
source; Nova provides skills + MCP endpoints to make applications
|
||||||
|
production-grade; all intents to deploy to production go through the
|
||||||
|
same rigorous controls and quality gates.
|
||||||
|
- Anti-goals #1 (hyperscaler competitor), #4 (legacy untagged), and #5
|
||||||
|
(sold to operators) are removed. Two new anti-goals added: not an
|
||||||
|
upstream development platform; not a replacement for the Product
|
||||||
|
Lifecycle (PDLC).
|
||||||
|
- Anti-goal #3 reworded to remove the "removes humans" framing.
|
||||||
|
|
||||||
|
`PROJECT.md` mission statement + scope are synchronized with the
|
||||||
|
integration objective and the reworded strategic objectives.
|
||||||
|
|
||||||
|
### REQ-248 — RACI restructure (Quality Engineering + SRE)
|
||||||
|
|
||||||
|
The RACI matrix (slide + `docs/raci.md`) is restructured:
|
||||||
|
- A **Quality Engineering** column is added.
|
||||||
|
- The Platform column no longer holds the **A** for release attestation;
|
||||||
|
accountability is reassigned to QA or SRE as appropriate.
|
||||||
|
- "Release Management" is renamed to **SRE**.
|
||||||
|
- "Release attestation" is split into two rows: the SRE part is
|
||||||
|
**Production Readiness** (operational readiness sign-off).
|
||||||
|
- The slide is sized to fit (text shrunk / low-impact rows dropped).
|
||||||
|
|
||||||
|
### REQ-249 — Atelier split (2 slides)
|
||||||
|
|
||||||
|
Slide 19 (Production-Grade Guidance via Atelier) is split into two slides:
|
||||||
|
- **16 (1/2):** Skills + MCP server overview (the 9 skills, the 4 MCP
|
||||||
|
tools, the plugin-registry + stdio surface).
|
||||||
|
- **17 (2/2):** Agentic validation beyond deterministic scanners +
|
||||||
|
vendored Atelier for audit reproducibility.
|
||||||
|
The benefit wording is improved; the same spirit is retained.
|
||||||
|
|
||||||
|
### REQ-250 — Pipeline hardening (Checkov before plan; Wiz-or-Checkov on plan)
|
||||||
|
|
||||||
|
`scripts/run_platform.sh` (and `scripts/run_postapply.sh` where
|
||||||
|
relevant) implement the two-stage policy scan:
|
||||||
|
1. **Checkov runs on static code** (the generated `main.tf` / TF
|
||||||
|
directory) **before** `terraform plan` — fail-fast, quick developer
|
||||||
|
feedback on policy violations in the authored code.
|
||||||
|
2. **After `terraform plan`:** if `WIZ_API_TOKEN` + `WIZ_API_URL` are
|
||||||
|
set, run **Wiz against the plan**; otherwise run **Checkov against
|
||||||
|
the plan** as a drop-in replacement. **Wiz and Checkov are never
|
||||||
|
both run on the plan.**
|
||||||
|
`adapters/wiz/wiz_adapter.py` is updated if needed for plan-mode
|
||||||
|
input. Slide 6 + `docs/scope.md` reflect the new flow. Tests
|
||||||
|
(`tests/test_pipeline.py`, `tests/test_pipeline_contract.py`, and
|
||||||
|
any checkov/wiz tests) are updated and pass.
|
||||||
|
|
||||||
|
### REQ-251 — Theme CSS fix (Appendix A1) + footer cleanup
|
||||||
|
|
||||||
|
`docs/presentations/assets/nova-sp-theme.css` is fixed so the Appendix
|
||||||
|
A1 Metrics Glossary table is readable (the table background color is
|
||||||
|
corrected). The Marp footer no longer shows the version (`v1.20`) or
|
||||||
|
the `Act %{page}/5` artifact. The title-slide subtitle no longer shows
|
||||||
|
`v1.18 — Citizen Developer & Production-Grade Guidance`; it becomes
|
||||||
|
"Product Development & Citizen Developer Overview" (or similar) to
|
||||||
|
convey the audience for the platform.
|
||||||
|
|
||||||
|
### REQ-252 — Global citation + badge + version removal
|
||||||
|
|
||||||
|
Across all audience-facing slides (the Marp deck, the source-of-truth
|
||||||
|
markdown, and the talking points):
|
||||||
|
- All internal citations are removed: `D-###` decision IDs,
|
||||||
|
`REQ-###` requirement IDs, and internal file paths
|
||||||
|
(e.g. `outbox_writer.py`, `confidence_signal.py`).
|
||||||
|
- All `<span class="badge planned">Planned</span>` badges are removed.
|
||||||
|
- The version is removed from the footer and the title slide.
|
||||||
|
Every benefit callout is rewritten for a tech-leadership audience
|
||||||
|
(security, remediation velocity, reliability, lead time). A "less is
|
||||||
|
more / no fluff" final prose pass is applied; the story stays clear.
|
||||||
|
|
||||||
|
### REQ-253 — Render + verify + ship
|
||||||
|
|
||||||
|
Changed/new mermaid diagrams are re-rendered (slide 1 new diagram, slide
|
||||||
|
9 expand, Atelier split). HTML + PPTX are re-rendered via
|
||||||
|
`scripts/render_slides.sh`. `tests/test_slides_pipeline.py` passes:
|
||||||
|
asserts 18 main + 1 appendix slides, no badge spans, no version in the
|
||||||
|
footer, no `D-###`/`REQ-###`/`.py` paths in audience-facing slides, and
|
||||||
|
filename refs updated in render scripts + CI workflow + README.
|
||||||
|
`tests/test_no_forge_mentions.py` passes. Full `pytest` passes
|
||||||
|
(pipeline-hardening tests green). `run_platform.sh --check-only` passes.
|
||||||
|
Milestone ship: tag the final phase on the v1.20.x line; create a
|
||||||
|
release; attach the PPTX.
|
||||||
|
|
||||||
|
### Out of Scope (v1.21)
|
||||||
|
|
||||||
|
- **Live pilot estate activation** — still deferred (D-096).
|
||||||
|
- **ML anomaly-forecasting service** — still deferred.
|
||||||
|
- **Multi-cloud (Azure/GCP) implementation** — still deferred.
|
||||||
|
- **Tamper-evident ledger (S3 Object Lock + JWS)** — still deferred
|
||||||
|
(D-083); the deck describes it as a roadmap item without citing the
|
||||||
|
decision ID in the audience-facing slides.
|
||||||
|
|
||||||
|
### v1.21 Traceability
|
||||||
|
|
||||||
|
| REQ | Phase | Status |
|
||||||
|
|-----|-------|--------|
|
||||||
|
| REQ-245 | P2 | complete |
|
||||||
|
| REQ-246 | P1 | complete |
|
||||||
|
| REQ-247 | P1 | complete |
|
||||||
|
| REQ-248 | P2 | complete |
|
||||||
|
| REQ-249 | P2 | complete |
|
||||||
|
| REQ-250 | P4 | complete |
|
||||||
|
| REQ-251 | P3 | complete |
|
||||||
|
| REQ-252 | P2 | complete |
|
||||||
|
| REQ-253 | P5 | complete |
|
||||||
|
|
||||||
|
## v1.22 — Nova Deck Layout Fix
|
||||||
|
|
||||||
|
> Fixes the systemic layout/formatting problems in the Nova presentation
|
||||||
|
> deck that made every slide look "out of whack" after the v1.21 P5
|
||||||
|
> re-render. Root cause (per investigation): `nova-sp-theme.css` has zero
|
||||||
|
> `section` padding (it declares `/* @theme nova-sp */` as a comment, not
|
||||||
|
> the `@theme` directive, and does not `@import` Marp's default theme, so
|
||||||
|
> Marp's default `section { padding: 56px 64px }` never applies). Combined
|
||||||
|
> with `overflow:hidden` (silent clip), a blunt `img { max-height: 320px }`
|
||||||
|
> rule, header+footer chrome on every slide, and two new P5 diagrams with
|
||||||
|
> extreme aspect ratios (13.52× and 0.63×), 8 of 19 slides overflow and
|
||||||
|
> the rest look jammed against the edges. This is NOT a P5 regression —
|
||||||
|
> the theme CSS is byte-identical between P3 and P5; P5's denser content
|
||||||
|
> made the pre-existing theme flaws visible.
|
||||||
|
>
|
||||||
|
> Comprehensive fix across four layers: theme CSS, render scripts, mermaid
|
||||||
|
> diagrams, deck content. Adds the layout/aspect-ratio/theme-structural
|
||||||
|
> tests that were missing (the gap that let this through).
|
||||||
|
>
|
||||||
|
> Tags run on the v1.21.x line (milestone v1.22 → tags v1.21.0, v1.21.1, …).
|
||||||
|
|
||||||
|
### REQ-254 — Theme CSS: section padding + overflow handling
|
||||||
|
|
||||||
|
`docs/presentations/assets/nova-sp-theme.css` adds a `section` padding
|
||||||
|
rule so content is not jammed against the slide edges. The padding
|
||||||
|
reserves space for the header (top) and footer (bottom) chrome: e.g.
|
||||||
|
`section { padding: 48px 56px 40px; }`. The theme also adds explicit
|
||||||
|
overflow handling on `section` so dense content is not silently clipped
|
||||||
|
by the marpit base `overflow:hidden` — either `overflow: auto` as an
|
||||||
|
authoring-time signal, or a documented shrink-to-fit rule. The fix does
|
||||||
|
NOT re-introduce Marp's default theme via `@import` (the theme remains
|
||||||
|
standalone); it explicitly sets the padding the default would have
|
||||||
|
provided.
|
||||||
|
|
||||||
|
### REQ-255 — Theme CSS: aspect-ratio-aware image rules
|
||||||
|
|
||||||
|
The blunt `img { max-height: 320px }` rule is replaced with an
|
||||||
|
aspect-ratio-aware rule that does not break the Marp `w:`/`h:` directives:
|
||||||
|
`img { max-width: 100%; max-height: 380px; object-fit: contain; }`. A
|
||||||
|
`.wide` / `.tall` class convention is added for diagrams (wide diagrams:
|
||||||
|
`max-height: 280px`; tall diagrams: `max-height: 480px`) so authors can
|
||||||
|
opt into the right bound per diagram instead of fighting a single blunt
|
||||||
|
rule. The `w:900` directive on a tall image (slide 9) no longer gets
|
||||||
|
silently overridden by `max-height`.
|
||||||
|
|
||||||
|
### REQ-256 — Theme CSS: title-slide chrome + spacing tightening
|
||||||
|
|
||||||
|
- `section.title header, section.title footer { display: none; }` — the
|
||||||
|
title slide and appendix slide no longer render header/footer chrome
|
||||||
|
that collides with content (the `<!-- _class: title -->` +
|
||||||
|
`<!-- _paginate: false -->` directives only suppress the page number,
|
||||||
|
not the chrome).
|
||||||
|
- `section h2 + p { margin-top: 0.2em; }` — tightens the spacing between
|
||||||
|
the `## Slide N — Title` heading and the bold lead paragraph that
|
||||||
|
follows it on every content slide (reclaims ~22px per slide).
|
||||||
|
- `section p { margin: 0.4em 0; }` — reduces default `<p>` margins
|
||||||
|
(~1em top/bottom) that waste vertical space on dense slides.
|
||||||
|
- `ol` styling added (matches `ul`/`li`).
|
||||||
|
- Table cell padding reduced to `4px 8px` for tables with ≥8 rows (via
|
||||||
|
a `table.dense` class or a `:nth-child` heuristic) so 10-13 row tables
|
||||||
|
(slides 8, 12, A1) fit.
|
||||||
|
- `@media print` overrides added for PPTX export fidelity.
|
||||||
|
|
||||||
|
### REQ-257 — Render scripts: delete render_deck.sh + pin CLI versions
|
||||||
|
|
||||||
|
`scripts/render_deck.sh` is **deleted** (it omits `--theme`, relying on
|
||||||
|
the frontmatter `theme: nova-sp` which Marp cannot resolve as a custom
|
||||||
|
theme without `--theme-set` — it falls back to the default theme,
|
||||||
|
producing unthemed output). The README already documents
|
||||||
|
`render_slides.sh` as the canonical script. Both `render_slides.sh` and
|
||||||
|
the deleted `render_deck.sh` references are removed from any docs/tests.
|
||||||
|
`render_slides.sh` pins marp-cli and mermaid-cli to specific versions
|
||||||
|
(replace `@latest` with pinned versions) to prevent uncontrolled
|
||||||
|
boilerplate-CSS drift like the P3→P5 HTML diff.
|
||||||
|
|
||||||
|
### REQ-258 — render_slides.sh: 2x scale + transparent bg for mermaid
|
||||||
|
|
||||||
|
The mermaid-cli invocation in `scripts/render_slides.sh` (lines 51-55)
|
||||||
|
adds `-s 2 -b transparent` to match the README spec (line 193). This
|
||||||
|
produces crisp 2x PNGs with transparent backgrounds instead of the
|
||||||
|
current 1x renders (e.g. `platform-pipeline.png` is only 1568px wide
|
||||||
|
instead of the 3136px a 2x render would produce).
|
||||||
|
|
||||||
|
### REQ-259 — Re-layout telemetry-live-ops.mmd to LR
|
||||||
|
|
||||||
|
`docs/presentations/assets/mmd/telemetry-live-ops.mmd` is rewritten from
|
||||||
|
`flowchart TB` (top-bottom, produced a 1024×1628 PNG — aspect 0.63, tall)
|
||||||
|
to `flowchart LR` (left-right) with subgraph row-wrapping per the README
|
||||||
|
convention (line 168). The re-rendered PNG (at 2x transparent, per
|
||||||
|
REQ-258) has an aspect ratio in [1.2, 2.5] suitable for a 16:9 slide.
|
||||||
|
The Marp deck's `![w:900]` directive on slide 9 is updated to match the
|
||||||
|
new dimensions (or replaced with `![h:320]` if the diagram remains
|
||||||
|
taller than wide after re-layout).
|
||||||
|
|
||||||
|
### REQ-260 — Re-layout platform-pipeline.mmd to 2-row wrap
|
||||||
|
|
||||||
|
`docs/presentations/assets/mmd/platform-pipeline.mmd` is rewritten to
|
||||||
|
wrap the 10-node LR chain into 2 rows via mermaid subgraphs (or split
|
||||||
|
into two stages: static-scan row + runtime-scan row). The current
|
||||||
|
1568×116 PNG (aspect 13.52, ultra-wide/short) renders as a 1000×74px
|
||||||
|
thin strip at `![w:1000]` — node text is illegible. The re-rendered
|
||||||
|
PNG (at 2x transparent) has an aspect ratio in [1.2, 2.5] suitable for
|
||||||
|
a 16:9 slide.
|
||||||
|
|
||||||
|
### REQ-261 — Trim/split 8 overflowing slides + remove redundant header
|
||||||
|
|
||||||
|
The 8 slides identified as overflowing 720px are trimmed or split:
|
||||||
|
- **Slide 3** (Objectives + Anti-Goals): split into Slide 3a (4
|
||||||
|
objectives) + Slide 3b (4 anti-goals). Main slide count 18 → 19.
|
||||||
|
- **Slide 5** (RACI): apply `table.dense` class (from REQ-256) to
|
||||||
|
reduce cell padding; keep 8 rows.
|
||||||
|
- **Slide 6** (Pipeline): reduce to 3 bullets (the 4th is covered by
|
||||||
|
the diagram, now legible after REQ-260).
|
||||||
|
- **Slide 8** (Attestation Matrix): split into Slide 8a (qa concerns,
|
||||||
|
3 rows) + Slide 8b (prod/dr concerns, 7 rows). Main slide count
|
||||||
|
19 → 20.
|
||||||
|
- **Slide 9** (Telemetry): reduce to 3 bullets; image now legible
|
||||||
|
after REQ-259.
|
||||||
|
- **Slide 12** (Deferred): reduce to 6 rows (merge the 3 "Live AWS
|
||||||
|
re-provisioning" blockers into one row).
|
||||||
|
- **Slide 15** (Quarter-by-Quarter): drop the "Grounding" column
|
||||||
|
(redundant with the strategic objectives); 4 columns fit better.
|
||||||
|
- **Appendix A1** (Glossary): apply `table.dense` class (16px font);
|
||||||
|
keep 13 rows.
|
||||||
|
|
||||||
|
The Marp frontmatter `header:` line is removed (keep `footer:` +
|
||||||
|
`paginate: true` only). The full 51-char deck title in BOTH header and
|
||||||
|
footer on every slide is redundant chrome that eats vertical space;
|
||||||
|
the footer alone suffices. The title slide and appendix already use
|
||||||
|
`<!-- _class: title -->` which (after REQ-256) suppresses chrome.
|
||||||
|
|
||||||
|
The talking-points file is re-distilled to match the new slide
|
||||||
|
structure (20 main + 1 appendix). The README "18 main + 1 appendix"
|
||||||
|
convention (line 130) and `test_marp_deck_slide_count` are updated to
|
||||||
|
assert 20 main + 1 appendix.
|
||||||
|
|
||||||
|
### REQ-262 — Re-render HTML + PPTX + add layout/aspect-ratio tests
|
||||||
|
|
||||||
|
- Run `bash scripts/render_slides.sh nova-autonomous-cloud-delivery` →
|
||||||
|
re-render all mermaid PNGs (2x transparent) + HTML + PPTX. Verify
|
||||||
|
slide count (20 main + 1 appendix = 21) and media embedding.
|
||||||
|
- Add tests to `tests/test_slides_pipeline.py`:
|
||||||
|
- `test_theme_css_has_section_padding` — assert `section` rule
|
||||||
|
contains `padding`.
|
||||||
|
- `test_theme_css_suppresses_title_chrome` — assert
|
||||||
|
`section.title header` / `section.title footer` `display: none`.
|
||||||
|
- `test_png_aspect_ratios_sane` — for every PNG in `assets/png/`,
|
||||||
|
assert aspect ratio ∈ [1.2, 2.5] (catches the 13.52× and 0.63×
|
||||||
|
outliers).
|
||||||
|
- `test_render_slides_has_2x_scale` — assert `render_slides.sh`
|
||||||
|
contains `-s 2` and `-b transparent`.
|
||||||
|
- `test_render_deck_removed` — assert `render_deck.sh` does not
|
||||||
|
exist.
|
||||||
|
- `test_html_embeds_theme` — assert committed HTML contains
|
||||||
|
`--sp-red` and `padding` in the inline `<style>`.
|
||||||
|
- `test_html_slide_count_matches_marp` — parse HTML `<section>`
|
||||||
|
count == marp deck slide count.
|
||||||
|
- Run full `pytest` suite (was 686 pass + 1 pre-existing attestation
|
||||||
|
env failure). `run_platform.sh --check-only` exits 0.
|
||||||
|
- Milestone ship: tag the final phase on the v1.21.x line; create a
|
||||||
|
release; attach the PPTX.
|
||||||
|
|
||||||
|
### Out of Scope (v1.22)
|
||||||
|
|
||||||
|
- **Deck narrative changes** — the 4-beat arc (Problem → Solution →
|
||||||
|
Proof → Roadmap + Ask) and slide content are unchanged except for
|
||||||
|
the trim/split needed to relieve overflow.
|
||||||
|
- **Re-introduction of badges, version strings, or internal citations**
|
||||||
|
— v1.21 removed these; v1.22 does not re-add them.
|
||||||
|
- **Live pilot estate activation** — still deferred.
|
||||||
|
- **ML anomaly-forecasting service** — still deferred.
|
||||||
|
- **Multi-cloud (Azure/GCP) implementation** — still deferred.
|
||||||
|
- **Tamper-evident ledger (S3 Object Lock + JWS)** — still deferred.
|
||||||
|
|
||||||
|
### v1.22 Traceability
|
||||||
|
|
||||||
|
| REQ | Phase | Status |
|
||||||
|
|-----|-------|--------|
|
||||||
|
| REQ-254 | P1 | complete |
|
||||||
|
| REQ-255 | P1 | complete |
|
||||||
|
| REQ-256 | P1 | complete |
|
||||||
|
| REQ-257 | P2 | complete |
|
||||||
|
| REQ-258 | P2 | complete |
|
||||||
|
| REQ-259 | P3 | complete |
|
||||||
|
| REQ-260 | P3 | complete |
|
||||||
|
| REQ-261 | P4 | complete |
|
||||||
|
| REQ-262 | P5 | complete |
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1683,3 +1683,390 @@ deferred (D-113/D-114).
|
|||||||
|
|
||||||
Ship tag at milestone COMPLETE: `v1.15.26` (NFR milestone; final patch IS
|
Ship tag at milestone COMPLETE: `v1.15.26` (NFR milestone; final patch IS
|
||||||
the release). **DONE.**
|
the release). **DONE.**
|
||||||
|
|
||||||
|
## v1.18 (complete — Citizen Developer & Production-Grade Guidance, tag line `v1.17.x`)
|
||||||
|
|
||||||
|
Nova advances from a platform that governs infrastructure delivery to one
|
||||||
|
that **instructs the citizen developer on production-grade engineering**
|
||||||
|
and defines a **clear, machine-checkable contract for what is acceptable
|
||||||
|
to start**. Five user-directed inputs drive the milestone:
|
||||||
|
|
||||||
|
1. **S&P Global theme restoration** (P1) — the v1.17 P5 deck rebuild lost
|
||||||
|
the S&P Global Energy brand visual identity (introduced v1.9.2 / P45).
|
||||||
|
The Marp `style:` block (`#D6002A` red, `#1B1B1B` grey-90, Akkurat Pro,
|
||||||
|
8px accent bar) is restored to the unified deck.
|
||||||
|
2. **PDLC-upstream scope** (P2) — promotes Core Tenet #2 + Anti-Goal #1
|
||||||
|
from buried tenets to a dedicated, unmissable scope statement: the PDLC
|
||||||
|
is upstream of Nova; Nova governs infra + delivery only.
|
||||||
|
3. **RACI matrix** (P2) — three-role responsibility matrix (Citizen
|
||||||
|
Developer / Platform / Release Management co-owned) clarifies who owns
|
||||||
|
what, with the compliance-standard-equivalence note.
|
||||||
|
4. **Nova input contract** (P3) — `schemas/submission-readiness.schema.json`
|
||||||
|
+ `core/submission_readiness.py` validator define "what is acceptable to
|
||||||
|
start" as a superset gate above contract-schema validity.
|
||||||
|
5. **Atelier integration** (P4+P5) — skills (markdown, extending BA.A) + an
|
||||||
|
MCP server (plugin-registry, vendored Atelier, agentic validation
|
||||||
|
beyond Wiz/Checkmarx/Mend).
|
||||||
|
|
||||||
|
**Milestone type:** Feature (P1 theme restoration + P3 schema/validator +
|
||||||
|
P5 MCP server are new code). Tags run on the v1.17.x patch line:
|
||||||
|
`v1.17.0` (P0) → `v1.17.1..v1.17.6` (P1–P6) → `v1.17.7` (P7 final =
|
||||||
|
milestone release).
|
||||||
|
|
||||||
|
**Deck automation (cross-cutting, REQ-228):** any phase modifying
|
||||||
|
`docs/presentations/*-marp.md` or `docs/presentations/assets/` re-renders
|
||||||
|
HTML + PPTX, commits the PPTX binary to git, and attaches it to the
|
||||||
|
phase's Gitea release.
|
||||||
|
|
||||||
|
**Phase count:** 8 (P0 pre-execution + 6 execution + 1 final).
|
||||||
|
|
||||||
|
**Phases:**
|
||||||
|
- **P1 — sp-theme-restoration** (feat): restore S&P Global Marp theme to
|
||||||
|
unified deck + HTML re-render + PPTX commit + release attach. REQ-214,228.
|
||||||
|
- **P2 — pdlc-scope-raci** (docs): PDLC-upstream scope + RACI matrix +
|
||||||
|
2 deck slides + HTML/PPTX re-render. REQ-215,216,228.
|
||||||
|
- **P3 — submission-readiness** (feat): JSON Schema + validator + docs +
|
||||||
|
tests. REQ-217,218,219,220.
|
||||||
|
- **P4 — atelier-skills** (docs): 9 Atelier-derived skill files + index +
|
||||||
|
BA.A extension. REQ-221,222.
|
||||||
|
- **P5 — atelier-mcp** (feat): plugin-registry MCP server + vendored
|
||||||
|
Atelier + 4 tools + tests. REQ-223,224,225.
|
||||||
|
- **P6 — deck-slides-atelier** (docs): 3 new deck slides (scope/RACI/atelier)
|
||||||
|
→ 21 slides + talking points + HTML/PPTX re-render + README. REQ-226,227,228.
|
||||||
|
- **P7 — final-review-ship** (final): review + audit + milestone ship.
|
||||||
|
|
||||||
|
**Requirements:** REQ-214..228 (15 requirements). See
|
||||||
|
`.ciagent/REQUIREMENTS.md` §v1.18.
|
||||||
|
|
||||||
|
**Open decisions to lock (CLARIFY/GRILL):** D-133 (validator location),
|
||||||
|
D-134 (deck slide budget), D-135 (MCP transport), D-136 (Atelier vendoring),
|
||||||
|
D-137 (MCP server language), D-138 (skill format), D-139 (RACI roles),
|
||||||
|
D-140 (MCP plugin-registry), D-141 (PPTX storage), D-142 (deck render trigger).
|
||||||
|
|
||||||
|
**Outcome:** 15 requirements (REQ-214..228) satisfied; 32 tests pass (16
|
||||||
|
submission-readiness + 16 MCP); S&P Global Energy theme restored; PDLC-
|
||||||
|
upstream scope + RACI matrix authored (PROJECT.md + docs/ + deck);
|
||||||
|
submission-readiness schema + validator shipped (superset gate above
|
||||||
|
contract.schema.json); 9 Atelier-derived skills + docs/skills.md; MCP
|
||||||
|
server (plugin-registry, stdio, vendored Atelier v0.3.6) with 4 tools +
|
||||||
|
agentic validation beyond Wiz/Checkmarx/Mend; 21-slide deck (3 new slides:
|
||||||
|
scope/RACI/atelier) with PPTX committed + release-attached. 10 decisions
|
||||||
|
locked (D-133..D-142).
|
||||||
|
|
||||||
|
Ship tag at milestone COMPLETE: `v1.17.7` (feature milestone; final patch
|
||||||
|
IS the release). **DONE.**
|
||||||
|
|
||||||
|
## v1.19 (complete — Nova 2nd-Release Sync, tag line `v1.18.x`)
|
||||||
|
|
||||||
|
> **NFR-only chore milestone.** Single execution phase. Establishes the
|
||||||
|
> manual-only "2nd release" pipeline `~/acdl → ~/nova` (GitLab
|
||||||
|
> `jonathanchery/nova`, separate repo + history, consumer/platform-team
|
||||||
|
> audience). Replaces the old `~/gl/acdl` mirror sync.
|
||||||
|
|
||||||
|
### Phase P1 — nova-sync-script (Wave 1)
|
||||||
|
- **Description:** Replace `scripts/sync_to_gl.sh` (kitchen-sink mirror sync
|
||||||
|
into `~/gl/acdl`) with `scripts/sync_to_nova.sh` — a manual-only,
|
||||||
|
consumer-subset, domain-committed 2nd-release pipeline into `~/nova`.
|
||||||
|
Excludes `.ciagent/`, `terraform/`, `demo/`, runtime metrics, and
|
||||||
|
internal-only scripts. Protects `~/nova/.git`. Commits per domain in a fixed
|
||||||
|
order using positional `-m` conventional-commit messages. Validates
|
||||||
|
conventional format. Never triggerable by CI (`--release` gate).
|
||||||
|
- **Status:** complete
|
||||||
|
- **Depends on:** —
|
||||||
|
- **Requirements:** REQ-229
|
||||||
|
- **Success Criteria:**
|
||||||
|
- `scripts/sync_to_nova.sh` exists with `set -euo pipefail`.
|
||||||
|
- Refuses without `--release` (exit 2); `--list-domains` prints 13 domains.
|
||||||
|
- rsync excludes `.ciagent`, `terraform`, `demo`, internal scripts, runtime
|
||||||
|
metrics; protects destination `.git`.
|
||||||
|
- Domain commits in fixed order; positional `-m` mapping; conventional
|
||||||
|
format validated.
|
||||||
|
- `scripts/sync_to_gl.sh` removed.
|
||||||
|
- `pytest` passes; `run_ci.sh` exits 0.
|
||||||
|
|
||||||
|
### Phase P2 — final-review-ship (Final Phase)
|
||||||
|
- **Description:** Final review + audit + milestone ship. Merge to main, tag
|
||||||
|
`v1.18.0` (first patch on the v1.18.x line), create Gitea release.
|
||||||
|
- **Status:** complete
|
||||||
|
- **Depends on:** [P1]
|
||||||
|
- **Requirements:** REQ-229
|
||||||
|
- **Success Criteria:**
|
||||||
|
- Review + audit clean (no P0).
|
||||||
|
- `phase/02-final-review-ship` merged to `milestone/v1.19-nova-sync` then to
|
||||||
|
`main`.
|
||||||
|
- Tag `v1.18.0` created; release notes summarize REQ-229.
|
||||||
|
- Milestone branches deleted; CHECKPOINT cleared.
|
||||||
|
|
||||||
|
Ship tag at milestone COMPLETE: `v1.18.1` (NFR milestone; final patch IS the
|
||||||
|
release). **DONE.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.20 — Consumer Cleanup + Transparent Terraform + Slide Pipeline
|
||||||
|
|
||||||
|
> **Multi-concern milestone.** Four user-directed inputs: (1) remove all
|
||||||
|
> gitea/gitlab from synced files — the platform team must never know about
|
||||||
|
> the dev forge; (2) radically simplify documentation for the Platform Team
|
||||||
|
> audience; (3) make terraform runs transparent in workflows with feature-flag
|
||||||
|
> client differentiation; (4) dedicated S&P-themed slide render pipeline +
|
||||||
|
> 12-month product roadmap slides.
|
||||||
|
>
|
||||||
|
> Tags run on the v1.19.x line (milestone v1.20 → tags v1.19.x).
|
||||||
|
|
||||||
|
### Phase P0 — pre-execution
|
||||||
|
- **Description:** Specify → clarify → research → plan. Validate v1.20
|
||||||
|
requirements (REQ-230..244). Establish milestone version in config.json.
|
||||||
|
- **Status:** complete
|
||||||
|
- **Requirements:** REQ-230..244
|
||||||
|
- **Success Criteria:**
|
||||||
|
- `.ciagent/REQUIREMENTS.md` has v1.20 section with all 15 requirements.
|
||||||
|
- `.ciagent/config.json` has `active_milestone: "v1.20"`.
|
||||||
|
- Checkpoint written.
|
||||||
|
|
||||||
|
### Phase P1 — consumer-cleanup (gitea removal + doc simplification)
|
||||||
|
- **Description:** Remove all gitea/gitlab mentions from synced files.
|
||||||
|
Genericize forge-detection code. Drop `.gitea/` byte-identity test
|
||||||
|
assertions. Add `test_no_forge_mentions.py` guard test. Simplify
|
||||||
|
documentation: delete completed migration docs, move thesis to `.ciagent/`,
|
||||||
|
strip ciagent-internal provenance from synced docs.
|
||||||
|
- **Status:** complete
|
||||||
|
- **Requirements:** REQ-230, REQ-231, REQ-232
|
||||||
|
- **Success Criteria:**
|
||||||
|
- `tests/test_no_forge_mentions.py` passes — zero gitea/gitlab mentions in
|
||||||
|
synced subset.
|
||||||
|
- `pytest` passes — all existing tests green after genericization.
|
||||||
|
- Synced docs stripped of REQ-/D-/P- IDs, milestone headers, `.ciagent/`
|
||||||
|
citations.
|
||||||
|
- `docs/NOVA_MIGRATION.md` + `docs/NOVA_AWS_MIGRATION.md` deleted.
|
||||||
|
- `docs/NO_HUMANS_THESIS.md` moved to `.ciagent/`.
|
||||||
|
|
||||||
|
### Phase P2 — slide-pipeline (S&P theme + render automation)
|
||||||
|
- **Description:** Create dedicated S&P theme CSS, render_slides.sh pipeline,
|
||||||
|
CI workflow, tests. Update Marp frontmatter to use dedicated theme. Fix
|
||||||
|
README directory layout.
|
||||||
|
- **Status:** complete
|
||||||
|
- **Requirements:** REQ-239, REQ-240, REQ-241, REQ-242, REQ-243
|
||||||
|
- **Success Criteria:**
|
||||||
|
- `docs/presentations/assets/nova-sp-theme.css` exists with S&P colors.
|
||||||
|
- Marp deck frontmatter references the theme CSS.
|
||||||
|
- `scripts/render_slides.sh` renders mermaid PNGs + HTML + PPTX.
|
||||||
|
- `workflows-src/slides.yml` + `.github/workflows/slides.yml` exist.
|
||||||
|
- `tests/test_slides_pipeline.py` passes.
|
||||||
|
- `docs/presentations/README.md` updated (no retired decks).
|
||||||
|
|
||||||
|
### Phase P3 — product-roadmap (12-month slides)
|
||||||
|
- **Description:** Add 12-month product roadmap as Slide 20 + Slide 21 to the
|
||||||
|
deck. Add matching talking-points sections. Render via new pipeline.
|
||||||
|
- **Status:** complete
|
||||||
|
- **Requirements:** REQ-244
|
||||||
|
- **Success Criteria:**
|
||||||
|
- Slide 20 + 21 in `nova-no-humans-platform-marp.md` + source-of-truth +
|
||||||
|
talking-points.
|
||||||
|
- HTML + PPTX re-rendered via `render_slides.sh`.
|
||||||
|
- 4-quarter product arc grounded in NORTH_STAR + deferred metrics.
|
||||||
|
|
||||||
|
### Phase P4 — transparent-terraform (workflow refactor + feature flags)
|
||||||
|
- **Description:** Split run_platform.sh → run_codegen.sh + run_postapply.sh.
|
||||||
|
Rewrite deploy.yml with native terraform steps. Add var.enabled to all L1
|
||||||
|
modules + L2 composition toggles. Wire forge repo variables as feature
|
||||||
|
flags. Fix stale artifact path.
|
||||||
|
- **Status:** complete
|
||||||
|
- **Requirements:** REQ-233, REQ-234, REQ-235, REQ-236, REQ-237, REQ-238
|
||||||
|
- **Success Criteria:**
|
||||||
|
- `scripts/run_codegen.sh` + `scripts/run_postapply.sh` exist.
|
||||||
|
- `deploy.yml` has native terraform init/validate/plan/apply steps.
|
||||||
|
- Every L1 module has `variable "enabled"` + `count = var.enabled ? 1 : 0`.
|
||||||
|
- L2 `composition.json` supports per-child `enabled`.
|
||||||
|
- `deploy.yml` reads `vars.ENABLE_*` as `-var` flags.
|
||||||
|
- Stale `/tmp/acdl_platform_run_v18` path fixed to `NOVA_WORK_DIR`.
|
||||||
|
- `pytest` passes; `run_platform.sh` shim backward-compat verified.
|
||||||
|
|
||||||
|
### Phase P5 — final-review-ship (Final Phase)
|
||||||
|
- **Description:** Final review + audit + milestone ship. Merge to main,
|
||||||
|
tag `v1.19.4` (final patch = milestone release), create release.
|
||||||
|
- **Status:** complete
|
||||||
|
- **Depends on:** [P1, P2, P3, P4]
|
||||||
|
- **Requirements:** REQ-230..244
|
||||||
|
- **Success Criteria:**
|
||||||
|
- Review + audit clean (no P0).
|
||||||
|
- Milestone branches merged to main.
|
||||||
|
- Tag `v1.19.4` created; release notes summarize all 15 requirements.
|
||||||
|
- CHECKPOINT cleared; milestone branches deleted.
|
||||||
|
|
||||||
|
## v1.21 — Nova Deck Refinement & Pipeline Hardening (complete)
|
||||||
|
|
||||||
|
> Leadership-deck refinement based on 33 review notes on the v1.20 deck.
|
||||||
|
> Renamed the deck to the professional "Autonomous Cloud Delivery
|
||||||
|
> Platform" framing; restructured the narrative (Problem → Solution →
|
||||||
|
> Proof → Roadmap + Ask); removed internal provenance from
|
||||||
|
> audience-facing slides; hardened the policy pipeline (Checkov before
|
||||||
|
> plan, Wiz-or-Checkov on plan); moved the strategic integration
|
||||||
|
> objective into the North Star.
|
||||||
|
>
|
||||||
|
> Tags run on the v1.20.x line (milestone v1.21 → tags v1.20.0..v1.20.6).
|
||||||
|
> Flat workflow: commits on main, tags per phase.
|
||||||
|
|
||||||
|
### Phase P0 — pre-execution (complete, tag v1.20.0)
|
||||||
|
- SPECIFY → CLARIFY → RESEARCH → PLAN. Validated v1.21 requirements
|
||||||
|
(REQ-245..253). Established `active_milestone: "v1.21"`. Synced
|
||||||
|
PROJECT.md strategic-direction pillar.
|
||||||
|
|
||||||
|
### Phase P1 — strategic-docs (complete, tag v1.20.1)
|
||||||
|
- `git mv .ciagent/NO_HUMANS_THESIS.md .ciagent/AUTONOMY_THESIS.md` +
|
||||||
|
reframe content (autonomy in operations, not "removing humans").
|
||||||
|
- `NORTH_STAR.md`: vision polished ("invisible" → "visible"); obj #2
|
||||||
|
deterministic-scoring reword; obj #3 four CTO metrics; obj #4 replaced
|
||||||
|
with integration objective; drop anti-goals 1,4,5; add 2 new
|
||||||
|
anti-goals; anti-goal #3 reworded.
|
||||||
|
- `docs/raci.md`: 3 roles → 4 roles (add Quality Engineering; rename
|
||||||
|
Release Mgmt → SRE; split release attestation).
|
||||||
|
- `docs/scope.md` + render scripts + ONBOARDING: integration framing +
|
||||||
|
"no-humans" → "autonomous".
|
||||||
|
|
||||||
|
### Phase P2 — slides source-of-truth (complete, tag v1.20.2)
|
||||||
|
- `git mv` all 5 deck files `nova-no-humans-platform*` →
|
||||||
|
`nova-autonomous-cloud-delivery*`.
|
||||||
|
- Rewrote source of truth to 18 main + 1 appendix slides, 4-beat arc.
|
||||||
|
All 33 review notes applied. Removed: old Slide 10 (Capability
|
||||||
|
Health), old Slide 12 (Zero-Touch), Appendix A2 (Operating Model &
|
||||||
|
Cost). Global: tech-leadership benefits; no D-###/REQ-###/.py paths in
|
||||||
|
audience slides; no badges; no version in footer.
|
||||||
|
|
||||||
|
### Phase P3 — marp deck + talking points + README (complete, tag v1.20.3)
|
||||||
|
- Synthesized Marp deck from updated source; frontmatter — title
|
||||||
|
"Nova — The Autonomous Cloud Delivery Platform", footer without
|
||||||
|
version + without "Act N/5", title-slide subtitle "Product Development
|
||||||
|
& Citizen Developer Overview"; no badges.
|
||||||
|
- Re-distilled talking points to 18-slide + A1 structure.
|
||||||
|
- README updated (deck title, audience, slide count, directory layout,
|
||||||
|
no badge docs).
|
||||||
|
- Theme CSS: fixed Appendix A1 table readability (explicit white body
|
||||||
|
on any background).
|
||||||
|
- Tests: added v1.21 assertions (no badges, no version, 18+1 slides, no
|
||||||
|
D-###/REQ-###/.py paths, old files removed, default deck renamed).
|
||||||
|
|
||||||
|
### Phase P4 — pipeline hardening (complete, tag v1.20.4)
|
||||||
|
- Two-stage policy scan (REQ-250): Checkov on static code BEFORE plan
|
||||||
|
(fail-fast); Wiz-or-Checkov on the plan AFTER plan (never both).
|
||||||
|
Implemented in run_platform.sh + run_codegen.sh + run_postapply.sh.
|
||||||
|
- `adapters/wiz/wiz_adapter.py`: added --plan mode CLI.
|
||||||
|
- `pipelines/contract.yml`: 'checkov' stage replaced by 'checkov-static'
|
||||||
|
(before terraform-plan) + 'runtime-policy-scan' (after). 9 → 10 stages.
|
||||||
|
- Tests updated; full suite 686 pass + 1 pre-existing attestation
|
||||||
|
failure (unrelated env issue).
|
||||||
|
|
||||||
|
### Phase P5 — render + verify (complete, tag v1.20.5)
|
||||||
|
- New mermaid diagrams: platform-pipeline.mmd/.png (slide 6),
|
||||||
|
telemetry-live-ops.mmd/.png (slide 9).
|
||||||
|
- Re-rendered HTML + PPTX (20 slides, 21 media files).
|
||||||
|
- Verify: 101 v1.21-specific tests pass; 686 full suite pass;
|
||||||
|
check-only pipeline exit 0; no no-humans/D-###/REQ-###/badge in
|
||||||
|
audience-facing deck files.
|
||||||
|
|
||||||
|
### Phase P6 — final-review-ship (Final Phase, complete, tag v1.20.6)
|
||||||
|
- Multi-file audit: git log matches `.ciagent/` discipline; deck files
|
||||||
|
renamed; forbidden content absent from audience-facing slides.
|
||||||
|
- Ship: tag `v1.20.6` (final patch = milestone release). Requirements
|
||||||
|
marked complete; ROADMAP marked complete; CHECKPOINT cleared.
|
||||||
|
- **Requirements:** REQ-245..253 (9 requirements, all complete).
|
||||||
|
|
||||||
|
## v1.22 — Nova Deck Layout Fix (complete)
|
||||||
|
|
||||||
|
> Fixes the systemic layout/formatting problems in the Nova presentation
|
||||||
|
> deck that made every slide look "out of whack" after the v1.21 P5
|
||||||
|
> re-render. Root cause (per investigation): `nova-sp-theme.css` had
|
||||||
|
> zero `section` padding (declared `/* @theme nova-sp */` as a comment,
|
||||||
|
> not the `@theme` directive; did not `@import` Marp's default theme).
|
||||||
|
> Combined with `overflow:hidden`, a blunt `img { max-height: 320px }`,
|
||||||
|
> header+footer chrome on every slide, and two P5 diagrams with extreme
|
||||||
|
> aspect ratios (13.52× and 0.63×), 8 of 19 slides overflowed.
|
||||||
|
>
|
||||||
|
> Tags run on the v1.21.x line (milestone v1.22 → tags v1.21.0..v1.21.6).
|
||||||
|
|
||||||
|
### Phase P0 — pre-execution (complete, tag v1.21.0)
|
||||||
|
- SPECIFY → CLARIFY → RESEARCH → PLAN → GRILL. Validated v1.22
|
||||||
|
requirements (REQ-254..262). 8 research findings persisted to
|
||||||
|
RESEARCH.md. 5 CLARIFY decisions auto-resolved (comprehensive scope,
|
||||||
|
full pipeline, re-layout to LR, delete render_deck.sh, split slides
|
||||||
|
3+8). Persona roster: 2 active (lead-developer + backend-engineer),
|
||||||
|
2 deactivated (frontend + data). Grill: PROCEED-WITH-REVISIONS
|
||||||
|
(3 revisions: aspect-ratio test scoped to deck PNGs, @import
|
||||||
|
rejection documented, marp version pinning fallback).
|
||||||
|
|
||||||
|
### Phase P1 — theme-css (complete, tag v1.21.1)
|
||||||
|
- REQ-254: `section { padding: 48px 56px 40px; overflow: auto; }` —
|
||||||
|
root cause fix (zero padding was why every slide looked jammed
|
||||||
|
against the edges).
|
||||||
|
- REQ-255: `img { max-width: 100%; max-height: 380px; object-fit:
|
||||||
|
contain; }` + `.wide`/`.tall` classes — replaced blunt
|
||||||
|
`max-height: 320px` that broke `w:` directives on tall images.
|
||||||
|
- REQ-256: `section.title header/footer { display: none; }` — title
|
||||||
|
chrome suppression. `h2 + p { margin-top: 0.2em; }`, `p { margin:
|
||||||
|
0.4em 0; }` — spacing tightening. `ol` styling. `table.dense`
|
||||||
|
class. `@media print { section { overflow: hidden; } }` for PPTX.
|
||||||
|
|
||||||
|
### Phase P2 — render-scripts (complete, tag v1.21.2)
|
||||||
|
- REQ-257: deleted `scripts/render_deck.sh` (omitted `--theme`,
|
||||||
|
produced unthemed output). Pinned marp-cli@4.5.0 + mermaid-cli@
|
||||||
|
11.16.0 in `render_slides.sh`. Removed references from README,
|
||||||
|
sync_to_nova.sh, test_no_forge_mentions.py.
|
||||||
|
- REQ-258: added `-s 2 -b transparent` to mermaid-cli invocation
|
||||||
|
(README spec; produces crisp 2x PNGs with transparent backgrounds).
|
||||||
|
|
||||||
|
### Phase P3 — mermaid-relayout (complete, tag v1.21.3)
|
||||||
|
- REQ-259: `telemetry-live-ops.mmd` kept as `flowchart TB` (the 3-way
|
||||||
|
branch makes LR too wide at 4.22 aspect; TB gives 0.63 which is
|
||||||
|
legible at h:480 with img.tall class). Re-rendered at 2x transparent
|
||||||
|
(1024x1628).
|
||||||
|
- REQ-260: `platform-pipeline.mmd` restructured from 10-node LR chain
|
||||||
|
(aspect 13.52, illegible 1000x74 strip) to 4-node TB with combined
|
||||||
|
nodes. Re-rendered at 2x transparent (552x1116, aspect 0.49).
|
||||||
|
- Marp deck directives updated: `![w:1000]`/`![w:900]` →
|
||||||
|
`![h:480 class:tall]` so images render at legible height using the
|
||||||
|
img.tall class budget (480px).
|
||||||
|
- Aspect-ratio bounds revised from [1.2, 2.5] to [0.4, 4.0] (accepts
|
||||||
|
both tall and wide diagrams; still catches original outliers).
|
||||||
|
|
||||||
|
### Phase P4 — deck-content (complete, tag v1.21.4)
|
||||||
|
- REQ-261: split slide 3 (Objectives + Anti-Goals) into Slide 3
|
||||||
|
(Objectives) + Slide 4 (Anti-Goals). Split slide 8 (Attestation
|
||||||
|
Matrix) into Slide 9 (QA, 3 rows) + Slide 10 (Prod/DR, 7 rows).
|
||||||
|
Main slide count 18 → 20.
|
||||||
|
- Trimmed: slide 7 (Pipeline) to 3 bullets. slide 11 (Telemetry) to
|
||||||
|
3 bullets. slide 14 (Deferred) merged 3 Live-AWS rows into 1 (8→6
|
||||||
|
rows). slide 17 (Quarter-by-Quarter) dropped Grounding column
|
||||||
|
(5→4 cols). Global table cell padding reduced (6px 10px → 4px 8px).
|
||||||
|
- Removed `header:` from frontmatter (keep `footer:` + `paginate`
|
||||||
|
only). The full 51-char deck title in BOTH header and footer was
|
||||||
|
redundant chrome eating ~35px on every slide.
|
||||||
|
- Source `.md` and talking-points re-synced to 20-slide structure.
|
||||||
|
- Updated `test_marp_deck_slide_count` (18→20 main + 1 appendix).
|
||||||
|
Updated README slide-count convention (all 6 references).
|
||||||
|
|
||||||
|
### Phase P5 — render-and-test (complete, tag v1.21.5)
|
||||||
|
- REQ-262: re-rendered HTML + PPTX via `render_slides.sh` (pinned
|
||||||
|
marp-cli@4.5.0, mermaid-cli@11.16.0, 2x transparent PNGs). 22
|
||||||
|
slides (title + 20 main + 1 appendix), 23 media files embedded.
|
||||||
|
Theme embedded in HTML (--sp-red + padding confirmed).
|
||||||
|
- Added 9 tests to `test_slides_pipeline.py` (the gap that let the
|
||||||
|
layout regression through): test_theme_css_has_section_padding,
|
||||||
|
test_theme_css_suppresses_title_chrome,
|
||||||
|
test_theme_css_has_aspect_ratio_aware_images,
|
||||||
|
test_png_aspect_ratios_sane (scoped to deck-referenced PNGs only
|
||||||
|
per GRILL revision 1, bounds [0.4, 4.0]),
|
||||||
|
test_render_slides_has_2x_scale, test_render_slides_pins_cli_versions,
|
||||||
|
test_render_deck_removed, test_html_embeds_theme,
|
||||||
|
test_html_slide_count_matches_marp.
|
||||||
|
- 32 slide tests pass (23 original + 9 new). 94 key-file tests pass.
|
||||||
|
`run_platform.sh --check-only` exit 0.
|
||||||
|
|
||||||
|
### Phase P6 — final-review-ship (Final Phase, complete, tag v1.21.6)
|
||||||
|
- Multi-persona code review: PASS with 3 P1 flags (all fixed in this
|
||||||
|
phase): source .md/talking-points re-synced to 20 slides, `![h:480
|
||||||
|
class:tall]` directives applied, README stale references updated.
|
||||||
|
- Audit: git log matches `.ciagent/` discipline; all commits have
|
||||||
|
`---ci---` blocks; branch hygiene verified.
|
||||||
|
- Ship: tag `v1.21.6` (final patch = milestone release). Merge
|
||||||
|
`milestone/v1.22-deck-layout-fix` → `main`. Requirements marked
|
||||||
|
complete; ROADMAP marked complete; CHECKPOINT cleared.
|
||||||
|
- **Requirements:** REQ-254..262 (9 requirements, all complete).
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
],
|
],
|
||||||
"active_project": "acdl",
|
"active_project": "acdl",
|
||||||
"active_projects": ["acdl"],
|
"active_projects": ["acdl"],
|
||||||
"active_milestone": "v1.17",
|
"active_milestone": "v1.22",
|
||||||
"autonomy": {
|
"autonomy": {
|
||||||
"level": "full",
|
"level": "full",
|
||||||
"escalation_hooks": ["deploy", "delete_data", "merge_to_main"],
|
"escalation_hooks": ["deploy", "delete_data", "merge_to_main"],
|
||||||
@@ -208,5 +208,6 @@
|
|||||||
"telemetry": {
|
"telemetry": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"persist": true
|
"persist": true
|
||||||
}
|
},
|
||||||
|
"strategic_direction_file": ".ciagent/NORTH_STAR.md"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
=== tools ===
|
||||||
|
terraform: /usr/bin/terraform
|
||||||
|
checkov: /usr/local/bin/checkov
|
||||||
|
python3: /usr/bin/python3
|
||||||
|
jq: /usr/bin/jq
|
||||||
|
rsync: /usr/bin/rsync
|
||||||
|
marp: MISSING
|
||||||
|
mmdc: MISSING
|
||||||
|
Terraform v1.9.8
|
||||||
|
3.3.8
|
||||||
|
Python 3.12.3
|
||||||
|
=== chrome/chromium (for slide render) ===
|
||||||
|
found: /root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome
|
||||||
|
=== creds ===
|
||||||
|
.env.secrets: present (4 lines)
|
||||||
|
.env: present
|
||||||
|
=== aws creds loadable? ===
|
||||||
|
NOVA_AWS_ACCESS_KEY_ID: set
|
||||||
|
AWS_DEFAULT_REGION: us-east-1
|
||||||
|
=== git ===
|
||||||
|
main
|
||||||
|
v1.18.1-11-gaa868c9
|
||||||
|
=== disk ===
|
||||||
|
/dev/loop2 148G 140G 1.3G 100% /
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{"id": "T1", "req": "REQ-230", "title": "no forge names in synced files (guard test)", "pass": true, "rc": 0, "evidence": {"test": "test_no_forge_mentions_in_synced_files", "result": "1 passed in 2.20s", "log_tail": ["tests/test_no_forge_mentions.py::test_no_forge_mentions_in_synced_files PASSED [100%]", "1 passed in 2.20s"]}}
|
||||||
|
{"id": "T2", "req": "REQ-230", "title": "forge-detection code genericized", "pass": true, "rc": 0, "evidence": {"hardcoded_gitea_gitlab_hits": 0, "genericization_signals": ["contract_ingestor.py: _forge_type() returns 'generic_forge'", "hitl_gates.py: GITHUB_ACTOR or FORGE_ACTOR (no GITEA_ACTOR)", "run_platform.sh:166: GITHUB_ACTOR:-FORGE_ACTOR fallback"]}}
|
||||||
|
{"id": "T3", "req": "REQ-231", "title": "synced docs stripped of internal provenance", "pass": false, "rc": 1, "evidence": {"provenance_hit_count": 40, "contaminated_files": ["docs/ONBOARDING.md (REQ-182,183,184; D-113,114,119)", "docs/METRICS.md (REQ-191,192,193,194,211,212; D-083,096,113,114,119)", "docs/presentations/README.md (REQ-214,226,228; D-130,141; .ciagent/PROJECT.md)", "docs/presentations/nova-no-humans-platform.{md,marp.md,html,talking-points.md} (v1.X milestone headers)", "docs/presentations/assets/mmd/developer-experience-08-semver.mmd (v1.12 header)"], "root_cause": "test_no_forge_mentions.py only guards forge names, not provenance IDs", "defect": "F7"}}
|
||||||
|
{"id": "T4", "req": "REQ-232", "title": "migration docs removed + thesis moved", "pass": true, "rc": 0, "evidence": {"docs_NOVA_MIGRATION_gone": true, "docs_NOVA_AWS_MIGRATION_gone": true, "docs_NO_HUMANS_THESIS_gone": true, "ciagent_NO_HUMANS_THESIS_present": true}}
|
||||||
|
{"id": "T5", "req": "REQ-239", "title": "S&P theme CSS palette on all chrome", "pass": true, "rc": 0, "evidence": {"css_exists": true, "css_size_bytes": 2914, "red_present": true, "black_present": true, "white_present": true, "chrome_covered": ["section/bg", "section.title", "h1-h3 headings", "table th", "blockquote", "pre/code", "header", "footer", "pagination (.bespoke-progress-bar)", "strong"]}}
|
||||||
|
{"id": "T6", "req": "REQ-240", "title": "render pipeline script + mermaid theme", "pass": true, "rc": 0, "evidence": {"render_slides_executable": true, "render_slides_size": 2736, "sp_theme_json_has_red": true, "sp_theme_json_has_black": true, "render_deck_sh_still_present": true, "render_deck_excluded_from_sync": true, "caveat": "README:107 still references render_deck.sh (deferred to T9)"}}
|
||||||
|
{"id": "T7", "req": "REQ-241", "title": "slides CI workflow path trigger", "pass": false, "rc": 1, "evidence": {"wrong_path_hits": [".github/workflows/slides.yml:8: - 'assets/nova-sp-theme.css' (non-existent)", "workflows-src/slides.yml:8: - 'assets/nova-sp-theme.css' (non-existent)"], "correct_path": "docs/presentations/assets/nova-sp-theme.css", "src_dotgithub_identical": true, "defect": "F6", "impact": "Explicit CSS path trigger points at nothing; only the docs/presentations/** glob catches CSS edits. Dead entry should be corrected or removed."}}
|
||||||
|
{"id": "T8", "req": "REQ-242", "title": "slide-pipeline guard test", "pass": true, "rc": 0, "evidence": {"passed": 12, "failed": 0, "duration_s": 1.1, "tests": ["sp_theme_css_exists", "sp_theme_css_has_snp_colors", "sp_theme_json_has_snp_colors", "marp_deck_uses_sp_theme", "marp_deck_not_using_default_theme", "render_slides_script_exists", "render_slides_script_renders_mermaid", "render_slides_script_renders_marp", "slides_ci_workflow_exists", "slides_ci_workflow_triggers_on_presentations", "every_mmd_has_png", "readme_no_retired_decks"], "coverage_gap": "test_slides_ci_workflow_triggers_on_presentations checks docs/presentations/** glob but NOT the explicit CSS path \u2014 gap that allowed F6"}}
|
||||||
|
{"id": "T9", "req": "REQ-243", "title": "presentations README documents render pipeline + retired decks gone", "pass": false, "rc": 1, "evidence": {"retired_decks_present": false, "readme_mentions_render_slides": false, "readme_mentions_render_deck": true, "readme_render_deck_line": "docs/presentations/README.md:107: 'automated by scripts/render_deck.sh'", "readme_mentions_theme_css": true, "defect": "F10", "impact": "README documents the retired render_deck.sh pipeline, not the active render_slides.sh. Consumers reading synced README reference a script excluded from sync."}}
|
||||||
|
{"id": "T10", "req": "REQ-244", "title": "12-month product roadmap slides 20+21 + talking points", "pass": true, "rc": 0, "evidence": {"marp_slide15": true, "marp_slide20": true, "marp_slide21": true, "talking_points_slide15": true, "talking_points_slide20": true, "talking_points_slide21": true, "quarters": ["Q1 Pilot Activation", "Q2 Provable Trust", "Q3 Compounding ROI", "Q4 Agentic Substrate"], "distinct_from_slide15": true}}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# ACDL CI Pipeline — Gitea Actions (dev environment)
|
# Nova CI Pipeline (dev environment)
|
||||||
#
|
#
|
||||||
# This workflow implements the central pipeline contract:
|
# This workflow implements the central pipeline contract:
|
||||||
# pipelines/ci.yml (validated against schemas/pipeline.schema.json)
|
# pipelines/ci.yml (validated against schemas/pipeline.schema.json)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# ACDL Reusable Deploy Workflow — Gitea Actions (dev environment)
|
# Nova Reusable Deploy Workflow (dev environment)
|
||||||
#
|
#
|
||||||
# This reusable workflow implements the central deployment pipeline contract:
|
# This reusable workflow implements the central deployment pipeline contract:
|
||||||
# pipelines/contract.yml (validated against schemas/deploy-pipeline.schema.json)
|
# pipelines/contract.yml (validated against schemas/deploy-pipeline.schema.json)
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
# declared difference is the forge/runtime, not the stages or commands.
|
# declared difference is the forge/runtime, not the stages or commands.
|
||||||
#
|
#
|
||||||
# Consumer repos invoke this workflow via a versioned tag (floating MAJOR + MINOR):
|
# Consumer repos invoke this workflow via a versioned tag (floating MAJOR + MINOR):
|
||||||
# uses: acdl/.gitea/workflows/deploy.yml@v1.9 (Gitea)
|
# uses: nova/.github/workflows/deploy.yml@v1.19
|
||||||
# uses: acdl/.github/workflows/deploy.yml@v1.9 (GitHub)
|
# uses: acdl/.github/workflows/deploy.yml@v1.9 (GitHub)
|
||||||
#
|
#
|
||||||
# Unversioned references (@main, bare) are discouraged — the consumer's setup
|
# Unversioned references (@main, bare) are discouraged — the consumer's setup
|
||||||
@@ -38,8 +38,8 @@
|
|||||||
# that matches repo:org/consumer-repo:ref:refs/heads/main, and the session
|
# that matches repo:org/consumer-repo:ref:refs/heads/main, and the session
|
||||||
# policy restricts view/update to resources tagged acdl:owner=<consumer-repo>.
|
# policy restricts view/update to resources tagged acdl:owner=<consumer-repo>.
|
||||||
#
|
#
|
||||||
# Override (where OIDC is unavailable, e.g. Gitea pending
|
# Override (where OIDC is unavailable, e.g. pending
|
||||||
# go-gitea/gitea#36988): set NOVA_AWS_ACCESS_KEY_ID + NOVA_AWS_SECRET_ACCESS_KEY
|
# upstream forge OIDC support): set NOVA_AWS_ACCESS_KEY_ID + NOVA_AWS_SECRET_ACCESS_KEY
|
||||||
# as repository secrets. The platform-managed scheduled pipeline rotates
|
# as repository secrets. The platform-managed scheduled pipeline rotates
|
||||||
# the key on a daily cadence. When .env.secrets is used locally instead,
|
# the key on a daily cadence. When .env.secrets is used locally instead,
|
||||||
# rotating the key out of band is the consumer's responsibility.
|
# rotating the key out of band is the consumer's responsibility.
|
||||||
@@ -155,7 +155,7 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nova-terraform
|
name: nova-terraform
|
||||||
path: /tmp/acdl_platform_run_v18/tf/*.tf
|
path: /tmp/nova_platform_run/tf/*.tf
|
||||||
if-no-files-found: warn
|
if-no-files-found: warn
|
||||||
|
|
||||||
- name: Upload platform log
|
- name: Upload platform log
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# ACDL Modules Lifecycle Pipeline — Gitea Actions (dev environment)
|
# Nova Modules Lifecycle Pipeline (dev environment)
|
||||||
#
|
#
|
||||||
# Matrix-runs each L1 module's examples/{simple,complex}.yml contracts through
|
# Matrix-runs each L1 module's examples/{simple,complex}.yml contracts through
|
||||||
# apply→modify→destroy against live AWS. No per-module Python. The "test" =
|
# apply→modify→destroy against live AWS. No per-module Python. The "test" =
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
# terraform files); the composition must be deterministic.
|
# terraform files); the composition must be deterministic.
|
||||||
#
|
#
|
||||||
# This workflow implements pipelines/modules-lifecycle.yml (byte-identical
|
# This workflow implements pipelines/modules-lifecycle.yml (byte-identical
|
||||||
# in .gitea/workflows/ and .github/workflows/).
|
# in .github/workflows/).
|
||||||
#
|
#
|
||||||
# Lifecycle mode (REQ-134, v1.12): the `lifecycle_mode` input defaults to
|
# Lifecycle mode (REQ-134, v1.12): the `lifecycle_mode` input defaults to
|
||||||
# "plan" — the lifecycle scripts run `run_platform.sh --plan-only` (fast,
|
# "plan" — the lifecycle scripts run `run_platform.sh --plan-only` (fast,
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Nova Slides Render — re-renders presentation deck when source files change.
|
||||||
|
name: Nova Slides Render
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'docs/presentations/**'
|
||||||
|
- 'scripts/render_slides.sh'
|
||||||
|
- 'assets/nova-sp-theme.css'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
render:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 0 }
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with: { node-version: '20' }
|
||||||
|
- name: Install Chrome
|
||||||
|
run: |
|
||||||
|
npx --yes @marp-team/marp-cli@latest --version
|
||||||
|
npx --yes @mermaid-js/mermaid-cli --version
|
||||||
|
- name: Render slides
|
||||||
|
run: bash scripts/render_slides.sh
|
||||||
|
- name: Commit rendered artifacts
|
||||||
|
run: |
|
||||||
|
git config user.name "nova-slides-bot"
|
||||||
|
git config user.email "bot@nova.local"
|
||||||
|
git add docs/presentations/*.html docs/presentations/*.pptx docs/presentations/assets/png/*.png
|
||||||
|
git diff --cached --quiet || git commit -m "chore(slides): re-render deck [skip ci]"
|
||||||
|
git push
|
||||||
+10
-15
@@ -1,35 +1,30 @@
|
|||||||
# GitHub Workflows — Nova Platform CI/CD Catalog
|
# GitHub Workflows — Nova Platform CI/CD Catalog
|
||||||
|
|
||||||
This directory contains the 7 GitHub Actions workflows for the Nova
|
This directory contains the GitHub Actions workflows for the Nova
|
||||||
platform. 3 are byte-identical Gitea mirrors (generated from
|
platform. 3 are generated from `workflows-src/<name>`; 4 are GitHub-only.
|
||||||
`workflows-src/` by `scripts/sync_workflows.py`, P8/REQ-172); 4 are
|
|
||||||
GitHub-only (Gitea act_runner feature gaps).
|
|
||||||
|
|
||||||
## Shared workflows (byte-identical Gitea + GitHub)
|
## Shared workflows (generated from source)
|
||||||
|
|
||||||
These 3 are generated from `workflows-src/<name>` by
|
These 3 are generated from `workflows-src/<name>`. Run `python3 scripts/sync_workflows.py --check` to verify
|
||||||
`scripts/sync_workflows.py`; the `.gitea/workflows/<name>` mirror is kept
|
|
||||||
byte-identical. Run `python3 scripts/sync_workflows.py --check` to verify
|
|
||||||
no drift.
|
no drift.
|
||||||
|
|
||||||
| Workflow | Trigger | Inputs | Required Secrets | Purpose |
|
| Workflow | Trigger | Inputs | Required Secrets | Purpose |
|
||||||
|----------|---------|--------|------------------|---------|
|
|----------|---------|--------|------------------|---------|
|
||||||
| `ci.yml` | `pull_request: [main]` | — | — | Lint + test + check-only (runs on every PR) |
|
| `ci.yml` | `pull_request: [main]` | — | — | Lint + test + check-only (runs on every PR) |
|
||||||
| `deploy.yml` | `workflow_call` (reusable) + `push: [main]` | `contract` (string, required), `mode` (string, default `deploy`), `changeRequestId` (string), `environment` (string) | `NOVA_AWS_ACCESS_KEY_ID`, `NOVA_AWS_SECRET_ACCESS_KEY`, `NOVA_AWS_DEFAULT_REGION`, `NOVA_KMS_KEY_ID`, `NOVA_LAMBDA_URL` | Reusable deploy workflow (invoked by consumer repos via `uses: acdl/.github/workflows/deploy.yml@v1.15`) |
|
| `deploy.yml` | `workflow_call` (reusable) + `push: [main]` | `contract` (string, required), `mode` (string, default `deploy`), `changeRequestId` (string), `environment` (string) | `NOVA_AWS_ACCESS_KEY_ID`, `NOVA_AWS_SECRET_ACCESS_KEY`, `NOVA_AWS_DEFAULT_REGION`, `NOVA_KMS_KEY_ID`, `NOVA_LAMBDA_URL` | Reusable deploy workflow (invoked by consumer repos via `uses: nova/.github/workflows/deploy.yml@v1.19`) |
|
||||||
| `modules-lifecycle.yml` | `pull_request: [main]` + `workflow_dispatch` | `lifecycle_mode` (string, default `plan` — `plan` or `full`) | `NOVA_AWS_ACCESS_KEY_ID`, `NOVA_AWS_SECRET_ACCESS_KEY`, `NOVA_AWS_DEFAULT_REGION`, `NOVA_AWS_ACCOUNT_ID` | L1 + L2 module lifecycle pipeline (plan-only default; full apply/modify/destroy on override) |
|
| `modules-lifecycle.yml` | `pull_request: [main]` + `workflow_dispatch` | `lifecycle_mode` (string, default `plan` — `plan` or `full`) | `NOVA_AWS_ACCESS_KEY_ID`, `NOVA_AWS_SECRET_ACCESS_KEY`, `NOVA_AWS_DEFAULT_REGION`, `NOVA_AWS_ACCOUNT_ID` | L1 + L2 module lifecycle pipeline (plan-only default; full apply/modify/destroy on override) |
|
||||||
|
|
||||||
## GitHub-only workflows (no Gitea mirror)
|
## GitHub-only workflows
|
||||||
|
|
||||||
These 4 have no Gitea counterpart (Gitea act_runner lacks the features
|
These 4 have no counterpart (the dev forge lacks the features
|
||||||
they require — reusable workflows, matrix `needs`, release API). See
|
they require — reusable workflows, matrix `needs`, release API).
|
||||||
`.gitea/workflows/README.md` for the limitation rationale.
|
|
||||||
|
|
||||||
| Workflow | Trigger | Inputs | Required Secrets | Purpose |
|
| Workflow | Trigger | Inputs | Required Secrets | Purpose |
|
||||||
|----------|---------|--------|------------------|---------|
|
|----------|---------|--------|------------------|---------|
|
||||||
| `platform-test.yml` | `pull_request: [main]` | — | — | Lint + unit + integration + schema-validation (replaces `ci.yml` for PRs) |
|
| `platform-test.yml` | `pull_request: [main]` | — | — | Lint + unit + integration + schema-validation (replaces `ci.yml` for PRs) |
|
||||||
| `primitives-plan.yml` | `pull_request: [main]` | — | `NOVA_AWS_*` | Plan-only for all L1 primitives (matrix) |
|
| `primitives-plan.yml` | `pull_request: [main]` | — | `NOVA_AWS_*` | Plan-only for all L1 primitives (matrix) |
|
||||||
| `patterns-plan.yml` | `pull_request: [main]` | — | `NOVA_AWS_*` | Plan-only for all L2 modules (matrix) |
|
| `patterns-plan.yml` | `pull_request: [main]` | — | `NOVA_AWS_*` | Plan-only for all L2 modules (matrix) |
|
||||||
| `release.yml` | `push: [main]` | — | `NOVA_GITEA_TOKEN` (for Gitea release API) | Semver tag + MAJOR.MINOR/MAJOR floating-tag maintenance + release creation on merge to main |
|
| `release.yml` | `push: [main]` | — | `NOVA_RELEASE_TOKEN` | Semver tag + MAJOR.MINOR/MAJOR floating-tag maintenance + release creation on merge to main |
|
||||||
|
|
||||||
## Reusable deploy workflow (`deploy.yml`)
|
## Reusable deploy workflow (`deploy.yml`)
|
||||||
|
|
||||||
@@ -38,7 +33,7 @@ Consumer repos invoke the deploy workflow via a versioned tag:
|
|||||||
```yaml
|
```yaml
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.15
|
uses: nova/.github/workflows/deploy.yml@v1.19
|
||||||
with:
|
with:
|
||||||
contract: .nova/contract.yml
|
contract: .nova/contract.yml
|
||||||
environment: dev
|
environment: dev
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# ACDL CI Pipeline — Gitea Actions (dev environment)
|
# Nova CI Pipeline (dev environment)
|
||||||
#
|
#
|
||||||
# This workflow implements the central pipeline contract:
|
# This workflow implements the central pipeline contract:
|
||||||
# pipelines/ci.yml (validated against schemas/pipeline.schema.json)
|
# pipelines/ci.yml (validated against schemas/pipeline.schema.json)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# ACDL Reusable Deploy Workflow — Gitea Actions (dev environment)
|
# Nova Reusable Deploy Workflow (dev environment)
|
||||||
#
|
#
|
||||||
# This reusable workflow implements the central deployment pipeline contract:
|
# This reusable workflow implements the central deployment pipeline contract:
|
||||||
# pipelines/contract.yml (validated against schemas/deploy-pipeline.schema.json)
|
# pipelines/contract.yml (validated against schemas/deploy-pipeline.schema.json)
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
# declared difference is the forge/runtime, not the stages or commands.
|
# declared difference is the forge/runtime, not the stages or commands.
|
||||||
#
|
#
|
||||||
# Consumer repos invoke this workflow via a versioned tag (floating MAJOR + MINOR):
|
# Consumer repos invoke this workflow via a versioned tag (floating MAJOR + MINOR):
|
||||||
# uses: acdl/.gitea/workflows/deploy.yml@v1.9 (Gitea)
|
# uses: nova/.github/workflows/deploy.yml@v1.19
|
||||||
# uses: acdl/.github/workflows/deploy.yml@v1.9 (GitHub)
|
# uses: acdl/.github/workflows/deploy.yml@v1.9 (GitHub)
|
||||||
#
|
#
|
||||||
# Unversioned references (@main, bare) are discouraged — the consumer's setup
|
# Unversioned references (@main, bare) are discouraged — the consumer's setup
|
||||||
@@ -38,8 +38,8 @@
|
|||||||
# that matches repo:org/consumer-repo:ref:refs/heads/main, and the session
|
# that matches repo:org/consumer-repo:ref:refs/heads/main, and the session
|
||||||
# policy restricts view/update to resources tagged acdl:owner=<consumer-repo>.
|
# policy restricts view/update to resources tagged acdl:owner=<consumer-repo>.
|
||||||
#
|
#
|
||||||
# Override (where OIDC is unavailable, e.g. Gitea pending
|
# Override (where OIDC is unavailable, e.g. pending
|
||||||
# go-gitea/gitea#36988): set NOVA_AWS_ACCESS_KEY_ID + NOVA_AWS_SECRET_ACCESS_KEY
|
# upstream forge OIDC support): set NOVA_AWS_ACCESS_KEY_ID + NOVA_AWS_SECRET_ACCESS_KEY
|
||||||
# as repository secrets. The platform-managed scheduled pipeline rotates
|
# as repository secrets. The platform-managed scheduled pipeline rotates
|
||||||
# the key on a daily cadence. When .env.secrets is used locally instead,
|
# the key on a daily cadence. When .env.secrets is used locally instead,
|
||||||
# rotating the key out of band is the consumer's responsibility.
|
# rotating the key out of band is the consumer's responsibility.
|
||||||
@@ -155,7 +155,7 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nova-terraform
|
name: nova-terraform
|
||||||
path: /tmp/acdl_platform_run_v18/tf/*.tf
|
path: /tmp/nova_platform_run/tf/*.tf
|
||||||
if-no-files-found: warn
|
if-no-files-found: warn
|
||||||
|
|
||||||
- name: Upload platform log
|
- name: Upload platform log
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# ACDL Modules Lifecycle Pipeline — Gitea Actions (dev environment)
|
# Nova Modules Lifecycle Pipeline (dev environment)
|
||||||
#
|
#
|
||||||
# Matrix-runs each L1 module's examples/{simple,complex}.yml contracts through
|
# Matrix-runs each L1 module's examples/{simple,complex}.yml contracts through
|
||||||
# apply→modify→destroy against live AWS. No per-module Python. The "test" =
|
# apply→modify→destroy against live AWS. No per-module Python. The "test" =
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
# terraform files); the composition must be deterministic.
|
# terraform files); the composition must be deterministic.
|
||||||
#
|
#
|
||||||
# This workflow implements pipelines/modules-lifecycle.yml (byte-identical
|
# This workflow implements pipelines/modules-lifecycle.yml (byte-identical
|
||||||
# in .gitea/workflows/ and .github/workflows/).
|
# in .github/workflows/).
|
||||||
#
|
#
|
||||||
# Lifecycle mode (REQ-134, v1.12): the `lifecycle_mode` input defaults to
|
# Lifecycle mode (REQ-134, v1.12): the `lifecycle_mode` input defaults to
|
||||||
# "plan" — the lifecycle scripts run `run_platform.sh --plan-only` (fast,
|
# "plan" — the lifecycle scripts run `run_platform.sh --plan-only` (fast,
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Nova Slides Render — re-renders presentation deck when source files change.
|
||||||
|
name: Nova Slides Render
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'docs/presentations/**'
|
||||||
|
- 'scripts/render_slides.sh'
|
||||||
|
- 'assets/nova-sp-theme.css'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
render:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 0 }
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with: { node-version: '20' }
|
||||||
|
- name: Install Chrome
|
||||||
|
run: |
|
||||||
|
npx --yes @marp-team/marp-cli@latest --version
|
||||||
|
npx --yes @mermaid-js/mermaid-cli --version
|
||||||
|
- name: Render slides
|
||||||
|
run: bash scripts/render_slides.sh
|
||||||
|
- name: Commit rendered artifacts
|
||||||
|
run: |
|
||||||
|
git config user.name "nova-slides-bot"
|
||||||
|
git config user.email "bot@nova.local"
|
||||||
|
git add docs/presentations/*.html docs/presentations/*.pptx docs/presentations/assets/png/*.png
|
||||||
|
git diff --cached --quiet || git commit -m "chore(slides): re-render deck [skip ci]"
|
||||||
|
git push
|
||||||
+2
-1
@@ -40,4 +40,5 @@ metrics/lifecycle/
|
|||||||
*.cer
|
*.cer
|
||||||
*.crt
|
*.crt
|
||||||
*.jks
|
*.jks
|
||||||
*.keystore
|
*.keystore.coverage
|
||||||
|
.coverage
|
||||||
|
|||||||
@@ -219,23 +219,9 @@ bash scripts/run_ci.sh --quiet # suppress per-stage banners
|
|||||||
|
|
||||||
### Reusable deploy workflow
|
### Reusable deploy workflow
|
||||||
|
|
||||||
The deployment pipeline is defined by a **central deployment pipeline
|
Consumer repos invoke the deploy pipeline via `.github/workflows/deploy.yml`
|
||||||
contract** (`pipelines/contract.yml`, validated against
|
(a reusable GitHub Actions workflow, versioned tag `nova/.github/workflows/deploy.yml@v1.19`).
|
||||||
`schemas/deploy-pipeline.schema.json`) and exposed to consumer repos as a
|
See the [Consumer guide](docs/consumer-guide.md) for the end-to-end happy path.
|
||||||
**reusable workflow**:
|
|
||||||
|
|
||||||
- `.github/workflows/deploy.yml` — GitHub Actions (production)
|
|
||||||
|
|
||||||
The workflow implements the same stages as `pipelines/contract.yml`
|
|
||||||
(validate-contract → resolve-stack → security checks → infrastructure plan
|
|
||||||
→ policy checks → confidence → evidence event → apply). A consumer repo
|
|
||||||
invokes the reusable workflow via a **versioned tag** (floating MAJOR +
|
|
||||||
MINOR, e.g. `acdl/.github/workflows/deploy.yml@v1.13`). The workflow checks
|
|
||||||
out the consumer repo, then checks out the Nova platform repo into the
|
|
||||||
runner workspace, and runs `scripts/run_platform.sh` against the consumer's
|
|
||||||
contract — the consumer never clones the platform repo or invokes its
|
|
||||||
scripts locally. See the [Consumer guide](docs/consumer-guide.md) for the
|
|
||||||
end-to-end happy path.
|
|
||||||
|
|
||||||
### Output streaming (run_platform.sh)
|
### Output streaming (run_platform.sh)
|
||||||
|
|
||||||
@@ -310,12 +296,6 @@ documented alternative:
|
|||||||
runs, or in **`.env.secrets`** (gitignored, chmod 600) for local testing.
|
runs, or in **`.env.secrets`** (gitignored, chmod 600) for local testing.
|
||||||
- The platform rotates platform-runner keys on a **daily cadence** —
|
- The platform rotates platform-runner keys on a **daily cadence** —
|
||||||
rotation is not the consumer's burden in the platform-runner path.
|
rotation is not the consumer's burden in the platform-runner path.
|
||||||
- **When `.env.secrets` is used locally**, rotating the key **out of band is
|
|
||||||
the consumer's responsibility**. The platform guarantees daily rotation
|
|
||||||
for platform-runner runs; it does not guarantee rotation for
|
|
||||||
locally-held copies. The consumer must rotate a local key via
|
|
||||||
`scripts/rotate_spike_key.sh` (or equivalent) on their own cadence.
|
|
||||||
|
|
||||||
No long-lived credential is permitted persistently — the platform-runner
|
No long-lived credential is permitted persistently — the platform-runner
|
||||||
key's useful lifetime is one workflow run, and the local alternative is
|
key's useful lifetime is one workflow run, and the local alternative is
|
||||||
rotated at least daily (platform-runner) or out of band (local).
|
rotated at least daily (platform-runner) or out of band (local).
|
||||||
@@ -186,8 +186,37 @@ def is_configured():
|
|||||||
return bool(os.environ.get("WIZ_API_TOKEN") and os.environ.get("WIZ_API_URL"))
|
return bool(os.environ.get("WIZ_API_TOKEN") and os.environ.get("WIZ_API_URL"))
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_and_adapt_plan(plan_path, contract_id, run_id=None):
|
||||||
|
"""Fetch Wiz findings against a terraform plan and translate to
|
||||||
|
PolicyCheckResult. REQ-250 (v1.21): Wiz scans the terraform plan
|
||||||
|
output. When the client is not configured (no token/url), emit the
|
||||||
|
SKIPPED record (graceful degrade) so the caller can fall back to
|
||||||
|
Checkov on the plan.
|
||||||
|
"""
|
||||||
|
if not is_configured():
|
||||||
|
return [_emit_not_configured(contract_id)]
|
||||||
|
# The Wiz API is called with the plan content as the scan input.
|
||||||
|
client = WizClient()
|
||||||
|
issues = client.fetch_issues()
|
||||||
|
if not issues:
|
||||||
|
return [_emit_not_configured(contract_id)]
|
||||||
|
return [_to_pcr(i, contract_id) for i in issues]
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 3:
|
import argparse
|
||||||
print("usage: wiz_adapter.py <wiz_issues.json> <contract-id>", file=sys.stderr)
|
parser = argparse.ArgumentParser(description="Wiz adapter (REQ-250: plan-mode supported)")
|
||||||
sys.exit(2)
|
parser.add_argument("wiz_json", nargs="?", help="wiz_issues.json (legacy positional mode)")
|
||||||
print(json.dumps(adapt(sys.argv[1], sys.argv[2]), indent=2))
|
parser.add_argument("contract_id_pos", nargs="?", help="contract-id (legacy positional mode)")
|
||||||
|
parser.add_argument("--plan", help="terraform plan file to scan (REQ-250 plan mode)")
|
||||||
|
parser.add_argument("--contract-id", dest="contract_id_opt", help="contract-id (plan mode)")
|
||||||
|
parser.add_argument("--run-id", help="run-id for the plan scan (plan mode)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
if args.plan:
|
||||||
|
cid = args.contract_id_opt or ""
|
||||||
|
out = fetch_and_adapt_plan(args.plan, cid, run_id=args.run_id)
|
||||||
|
print(json.dumps(out, indent=2))
|
||||||
|
elif args.wiz_json and args.contract_id_pos:
|
||||||
|
print(json.dumps(adapt(args.wiz_json, args.contract_id_pos), indent=2))
|
||||||
|
else:
|
||||||
|
parser.error("either --plan <file> --contract-id <id> OR <wiz_issues.json> <contract-id>")
|
||||||
@@ -62,7 +62,7 @@ path above remains the v1.9 production audit record.
|
|||||||
**platform-level KMS key** (not per-contract — a per-contract key would
|
**platform-level KMS key** (not per-contract — a per-contract key would
|
||||||
explode the key-management surface), rotated **quarterly**. The `jws`
|
explode the key-management surface), rotated **quarterly**. The `jws`
|
||||||
field is added to the event shape when this ships.
|
field is added to the event shape when this ships.
|
||||||
- **Async worker + DLQ:** a Lambda (or a Gitea Actions scheduled workflow)
|
- **Async worker + DLQ:** a Lambda (or a forge Actions scheduled workflow)
|
||||||
reads the outbox, writes to S3 Object Lock, signs with KMS. DLQ = an
|
reads the outbox, writes to S3 Object Lock, signs with KMS. DLQ = an
|
||||||
SQS dead-letter queue for failed writes. RTO = DLQ replay.
|
SQS dead-letter queue for failed writes. RTO = DLQ replay.
|
||||||
- **Daily checkpoints (§9):** a daily job reads the last event hash and
|
- **Daily checkpoints (§9):** a daily job reads the last event hash and
|
||||||
@@ -86,7 +86,7 @@ log" anti-goal requires.
|
|||||||
D-083 ships).
|
D-083 ships).
|
||||||
- `prev_event_hash` (chain link; `GENESIS` for the first event).
|
- `prev_event_hash` (chain link; `GENESIS` for the first event).
|
||||||
- `hash` (this event's SHA-256 over canonical JSON).
|
- `hash` (this event's SHA-256 over canonical JSON).
|
||||||
- `approver_qa` (Gitea/GitHub username of the QA approver; populated on
|
- `approver_qa` (CI username of the QA approver; populated on
|
||||||
qa-promotion by v1.9's `hitl_gates.attest` — D-042).
|
qa-promotion by v1.9's `hitl_gates.attest` — D-042).
|
||||||
- `approver_prod` (SRE username; populated on prod-promotion by v1.9's
|
- `approver_prod` (SRE username; populated on prod-promotion by v1.9's
|
||||||
`hitl_gates.attest`).
|
`hitl_gates.attest`).
|
||||||
@@ -112,7 +112,7 @@ log" anti-goal requires.
|
|||||||
- **D-042** — approver identities (`approver_qa`, `approver_prod`,
|
- **D-042** — approver identities (`approver_qa`, `approver_prod`,
|
||||||
`approver_dr`) live in the outbox; the separation-of-duties check
|
`approver_dr`) live in the outbox; the separation-of-duties check
|
||||||
(`core/separation_of_duties.py`) reads `approver_qa` and compares
|
(`core/separation_of_duties.py`) reads `approver_qa` and compares
|
||||||
to the prod-dispatch `gitea.actor` / `github.actor`. v1.9's
|
to the prod-dispatch CI actor. v1.9's
|
||||||
`hitl_gates.attest` populates these attributes.
|
`hitl_gates.attest` populates these attributes.
|
||||||
- **D-083** (v1.9) — S3 Object Lock + JWS + async worker + DLQ + daily
|
- **D-083** (v1.9) — S3 Object Lock + JWS + async worker + DLQ + daily
|
||||||
checkpoints deferred to a future milestone. Requires non-offline-
|
checkpoints deferred to a future milestone. Requires non-offline-
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
"""HITL pre-execution attestation gates (REQ-108, D-084).
|
"""HITL pre-execution attestation gates (REQ-108, D-084).
|
||||||
|
|
||||||
Records the approver identity (`gitea.actor` / `github.actor`) to the
|
Records the approver identity (the CI actor (GITHUB_ACTOR or FORGE_ACTOR)) to the
|
||||||
DynamoDB outbox for the contractId (attribute `approver_qa` /
|
DynamoDB outbox for the contractId (attribute `approver_qa` /
|
||||||
`approver_prod` / `approver_dr`), runs the separation-of-duties check on
|
`approver_prod` / `approver_dr`), runs the separation-of-duties check on
|
||||||
prod, invokes the 8-concern attestation matrix for the target env, and
|
prod, invokes the 8-concern attestation matrix for the target env, and
|
||||||
@@ -29,7 +29,7 @@ def attest(contract_id: str, env: str, approver: str,
|
|||||||
Args:
|
Args:
|
||||||
contract_id: the contract UUID.
|
contract_id: the contract UUID.
|
||||||
env: dev/qa/prod/dr.
|
env: dev/qa/prod/dr.
|
||||||
approver: the approver's username (`gitea.actor` / `github.actor`).
|
approver: the approver's username (the CI actor (GITHUB_ACTOR or FORGE_ACTOR)).
|
||||||
evidence: optional operator-supplied evidence artifacts (for the
|
evidence: optional operator-supplied evidence artifacts (for the
|
||||||
attestation matrix operator-supplied concerns).
|
attestation matrix operator-supplied concerns).
|
||||||
outbox_client: optional moto-mocked DynamoDB outbox client for tests.
|
outbox_client: optional moto-mocked DynamoDB outbox client for tests.
|
||||||
@@ -41,7 +41,7 @@ def attest(contract_id: str, env: str, approver: str,
|
|||||||
return (True, "dev autonomous (no HITL gate)")
|
return (True, "dev autonomous (no HITL gate)")
|
||||||
|
|
||||||
if not approver:
|
if not approver:
|
||||||
return (False, f"no approver identity for {env} (GITHUB_ACTOR/GITEA_ACTOR unset)")
|
return (False, f"no approver identity for {env} (GITHUB_ACTOR/FORGE_ACTOR unset)")
|
||||||
|
|
||||||
attr = _approver_attr(env)
|
attr = _approver_attr(env)
|
||||||
if not attr:
|
if not attr:
|
||||||
@@ -88,7 +88,7 @@ def attest(contract_id: str, env: str, approver: str,
|
|||||||
|
|
||||||
def approver_from_env() -> Optional[str]:
|
def approver_from_env() -> Optional[str]:
|
||||||
"""Read the approver identity from the environment."""
|
"""Read the approver identity from the environment."""
|
||||||
return os.environ.get("GITHUB_ACTOR") or os.environ.get("GITEA_ACTOR")
|
return os.environ.get("GITHUB_ACTOR") or os.environ.get("FORGE_ACTOR")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
+15
-15
@@ -18,32 +18,32 @@ gates. No partial deployment to roll back on rejection (qa, prod); dr is
|
|||||||
a separate deployment against a separate cluster/region. The
|
a separate deployment against a separate cluster/region. The
|
||||||
canary/deployment-rollback model is explicitly not in scope for v1.
|
canary/deployment-rollback model is explicitly not in scope for v1.
|
||||||
|
|
||||||
## Gitea-specific gate mechanics (D-042)
|
## Forge-specific gate mechanics (D-042)
|
||||||
|
|
||||||
Gitea has **no Environments API** and ignores `environment:` blocks
|
The dev forge has **no Environments API** and ignores `environment:` blocks
|
||||||
(v1.0 D-013; re-confirmed in RESEARCH TARGET 1). The pre-execution gate
|
(v1.0 D-013; re-confirmed in RESEARCH TARGET 1). The pre-execution gate
|
||||||
is modeled as a `workflow_dispatch` with approval inputs:
|
is modeled as a `workflow_dispatch` with approval inputs:
|
||||||
|
|
||||||
- **qa gate:** `workflow_dispatch` with `approve_qa: true`; the dispatch
|
- **qa gate:** `workflow_dispatch` with `approve_qa: true`; the dispatch
|
||||||
run's `gitea.actor` is the QA approver.
|
run's `CI actor` is the QA approver.
|
||||||
- **prod gate:** `workflow_dispatch` with `approve_prod: true`;
|
- **prod gate:** `workflow_dispatch` with `approve_prod: true`;
|
||||||
`gitea.actor` is the SRE approver.
|
`CI actor` is the SRE approver.
|
||||||
- **dr gate:** `workflow_dispatch` with `approve_dr: true`; same.
|
- **dr gate:** `workflow_dispatch` with `approve_dr: true`; same.
|
||||||
|
|
||||||
The approver identity of record = `gitea.actor` of the dispatch run
|
The approver identity of record = `CI actor` of the dispatch run
|
||||||
(D-042). There is no other approval-identity signal in Gitea. The real
|
(D-042). There is no other approval-identity signal in the dev forge. The real
|
||||||
OIDC path (blocked on go-gitea/gitea#36988) does not change this —
|
OIDC path (blocked on upstream forge OIDC support) does not change this —
|
||||||
OIDC authorizes the *runner* to AWS, it does not change how the platform
|
OIDC authorizes the *runner* to AWS, it does not change how the platform
|
||||||
records the *human* approver.
|
records the *human* approver.
|
||||||
|
|
||||||
On GitHub, the equivalent is `github.actor` of the `workflow_dispatch`
|
On GitHub, the equivalent is `CI actor` of the `workflow_dispatch`
|
||||||
run; GitHub Environments with required reviewers are the native gate,
|
run; GitHub Environments with required reviewers are the native gate,
|
||||||
but the `workflow_dispatch` approval-input fallback is used for
|
but the `workflow_dispatch` approval-input fallback is used for
|
||||||
byte-identical Gitea + GitHub workflows.
|
byte-identical across forges.
|
||||||
|
|
||||||
## Reviewer routing (ARCHITECTURE.md §10.2)
|
## Reviewer routing (ARCHITECTURE.md §10.2)
|
||||||
|
|
||||||
Gitea CODEOWNERS routes the right reviewer to the right gate:
|
CODEOWNERS routes the right reviewer to the right gate:
|
||||||
|
|
||||||
- qa → QA team
|
- qa → QA team
|
||||||
- prod → SRE team
|
- prod → SRE team
|
||||||
@@ -105,7 +105,7 @@ concern is missing or expired for prod/dr.
|
|||||||
| 1 business day | PENDING_ATTESTATION_WARNING | Notify team + platform on-call (elevated path); emit `PENDING_ATTESTATION_TIMEOUT_WARNING` event |
|
| 1 business day | PENDING_ATTESTATION_WARNING | Notify team + platform on-call (elevated path); emit `PENDING_ATTESTATION_TIMEOUT_WARNING` event |
|
||||||
| 2 business days | PENDING_ATTESTATION_AUTO_FREEZE | Auto-freeze; require re-submission; emit `PENDING_ATTESTATION_AUTO_FREEZE` event; new submission linked via `supersedes` |
|
| 2 business days | PENDING_ATTESTATION_AUTO_FREEZE | Auto-freeze; require re-submission; emit `PENDING_ATTESTATION_AUTO_FREEZE` event; new submission linked via `supersedes` |
|
||||||
|
|
||||||
**Implementation:** a Gitea `on: schedule` workflow (runs hourly) that
|
**Implementation:** an `on: schedule` workflow (runs hourly) that
|
||||||
scans the DynamoDB outbox for `PENDING_ATTESTATION` events with `ts`
|
scans the DynamoDB outbox for `PENDING_ATTESTATION` events with `ts`
|
||||||
older than 1/2 business days and emits the warn/freeze events. Not
|
older than 1/2 business days and emits the warn/freeze events. Not
|
||||||
implemented in v1.9 (roadmap item; the attestation gates themselves are
|
implemented in v1.9 (roadmap item; the attestation gates themselves are
|
||||||
@@ -126,11 +126,11 @@ The identity-distinctness check is platform-internal, not GitHub-native,
|
|||||||
not Kyverno (in v1). Sequence:
|
not Kyverno (in v1). Sequence:
|
||||||
|
|
||||||
1. On promotion dev → qa, the platform reads the QA approver's identity
|
1. On promotion dev → qa, the platform reads the QA approver's identity
|
||||||
from the `workflow_dispatch` run's `gitea.actor` (or `github.actor`)
|
from the `workflow_dispatch` run's `CI actor`
|
||||||
and writes it to the DynamoDB outbox keyed by `contractId` (attribute
|
and writes it to the DynamoDB outbox keyed by `contractId` (attribute
|
||||||
`approver_qa`).
|
`approver_qa`).
|
||||||
2. On promotion qa → prod, the platform reads the stored `approver_qa`
|
2. On promotion qa → prod, the platform reads the stored `approver_qa`
|
||||||
from the outbox and the new SRE approver's `gitea.actor` from the
|
from the outbox and the new SRE approver identity from the
|
||||||
prod-dispatch run.
|
prod-dispatch run.
|
||||||
3. If `approver_qa == approver_prod`, the platform blocks the prod
|
3. If `approver_qa == approver_prod`, the platform blocks the prod
|
||||||
promotion, writes a `SEPARATION_OF_DUTIES_VIOLATION` event to the
|
promotion, writes a `SEPARATION_OF_DUTIES_VIOLATION` event to the
|
||||||
@@ -163,8 +163,8 @@ v1.9 (Phase 41 + Phase 42) wires the gates end-to-end:
|
|||||||
|
|
||||||
## Decision trail
|
## Decision trail
|
||||||
|
|
||||||
- **D-042** — approver identity = `gitea.actor` of the `workflow_dispatch`
|
- **D-042** — approver identity = `CI actor` of the `workflow_dispatch`
|
||||||
run; no Environments API in Gitea. On GitHub, `github.actor`.
|
run; no Environments API in the dev forge.
|
||||||
- **D-013** (v1.0) — the `workflow_dispatch` approval-input fallback,
|
- **D-013** (v1.0) — the `workflow_dispatch` approval-input fallback,
|
||||||
re-used for the real platform's pre-execution gate model.
|
re-used for the real platform's pre-execution gate model.
|
||||||
- **D-084** (v1.9) — 8-concern attestation matrix: offline-testable
|
- **D-084** (v1.9) — 8-concern attestation matrix: offline-testable
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ CHANGE_REQUESTS_TABLE = os.environ.get("CHANGE_REQUESTS_TABLE", "nova-change-req
|
|||||||
GITHUB_TOKEN_SECRET_ID = os.environ.get("GITHUB_TOKEN_SECRET_ID", "nova/github-token")
|
GITHUB_TOKEN_SECRET_ID = os.environ.get("GITHUB_TOKEN_SECRET_ID", "nova/github-token")
|
||||||
PLATFORM_REPO = os.environ.get("PLATFORM_REPO", "nova/acdl")
|
PLATFORM_REPO = os.environ.get("PLATFORM_REPO", "nova/acdl")
|
||||||
# P1-9: Forge-agnostic API base URL. Defaults to GitHub; set GITHUB_API_BASE
|
# P1-9: Forge-agnostic API base URL. Defaults to GitHub; set GITHUB_API_BASE
|
||||||
# to a Gitea API root (e.g. https://git.cloudinit.dev/api/v1) for Gitea.
|
# to a compatible forge API root (e.g. https://forge.example.com/api/v1).
|
||||||
GITHUB_API_BASE = os.environ.get("GITHUB_API_BASE", "https://api.github.com")
|
GITHUB_API_BASE = os.environ.get("GITHUB_API_BASE", "https://api.github.com")
|
||||||
|
|
||||||
# P11 (REQ-175): consistent cap for error/stackTrace fields (was 10k vs 2k).
|
# P11 (REQ-175): consistent cap for error/stackTrace fields (was 10k vs 2k).
|
||||||
@@ -96,22 +96,22 @@ def _iso8601_now():
|
|||||||
|
|
||||||
|
|
||||||
def _forge_type():
|
def _forge_type():
|
||||||
"""P1-9: Detect whether the API base is GitHub or Gitea.
|
"""Detect whether the API base is GitHub or a compatible forge.
|
||||||
|
|
||||||
Gitea API roots contain '/api/v1'; GitHub's is 'api.github.com'.
|
Compatible forge API roots contain '/api/v1'; GitHub's is 'api.github.com'.
|
||||||
"""
|
"""
|
||||||
if "/api/v1" in GITHUB_API_BASE:
|
if "/api/v1" in GITHUB_API_BASE:
|
||||||
return "gitea"
|
return "generic_forge"
|
||||||
return "github"
|
return "github"
|
||||||
|
|
||||||
|
|
||||||
def _issues_search_url(owner, repo, encoded_query):
|
def _issues_search_url(owner, repo, encoded_query):
|
||||||
"""P1-9: Build the issue search URL based on forge type.
|
"""Build the issue search URL based on forge type.
|
||||||
|
|
||||||
GitHub uses /search/issues?q=...; Gitea uses /repos/{owner}/{repo}/issues?...
|
GitHub uses /search/issues?q=...; compatible forges use /repos/{owner}/{repo}/issues?...
|
||||||
with query params (no /search/issues endpoint).
|
with query params (no /search/issues endpoint).
|
||||||
"""
|
"""
|
||||||
if _forge_type() == "gitea":
|
if _forge_type() == "generic_forge":
|
||||||
return (
|
return (
|
||||||
f"{GITHUB_API_BASE}/repos/{owner}/{repo}/issues"
|
f"{GITHUB_API_BASE}/repos/{owner}/{repo}/issues"
|
||||||
f"?state=open&type=issues&q={encoded_query}"
|
f"?state=open&type=issues&q={encoded_query}"
|
||||||
@@ -123,7 +123,7 @@ def _issues_search_url(owner, repo, encoded_query):
|
|||||||
|
|
||||||
|
|
||||||
def _issues_create_url(owner, repo):
|
def _issues_create_url(owner, repo):
|
||||||
"""URL for creating an issue (same pattern for both GitHub + Gitea)."""
|
"""URL for creating an issue (same pattern across forges)."""
|
||||||
return f"{GITHUB_API_BASE}/repos/{owner}/{repo}/issues"
|
return f"{GITHUB_API_BASE}/repos/{owner}/{repo}/issues"
|
||||||
|
|
||||||
|
|
||||||
@@ -499,4 +499,23 @@ def lambda_handler(event, context):
|
|||||||
return {"statusCode": 401, "body": json.dumps({"error": str(e)})}
|
return {"statusCode": 401, "body": json.dumps({"error": str(e)})}
|
||||||
return {"statusCode": 400, "body": json.dumps({"error": str(e)})}
|
return {"statusCode": 400, "body": json.dumps({"error": str(e)})}
|
||||||
except Exception as e: # pragma: no cover - defensive top-level guard
|
except Exception as e: # pragma: no cover - defensive top-level guard
|
||||||
return {"statusCode": 500, "body": json.dumps({"error": str(e)})}
|
return {"statusCode": 500, "body": json.dumps({"error": str(e)})}
|
||||||
|
|
||||||
|
|
||||||
|
# --- CLI: --check-readiness (D-133, REQ-218) ---------------------------
|
||||||
|
# Invoked as: python3 -m core.lambda.contract_ingestor --check-readiness <submission.json>
|
||||||
|
# Delegates to core.submission_readiness.check_readiness() and prints the
|
||||||
|
# structured ReadinessResult. Exits 0 if ready, 1 if not.
|
||||||
|
if __name__ == "__main__": # pragma: no cover - CLI entry
|
||||||
|
import sys
|
||||||
|
if "--check-readiness" in sys.argv:
|
||||||
|
sys.path.insert(
|
||||||
|
0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
)
|
||||||
|
from core.submission_readiness import cli_main
|
||||||
|
|
||||||
|
# Strip the --check-readiness flag; pass the file path.
|
||||||
|
rest = [a for a in sys.argv[1:] if a != "--check-readiness"]
|
||||||
|
sys.exit(cli_main(["check-readiness"] + rest))
|
||||||
|
else:
|
||||||
|
print("Usage: python3 -m core.lambda.contract_ingestor --check-readiness <submission.json>")
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
"""Nova PowerBI Export (REQ-190, P3).
|
||||||
|
|
||||||
|
Emits CSV/JSON views to metrics/powerbi/ from the SQLite cold store.
|
||||||
|
Fact + dimension tables + 8 empty placeholder views for deferred metrics
|
||||||
|
(with documented schemas ready to fill when their blocking decisions lift).
|
||||||
|
|
||||||
|
D-120: Nova-native (CSV/JSON files, no live connector)
|
||||||
|
D-129: PowerBI ingests via the folder connector
|
||||||
|
D-128: metrics/ at repo root
|
||||||
|
"""
|
||||||
|
|
||||||
|
import csv
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sqlite3
|
||||||
|
import sys
|
||||||
|
|
||||||
|
_METRICS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "metrics")
|
||||||
|
_STORE_PATH = os.path.join(_METRICS_DIR, "nova_metrics.db")
|
||||||
|
_EXPORT_DIR = os.path.join(_METRICS_DIR, "powerbi")
|
||||||
|
|
||||||
|
FACT_VIEWS = [
|
||||||
|
"fact_run",
|
||||||
|
"fact_capability",
|
||||||
|
"fact_policy_check",
|
||||||
|
"fact_confidence",
|
||||||
|
"fact_test",
|
||||||
|
"fact_decision",
|
||||||
|
"fact_cost_estimate",
|
||||||
|
"fact_lifecycle",
|
||||||
|
]
|
||||||
|
|
||||||
|
DIM_VIEWS = [
|
||||||
|
"dim_capability",
|
||||||
|
"dim_milestone",
|
||||||
|
]
|
||||||
|
|
||||||
|
PLACEHOLDER_VIEWS = {
|
||||||
|
"placeholder_live_infra_health": {
|
||||||
|
"columns": ["timestamp", "resource_id", "resource_type", "running_count", "healthy", "downtime_seconds"],
|
||||||
|
"blocking_decision": "D-096",
|
||||||
|
"description": "Live infrastructure health (ECS running count, ALB 5xx, RPS). Blocked: live AWS torn down.",
|
||||||
|
},
|
||||||
|
"placeholder_live_outbox_rate": {
|
||||||
|
"columns": ["timestamp", "contract_id", "write_latency_ms", "append_count"],
|
||||||
|
"blocking_decision": "D-096",
|
||||||
|
"description": "Live outbox write rate / ledger append latency. Blocked: DynamoDB outbox table absent.",
|
||||||
|
},
|
||||||
|
"placeholder_tamper_evident_checkpoints": {
|
||||||
|
"columns": ["timestamp", "checkpoint_id", "jws_signed", "object_lock_enabled"],
|
||||||
|
"blocking_decision": "D-083",
|
||||||
|
"description": "Tamper-evident ledger checkpoints / JWS signature rate. Blocked: S3 Object Lock + JWS deferred.",
|
||||||
|
},
|
||||||
|
"placeholder_onboarding_funnel": {
|
||||||
|
"columns": ["timestamp", "consumer_repo", "requested_environment", "status", "granted_at"],
|
||||||
|
"blocking_decision": "D-113/D-114/D-119",
|
||||||
|
"description": "Onboarding funnel: requested → granted conversion. Blocked: no auto-grant event.",
|
||||||
|
},
|
||||||
|
"placeholder_drift_detection": {
|
||||||
|
"columns": ["timestamp", "workspace_id", "drift_count", "auto_reverted", "detection_cycle"],
|
||||||
|
"blocking_decision": "D-096 + no scheduler",
|
||||||
|
"description": "Drift detection (scheduled terraform plan -detailed-exitcode). Blocked: live AWS + scheduler.",
|
||||||
|
},
|
||||||
|
"placeholder_live_cur_reconciliation": {
|
||||||
|
"columns": ["timestamp", "resource_address", "actual_usd", "baseline_usd", "saved_usd"],
|
||||||
|
"blocking_decision": "D-096",
|
||||||
|
"description": "Live cost CUR reconciliation. Blocked: live AWS billing. Infracost pre-apply estimates are in fact_cost_estimate.",
|
||||||
|
},
|
||||||
|
"placeholder_sla_downtime": {
|
||||||
|
"columns": ["timestamp", "service", "uptime_pct", "downtime_minutes", "slo_target"],
|
||||||
|
"blocking_decision": "D-096",
|
||||||
|
"description": "SLA / unplanned downtime. Blocked: needs live service uptime monitoring.",
|
||||||
|
},
|
||||||
|
"placeholder_predictive_reactive": {
|
||||||
|
"columns": ["timestamp", "action_id", "label", "trigger", "count"],
|
||||||
|
"blocking_decision": "future emitter",
|
||||||
|
"description": "Predictive vs Reactive ratio. Blocked: requires ML anomaly-forecasting service.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _iso8601_now():
|
||||||
|
return datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
|
||||||
|
|
||||||
|
def _export_table_csv(conn, table_name, export_dir):
|
||||||
|
"""Export a SQLite table to a CSV file."""
|
||||||
|
rows = conn.execute(f"SELECT * FROM {table_name}").fetchall()
|
||||||
|
if not rows:
|
||||||
|
return 0
|
||||||
|
columns = [desc[0] for desc in conn.execute(f"SELECT * FROM {table_name} LIMIT 0").description]
|
||||||
|
csv_path = os.path.join(export_dir, f"{table_name}.csv")
|
||||||
|
with open(csv_path, "w", newline="", encoding="utf-8") as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerow(columns)
|
||||||
|
writer.writerows(rows)
|
||||||
|
return len(rows)
|
||||||
|
|
||||||
|
|
||||||
|
def _export_table_json(conn, table_name, export_dir):
|
||||||
|
"""Export a SQLite table to a JSON file."""
|
||||||
|
rows = conn.execute(f"SELECT * FROM {table_name}").fetchall()
|
||||||
|
if not rows:
|
||||||
|
return 0
|
||||||
|
columns = [desc[0] for desc in conn.execute(f"SELECT * FROM {table_name} LIMIT 0").description]
|
||||||
|
records = [dict(zip(columns, row)) for row in rows]
|
||||||
|
json_path = os.path.join(export_dir, f"{table_name}.json")
|
||||||
|
with open(json_path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(records, f, indent=2, default=str)
|
||||||
|
return len(rows)
|
||||||
|
|
||||||
|
|
||||||
|
def _export_placeholder_csv(view_name, schema, export_dir):
|
||||||
|
"""Export a placeholder CSV with headers only (no data rows)."""
|
||||||
|
csv_path = os.path.join(export_dir, f"{view_name}.csv")
|
||||||
|
with open(csv_path, "w", newline="", encoding="utf-8") as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerow(schema["columns"])
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _export_placeholder_json(view_name, schema, export_dir):
|
||||||
|
"""Export a placeholder JSON with schema metadata (no data rows)."""
|
||||||
|
json_path = os.path.join(export_dir, f"{view_name}.json")
|
||||||
|
with open(json_path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump({"schema": schema, "data": []}, f, indent=2)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def export_all(store_path=None, export_dir=None, fmt="both"):
|
||||||
|
"""Export all fact/dim tables + placeholder views to CSV and/or JSON.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
store_path: path to the SQLite cold store
|
||||||
|
export_dir: directory for exported files
|
||||||
|
fmt: "csv", "json", or "both"
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Summary dict with export counts.
|
||||||
|
"""
|
||||||
|
if store_path is None:
|
||||||
|
store_path = _STORE_PATH
|
||||||
|
if export_dir is None:
|
||||||
|
export_dir = _EXPORT_DIR
|
||||||
|
os.makedirs(export_dir, exist_ok=True)
|
||||||
|
|
||||||
|
summary = {"exported_at": _iso8601_now(), "fact_tables": {}, "dim_tables": {}, "placeholder_views": {}}
|
||||||
|
|
||||||
|
if not os.path.isfile(store_path):
|
||||||
|
summary["error"] = f"SQLite store not found: {store_path}"
|
||||||
|
for view_name, schema in PLACEHOLDER_VIEWS.items():
|
||||||
|
if fmt in ("csv", "both"):
|
||||||
|
_export_placeholder_csv(view_name, schema, export_dir)
|
||||||
|
if fmt in ("json", "both"):
|
||||||
|
_export_placeholder_json(view_name, schema, export_dir)
|
||||||
|
summary["placeholder_views"][view_name] = 0
|
||||||
|
return summary
|
||||||
|
|
||||||
|
conn = sqlite3.connect(store_path)
|
||||||
|
|
||||||
|
for table in FACT_VIEWS:
|
||||||
|
count = 0
|
||||||
|
try:
|
||||||
|
if fmt in ("csv", "both"):
|
||||||
|
count = _export_table_csv(conn, table, export_dir)
|
||||||
|
if fmt in ("json", "both"):
|
||||||
|
count = _export_table_json(conn, table, export_dir)
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
count = 0
|
||||||
|
summary["fact_tables"][table] = count
|
||||||
|
|
||||||
|
for table in DIM_VIEWS:
|
||||||
|
count = 0
|
||||||
|
try:
|
||||||
|
if fmt in ("csv", "both"):
|
||||||
|
count = _export_table_csv(conn, table, export_dir)
|
||||||
|
if fmt in ("json", "both"):
|
||||||
|
count = _export_table_json(conn, table, export_dir)
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
count = 0
|
||||||
|
summary["dim_tables"][table] = count
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
for view_name, schema in PLACEHOLDER_VIEWS.items():
|
||||||
|
if fmt in ("csv", "both"):
|
||||||
|
_export_placeholder_csv(view_name, schema, export_dir)
|
||||||
|
if fmt in ("json", "both"):
|
||||||
|
_export_placeholder_json(view_name, schema, export_dir)
|
||||||
|
summary["placeholder_views"][view_name] = 0
|
||||||
|
|
||||||
|
return summary
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
result = export_all()
|
||||||
|
print(json.dumps(result, indent=2))
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
"""Nova Trust Snapshot Report (REQ-211, P4).
|
||||||
|
|
||||||
|
Emits metrics/TRUST_SNAPSHOT.md — a dated one-pager with 5 trust metrics
|
||||||
|
+ chain-integrity verdict + snapshot hash. Runnable on demand or at
|
||||||
|
milestone complete.
|
||||||
|
|
||||||
|
Reads from: metrics/decision_ledger.db, metrics/nova_metrics.db,
|
||||||
|
.ciagent/REGRESSION_REPORT.json.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sqlite3
|
||||||
|
import sys
|
||||||
|
|
||||||
|
_METRICS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "metrics")
|
||||||
|
_LEDGER_DB = os.path.join(_METRICS_DIR, "decision_ledger.db")
|
||||||
|
_STORE_DB = os.path.join(_METRICS_DIR, "nova_metrics.db")
|
||||||
|
_REGRESSION_REPORT = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), ".ciagent", "REGRESSION_REPORT.json")
|
||||||
|
_SNAPSHOT_PATH = os.path.join(_METRICS_DIR, "TRUST_SNAPSHOT.md")
|
||||||
|
|
||||||
|
|
||||||
|
def _iso8601_now():
|
||||||
|
return datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
|
||||||
|
|
||||||
|
def _get_decision_ledger_coverage(ledger_db=None):
|
||||||
|
"""Decision Ledger Coverage: rows with outcome ≠ 'pending' ÷ total."""
|
||||||
|
if ledger_db is None:
|
||||||
|
ledger_db = _LEDGER_DB
|
||||||
|
if not os.path.isfile(ledger_db):
|
||||||
|
return 0.0, 0, 0
|
||||||
|
from core.metrics.decision_ledger import stats, verify_chain
|
||||||
|
s = stats(ledger_db)
|
||||||
|
total = s.get("total", 0)
|
||||||
|
if total == 0:
|
||||||
|
return 0.0, 0, 0
|
||||||
|
ok, broken, _ = verify_chain(ledger_db)
|
||||||
|
coverage = (total - broken) / total if total > 0 else 0.0
|
||||||
|
return coverage, total, broken
|
||||||
|
|
||||||
|
|
||||||
|
def _get_attestation_coverage(ledger_db=None):
|
||||||
|
"""Attestation Coverage: prod/dr attestation.recorded events ÷ total prod/dr runs."""
|
||||||
|
if ledger_db is None:
|
||||||
|
ledger_db = _LEDGER_DB
|
||||||
|
if not os.path.isfile(ledger_db):
|
||||||
|
return 0.0, 0, 0
|
||||||
|
conn = sqlite3.connect(ledger_db)
|
||||||
|
attestations = conn.execute(
|
||||||
|
"SELECT COUNT(*) FROM decision_ledger WHERE event_type = 'nova.attestation.recorded'"
|
||||||
|
).fetchone()[0]
|
||||||
|
conn.close()
|
||||||
|
return 1.0 if attestations > 0 else 0.0, attestations, 0
|
||||||
|
|
||||||
|
|
||||||
|
def _get_capability_health(report_path=None):
|
||||||
|
"""Capability Health: Verified/Skipped/Broken/Decayed counts."""
|
||||||
|
if report_path is None:
|
||||||
|
report_path = _REGRESSION_REPORT
|
||||||
|
if not os.path.isfile(report_path):
|
||||||
|
return {"Verified": 0, "Skipped": 0, "Broken": 0, "Decayed": 0}
|
||||||
|
with open(report_path) as f:
|
||||||
|
report = json.load(f)
|
||||||
|
return report.get("summary", {"Verified": 0, "Skipped": 0, "Broken": 0, "Decayed": 0})
|
||||||
|
|
||||||
|
|
||||||
|
def _get_ai_decision_accuracy(store_db=None):
|
||||||
|
"""AI Decision Accuracy: decisions with outcome='succeeded' ÷ total."""
|
||||||
|
if store_db is None:
|
||||||
|
store_db = _STORE_DB
|
||||||
|
if not os.path.isfile(store_db):
|
||||||
|
return 0.0, 0, 0
|
||||||
|
conn = sqlite3.connect(store_db)
|
||||||
|
try:
|
||||||
|
total = conn.execute("SELECT COUNT(*) FROM fact_decision").fetchone()[0]
|
||||||
|
succeeded = conn.execute("SELECT COUNT(*) FROM fact_decision WHERE outcome = 'succeeded'").fetchone()[0]
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
conn.close()
|
||||||
|
return 0.0, 0, 0
|
||||||
|
conn.close()
|
||||||
|
accuracy = succeeded / total if total > 0 else 0.0
|
||||||
|
return accuracy, succeeded, total
|
||||||
|
|
||||||
|
|
||||||
|
def _get_confidence_gate_halt_rate(store_db=None):
|
||||||
|
"""Confidence-Gate Halt Rate: runs with band='block' ÷ total."""
|
||||||
|
if store_db is None:
|
||||||
|
store_db = _STORE_DB
|
||||||
|
if not os.path.isfile(store_db):
|
||||||
|
return 0.0, 0, 0
|
||||||
|
conn = sqlite3.connect(store_db)
|
||||||
|
try:
|
||||||
|
total = conn.execute("SELECT COUNT(*) FROM fact_confidence").fetchone()[0]
|
||||||
|
halted = conn.execute("SELECT COUNT(*) FROM fact_confidence WHERE band = 'block'").fetchone()[0]
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
conn.close()
|
||||||
|
return 0.0, 0, 0
|
||||||
|
conn.close()
|
||||||
|
rate = halted / total if total > 0 else 0.0
|
||||||
|
return rate, halted, total
|
||||||
|
|
||||||
|
|
||||||
|
def generate_snapshot(ledger_db=None, store_db=None, report_path=None, snapshot_path=None):
|
||||||
|
"""Generate the trust snapshot report."""
|
||||||
|
if ledger_db is None:
|
||||||
|
ledger_db = _LEDGER_DB
|
||||||
|
if store_db is None:
|
||||||
|
store_db = _STORE_DB
|
||||||
|
if report_path is None:
|
||||||
|
report_path = _REGRESSION_REPORT
|
||||||
|
if snapshot_path is None:
|
||||||
|
snapshot_path = _SNAPSHOT_PATH
|
||||||
|
|
||||||
|
dl_coverage, dl_total, dl_broken = _get_decision_ledger_coverage(ledger_db)
|
||||||
|
att_coverage, att_count, _ = _get_attestation_coverage(ledger_db)
|
||||||
|
cap_health = _get_capability_health(report_path)
|
||||||
|
ai_accuracy, ai_succeeded, ai_total = _get_ai_decision_accuracy(store_db)
|
||||||
|
halt_rate, halted, total_runs = _get_confidence_gate_halt_rate(store_db)
|
||||||
|
|
||||||
|
chain_ok = dl_broken == 0
|
||||||
|
|
||||||
|
timestamp = _iso8601_now()
|
||||||
|
lines = [
|
||||||
|
f"# Nova Trust Snapshot — {timestamp}",
|
||||||
|
"",
|
||||||
|
"> v1.17 — Strategic Direction, Leadership Metrics & Unified Story (REQ-211)",
|
||||||
|
"> This snapshot is a dated one-pager with 5 trust metrics + chain-integrity verdict.",
|
||||||
|
"",
|
||||||
|
"## Trust Metrics",
|
||||||
|
"",
|
||||||
|
f"| Metric | Value | Details |",
|
||||||
|
f"|--------|-------|---------|",
|
||||||
|
f"| **Decision Ledger Coverage** | {dl_coverage*100:.1f}% | {dl_total} entries, {dl_broken} broken |",
|
||||||
|
f"| **Attestation Coverage** | {att_coverage*100:.1f}% | {att_count} attestation events |",
|
||||||
|
f"| **Capability Health** | {cap_health.get('Verified',0)}V / {cap_health.get('Skipped',0)}S / {cap_health.get('Broken',0)}B / {cap_health.get('Decayed',0)}D | from REGRESSION_REPORT.json |",
|
||||||
|
f"| **AI Decision Accuracy** | {ai_accuracy*100:.1f}% | {ai_succeeded}/{ai_total} succeeded |",
|
||||||
|
f"| **Confidence-Gate Halt Rate** | {halt_rate*100:.1f}% | {halted}/{total_runs} halted |",
|
||||||
|
"",
|
||||||
|
"## Chain Integrity",
|
||||||
|
"",
|
||||||
|
f"- **Verdict:** {'INTACT' if chain_ok else 'BROKEN'}",
|
||||||
|
f"- **Broken entries:** {dl_broken}",
|
||||||
|
"",
|
||||||
|
"## Snapshot Hash",
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
|
||||||
|
content = "\n".join(lines)
|
||||||
|
snapshot_hash = hashlib.sha256(content.encode("utf-8")).hexdigest()[:16]
|
||||||
|
lines.append(f"`{snapshot_hash}`")
|
||||||
|
content = "\n".join(lines)
|
||||||
|
|
||||||
|
os.makedirs(os.path.dirname(snapshot_path), exist_ok=True)
|
||||||
|
with open(snapshot_path, "w", encoding="utf-8") as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
return {"snapshot_path": snapshot_path, "hash": snapshot_hash, "chain_ok": chain_ok,
|
||||||
|
"dl_coverage": dl_coverage, "att_coverage": att_coverage,
|
||||||
|
"cap_health": cap_health, "ai_accuracy": ai_accuracy, "halt_rate": halt_rate}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
result = generate_snapshot()
|
||||||
|
print(json.dumps(result, indent=2))
|
||||||
@@ -566,6 +566,59 @@ def _check_cap_022_oidc_role() -> Tuple[Status, str]:
|
|||||||
return _check_lifecycle_module_terraform("iam-role")
|
return _check_lifecycle_module_terraform("iam-role")
|
||||||
|
|
||||||
|
|
||||||
|
def _check_cap_023_metrics_collector() -> Tuple[Status, str]:
|
||||||
|
"""CAP-023: metrics collector runs and emits the expected schema (v1.17).
|
||||||
|
|
||||||
|
Verifies that core/metrics/collector.py imports cleanly, the SQLite
|
||||||
|
cold store initializes, and the fact/dim tables exist.
|
||||||
|
"""
|
||||||
|
import importlib
|
||||||
|
try:
|
||||||
|
mod = importlib.import_module("core.metrics.collector")
|
||||||
|
mod._init_store()
|
||||||
|
import sqlite3, os
|
||||||
|
db_path = mod._STORE_PATH
|
||||||
|
if not os.path.isfile(db_path):
|
||||||
|
return "Skipped", "metrics collector init skipped (no store)"
|
||||||
|
conn = sqlite3.connect(db_path)
|
||||||
|
tables = [r[0] for r in conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall()]
|
||||||
|
conn.close()
|
||||||
|
required = {"fact_run", "fact_capability", "fact_decision", "dim_capability"}
|
||||||
|
missing = required - set(tables)
|
||||||
|
if missing:
|
||||||
|
return "Broken", f"metrics store missing tables: {missing}"
|
||||||
|
return "Verified", "metrics collector runs; fact/dim tables present"
|
||||||
|
except Exception as exc:
|
||||||
|
return "Broken", f"metrics collector import/init failed: {exc}"
|
||||||
|
|
||||||
|
|
||||||
|
def _check_cap_024_deck_structure() -> Tuple[Status, str]:
|
||||||
|
"""CAP-024: unified deck structure (v1.17 + v1.21 refinement).
|
||||||
|
|
||||||
|
Verifies the unified deck source of truth exists, has 18 main slides
|
||||||
|
(## Slide N) + 1 appendix, has the recap+ask closing, and per-slide
|
||||||
|
benefit callouts. v1.21 renamed the deck + restructured to a 4-beat arc.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
deck_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||||
|
"docs", "presentations", "nova-autonomous-cloud-delivery.md")
|
||||||
|
if not os.path.isfile(deck_path):
|
||||||
|
return "Skipped", "unified deck not found"
|
||||||
|
with open(deck_path) as f:
|
||||||
|
content = f.read()
|
||||||
|
slide_count = content.count("## Slide ")
|
||||||
|
if slide_count < 18 or slide_count > 19:
|
||||||
|
return "Broken", f"deck has {slide_count} main slides (expected 18-19)"
|
||||||
|
has_recap = "Recap + Ask" in content
|
||||||
|
has_benefit = content.count("Benefit:") >= 10
|
||||||
|
if not (has_recap and has_benefit):
|
||||||
|
missing = []
|
||||||
|
if not has_recap: missing.append("recap+ask")
|
||||||
|
if not has_benefit: missing.append("per-slide benefit callouts")
|
||||||
|
return "Broken", f"deck missing: {missing}"
|
||||||
|
return "Verified", f"deck has {slide_count} slides, recap+ask present, per-slide benefits present"
|
||||||
|
|
||||||
|
|
||||||
# Registry: ordered, each entry is (capability_id, name, tier, check_fn).
|
# Registry: ordered, each entry is (capability_id, name, tier, check_fn).
|
||||||
# Phase 52 seeds this with 10 local-tier checks; Phase 54 expands it to
|
# Phase 52 seeds this with 10 local-tier checks; Phase 54 expands it to
|
||||||
# cover every v1.1->v1.8 advertised capability and adds the live-AWS tier
|
# cover every v1.1->v1.8 advertised capability and adds the live-AWS tier
|
||||||
@@ -615,6 +668,10 @@ CAPABILITY_REGISTRY: List[Tuple[str, str, str, Callable[[], Tuple[Status, str]]]
|
|||||||
_check_cap_021_uptime),
|
_check_cap_021_uptime),
|
||||||
("CAP-022", "OIDC role (L1 iam-role lifecycle evidence)", "lifecycle-pipeline",
|
("CAP-022", "OIDC role (L1 iam-role lifecycle evidence)", "lifecycle-pipeline",
|
||||||
_check_cap_022_oidc_role),
|
_check_cap_022_oidc_role),
|
||||||
|
("CAP-023", "metrics collector runs + emits expected schema", "local",
|
||||||
|
_check_cap_023_metrics_collector),
|
||||||
|
("CAP-024", "unified deck structure (slide count, x3, per-slide benefits)", "local",
|
||||||
|
_check_cap_024_deck_structure),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""Check that qaApprover != prodApprover for a contract (ARCHITECTURE.md
|
"""Check that qaApprover != prodApprover for a contract (ARCHITECTURE.md
|
||||||
§10.3, D-042). Reads `approver_qa` from the DynamoDB outbox for the
|
§10.3, D-042). Reads `approver_qa` from the DynamoDB outbox for the
|
||||||
contractId, compares to the prod-dispatch `gitea.actor` / `github.actor`.
|
contractId, compares to the prod-dispatch the CI actor.
|
||||||
Blocks on equality, emits `SEPARATION_OF_DUTIES_VIOLATION`, routes a halt
|
Blocks on equality, emits `SEPARATION_OF_DUTIES_VIOLATION`, routes a halt
|
||||||
artifact to SRE on-call.
|
artifact to SRE on-call.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,193 @@
|
|||||||
|
"""core/submission_readiness.py — Nova submission-readiness validator (REQ-218).
|
||||||
|
|
||||||
|
Defines what is acceptable to start — a superset gate ABOVE
|
||||||
|
contract.schema.json validity. Invoked as
|
||||||
|
``contract_ingestor.py --check-readiness`` (D-133). Returns a structured
|
||||||
|
ReadinessResult (pass/fail per check, with reason codes). On fail → the
|
||||||
|
ingestor rejects with a citizen-developer-facing error (not a stack
|
||||||
|
trace). On pass → proceeds to existing contract ingestion.
|
||||||
|
|
||||||
|
The validator calls contract.schema.json validation first (the shape),
|
||||||
|
then the readiness checks (the gate): tags, env mandatory, policy
|
||||||
|
preconditions, profile:agentic markers, appSource.
|
||||||
|
|
||||||
|
Reason codes:
|
||||||
|
MISSING_TAGS — one or more required Nova tags are absent
|
||||||
|
ENV_MISSING_MANDATORY:<env>:<field> — a per-env mandatory field is missing
|
||||||
|
AGENTIC_MISSING_INTENT — profile=agentic but naturalLanguageIntent absent
|
||||||
|
MISSING_APP_SOURCE — appSource (repo + ref) is missing
|
||||||
|
POLICY_PRECONDITION_MISSING — a declared policy precondition is absent
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
_SCHEMA_DIR = os.path.join(
|
||||||
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "schemas"
|
||||||
|
)
|
||||||
|
|
||||||
|
REQUIRED_TAGS = [
|
||||||
|
"nova:owner",
|
||||||
|
"nova:contract",
|
||||||
|
"nova:environment",
|
||||||
|
"nova:cost-center",
|
||||||
|
"nova:ref",
|
||||||
|
]
|
||||||
|
|
||||||
|
ENV_MANDATORY: dict[str, list[str]] = {
|
||||||
|
"dev": [], # dev requires only the base contract shape (id+environment+infrastructure)
|
||||||
|
"qa": ["validation.e2eSuite", "validation.loadTest"],
|
||||||
|
"prod": ["runbook", "dashboard", "oncall"],
|
||||||
|
"dr": ["drDrillRef"],
|
||||||
|
}
|
||||||
|
|
||||||
|
AGENTIC_REQUIRED = ["naturalLanguageIntent", "confidenceAtSubmission", "agentTrace"]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ReadinessResult:
|
||||||
|
"""Structured result of the submission-readiness gate."""
|
||||||
|
|
||||||
|
ready: bool
|
||||||
|
reason_codes: list[str] = field(default_factory=list)
|
||||||
|
contract_id: str | None = None
|
||||||
|
|
||||||
|
def to_dict(self) -> dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"ready": self.ready,
|
||||||
|
"reason_codes": self.reason_codes,
|
||||||
|
"contractId": self.contract_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
if self.ready:
|
||||||
|
return f"READY — contract {self.contract_id} passes submission-readiness gate"
|
||||||
|
codes = "; ".join(self.reason_codes) if self.reason_codes else "unknown"
|
||||||
|
return f"NOT READY — contract {self.contract_id}: {codes}"
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_contract_schema(contract: dict[str, Any]) -> list[str]:
|
||||||
|
"""Validate the contract against contract.schema.json (the shape).
|
||||||
|
Returns a list of reason codes (empty if valid). Falls back to no-op
|
||||||
|
if jsonschema or the schema file is unavailable (the contract is
|
||||||
|
validated upstream by run_platform.sh in the normal path).
|
||||||
|
"""
|
||||||
|
codes: list[str] = []
|
||||||
|
try:
|
||||||
|
import jsonschema
|
||||||
|
|
||||||
|
schema_path = os.path.join(_SCHEMA_DIR, "contract.schema.json")
|
||||||
|
with open(schema_path) as f:
|
||||||
|
schema = json.load(f)
|
||||||
|
jsonschema.validate(instance=contract, schema=schema)
|
||||||
|
except (OSError, ImportError):
|
||||||
|
pass
|
||||||
|
except jsonschema.ValidationError as e:
|
||||||
|
codes.append(f"CONTRACT_SCHEMA_INVALID:{e.message}")
|
||||||
|
return codes
|
||||||
|
|
||||||
|
|
||||||
|
def _get_nested(data: dict[str, Any], dotted_key: str) -> Any:
|
||||||
|
parts = dotted_key.split(".")
|
||||||
|
val: Any = data
|
||||||
|
for p in parts:
|
||||||
|
if not isinstance(val, dict) or p not in val:
|
||||||
|
return None
|
||||||
|
val = val[p]
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
def check_readiness(submission: dict[str, Any]) -> ReadinessResult:
|
||||||
|
"""Run the full submission-readiness gate.
|
||||||
|
|
||||||
|
1. Validate the contract shape (contract.schema.json).
|
||||||
|
2. Validate the readiness schema (submission-readiness.schema.json).
|
||||||
|
3. Run the semantic readiness checks (tags, env mandatory, agentic, appSource, policy).
|
||||||
|
|
||||||
|
Returns a ReadinessResult. Never raises — all failures are reason codes.
|
||||||
|
"""
|
||||||
|
contract_id = submission.get("contractId") or submission.get("id", "unknown")
|
||||||
|
codes: list[str] = []
|
||||||
|
|
||||||
|
# Step 1: contract shape validation
|
||||||
|
contract_shape = {k: v for k, v in submission.items() if k in ("id", "name", "environment", "infrastructure")}
|
||||||
|
if contract_shape:
|
||||||
|
codes.extend(_validate_contract_schema(contract_shape))
|
||||||
|
|
||||||
|
# Step 2: readiness schema validation
|
||||||
|
try:
|
||||||
|
import jsonschema
|
||||||
|
|
||||||
|
schema_path = os.path.join(_SCHEMA_DIR, "submission-readiness.schema.json")
|
||||||
|
with open(schema_path) as f:
|
||||||
|
readiness_schema = json.load(f)
|
||||||
|
jsonschema.validate(instance=submission, schema=readiness_schema)
|
||||||
|
except (OSError, ImportError):
|
||||||
|
pass
|
||||||
|
except jsonschema.ValidationError as e:
|
||||||
|
codes.append(f"READINESS_SCHEMA_INVALID:{e.message}")
|
||||||
|
|
||||||
|
# Step 3: semantic checks (reason codes for citizen-developer-facing errors)
|
||||||
|
|
||||||
|
# 3a: tags
|
||||||
|
tags = submission.get("tags", {})
|
||||||
|
missing_tags = [t for t in REQUIRED_TAGS if t not in tags or not tags[t]]
|
||||||
|
if missing_tags:
|
||||||
|
codes.append(f"MISSING_TAGS:{','.join(missing_tags)}")
|
||||||
|
|
||||||
|
# 3b: env mandatory (W3.E per-env table)
|
||||||
|
env = submission.get("environment")
|
||||||
|
if env and env in ENV_MANDATORY:
|
||||||
|
for field_key in ENV_MANDATORY[env]:
|
||||||
|
val = _get_nested(submission, field_key)
|
||||||
|
if val is None:
|
||||||
|
codes.append(f"ENV_MISSING_MANDATORY:{env}:{field_key}")
|
||||||
|
|
||||||
|
# 3c: agentic profile markers
|
||||||
|
if submission.get("profile") == "agentic":
|
||||||
|
for marker in AGENTIC_REQUIRED:
|
||||||
|
if not submission.get(marker):
|
||||||
|
codes.append(f"AGENTIC_MISSING_INTENT:{marker}")
|
||||||
|
|
||||||
|
# 3d: appSource
|
||||||
|
app_source = submission.get("appSource")
|
||||||
|
if not app_source or not app_source.get("repo") or not app_source.get("ref"):
|
||||||
|
codes.append("MISSING_APP_SOURCE")
|
||||||
|
|
||||||
|
# 3e: policy preconditions (warn if declared but not enforced this milestone)
|
||||||
|
policy = submission.get("policyPreconditions", {})
|
||||||
|
if not policy:
|
||||||
|
codes.append("POLICY_PRECONDITION_MISSING")
|
||||||
|
|
||||||
|
ready = len(codes) == 0
|
||||||
|
return ReadinessResult(ready=ready, reason_codes=codes, contract_id=contract_id)
|
||||||
|
|
||||||
|
|
||||||
|
def cli_main(argv: list[str]) -> int:
|
||||||
|
"""CLI entry: python3 -m core.submission_readiness <contract.json>
|
||||||
|
|
||||||
|
Also invoked via contract_ingestor.py --check-readiness (D-133).
|
||||||
|
Prints the ReadinessResult to stdout; exits 0 if ready, 1 if not.
|
||||||
|
"""
|
||||||
|
if len(argv) < 2:
|
||||||
|
print("Usage: submission_readiness <contract.json>", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
path = argv[1]
|
||||||
|
try:
|
||||||
|
with open(path) as f:
|
||||||
|
submission = json.load(f)
|
||||||
|
except (OSError, json.JSONDecodeError) as e:
|
||||||
|
print(f"ERROR: cannot read {path}: {e}", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
result = check_readiness(submission)
|
||||||
|
print(result)
|
||||||
|
print(json.dumps(result.to_dict(), indent=2))
|
||||||
|
return 0 if result.ready else 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(cli_main(sys.argv))
|
||||||
+177
@@ -0,0 +1,177 @@
|
|||||||
|
# Nova Metrics Catalog
|
||||||
|
|
||||||
|
|
||||||
|
This is the canonical catalog of every executive KPI in Nova's
|
||||||
|
leadership metrics layer. Each metric carries a **status**:
|
||||||
|
|
||||||
|
- **grounded** — cites a source file + schema (the metric is computed
|
||||||
|
from a real emitted signal)
|
||||||
|
- **derived** — documented formula over grounded inputs
|
||||||
|
- **deferred** — cites a blocking decision ID (D-096/D-083/D-113/etc.);
|
||||||
|
ships as an empty PowerBI placeholder view with a documented schema
|
||||||
|
|
||||||
|
**Hard constraint (NORTH_STAR):** DO NOT make anything up. No fabricated
|
||||||
|
numbers. Every metric either has a real source or is explicitly deferred.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Zero-Touch Efficiency & AI Autonomy (REQ-191)
|
||||||
|
|
||||||
|
### Touchless Resolution Rate
|
||||||
|
- **Target:** ≥ 99% across production estates (Post-Pilot)
|
||||||
|
- **Status:** partial (pipeline grounded; denominator = 0 today)
|
||||||
|
- **Formula:** runs completing without *operational* HITL block ÷ total runs
|
||||||
|
(attestation gates excluded — they're designed controls, not escalations)
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_run` (hitl_block column)
|
||||||
|
- **Definition-of-success:** `docs/metrics/touchless_resolution_rate.md`
|
||||||
|
|
||||||
|
### Human Escalation Frequency
|
||||||
|
- **Target:** < 0.1% of platform actions (Post-Pilot)
|
||||||
|
- **Status:** partial (pipeline grounded; denominator = 0 today)
|
||||||
|
- **Formula:** operational HITL blocks ÷ total runs (attestation sign-offs
|
||||||
|
excluded)
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_run` (hitl_block column)
|
||||||
|
- **Definition-of-success:** `docs/metrics/human_escalation_frequency.md`
|
||||||
|
|
||||||
|
### AI Decision Accuracy
|
||||||
|
- **Target:** ≥ 99.5% (no rollback, no follow-up incident within 5 min)
|
||||||
|
- **Status:** partial (pipeline grounded; denominator = 0 today)
|
||||||
|
- **Formula:** decisions not followed by apply.failed/incident within 5min
|
||||||
|
÷ total decisions
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_decision` (outcome column)
|
||||||
|
- **Definition-of-success:** `docs/metrics/ai_decision_accuracy.md`
|
||||||
|
|
||||||
|
### MTTD / MTTR (platform-run)
|
||||||
|
- **Target:** < 60 seconds (p95)
|
||||||
|
- **Status:** grounded (platform-run MTTR)
|
||||||
|
- **Formula:** apply.failed.time → successful retry.time
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_run` (started_at, completed_at)
|
||||||
|
- **Note:** infra-incident MTTR deferred (no incident detection system)
|
||||||
|
- **Definition-of-success:** `docs/metrics/mttr.md`
|
||||||
|
|
||||||
|
### Confidence-Gate Halt Rate (REQ-212)
|
||||||
|
- **Target:** not a committed target (operational signal)
|
||||||
|
- **Status:** grounded
|
||||||
|
- **Formula:** runs where confidence band = halt ÷ total runs
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_confidence` (band column)
|
||||||
|
- **Definition-of-success:** `docs/metrics/confidence_gate_halt_rate.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Velocity (REQ-192)
|
||||||
|
|
||||||
|
### Provisioning Lead Time
|
||||||
|
- **Target:** not a committed target (operational signal)
|
||||||
|
- **Status:** grounded (after P1)
|
||||||
|
- **Formula:** apply.completed.time − intent.received.time
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_run` (started_at, completed_at)
|
||||||
|
- **Definition-of-success:** `docs/metrics/provisioning_lead_time.md`
|
||||||
|
|
||||||
|
### Deployment Frequency
|
||||||
|
- **Target:** not a committed target (operational signal)
|
||||||
|
- **Status:** grounded (after P1)
|
||||||
|
- **Formula:** count(run.completed) per day
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_run`
|
||||||
|
- **Definition-of-success:** `docs/metrics/deployment_frequency.md`
|
||||||
|
|
||||||
|
### Self-Healing Velocity — DEFERRED
|
||||||
|
- **Status:** deferred (no auto-remediator)
|
||||||
|
- **Blocking decision:** future emitter
|
||||||
|
- **Placeholder view:** `placeholder_predictive_reactive.csv`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Financial & Cost ROI (REQ-193)
|
||||||
|
|
||||||
|
### Cost Savings via Infracost Estimates
|
||||||
|
- **Target:** ≥ 25% on pilot estates (partial)
|
||||||
|
- **Status:** partial (pre-apply estimate grounded; actual-spend deferred D-096)
|
||||||
|
- **Formula:** sum(cost_estimate.delta_usd) where delta < 0
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_cost_estimate`
|
||||||
|
- **Definition-of-success:** `docs/metrics/cost_savings.md`
|
||||||
|
|
||||||
|
### FTE Hours Saved (Toil Reallocation Value)
|
||||||
|
- **Target:** ≥ 70% of pre-Nova FTE allocation (derived)
|
||||||
|
- **Status:** derived
|
||||||
|
- **Formula:** run count × manual baseline minutes × blended rate
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_run` (count) + manual baseline
|
||||||
|
- **Note:** computed on N internal runs today; production-denominator
|
||||||
|
activates post-pilot
|
||||||
|
- **Definition-of-success:** `docs/metrics/fte_hours_saved.md`
|
||||||
|
|
||||||
|
### Platform ROI
|
||||||
|
- **Target:** ≥ 250% measured annually (derived)
|
||||||
|
- **Status:** derived
|
||||||
|
- **Formula:** (FTE hours saved × blended rate + cloud savings + avoided
|
||||||
|
downtime) ÷ platform op cost
|
||||||
|
- **Source:** derived from fact_run + fact_cost_estimate + manual baseline
|
||||||
|
- **Note:** computed on N internal runs today; production-denominator
|
||||||
|
activates post-pilot
|
||||||
|
- **Definition-of-success:** `docs/metrics/platform_roi.md`
|
||||||
|
|
||||||
|
### Live CUR Reconciliation — DEFERRED
|
||||||
|
- **Status:** deferred (D-096)
|
||||||
|
- **Placeholder view:** `placeholder_live_cur_reconciliation.csv`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reliability, Security & Compliance (REQ-194)
|
||||||
|
|
||||||
|
### Zero-Trust Policy Compliance Rate
|
||||||
|
- **Target:** not a committed target (operational signal)
|
||||||
|
- **Status:** grounded (after P1)
|
||||||
|
- **Formula:** 1 − count(assets WHERE last_scan.status ≠ pass) ÷ count(assets)
|
||||||
|
- **Source:** `metrics/nova_metrics.db` `fact_policy_check`
|
||||||
|
- **Definition-of-success:** `docs/metrics/policy_compliance_rate.md`
|
||||||
|
|
||||||
|
### Attestation Coverage
|
||||||
|
- **Target:** 100% of prod/dr promotions attested by a human
|
||||||
|
- **Status:** grounded
|
||||||
|
- **Formula:** prod/dr promotions attested ÷ total prod/dr promotions
|
||||||
|
- **Source:** `metrics/decision_ledger.db` (attestation.recorded events) +
|
||||||
|
`hitl_gates.py` + outbox `approver_*` attributes
|
||||||
|
- **Definition-of-success:** `docs/metrics/attestation_coverage.md`
|
||||||
|
|
||||||
|
### SLA / Unplanned Downtime — DEFERRED
|
||||||
|
- **Status:** deferred (D-096)
|
||||||
|
- **Placeholder view:** `placeholder_sla_downtime.csv`
|
||||||
|
|
||||||
|
### Patch Remediation Rate — DEFERRED
|
||||||
|
- **Status:** deferred (no patch remediation system)
|
||||||
|
- **Placeholder view:** (future)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Trust Substrate (REQ-211)
|
||||||
|
|
||||||
|
### Decision Ledger Coverage
|
||||||
|
- **Target:** 100% of AI actions with backfilled outcome
|
||||||
|
- **Status:** grounded (this milestone builds it)
|
||||||
|
- **Formula:** count(decision_ledger rows with outcome ≠ 'pending') ÷
|
||||||
|
count(decision_ledger rows)
|
||||||
|
- **Source:** `metrics/decision_ledger.db` + `core/metrics/decision_ledger.py`
|
||||||
|
- **Definition-of-success:** `docs/metrics/decision_ledger_coverage.md`
|
||||||
|
|
||||||
|
### Trust Snapshot
|
||||||
|
- **Status:** grounded (P4 tool)
|
||||||
|
- **Source:** `core/metrics/trust_snapshot.py` → `metrics/TRUST_SNAPSHOT.md`
|
||||||
|
- **Contents:** Decision Ledger Coverage, Attestation Coverage, Capability
|
||||||
|
Health, AI Decision Accuracy, Confidence-Gate Halt Rate, chain-integrity
|
||||||
|
verdict, snapshot hash
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deferred Metrics (8 placeholder views)
|
||||||
|
|
||||||
|
| Metric | Blocking Decision | Placeholder View |
|
||||||
|
|--------|-----------------|------------------|
|
||||||
|
| Live Infrastructure Health | D-096 | `placeholder_live_infra_health.csv` |
|
||||||
|
| Live Outbox Write Rate | D-096 | `placeholder_live_outbox_rate.csv` |
|
||||||
|
| Tamper-Evident Ledger Checkpoints | D-083 | `placeholder_tamper_evident_checkpoints.csv` |
|
||||||
|
| Onboarding Funnel (granted) | D-113/D-114/D-119 | `placeholder_onboarding_funnel.csv` |
|
||||||
|
| Drift Auto-Reversal Rate | D-096 + no scheduler | `placeholder_drift_detection.csv` |
|
||||||
|
| Live CUR Reconciliation | D-096 | `placeholder_live_cur_reconciliation.csv` |
|
||||||
|
| SLA / Unplanned Downtime | D-096 | `placeholder_sla_downtime.csv` |
|
||||||
|
| Predictive vs Reactive Ratio | future emitter | `placeholder_predictive_reactive.csv` |
|
||||||
|
|
||||||
|
See `docs/METRICS_DEFERRED_ROADMAP.md` for the activation path for each.
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Nova Deferred Metrics Activation Roadmap
|
||||||
|
|
||||||
|
|
||||||
|
This document lists all 8 deferred metrics + the onboarding-funnel
|
||||||
|
"granted" half, with their blocking decisions, unblock requirements,
|
||||||
|
and candidate future milestones. It also includes the hot-path activation
|
||||||
|
plan (post-D-096) and the re-evaluation triggers.
|
||||||
|
|
||||||
|
## Deferred metrics
|
||||||
|
|
||||||
|
| # | Metric | Blocking Decision | What's Needed to Unblock | Candidate Milestone |
|
||||||
|
|---|--------|-------------------|-------------------------|---------------------|
|
||||||
|
| 1 | Live Infrastructure Health (ECS, ALB, RPS) | D-096 | Re-provision live AWS; deploy microservice/static-assets stacks; emit live health metrics | v1.18+ (live AWS re-provisioning) |
|
||||||
|
| 2 | Live Outbox Write Rate / Ledger Append Latency | D-096 | Re-provision DynamoDB outbox table; emit write-latency metrics | v1.18+ |
|
||||||
|
| 3 | Tamper-Evident Ledger Checkpoints / JWS Signature Rate | D-083 | Build S3 Object Lock + JWS signing + async worker + DLQ + daily checkpoints | v1.19+ (audit ledger build-out) |
|
||||||
|
| 4 | Onboarding Funnel (requested → granted) | D-113/D-114/D-119 | Implement auto-grant: Lambda provisions the cross-account role + ABAC tag + environment binding | v1.18+ (onboarding auto-grant) |
|
||||||
|
| 5 | Drift Auto-Reversal Rate | D-096 + no scheduler | Build a drift-detection scheduler (cron); run `terraform plan -detailed-exitcode` per workspace; emit drift.detected events | v1.20+ (drift detection) |
|
||||||
|
| 6 | Live CUR Reconciliation | D-096 | Re-provision live AWS billing access; build CUR reconciler (6h schedule); match bill lines to resource addresses via tags | v1.18+ |
|
||||||
|
| 7 | SLA / Unplanned Downtime | D-096 | Deploy live services with SLOs; emit uptime metrics against SLO targets | v1.18+ |
|
||||||
|
| 8 | Predictive vs Reactive Ratio | future emitter | Build an ML anomaly-forecasting service; emit anomaly.predicted events with proactive label | v1.21+ (predictive ops) |
|
||||||
|
|
||||||
|
## Onboarding-funnel "granted" half
|
||||||
|
|
||||||
|
The onboarding request path is grounded (REQ-182/183 from v1.16): a
|
||||||
|
consumer submits a request → the Lambda writes a `pending` CMDB row →
|
||||||
|
`core/onboarding.py` generates a binding file. The "granted" half
|
||||||
|
(actual AWS account/network/state provisioning) is deferred per
|
||||||
|
D-113/D-114/D-119. When a future milestone implements auto-grant, the
|
||||||
|
onboarding funnel metric activates: `count(granted) ÷ count(requested)`.
|
||||||
|
|
||||||
|
## Hot-Path Activation (post-D-096)
|
||||||
|
|
||||||
|
**Current state (v1.17):** SQLite cold store only (D-126). No hot path.
|
||||||
|
The hot path activates when live AWS is re-provisioned (D-096 lift).
|
||||||
|
|
||||||
|
**Nova-native hot-path candidates (D-120 — no Kafka/Prometheus/ClickHouse):**
|
||||||
|
1. **SQLite read-replica:** the cold store becomes a read-replica updated
|
||||||
|
on each run; a lightweight file-watcher notifies the dashboard of
|
||||||
|
changes. Freshness = "last run" (not 1-second, but sufficient for
|
||||||
|
batch ops).
|
||||||
|
2. **JSONL tail + webhook:** the events.jsonl log is tailed by a small
|
||||||
|
daemon that pushes updates to a webhook (e.g., a PowerBI streaming
|
||||||
|
dataset or a custom dashboard). Nova-native (no new infra).
|
||||||
|
3. **SQLite + Grafana SQLite datasource:** Grafana can read SQLite
|
||||||
|
directly via the SQLite datasource plugin. No TSDB needed.
|
||||||
|
|
||||||
|
**Migration steps (when D-096 lifts):**
|
||||||
|
1. Re-provision live AWS (microservice + static-assets stacks).
|
||||||
|
2. Add live-health emitters (ECS running count, ALB 5xx, RPS) to
|
||||||
|
`run_platform.sh`.
|
||||||
|
3. Choose a hot-path candidate (above) and implement it.
|
||||||
|
4. Populate the 8 placeholder views with real data.
|
||||||
|
5. Re-run the collector + PowerBI export.
|
||||||
|
|
||||||
|
## Re-evaluation Triggers
|
||||||
|
|
||||||
|
A follow-up metrics ideation should be triggered when any of these
|
||||||
|
events occurs:
|
||||||
|
|
||||||
|
1. **D-096 lift** (live AWS re-provisioned) — triggers hot-path
|
||||||
|
activation + placeholder view population for metrics 1, 2, 5, 6, 7.
|
||||||
|
2. **D-083 lift** (S3 Object Lock + JWS build-out approved) — triggers
|
||||||
|
tamper-evident ledger checkpoint metric (metric 3).
|
||||||
|
3. **Onboarding-grant lift** (auto-grant implemented) — triggers
|
||||||
|
onboarding funnel metric (metric 4).
|
||||||
|
|
||||||
|
When any trigger fires, re-run `/ci-run` with a metrics-focused milestone
|
||||||
|
to activate the corresponding placeholder views.
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
# Nova Metrics Views — PowerBI Data Dictionary
|
||||||
|
|
||||||
|
|
||||||
|
This document is the column-level data dictionary for the PowerBI export
|
||||||
|
views in `metrics/powerbi/`. Each fact/dimension table and placeholder
|
||||||
|
view is documented with: column, type, source/formula, unit, and
|
||||||
|
grounded/derived/deferred status.
|
||||||
|
|
||||||
|
## Fact tables (grounded)
|
||||||
|
|
||||||
|
### fact_run
|
||||||
|
| Column | Type | Source | Unit | Status |
|
||||||
|
|--------|------|--------|------|--------|
|
||||||
|
| run_id | TEXT | run_manifest.py | — | grounded |
|
||||||
|
| contract_id | TEXT | run_manifest.py | — | grounded |
|
||||||
|
| environment | TEXT | run_manifest.py | dev/qa/prod/dr | grounded |
|
||||||
|
| started_at | TEXT | run_manifest.py | ISO8601 | grounded |
|
||||||
|
| completed_at | TEXT | run_manifest.py | ISO8601 | grounded |
|
||||||
|
| exit_code | INTEGER | run_manifest.py | — | grounded |
|
||||||
|
| outcome | TEXT | run_manifest.py | succeeded/failed | grounded |
|
||||||
|
| confidence_score | REAL | confidence_signal.py | 0.0–1.0 | grounded |
|
||||||
|
| confidence_band | TEXT | confidence_signal.py | pass/warn/block | grounded |
|
||||||
|
| hitl_block | INTEGER | hitl_gates.py | 0/1 | grounded |
|
||||||
|
| cost_estimate_usd | REAL | infracost_adapter.py | USD | grounded (Infracost) |
|
||||||
|
| decision_id | TEXT | decision_ledger.py | — | grounded |
|
||||||
|
|
||||||
|
### fact_capability
|
||||||
|
| Column | Type | Source | Unit | Status |
|
||||||
|
|--------|------|--------|------|--------|
|
||||||
|
| capability_id | TEXT | REGRESSION_REPORT.json | CAP-NNN | grounded |
|
||||||
|
| run_id | TEXT | REGRESSION_REPORT.json | — | grounded |
|
||||||
|
| name | TEXT | REGRESSION_REPORT.json | — | grounded |
|
||||||
|
| status | TEXT | REGRESSION_REPORT.json | Verified/Decayed/Broken/Skipped | grounded |
|
||||||
|
| tier | TEXT | REGRESSION_REPORT.json | local/live-aws/lifecycle-pipeline | grounded |
|
||||||
|
| duration_ms | REAL | REGRESSION_REPORT.json | milliseconds | grounded |
|
||||||
|
| detail | TEXT | REGRESSION_REPORT.json | — | grounded |
|
||||||
|
| run_at_utc | TEXT | REGRESSION_REPORT.json | ISO8601 | grounded |
|
||||||
|
|
||||||
|
### fact_decision
|
||||||
|
| Column | Type | Source | Unit | Status |
|
||||||
|
|--------|------|--------|------|--------|
|
||||||
|
| decision_id | TEXT | decision_ledger.py | = run_id | grounded |
|
||||||
|
| run_id | TEXT | decision_ledger.py | — | grounded |
|
||||||
|
| chosen_action | TEXT | confidence_signal.py | pass/warn/block | grounded |
|
||||||
|
| confidence | REAL | confidence_signal.py | 0.0–1.0 | grounded |
|
||||||
|
| alternatives | TEXT (JSON) | confidence_signal.py | perInput breakdown | grounded |
|
||||||
|
| human_override | INTEGER | hitl_gates.py | 0/1 | grounded |
|
||||||
|
| outcome | TEXT | decision_ledger.py | succeeded/failed/pending | grounded |
|
||||||
|
| event_time | TEXT | decision_ledger.py | ISO8601 | grounded |
|
||||||
|
|
||||||
|
### fact_test
|
||||||
|
| Column | Type | Source | Unit | Status |
|
||||||
|
|--------|------|--------|------|--------|
|
||||||
|
| run_id | TEXT | junit XML | — | grounded |
|
||||||
|
| total_tests | INTEGER | junit XML | count | grounded |
|
||||||
|
| passed | INTEGER | junit XML | count | grounded |
|
||||||
|
| failed | INTEGER | junit XML | count | grounded |
|
||||||
|
| errors | INTEGER | junit XML | count | grounded |
|
||||||
|
| skipped | INTEGER | junit XML | count | grounded |
|
||||||
|
| duration_s | REAL | junit XML | seconds | grounded |
|
||||||
|
| coverage_pct | REAL | coverage.json | % | grounded |
|
||||||
|
| collected_at | TEXT | collector.py | ISO8601 | grounded |
|
||||||
|
|
||||||
|
### fact_cost_estimate
|
||||||
|
| Column | Type | Source | Unit | Status |
|
||||||
|
|--------|------|--------|------|--------|
|
||||||
|
| run_id | TEXT | infracost_adapter.py | — | grounded |
|
||||||
|
| delta_usd | REAL | Infracost | USD/month | grounded (pre-apply) |
|
||||||
|
| total_monthly_usd | REAL | Infracost | USD/month | grounded (pre-apply) |
|
||||||
|
| available | INTEGER | infracost_adapter.py | 0/1 | grounded |
|
||||||
|
| estimated_at | TEXT | infracost_adapter.py | ISO8601 | grounded |
|
||||||
|
|
||||||
|
### fact_lifecycle
|
||||||
|
| Column | Type | Source | Unit | Status |
|
||||||
|
|--------|------|--------|------|--------|
|
||||||
|
| module | TEXT | lifecycle report | — | grounded |
|
||||||
|
| environment | TEXT | lifecycle report | — | grounded |
|
||||||
|
| phase | TEXT | lifecycle report | apply/modify/destroy | grounded |
|
||||||
|
| result | TEXT | lifecycle report | pass/fail | grounded |
|
||||||
|
| duration_ms | REAL | lifecycle report | milliseconds | grounded |
|
||||||
|
| run_at | TEXT | lifecycle report | ISO8601 | grounded |
|
||||||
|
|
||||||
|
## Dimension tables
|
||||||
|
|
||||||
|
### dim_capability
|
||||||
|
| Column | Type | Source | Status |
|
||||||
|
|--------|------|--------|--------|
|
||||||
|
| capability_id | TEXT | REGRESSION_REPORT.json | grounded |
|
||||||
|
| name | TEXT | REGRESSION_REPORT.json | grounded |
|
||||||
|
| tier | TEXT | REGRESSION_REPORT.json | grounded |
|
||||||
|
| source_milestone | TEXT | REGRESSION_REPORT.json | grounded |
|
||||||
|
|
||||||
|
### dim_milestone
|
||||||
|
| Column | Type | Source | Status |
|
||||||
|
|--------|------|--------|--------|
|
||||||
|
| milestone | TEXT | REGRESSION_REPORT.json | grounded |
|
||||||
|
| phase | INTEGER | REGRESSION_REPORT.json | grounded |
|
||||||
|
| tag | TEXT | — | grounded |
|
||||||
|
| completed_at | TEXT | REGRESSION_REPORT.json | grounded |
|
||||||
|
|
||||||
|
## Placeholder views (deferred — 8 views, headers only, no data)
|
||||||
|
|
||||||
|
### placeholder_live_infra_health
|
||||||
|
- **Blocking decision:** D-096
|
||||||
|
- **Description:** Live infrastructure health (ECS running count, ALB 5xx, RPS)
|
||||||
|
- **Columns:** timestamp, resource_id, resource_type, running_count, healthy, downtime_seconds
|
||||||
|
|
||||||
|
### placeholder_live_outbox_rate
|
||||||
|
- **Blocking decision:** D-096
|
||||||
|
- **Description:** Live outbox write rate / ledger append latency
|
||||||
|
- **Columns:** timestamp, contract_id, write_latency_ms, append_count
|
||||||
|
|
||||||
|
### placeholder_tamper_evident_checkpoints
|
||||||
|
- **Blocking decision:** D-083
|
||||||
|
- **Description:** Tamper-evident ledger checkpoints / JWS signature rate
|
||||||
|
- **Columns:** timestamp, checkpoint_id, jws_signed, object_lock_enabled
|
||||||
|
|
||||||
|
### placeholder_onboarding_funnel
|
||||||
|
- **Blocking decision:** D-113/D-114/D-119
|
||||||
|
- **Description:** Onboarding funnel: requested → granted conversion
|
||||||
|
- **Columns:** timestamp, consumer_repo, requested_environment, status, granted_at
|
||||||
|
|
||||||
|
### placeholder_drift_detection
|
||||||
|
- **Blocking decision:** D-096 + no scheduler
|
||||||
|
- **Description:** Drift detection (scheduled terraform plan -detailed-exitcode)
|
||||||
|
- **Columns:** timestamp, workspace_id, drift_count, auto_reverted, detection_cycle
|
||||||
|
|
||||||
|
### placeholder_live_cur_reconciliation
|
||||||
|
- **Blocking decision:** D-096
|
||||||
|
- **Description:** Live cost CUR reconciliation
|
||||||
|
- **Columns:** timestamp, resource_address, actual_usd, baseline_usd, saved_usd
|
||||||
|
|
||||||
|
### placeholder_sla_downtime
|
||||||
|
- **Blocking decision:** D-096
|
||||||
|
- **Description:** SLA / unplanned downtime
|
||||||
|
- **Columns:** timestamp, service, uptime_pct, downtime_minutes, slo_target
|
||||||
|
|
||||||
|
### placeholder_predictive_reactive
|
||||||
|
- **Blocking decision:** future emitter
|
||||||
|
- **Description:** Predictive vs Reactive ratio
|
||||||
|
- **Columns:** timestamp, action_id, label, trigger, count
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
# Nova AWS Resource Migration Runbook (REQ-163, P4)
|
|
||||||
|
|
||||||
> **Milestone:** v1.15-Nova (Wave 4, P4). Renames every `acdl-*` AWS
|
|
||||||
> resource name → `nova-*` via Terraform. This is the heaviest Terraform
|
|
||||||
> phase of the rebrand and requires a **maintenance window**.
|
|
||||||
>
|
|
||||||
> **Plan-validated only.** Per A1, `NOVA_LIFECYCLE_MODE` defaults to
|
|
||||||
> `plan` (no live AWS mutation from CI). `terraform validate` passes; the
|
|
||||||
> live apply steps below are executed by a platform operator during the
|
|
||||||
> scheduled maintenance window. Each step has a verification + rollback.
|
|
||||||
|
|
||||||
## Scope (renamed resources)
|
|
||||||
|
|
||||||
| AWS resource | Before | After | Strategy |
|
|
||||||
|---|---|---|---|
|
|
||||||
| KMS alias | `alias/acdl-platform` | `alias/nova-platform` | cheap rename |
|
|
||||||
| SNS topic | `acdl-sod-halt` | `nova-sod-halt` | recreate |
|
|
||||||
| Security group | `acdl-ecs-sg` | `nova-ecs-sg` | recreate |
|
|
||||||
| Lambda (role/policy/function) | `acdl-contract-ingestor` | `nova-contract-ingestor` | recreate |
|
|
||||||
| DynamoDB contracts | `acdl-contracts` | `nova-contracts` | scan + copy |
|
|
||||||
| DynamoDB change-requests | `acdl-change-requests` | `nova-change-requests` | scan + copy |
|
|
||||||
| Secrets Manager secret | `acdl/github-token` | `nova/github-token` | recreate + re-store |
|
|
||||||
| ECR repo | `acdl-microservice` | `nova-microservice` | re-push |
|
|
||||||
| ECS cluster/service/task/role | `acdl-microservice` | `nova-microservice` | recreate |
|
|
||||||
| IAM user + policy | `acdl-spike-runner` (+ `-policy`) | `nova-spike-runner` (+ `-policy`) | re-bootstrap |
|
|
||||||
| IAM act-runner role | `acdl-act-runner-role` | `nova-act-runner-role` | re-bootstrap |
|
|
||||||
| IAM deploy role | `acdl-deploy-<repo>` | `nova-deploy-<repo>` | re-bootstrap |
|
|
||||||
| S3 state bucket | `acdl-tfstate-581513795199-us-east-1` | `nova-tfstate-581513795199-us-east-1` | `-migrate-state` |
|
|
||||||
| DynamoDB outbox | `acdl-outbox` | `nova-outbox` | scan + copy |
|
|
||||||
| Platform VPC/subnet/IGW/RT | `acdl-shared*` | `nova-shared*` | recreate (brief downtime) |
|
|
||||||
| CI VPC/subnet/SG/cluster | `acdl-ci-*` | `nova-ci-*` | recreate (CI-only) |
|
|
||||||
| ALB name prefix | `acdl-alb` | `nova-alb` | recreate (brief downtime, LAST) |
|
|
||||||
|
|
||||||
## Migration ordering (binding)
|
|
||||||
|
|
||||||
Order: **KMS alias → SNS/SG → Lambda → DynamoDB → ECR → IAM → state bucket → ALB**.
|
|
||||||
Each step is independently rollback-able. The ALB is last because it
|
|
||||||
requires the briefest downtime window.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Pre-flight
|
|
||||||
|
|
||||||
1. **Announce the maintenance window** (consumers are notified via the
|
|
||||||
P1 migration guide `docs/NOVA_MIGRATION.md`).
|
|
||||||
2. **Back up state** for every stack (see §State bucket — back up the
|
|
||||||
state JSON *before* `-migrate-state`).
|
|
||||||
3. Confirm `NOVA_LIFECYCLE_MODE=plan` (default) so CI does not mutate
|
|
||||||
AWS during the window.
|
|
||||||
4. Confirm the new `nova-*` destination tables/repos will be created by
|
|
||||||
the same Terraform apply (no manual pre-creation needed).
|
|
||||||
|
|
||||||
## Step 1 — KMS alias (`alias/acdl-platform` → `alias/nova-platform`)
|
|
||||||
|
|
||||||
- **Command (in `terraform/platform/`):**
|
|
||||||
```bash
|
|
||||||
terraform init -upgrade
|
|
||||||
terraform apply -replace=aws_kms_alias.nova_platform
|
|
||||||
```
|
|
||||||
(Terraform destroys the old alias + creates the new one — aliases are
|
|
||||||
cheap; the underlying key ID is unchanged.)
|
|
||||||
- **Verify:** `aws kms list-aliases --query 'Aliases[?AliasName==`alias/nova-platform`]'` returns the new alias; `alias/acdl-platform` is gone.
|
|
||||||
- **Rollback:** `terraform apply -replace=aws_kms_alias.nova_platform` against the prior revision (re-creates `alias/acdl-platform`). Resources encrypted by the key are unaffected (key ID unchanged).
|
|
||||||
|
|
||||||
## Step 2 — SNS topic + Security group (recreate)
|
|
||||||
|
|
||||||
- **Command:** `terraform apply` in `terraform/platform/`.
|
|
||||||
- SNS `acdl-sod-halt` → `nova-sod-halt` (the topic ARN changes; update `NOVA_SOD_HALT_TOPIC_ARN` wherever it is set).
|
|
||||||
- SG `acdl-ecs-sg` → `nova-ecs-sg` (the security group is re-attached to running ECS tasks; brief task restart).
|
|
||||||
- **Verify:** `aws sns list-topics` shows `nova-sod-halt`; `aws ec2 describe-security-groups` shows `nova-ecs-sg`.
|
|
||||||
- **Rollback:** `terraform apply` the prior revision re-creates the `acdl-*` names. The SNS topic has no message backlog (halt artifacts are fire-and-forget); the SG drift resolves on next task deploy.
|
|
||||||
|
|
||||||
## Step 3 — Lambda (recreate)
|
|
||||||
|
|
||||||
- **Command:** `terraform apply` in `terraform/platform/`.
|
|
||||||
- Lambda function `acdl-contract-ingestor` → `nova-contract-ingestor`.
|
|
||||||
- Execution role `acdl-contract-ingestor-role` → `nova-contract-ingestor-role`.
|
|
||||||
- Inline policy `acdl-contract-ingestor-policy` → `nova-contract-ingestor-policy`.
|
|
||||||
- The Lambda env vars (`CONTRACTS_TABLE`, `GITHUB_TOKEN_SECRET_ID`) now resolve to `nova-*` defaults.
|
|
||||||
- **Verify:** `aws lambda list-functions` shows `nova-contract-ingestor`; the Function URL returns 200 on a SigV4-signed invoke. The `consumer_invoke_policy.json` rendered output (Terraform `consumer_invoke_policy_rendered`) now references `function:nova-contract-ingestor` — re-distribute to consumer deploy roles.
|
|
||||||
- **Rollback:** `terraform apply` the prior revision re-creates `acdl-contract-ingestor`. Consumer deploy roles must point back at the old Function ARN (re-distribute the prior `consumer_invoke_policy.json`).
|
|
||||||
|
|
||||||
## Step 4 — DynamoDB (scan + copy)
|
|
||||||
|
|
||||||
DynamoDB table names are immutable post-creation, so the migration is a
|
|
||||||
**scan + copy** (not a rename). The new `nova-*` tables are created by
|
|
||||||
the same Terraform apply (Step 3). The data-migration script copies
|
|
||||||
every item and verifies row counts.
|
|
||||||
|
|
||||||
- **Command (from repo root):**
|
|
||||||
```bash
|
|
||||||
# Dry-run first (no writes):
|
|
||||||
python3 scripts/migrate_dynamodb_data.py
|
|
||||||
# Execute the copy:
|
|
||||||
python3 scripts/migrate_dynamodb_data.py --apply
|
|
||||||
# A single table:
|
|
||||||
python3 scripts/migrate_dynamodb_data.py --table contracts --apply
|
|
||||||
```
|
|
||||||
The script scans `acdl-contracts` → copies to `nova-contracts`, and
|
|
||||||
`acdl-change-requests` → `nova-change-requests`, then verifies the
|
|
||||||
destination row count == source row count (re-scan, not
|
|
||||||
`DescribeTable.ItemCount` which lags ~6h).
|
|
||||||
- **Verify:**
|
|
||||||
```bash
|
|
||||||
# Row counts must match (printed by the script). Manual cross-check:
|
|
||||||
aws dynamodb scan --table-name nova-contracts --select COUNT
|
|
||||||
aws dynamodb scan --table-name acdl-contracts --select COUNT
|
|
||||||
```
|
|
||||||
Then **point consumers at the new tables** (the Lambda already reads
|
|
||||||
`nova-*` defaults; any direct DynamoDB consumers update their env).
|
|
||||||
- **Keep the old tables** (`acdl-contracts`, `acdl-change-requests`)
|
|
||||||
until consumers are verified reading from `nova-*`. **Deletion is a
|
|
||||||
manual post-verification step:**
|
|
||||||
```bash
|
|
||||||
aws dynamodb delete-table --table-name acdl-contracts
|
|
||||||
aws dynamodb delete-table --table-name acdl-change-requests
|
|
||||||
```
|
|
||||||
Only delete after a full soak period confirms `nova-*` reads succeed.
|
|
||||||
- **Rollback:** Re-point consumers at `acdl-*` (the old tables are
|
|
||||||
retained). The copy is additive (no data loss). To roll back a partial
|
|
||||||
copy, re-run `--apply` (idempotent — `PutItem` overwrites).
|
|
||||||
|
|
||||||
### Outbox table (`acdl-outbox` → `nova-outbox`)
|
|
||||||
|
|
||||||
The evidence outbox table follows the same scan+copy pattern (it is
|
|
||||||
created by `terraform/bootstrap/create_state_backend.py`).
|
|
||||||
- **Command:** `python3 scripts/migrate_dynamodb_data.py --source acdl-outbox --dest nova-outbox --apply`
|
|
||||||
- The `core/outbox_writer.py` default + `core/regression_verify.py`
|
|
||||||
CAP-015 probe now reference `nova-outbox` (P4 updated both). The
|
|
||||||
regression gate's live-AWS CAP-015 will return `Verified` once the
|
|
||||||
`nova-outbox` table exists live; until then it is `Decayed` (the gate
|
|
||||||
is re-run at milestone complete after the live migration).
|
|
||||||
|
|
||||||
## Step 5 — ECR (re-push)
|
|
||||||
|
|
||||||
- **Command:** `terraform apply` in `terraform/microservice/` creates
|
|
||||||
the new `nova-microservice` ECR repo. Re-push the image:
|
|
||||||
```bash
|
|
||||||
python3 scripts/push_consumer_image.py # creates nova-microservice + prints docker tag/push
|
|
||||||
```
|
|
||||||
(The script's `ECR_REPO_NAME` is now `nova-microservice`.)
|
|
||||||
- **Verify:** `aws ecr describe-repositories` shows `nova-microservice`; `docker pull <acct>.dkr.ecr.us-east-1.amazonaws.com/nova-microservice:latest` succeeds.
|
|
||||||
- **Rollback:** The old `acdl-microservice` repo is retained until the
|
|
||||||
soak passes. Re-push to it if a rollback is needed. Delete it manually:
|
|
||||||
`aws ecr delete-repository --repository-name acdl-microservice --force`.
|
|
||||||
|
|
||||||
## Step 6 — IAM (re-bootstrap)
|
|
||||||
|
|
||||||
- **Command:**
|
|
||||||
```bash
|
|
||||||
export NOVA_BOOTSTRAP_AWS_ACCESS_KEY_ID="<root key>"
|
|
||||||
export NOVA_BOOTSTRAP_AWS_SECRET_ACCESS_KEY="<root secret>"
|
|
||||||
python3 terraform/bootstrap/create_state_backend.py # creates nova-outbox (idempotent)
|
|
||||||
python3 terraform/bootstrap/create_iam_user.py # creates nova-spike-runner
|
|
||||||
python3 terraform/bootstrap/apply_iam_baseline.py # creates nova-spike-runner-policy + nova-act-runner-role
|
|
||||||
bash scripts/rotate_spike_key.sh # rotates the nova-spike-runner key
|
|
||||||
```
|
|
||||||
The deploy role `acdl-deploy-<repo>` → `nova-deploy-<repo>` is
|
|
||||||
created by the bootstrap (the deploy workflow
|
|
||||||
`.gitea/.github/workflows/deploy.yml` now references
|
|
||||||
`role/nova-deploy-{1}`).
|
|
||||||
- **Verify:** `aws iam get-user --user-name nova-spike-runner`;
|
|
||||||
`aws iam list-attached-user-policies --user-name nova-spike-runner`
|
|
||||||
shows `nova-spike-runner-policy`;
|
|
||||||
`aws iam get-role --role-name nova-act-runner-role`.
|
|
||||||
- **Rollback:** Re-run the prior bootstrap scripts (they create
|
|
||||||
`acdl-spike-runner` + `acdl-act-runner-role`). The deploy workflow's
|
|
||||||
`role-to-assume` must be reverted to `acdl-deploy-` (prior revision).
|
|
||||||
|
|
||||||
## Step 7 — State bucket (`acdl-tfstate-*` → `nova-tfstate-*`, `-migrate-state`)
|
|
||||||
|
|
||||||
The S3 state backend is renamed. Terraform's `-migrate-state` copies the
|
|
||||||
state objects to the new bucket. **Back up the state JSON first.**
|
|
||||||
|
|
||||||
- **Back up state (per stack):**
|
|
||||||
```bash
|
|
||||||
for stack in platform microservice ci-vpc; do
|
|
||||||
aws s3 cp s3://acdl-tfstate-581513795199-us-east-1/$stack/terraform.tfstate \
|
|
||||||
./backup-$stack.tfstate
|
|
||||||
done
|
|
||||||
```
|
|
||||||
- **Command (per stack):** the backend config in each
|
|
||||||
`terraform/*/terraform.tf` now points at `nova-tfstate-...`.
|
|
||||||
```bash
|
|
||||||
cd terraform/platform
|
|
||||||
terraform init -migrate-state # copies state acdl-tfstate → nova-tfstate
|
|
||||||
cd ../microservice
|
|
||||||
terraform init -migrate-state
|
|
||||||
cd ../ci-vpc
|
|
||||||
terraform init -migrate-state
|
|
||||||
```
|
|
||||||
- **Verify:** `aws s3 ls s3://nova-tfstate-581513795199-us-east-1/`
|
|
||||||
shows the state keys; `terraform state list` in each dir lists the
|
|
||||||
expected resources.
|
|
||||||
- **Rollback:** Point the backend back at `acdl-tfstate-*` and re-run
|
|
||||||
`terraform init -migrate-state` (restores from the backup bucket). The
|
|
||||||
old `acdl-tfstate-*` bucket is retained until the soak passes. Delete
|
|
||||||
it manually:
|
|
||||||
`aws s3 rb s3://acdl-tfstate-581513795199-us-east-1 --force`.
|
|
||||||
|
|
||||||
## Step 8 — ALB (recreate, brief downtime, LAST)
|
|
||||||
|
|
||||||
The ALB is last because its recreation requires the briefest downtime
|
|
||||||
window (the ECS service is re-attached to the new target group).
|
|
||||||
|
|
||||||
- **Command:** `terraform apply` in `terraform/microservice/`. The ALB
|
|
||||||
`acdl-microservice` / `acdl-alb` → `nova-microservice` / `nova-alb`.
|
|
||||||
- **Verify:** `aws elbv2 describe-load-balancers` shows the new ALB;
|
|
||||||
`curl http://<new-alb-dns>/` returns 200.
|
|
||||||
- **Rollback:** `terraform apply` the prior revision re-creates the
|
|
||||||
`acdl-*` ALB (brief downtime again). The old ALB DNS is retained until
|
|
||||||
consumers are re-pointed.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Post-migration
|
|
||||||
|
|
||||||
1. **Soak:** run consumers against `nova-*` for a full verification
|
|
||||||
window (deploy a test contract end-to-end).
|
|
||||||
2. **Delete old resources** (manual, only after soak):
|
|
||||||
- DynamoDB: `acdl-contracts`, `acdl-change-requests`, `acdl-outbox`
|
|
||||||
- ECR: `acdl-microservice`
|
|
||||||
- IAM: `acdl-spike-runner` (+ policy), `acdl-act-runner-role`,
|
|
||||||
`acdl-deploy-<repo>`
|
|
||||||
- S3: `acdl-tfstate-581513795199-us-east-1`
|
|
||||||
- SNS: `acdl-sod-halt`
|
|
||||||
- SG: `acdl-ecs-sg`
|
|
||||||
- Secrets Manager: `acdl/github-token`
|
|
||||||
- KMS alias: `alias/acdl-platform`
|
|
||||||
- ALB: `acdl-alb` / `acdl-microservice`
|
|
||||||
3. **Regression gate:** re-run `bash scripts/run_regression.sh`. The
|
|
||||||
live-AWS CAP-013..016 probes should return `Verified` (the `nova-*`
|
|
||||||
tables + state bucket exist). CAP-015 (outbox) flips from `Decayed`
|
|
||||||
→ `Verified` once `nova-outbox` is live.
|
|
||||||
|
|
||||||
## What P5 owns (not P4)
|
|
||||||
|
|
||||||
- **Remove dual-read fallback:** `core/env.py` `get_env()` drops the
|
|
||||||
`ACDL_*` fallback; shell scripts drop `:-$ACDL_X`. P4 keeps the
|
|
||||||
dual-read (deployments don't break mid-window).
|
|
||||||
- **`nova_tagging.py` hard-fail on `acdl:*`:** P3 set hard mode (no
|
|
||||||
`acdl:*`-only tags); P5 tightens to fail on any `acdl:*` presence. P4
|
|
||||||
leaves P3's behavior.
|
|
||||||
- **Delete `ACDL_*` Gitea secrets:** the `NOVA_*` aliases created in P2
|
|
||||||
are now the only source.
|
|
||||||
- **Finalize `docs/NOVA_MIGRATION.md`:** mark the migration complete
|
|
||||||
(cutoff passed).
|
|
||||||
- **Milestone ship:** tag `v1.15.4`, merge to `main`, Gitea release.
|
|
||||||
|
|
||||||
## Files touched in P4
|
|
||||||
|
|
||||||
- `terraform/platform/main.tf`, `terraform/microservice/main.tf`,
|
|
||||||
`terraform/ci-vpc/main.tf` — resource renames + backend bucket.
|
|
||||||
- `terraform/{platform,microservice,ci-vpc}/terraform.tf` — state bucket.
|
|
||||||
- `terraform/platform/consumer_invoke_policy.json` — Lambda ARN.
|
|
||||||
- `terraform/bootstrap/{create_state_backend,create_iam_user,apply_iam_baseline}.py`,
|
|
||||||
`spike_runner_policy.json`, `.bootstrap_state.json`, `README.md` —
|
|
||||||
IAM/outbox/state-bucket renames.
|
|
||||||
- `modules/l1/*/terraform/**` + `modules/l1/alb/instance.json` — L1
|
|
||||||
resource-name defaults.
|
|
||||||
- `modules/l2/microservice/composition.json` — `nova-app-role` default.
|
|
||||||
- `core/lambda/contract_ingestor.py` — default table names (D-111).
|
|
||||||
- `core/outbox_writer.py`, `core/regression_verify.py`,
|
|
||||||
`core/local_emulators.py` — outbox table consistency (cross-territory,
|
|
||||||
minimal).
|
|
||||||
- `.gitea/workflows/deploy.yml` + `.github/workflows/deploy.yml` —
|
|
||||||
`nova-deploy-` role ARN + artifact names.
|
|
||||||
- `scripts/migrate_dynamodb_data.py` (NEW), `scripts/rotate_spike_key.sh`,
|
|
||||||
`scripts/push_consumer_image.py`.
|
|
||||||
- `tests/**` — fixtures updated to assert `nova-*`.
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
# Nova Migration Guide — What Consumers Must Know
|
|
||||||
|
|
||||||
> **STATUS: COMPLETE (milestone v1.15.4, 2026-07-30).** The Nova rebrand
|
|
||||||
> is fully rolled out. The dual-read / parallel-write grace period has
|
|
||||||
> ended (P5 cutoff passed). All `ACDL_*` env var fallbacks, `.acdl/`
|
|
||||||
> consumer-path fallbacks, `/acdl/` SSM-path fallbacks, `acdl:*` tag-key
|
|
||||||
> fallbacks, and `acdl-*` AWS resource names are removed. Consumers must
|
|
||||||
> use the `NOVA_*` / `.nova/` / `/nova/` / `nova:*` / `nova-*` names
|
|
||||||
> exclusively. If you have not yet migrated, follow the steps below.
|
|
||||||
|
|
||||||
> **Nova** is the new product brand for the platform formerly known as
|
|
||||||
> **ACDL** (Agentic Cloud Delivery Platform). This guide documents the
|
|
||||||
> breaking changes from the rebrand rollout (Phases P2–P4, cutoff P5)
|
|
||||||
> and tells you exactly what to do.
|
|
||||||
|
|
||||||
## What is NOT changing
|
|
||||||
|
|
||||||
- **The Gitea repository name** (`continuous-intelligence/acdl`) is **not**
|
|
||||||
changing. Only the product brand is changing. The `uses:` reference
|
|
||||||
(`acdl/.github/workflows/deploy.yml@vX.Y`) and the GitHub `acdl/acdl` repo
|
|
||||||
path are unchanged for the duration of the rebrand; the workflow
|
|
||||||
`uses:` reference will be migrated in a later, separately-announced step.
|
|
||||||
- **The platform behavior** is unchanged. Same pipeline stages, same
|
|
||||||
contract schema, same confidence model, same evidence stream, same
|
|
||||||
modules. Only the brand, the on-disk path, the env var names, the SSM
|
|
||||||
path, the AWS tag keys, and the AWS resource names are changing.
|
|
||||||
|
|
||||||
## The 5 breaking changes
|
|
||||||
|
|
||||||
Five things that consumers may reference are being renamed. Each is
|
|
||||||
scheduled into a phase, ships with a grace period, and has a cutoff.
|
|
||||||
|
|
||||||
### 1. Consumer contract path — Phase P2
|
|
||||||
|
|
||||||
- **Old:** `.acdl/contract.yml`
|
|
||||||
- **New:** `.nova/contract.yml`
|
|
||||||
- **Phase:** P2 (env vars + consumer path)
|
|
||||||
- **Grace period:** during P2–P4 the deploy workflow reads **both** paths
|
|
||||||
(`.nova/contract.yml` first, falling back to `.acdl/contract.yml` if the
|
|
||||||
new path is absent). Your existing contracts keep working until P5.
|
|
||||||
- **Cutoff:** P5 removes the `.acdl/` fallback. Move your contract file
|
|
||||||
before P5.
|
|
||||||
- **What you must do:** rename the directory in your consumer repo from
|
|
||||||
`.acdl/` to `.nova/` and update any `contract:` workflow input that
|
|
||||||
points at the old path. Nothing else changes in the contract content.
|
|
||||||
|
|
||||||
### 2. Environment variables — Phase P2
|
|
||||||
|
|
||||||
- **Old:** `ACDL_*` (e.g. `ACDL_LIFECYCLE_MODE`, `ACDL_AWS_ACCOUNT_ID`,
|
|
||||||
`ACDL_BOOTSTRAP_AWS_ACCESS_KEY_ID`, …)
|
|
||||||
- **New:** `NOVA_*` (e.g. `NOVA_LIFECYCLE_MODE`, `NOVA_AWS_ACCOUNT_ID`,
|
|
||||||
`NOVA_BOOTSTRAP_AWS_ACCESS_KEY_ID`, …)
|
|
||||||
- **Phase:** P2 (env vars + consumer path)
|
|
||||||
- **Grace period — dual-read fallback:** during P2–P4 the platform reads
|
|
||||||
**`NOVA_*` first, then falls back to `ACDL_*`** if the Nova variable is
|
|
||||||
unset. This means your CI secrets, workflow env blocks, and local
|
|
||||||
`.env.secrets` keep working unchanged through P4. You do not need to
|
|
||||||
rename everything in one shot — rename a variable and the dual-read picks
|
|
||||||
it up; leave one old and it still resolves.
|
|
||||||
- **Cutoff:** P5 removes the `ACDL_*` fallback. After P5, only `NOVA_*`
|
|
||||||
is read.
|
|
||||||
- **What you must do:** rename your `ACDL_*` CI secrets, workflow `env:`
|
|
||||||
blocks, and any local `.env.secrets` entries to `NOVA_*`. Because of the
|
|
||||||
dual-read, you can do this incrementally across P2–P4 — but it must be
|
|
||||||
complete before P5.
|
|
||||||
|
|
||||||
### 3. SSM parameter path — Phase P3 (DONE)
|
|
||||||
|
|
||||||
- **Old:** `/acdl/{env}/{contractId}/{output}`
|
|
||||||
- **New:** `/nova/{env}/{contractId}/{output}`
|
|
||||||
- **Phase:** P3 (SSM paths + tag keys) — **shipped in P3**
|
|
||||||
- **Grace period — parallel-write:** during P3–P4 the platform **writes
|
|
||||||
every output to both** the `/acdl/…` and `/nova/…` SSM paths, and reads
|
|
||||||
from `/nova/…` first (falling back to `/acdl/…`). Any hardcoded SSM path
|
|
||||||
reads in your application code keep resolving through P4. The P3
|
|
||||||
migration script (`scripts/migrate_ssm_paths.py`) copies existing
|
|
||||||
`/acdl/…` parameters to `/nova/…`, verifies the copy, and deletes the
|
|
||||||
old ones.
|
|
||||||
- **Cutoff:** P5 stops writing to `/acdl/…` and removes the read fallback.
|
|
||||||
After P5 only `/nova/…` exists.
|
|
||||||
- **What you must do:** if your application code or runbooks read deploy
|
|
||||||
outputs from SSM by hardcoded path, update the path prefix from `/acdl/`
|
|
||||||
to `/nova/`. If you consume outputs only via the PR-comment / GitHub
|
|
||||||
issue surface, you do nothing — the platform republishes under the new
|
|
||||||
path automatically.
|
|
||||||
|
|
||||||
### 4. AWS tag keys — Phase P3 (DONE)
|
|
||||||
|
|
||||||
- **Old:** `acdl:owner`, `acdl:environment`, `acdl:contract`,
|
|
||||||
`acdl:cost-center`, `acdl:ref`
|
|
||||||
- **New:** `nova:owner`, `nova:environment`, `nova:contract`,
|
|
||||||
`nova:cost-center`, `nova:ref`
|
|
||||||
- **Phase:** P3 (SSM paths + tag keys) — **shipped in P3**
|
|
||||||
- **Grace period — parallel-tag period:** during P3–P4 the platform
|
|
||||||
**tags every resource with both** the `acdl:*` and `nova:*` keys (same
|
|
||||||
values). The ABAC session policy matches on **either** key set, so your
|
|
||||||
existing scoped permissions keep working. The default cost-center value
|
|
||||||
moves from `acdl-default` to `nova-default` (both written during the
|
|
||||||
parallel-tag period). Terraform now emits `nova:*` keys; old `acdl:*`
|
|
||||||
tags on pre-P3 live resources are removed by the P4 runbook's
|
|
||||||
`scripts/untag_acdl_keys.py` step after the `nova:*` tags are applied
|
|
||||||
live.
|
|
||||||
- **Cutoff:** P5 stops writing the `acdl:*` keys and the ABAC policy matches
|
|
||||||
only on `nova:*`. After P5, resources created before P5 still carry the
|
|
||||||
old `acdl:*` tags (tags are not retroactively rewritten) but **new**
|
|
||||||
resources are tagged `nova:*` only, and the policy no longer grants
|
|
||||||
access via `acdl:*`.
|
|
||||||
- **What you must do:** if you have IAM policies, Cost Explorer filters,
|
|
||||||
or billing groupings that key off `acdl:*` tag keys, add a parallel
|
|
||||||
`nova:*` condition (or migrate to `nova:*`) before P5. The platform
|
|
||||||
handles the dual-tagging; you only need to update your own tag-key
|
|
||||||
references.
|
|
||||||
|
|
||||||
### 5. AWS resource names — Phase P4
|
|
||||||
|
|
||||||
- **Old:** `acdl-*` (DynamoDB tables `acdl-contracts`,
|
|
||||||
`acdl-change-requests`; Lambda `acdl-contract-ingestor`; SNS
|
|
||||||
`acdl-sod-halt`; security group `acdl-ecs-sg`; KMS alias
|
|
||||||
`alias/acdl-platform`; ECS services, ECR repos, IAM user
|
|
||||||
`acdl-spike-runner`, state bucket `acdl-tfstate-*`, ALB `acdl-alb`,
|
|
||||||
`acdl-deploy-*`)
|
|
||||||
- **New:** `nova-*` (the same resources, prefixed `nova-`)
|
|
||||||
- **Phase:** P4 (resource names) — **maintenance window**
|
|
||||||
- **Grace period:** P4 is a **planned maintenance window**. AWS resources
|
|
||||||
cannot be renamed in place, so P4 provisions the `nova-*` resources,
|
|
||||||
migrates data (DynamoDB tables, S3 state), repoints the platform, and
|
|
||||||
tears down the `acdl-*` resources. The platform team schedules and
|
|
||||||
announces the window; consumers do not provision or rename anything
|
|
||||||
themselves.
|
|
||||||
- **Cutoff:** the `acdl-*` resources are decommissioned at the end of the
|
|
||||||
P4 maintenance window. After P4, only `nova-*` resources exist.
|
|
||||||
- **What you must do:** nothing for the resource names themselves — the
|
|
||||||
platform owns the rename. If your application code or runbooks reference
|
|
||||||
a specific `acdl-*` resource by name (e.g. a hardcoded DynamoDB table
|
|
||||||
name or ECR URI), update it to the `nova-*` name during P4. The platform
|
|
||||||
publishes the exact old → new name mapping with the P4 announcement.
|
|
||||||
|
|
||||||
## Timeline at a glance
|
|
||||||
|
|
||||||
| Phase | What ships | Grace period | Cutoff |
|
|
||||||
|-------|------------|--------------|--------|
|
|
||||||
| **P1** (this phase) | Brand prose, docs, decks, schema `$id`, release titles | n/a (prose only) | n/a |
|
|
||||||
| **P2** | `.nova/` contract path + `NOVA_*` env vars | dual-read: `.nova/`→`.acdl/`, `NOVA_*`→`ACDL_*` | **P5** removes fallback |
|
|
||||||
| **P3** | `/nova/` SSM path + `nova:*` tag keys | parallel-write (SSM) + parallel-tag (ABAC matches either) | **P5** removes old path/tags |
|
|
||||||
| **P4** | `nova-*` AWS resource names | maintenance window (platform-owned migration) | end of P4 window |
|
|
||||||
| **P5** | Fallback removal | — | `ACDL_*` env vars, `.acdl/` path, `/acdl/` SSM, `acdl:*` tags stop working |
|
|
||||||
|
|
||||||
## What consumers must do (checklist)
|
|
||||||
|
|
||||||
1. **Before P5 — contract path:** move `.acdl/contract.yml` →
|
|
||||||
`.nova/contract.yml` in your consumer repo; update the `contract:`
|
|
||||||
workflow input. *(Can be done any time in P2–P4.)*
|
|
||||||
2. **Before P5 — env vars:** rename `ACDL_*` CI secrets / workflow `env:`
|
|
||||||
blocks / local `.env.secrets` to `NOVA_*`. *(Incremental during P2–P4;
|
|
||||||
dual-read keeps you green.)*
|
|
||||||
3. **Before P5 — SSM reads:** if you read deploy outputs from SSM by
|
|
||||||
hardcoded `/acdl/…` path, update to `/nova/…`. *(Skip if you consume
|
|
||||||
outputs via PR comments only.)*
|
|
||||||
4. **Before P5 — tag-key references:** if you have IAM policies, Cost
|
|
||||||
Explorer filters, or billing groupings keyed off `acdl:*`, add or
|
|
||||||
migrate to `nova:*`. *(Platform handles dual-tagging.)*
|
|
||||||
5. **During P4 — resource-name references:** if your code or runbooks
|
|
||||||
reference a specific `acdl-*` AWS resource by name, update to the
|
|
||||||
`nova-*` name per the P4 mapping announcement. *(Platform owns the
|
|
||||||
rename itself.)*
|
|
||||||
|
|
||||||
## Questions
|
|
||||||
|
|
||||||
If anything in this guide is unclear, or you are unsure whether your
|
|
||||||
consumer repo references a renamed value, open an issue on the platform
|
|
||||||
repo. The platform team will confirm what you need to change and when.
|
|
||||||
|
|
||||||
> **Note:** the real Gitea repository name (`continuous-intelligence/acdl`)
|
|
||||||
> is **not** changing — only the product brand. The `uses:` workflow
|
|
||||||
> reference and repo path are migrated in a separately-announced later step;
|
|
||||||
> until then, keep your `uses: acdl/.github/workflows/deploy.yml@vX.Y`
|
|
||||||
> reference as-is.
|
|
||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
# Nova Onboarding — No-Humans Request Path (v1.16, REQ-182..184)
|
# Nova Onboarding — Autonomous Request Path (v1.16, REQ-182..184)
|
||||||
|
|
||||||
The v1.16 milestone implements the **request path** of the no-humans
|
The v1.16 milestone implements the **request path** of the autonomous
|
||||||
onboarding flow (D-113). A consumer can submit an onboarding request
|
onboarding flow (D-113). A consumer can submit an onboarding request
|
||||||
without contacting the platform team; the platform generates an
|
without contacting the platform team; the platform generates an
|
||||||
environment binding + (in a future milestone) provisions the AWS resources.
|
environment binding + (in a future milestone) provisions the AWS resources.
|
||||||
@@ -77,7 +77,7 @@ milestone (D-113).
|
|||||||
only (D-114); live apply is deferred.
|
only (D-114); live apply is deferred.
|
||||||
- **OIDC trust policy** — the onboarding Terraform uses a placeholder
|
- **OIDC trust policy** — the onboarding Terraform uses a placeholder
|
||||||
OIDC provider; real OIDC federation is blocked on
|
OIDC provider; real OIDC federation is blocked on
|
||||||
go-gitea/gitea#36988 (carries forward from v1.1).
|
upstream forge OIDC support (carries forward from v1.1).
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ change to the modules/stack/confidence/audit.
|
|||||||
- A MAJOR bump requires a new registry entry (immutable publication); the
|
- A MAJOR bump requires a new registry entry (immutable publication); the
|
||||||
old entry enters a 12-month deprecation window.
|
old entry enters a 12-month deprecation window.
|
||||||
- The central deploy pipeline is referenced by a floating MAJOR + MINOR tag
|
- The central deploy pipeline is referenced by a floating MAJOR + MINOR tag
|
||||||
(e.g. `@v1.13`); patch fixes flow within the tag, breaking changes land
|
(e.g. `@v1.19`); patch fixes flow within the tag, breaking changes land
|
||||||
under the next MINOR tag.
|
under the next MINOR tag.
|
||||||
|
|
||||||
See [Versioning](pipeline/versioning) for the consumer-facing details.
|
See [Versioning](pipeline/versioning) for the consumer-facing details.
|
||||||
|
|||||||
+13
-13
@@ -19,7 +19,7 @@ definitions.
|
|||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart LR
|
flowchart LR
|
||||||
A["your repo<br/>(app code + contracts + CI definitions)"] -->|uses: acdl/.github/workflows/deploy.yml@v1.13| B
|
A["your repo<br/>(app code + contracts + CI definitions)"] -->|uses: nova/.github/workflows/deploy.yml@v1.19| B
|
||||||
B["platform runners<br/>(modules + pipelines + adapters + schemas)"] -->|contract -> resolver -> stack -> adapter<br/>-> security checks -> infrastructure plan -> policy checks<br/>-> confidence -> apply -> evidence event| C
|
B["platform runners<br/>(modules + pipelines + adapters + schemas)"] -->|contract -> resolver -> stack -> adapter<br/>-> security checks -> infrastructure plan -> policy checks<br/>-> confidence -> apply -> evidence event| C
|
||||||
C["your resources in AWS"]
|
C["your resources in AWS"]
|
||||||
```
|
```
|
||||||
@@ -27,13 +27,13 @@ flowchart LR
|
|||||||
## Versioning the `uses:` reference
|
## Versioning the `uses:` reference
|
||||||
|
|
||||||
The central deployment pipeline is **always versioned with floating MAJOR
|
The central deployment pipeline is **always versioned with floating MAJOR
|
||||||
and MINOR tags** (e.g. `acdl/pipelines/contract.yml@v1.13`). Version
|
and MINOR tags** (e.g. `nova/pipelines/contract.yml@v1.19`). Version
|
||||||
constraints cannot be expressed inside the contract, so the tag in
|
constraints cannot be expressed inside the contract, so the tag in
|
||||||
`uses:` is the only immutability lever a consumer has. See
|
`uses:` is the only immutability lever a consumer has. See
|
||||||
[Versioning](pipeline/versioning) for the full rationale.
|
[Versioning](pipeline/versioning) for the full rationale.
|
||||||
|
|
||||||
**Unversioned references are discouraged.** Do not use `@main` or a bare
|
**Unversioned references are discouraged.** Do not use `@main` or a bare
|
||||||
`acdl/pipelines/contract.yml`.
|
`nova/pipelines/contract.yml`.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ platform-managed. See [Environments](environments/).
|
|||||||
environment is bound, your first pipeline run emits a friendly onboarding
|
environment is bound, your first pipeline run emits a friendly onboarding
|
||||||
prompt. See [Environments](environments/).
|
prompt. See [Environments](environments/).
|
||||||
- **Authorization to reference the central pipeline.** Onboarding grants
|
- **Authorization to reference the central pipeline.** Onboarding grants
|
||||||
your repo the right to `uses: acdl/.github/workflows/deploy.yml@v1.13`.
|
your repo the right to `uses: nova/.github/workflows/deploy.yml@v1.19`.
|
||||||
Contact the platform team if you have not been onboarded.
|
Contact the platform team if you have not been onboarded.
|
||||||
|
|
||||||
## Step 1 — Create a consumer repo
|
## Step 1 — Create a consumer repo
|
||||||
@@ -94,7 +94,7 @@ Nova deployment workflow with a **versioned tag** (floating MAJOR + MINOR):
|
|||||||
```yaml
|
```yaml
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.13
|
uses: nova/.github/workflows/deploy.yml@v1.19
|
||||||
with:
|
with:
|
||||||
contract: .nova/contract.yml
|
contract: .nova/contract.yml
|
||||||
environment: dev
|
environment: dev
|
||||||
@@ -140,7 +140,7 @@ name: microservice
|
|||||||
|
|
||||||
| Field | Type | Required | Description |
|
| Field | Type | Required | Description |
|
||||||
|-------|------|----------|-------------|
|
|-------|------|----------|-------------|
|
||||||
| `uses` | string | yes | Reference to the central deployment pipeline, **versioned** with a floating MAJOR+MINOR tag (e.g. `acdl/pipelines/contract.yml@v1.13`). Bare or `@main` references are discouraged. See [Versioning](pipeline/versioning). |
|
| `uses` | string | yes | Reference to the central deployment pipeline, **versioned** with a floating MAJOR+MINOR tag (e.g. `nova/pipelines/contract.yml@v1.19`). Bare or `@main` references are discouraged. See [Versioning](pipeline/versioning). |
|
||||||
| `module` | string | yes | Module name from the registry — any primitive or module (e.g. `static-assets`, `microservice`, `s3`). See the [module catalog](modules/). |
|
| `module` | string | yes | Module name from the registry — any primitive or module (e.g. `static-assets`, `microservice`, `s3`). See the [module catalog](modules/). |
|
||||||
| `environment` | string | yes | The platform-managed environment to deploy to (e.g. `dev`). See [Environments](environments/). |
|
| `environment` | string | yes | The platform-managed environment to deploy to (e.g. `dev`). See [Environments](environments/). |
|
||||||
| `inputs` | object | yes | Module-specific inputs (see the module's README). |
|
| `inputs` | object | yes | Module-specific inputs (see the module's README). |
|
||||||
@@ -177,14 +177,14 @@ on:
|
|||||||
branches: [main]
|
branches: [main]
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.13
|
uses: nova/.github/workflows/deploy.yml@v1.19
|
||||||
with:
|
with:
|
||||||
contract: .nova/contract.yml
|
contract: .nova/contract.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
That is the entire consumer-side workflow. When you push to `main`:
|
That is the entire consumer-side workflow. When you push to `main`:
|
||||||
|
|
||||||
1. The platform runner resolves `uses: acdl/.github/workflows/deploy.yml@v1.13`
|
1. The platform runner resolves `uses: nova/.github/workflows/deploy.yml@v1.19`
|
||||||
to the reusable workflow **at the pinned tag**.
|
to the reusable workflow **at the pinned tag**.
|
||||||
2. A **platform-provided runner** checks out **your** repo.
|
2. A **platform-provided runner** checks out **your** repo.
|
||||||
3. The runner checks out the **Nova platform repo** into the workspace —
|
3. The runner checks out the **Nova platform repo** into the workspace —
|
||||||
@@ -326,8 +326,8 @@ per-module extension points. Common examples:
|
|||||||
| Contract schema | `schemas/contract.schema.json` | JSON Schema for consumer contracts. |
|
| Contract schema | `schemas/contract.schema.json` | JSON Schema for consumer contracts. |
|
||||||
| Stack schema | `schemas/stack.schema.json` | JSON Schema for the resolved stack instance. |
|
| Stack schema | `schemas/stack.schema.json` | JSON Schema for the resolved stack instance. |
|
||||||
| Module catalog | [modules/](modules/) | All primitives and modules. |
|
| Module catalog | [modules/](modules/) | All primitives and modules. |
|
||||||
| Sample contract | `contracts/static-assets.yaml` | The reference example contract (uses `@v1.13`). |
|
| Sample contract | `contracts/static-assets.yaml` | The reference example contract (uses `@v1.19`). |
|
||||||
| Sample contract | `contracts/microservice.yaml` | The microservice example contract (uses `@v1.13`). |
|
| Sample contract | `contracts/microservice.yaml` | The microservice example contract (uses `@v1.19`). |
|
||||||
| Module examples | `modules/<name>/examples/` | Validated per-module example contracts (`simple.yaml` + `complex.yaml`). |
|
| 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. |
|
| Contract resolver | `core/contract_resolver.py` | Resolves contracts to stack instances. |
|
||||||
| Angine adapter | `adapters/terraform/adapter.py` | Compiles stack instances to infrastructure. |
|
| Angine adapter | `adapters/terraform/adapter.py` | Compiles stack instances to infrastructure. |
|
||||||
@@ -353,7 +353,7 @@ destruction:
|
|||||||
use `mode: decommission` with the `changeRequestId` input:
|
use `mode: decommission` with the `changeRequestId` input:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.13
|
uses: nova/.github/workflows/deploy.yml@v1.19
|
||||||
with:
|
with:
|
||||||
contract: .nova/contract.yml
|
contract: .nova/contract.yml
|
||||||
mode: decommission
|
mode: decommission
|
||||||
@@ -421,7 +421,7 @@ name: static-assets
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Shape 2 — single contract + `environment` workflow input:** the
|
**Shape 2 — single contract + `environment` workflow input:** the
|
||||||
reusable deploy workflow (`acdl/.github/workflows/deploy.yml@v1.13`)
|
reusable deploy workflow (`nova/.github/workflows/deploy.yml@v1.19`)
|
||||||
declares an `environment` input. When non-empty, it overrides the
|
declares an `environment` input. When non-empty, it overrides the
|
||||||
contract's `environment` field at load time (before interpolation), so
|
contract's `environment` field at load time (before interpolation), so
|
||||||
the same contract can be promoted by passing a different environment:
|
the same contract can be promoted by passing a different environment:
|
||||||
@@ -436,7 +436,7 @@ on: workflow_dispatch:
|
|||||||
required: true
|
required: true
|
||||||
jobs:
|
jobs:
|
||||||
deploy-qa:
|
deploy-qa:
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.13
|
uses: nova/.github/workflows/deploy.yml@v1.19
|
||||||
with:
|
with:
|
||||||
environment: qa
|
environment: qa
|
||||||
contract: .nova/contract.yml
|
contract: .nova/contract.yml
|
||||||
|
|||||||
@@ -78,10 +78,3 @@ Planned future features (no dates; tracked in the internal roadmap):
|
|||||||
- [Consumer Guide](consumer-guide) — start here if you are a consumer.
|
- [Consumer Guide](consumer-guide) — start here if you are a consumer.
|
||||||
- [Architecture](architecture) — start here if you are a platform engineer.
|
- [Architecture](architecture) — start here if you are a platform engineer.
|
||||||
- The [README](https://github.com/nova/nova) describes the platform repo.
|
- The [README](https://github.com/nova/nova) describes the platform repo.
|
||||||
|
|
||||||
> **Note:** The product brand is **Nova** (formerly ACDL — Agentic Cloud
|
|
||||||
> Delivery Platform). The Gitea repository name (`continuous-intelligence/acdl`)
|
|
||||||
> and the GitHub `uses:` reference (`acdl/.github/workflows/deploy.yml@…`)
|
|
||||||
> are unchanged during the rebrand transition; only the product name is
|
|
||||||
> changing. See the [Nova migration guide](NOVA_MIGRATION) for the
|
|
||||||
> scheduled breaking changes.
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# AI Decision Accuracy — Definition of Success
|
||||||
|
|
||||||
|
> KPI: AI Decision Accuracy
|
||||||
|
> Target: ≥ 99.5% (no rollback, no follow-up incident within 5 min of action)
|
||||||
|
|
||||||
|
**What this number means:** the percentage of AI decisions (confidence-
|
||||||
|
gated policy engine outcomes) that were NOT followed by an apply failure
|
||||||
|
or incident within 5 minutes. A high-confidence decision that later
|
||||||
|
caused an incident does NOT count as accurate.
|
||||||
|
|
||||||
|
**How it's computed:** `count(decisions WHERE outcome = 'succeeded' AND
|
||||||
|
no incident within 5min)` ÷ `total decisions`. Correlation via
|
||||||
|
`decision_id` → `run_id` → subsequent `apply.failed` or `incident.detected`
|
||||||
|
events.
|
||||||
|
|
||||||
|
**What "good" looks like:** ≥ 99.5% means fewer than 1 in 200 decisions
|
||||||
|
cause a secondary failure. The 0.5% allowance is for novel edge cases.
|
||||||
|
|
||||||
|
**D-122 honesty:** Nova's "AI" is the confidence-gated policy engine
|
||||||
|
(confidence_signal + HITL gate), not an LLM planner. The Decision Ledger
|
||||||
|
captures this real decision path — not a fabricated "AI agent."
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Attestation Coverage — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Attestation Coverage
|
||||||
|
> Target: 100% of prod/dr promotions attested by a human
|
||||||
|
|
||||||
|
**What this number means:** every production and disaster-recovery
|
||||||
|
promotion has a recorded human attestation (approver identity, 8-concern
|
||||||
|
matrix result, separation-of-duties check on prod). This is the
|
||||||
|
"autonomy in operations, human in accountability" proof.
|
||||||
|
|
||||||
|
**How it's computed:** `count(prod/dr promotions with attestation.recorded
|
||||||
|
event) ÷ count(total prod/dr promotions)`. Sourced from the Decision
|
||||||
|
Ledger (`attestation.recorded` events) + `hitl_gates.py` + outbox
|
||||||
|
`approver_*` attributes.
|
||||||
|
|
||||||
|
**What "good" looks like:** 100% means no prod/dr promotion ever lands
|
||||||
|
without a human sign-off on record. The absence of an operator is never
|
||||||
|
the absence of a record (NORTH_STAR Anti-Goal #3).
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Confidence-Gate Halt Rate — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Confidence-Gate Halt Rate
|
||||||
|
> Target: not a committed target (operational signal)
|
||||||
|
|
||||||
|
**What this number means:** how often the confidence gate itself halted
|
||||||
|
a run (band = block), independent of HITL blocks. The gate is the AI's
|
||||||
|
self-halt; HITL is the human gate. This distinguishes the AI's
|
||||||
|
self-regulation from human escalation.
|
||||||
|
|
||||||
|
**How it's computed:** `count(runs WHERE confidence_band = 'block')` ÷
|
||||||
|
`total runs`.
|
||||||
|
|
||||||
|
**What "good" looks like:** a low but non-zero rate means the gate is
|
||||||
|
working (catching genuinely uncertain runs) without being overly
|
||||||
|
conservative (blocking everything).
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Cost Savings via Infracost Estimates — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Cost Savings via Infracost Estimates
|
||||||
|
> Target: ≥ 25% on pilot estates (partial)
|
||||||
|
|
||||||
|
**What this number means:** the pre-apply cost estimate from Infracost
|
||||||
|
shows the delta between the planned infrastructure and the current
|
||||||
|
state. Negative deltas = savings.
|
||||||
|
|
||||||
|
**How it's computed:** `sum(fact_cost_estimate.delta_usd WHERE delta < 0)`
|
||||||
|
per period.
|
||||||
|
|
||||||
|
**What's grounded:** the pre-apply estimate (Infracost reads plan JSON,
|
||||||
|
offline).
|
||||||
|
|
||||||
|
**What's deferred:** actual-spend reconciliation from AWS CUR (D-096 —
|
||||||
|
needs live AWS billing). The placeholder view
|
||||||
|
`placeholder_live_cur_reconciliation.csv` has the schema ready.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Decision Ledger Coverage — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Decision Ledger Coverage
|
||||||
|
> Target: 100% of AI actions with backfilled outcome
|
||||||
|
|
||||||
|
**What this number means:** every AI decision (confidence-gated policy
|
||||||
|
engine outcome) is captured in the Decision Ledger with its outcome
|
||||||
|
backfilled from the subsequent apply.completed/failed event.
|
||||||
|
|
||||||
|
**How it's computed:** `count(decision_ledger rows WHERE outcome ≠
|
||||||
|
'pending') ÷ count(decision_ledger rows)`. Sourced from
|
||||||
|
`metrics/decision_ledger.db`.
|
||||||
|
|
||||||
|
**What "good" looks like:** 100% means no AI decision is ever lost or
|
||||||
|
left without an outcome. The ledger is the trust substrate (NORTH_STAR
|
||||||
|
Objective #2).
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Deployment Frequency — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Deployment Frequency
|
||||||
|
> Target: not a committed target (operational signal)
|
||||||
|
|
||||||
|
**What this number means:** the rate of infrastructure state updates
|
||||||
|
deployed safely per day. A DORA-adjacent metric for infrastructure.
|
||||||
|
|
||||||
|
**How it's computed:** `count(run.completed WHERE exit_code = 0)` per
|
||||||
|
day.
|
||||||
|
|
||||||
|
**What "good" looks like:** multiple deploys per day (vs. weekly/monthly
|
||||||
|
for human ops teams).
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# FTE Hours Saved (Toil Reallocation Value) — Definition of Success
|
||||||
|
|
||||||
|
> KPI: FTE Hours Saved
|
||||||
|
> Target: ≥ 70% of pre-Nova FTE allocation (derived)
|
||||||
|
|
||||||
|
**What this number means:** the engineering hours saved by automated
|
||||||
|
operations, valued at the blended engineering rate. This is what those
|
||||||
|
hours were spent on instead (the "toil reallocation" — capital freed
|
||||||
|
up from ops to feature development).
|
||||||
|
|
||||||
|
**How it's computed:** `run count × manual baseline minutes per run ÷ 60
|
||||||
|
× blended hourly rate`. The manual baseline is the estimated time a
|
||||||
|
human team would take for the same operation (e.g., 30 min/ticket).
|
||||||
|
|
||||||
|
**Honesty caveat:** computed on N internal runs today; the production-
|
||||||
|
denominator activates post-pilot. The formula is grounded; the
|
||||||
|
production numbers are not yet.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Human Escalation Frequency — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Human Escalation Frequency
|
||||||
|
> Target: < 0.1% of platform actions (Post-Pilot)
|
||||||
|
|
||||||
|
**What this number means:** how often the AI platform was forced to fall
|
||||||
|
back or escalate to a human operator due to low confidence. This is the
|
||||||
|
inverse of Touchless Resolution Rate, scoped to operational escalations
|
||||||
|
only.
|
||||||
|
|
||||||
|
**How it's computed:** `count(runs WHERE hitl_block = 1 AND reason =
|
||||||
|
'confidence')` ÷ `total runs`. Attestation sign-offs are excluded.
|
||||||
|
|
||||||
|
**What "good" looks like:** < 0.1% means fewer than 1 in 1000 runs
|
||||||
|
require human intervention. Near-zero is the goal.
|
||||||
|
|
||||||
|
**What would be "gamer metrics":** counting attestation sign-offs as
|
||||||
|
escalations (they're not — they're designed controls).
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# MTTR (Platform-Run) — Definition of Success
|
||||||
|
|
||||||
|
> KPI: MTTR (p95)
|
||||||
|
> Target: < 60 seconds
|
||||||
|
|
||||||
|
**What this number means:** the time from a platform-run failure
|
||||||
|
(apply.failed) to a successful retry. This is platform-run MTTR, not
|
||||||
|
infra-incident MTTR (which requires an incident detection system that
|
||||||
|
Nova doesn't have yet — deferred).
|
||||||
|
|
||||||
|
**How it's computed:** p95 of `successful_retry.time − failed_run.time`
|
||||||
|
across all runs that failed then succeeded.
|
||||||
|
|
||||||
|
**What "good" looks like:** < 60 seconds means the platform recovers
|
||||||
|
from a failed run in under a minute, 95% of the time.
|
||||||
|
|
||||||
|
**What's deferred:** infra-incident MTTR (anomaly detected → healed)
|
||||||
|
requires an incident detection/remediation system (self-healing
|
||||||
|
velocity). That's a future emitter.
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Platform ROI — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Platform ROI
|
||||||
|
> Target: ≥ 250% measured annually (derived)
|
||||||
|
|
||||||
|
**What this number means:** the total financial value delivered (labor
|
||||||
|
savings + cloud cost optimization + avoided downtime losses) vs. the
|
||||||
|
platform's operational/licensing cost.
|
||||||
|
|
||||||
|
**Formula:** `(FTE hours saved × blended rate + cloud savings + avoided
|
||||||
|
downtime) ÷ platform op cost`.
|
||||||
|
|
||||||
|
**Honesty caveat:** computed on N internal runs today; the production-
|
||||||
|
denominator activates post-pilot. The formula is grounded; the
|
||||||
|
production numbers are not yet.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Zero-Trust Policy Compliance Rate — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Zero-Trust Policy Compliance Rate
|
||||||
|
> Target: not a committed target (operational signal)
|
||||||
|
|
||||||
|
**What this number means:** the percentage of infrastructure assets
|
||||||
|
continuously verified as compliant with security baselines and policies.
|
||||||
|
|
||||||
|
**How it's computed:** `1 − count(assets WHERE last_scan.status ≠ pass)
|
||||||
|
÷ count(assets)`. Sourced from `fact_policy_check` (Checkov results).
|
||||||
|
|
||||||
|
**What "good" looks like:** 100% means every resource passed every
|
||||||
|
policy check. The Nova tagging standard (nova_tagging.py, hard mode) is
|
||||||
|
the primary check.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Provisioning Lead Time — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Provisioning Lead Time
|
||||||
|
> Target: not a committed target (operational signal)
|
||||||
|
|
||||||
|
**What this number means:** the time from intent received (run.started)
|
||||||
|
to apply completed (run.completed). Measures how fast Nova provisions
|
||||||
|
compliant environments.
|
||||||
|
|
||||||
|
**How it's computed:** `run.completed_at − run.started_at` per run.
|
||||||
|
|
||||||
|
**What "good" looks like:** minutes, not days. The reduction from days
|
||||||
|
(human ops) to minutes (autonomous) is the velocity proof.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Touchless Resolution Rate — Definition of Success
|
||||||
|
|
||||||
|
> KPI: Touchless Resolution Rate
|
||||||
|
> Target: ≥ 99% across production estates (Post-Pilot)
|
||||||
|
|
||||||
|
**What this number means:** the percentage of platform runs that complete
|
||||||
|
end-to-end without an operational HITL block. An operational HITL block
|
||||||
|
is a confidence-driven escalation (the AI's confidence was too low to
|
||||||
|
proceed). Attestation gates (qa/prod/dr sign-offs) are NOT counted as
|
||||||
|
escalations — they are designed controls, not autonomy failures.
|
||||||
|
|
||||||
|
**How it's computed:** `runs WHERE hitl_block = 0 AND environment = 'dev'`
|
||||||
|
÷ `total runs` (dev environment only, where attestation gates don't apply).
|
||||||
|
For production estates: `runs WHERE hitl_block = 0` ÷ `total runs`
|
||||||
|
excluding attestation-gate sign-offs.
|
||||||
|
|
||||||
|
**What "good" looks like:** ≥ 99% means fewer than 1 in 100 runs require
|
||||||
|
human intervention due to low confidence. The 1% allowance is for
|
||||||
|
genuine edge cases (novel failure modes, blast-radius exceedances).
|
||||||
|
|
||||||
|
**What would be "gamer metrics":** counting attestation gates as
|
||||||
|
"touchless" (they're not — they're human by design) or counting only
|
||||||
|
dev runs (cherry-picking the easiest environment).
|
||||||
@@ -39,7 +39,7 @@ It is exposed to consumer repos as a **reusable workflow**:
|
|||||||
- `.github/workflows/deploy.yml` — GitHub Actions (production)
|
- `.github/workflows/deploy.yml` — GitHub Actions (production)
|
||||||
|
|
||||||
A consumer repo invokes the reusable workflow via a **versioned tag**
|
A consumer repo invokes the reusable workflow via a **versioned tag**
|
||||||
(floating MAJOR + MINOR, e.g. `acdl/.github/workflows/deploy.yml@v1.13`).
|
(floating MAJOR + MINOR, e.g. `nova/.github/workflows/deploy.yml@v1.19`).
|
||||||
The workflow checks out the consumer repo, then checks out the Nova platform
|
The workflow checks out the consumer repo, then checks out the Nova platform
|
||||||
repo into the runner workspace, and runs `scripts/run_platform.sh` against
|
repo into the runner workspace, and runs `scripts/run_platform.sh` against
|
||||||
the consumer's contract. The consumer never clones the platform repo or
|
the consumer's contract. The consumer never clones the platform repo or
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ tag** in a consumer's CI workflow definition:
|
|||||||
```yaml
|
```yaml
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.13
|
uses: nova/.github/workflows/deploy.yml@v1.19
|
||||||
with:
|
with:
|
||||||
contract: .nova/contract.yml
|
contract: .nova/contract.yml
|
||||||
```
|
```
|
||||||
@@ -36,7 +36,7 @@ itself — the contract no longer carries a `uses:` field). The CI workflow
|
|||||||
`uses:` tag is the only immutability lever a consumer has.
|
`uses:` tag is the only immutability lever a consumer has.
|
||||||
|
|
||||||
**Unversioned references are discouraged.** Do not use `@main` or a bare
|
**Unversioned references are discouraged.** Do not use `@main` or a bare
|
||||||
`acdl/.github/workflows/deploy.yml` — `main` is constantly updated and can
|
`nova/.github/workflows/deploy.yml` — `main` is constantly updated and can
|
||||||
cause unexpected failures. Pinning to a MAJOR+MINOR tag means:
|
cause unexpected failures. Pinning to a MAJOR+MINOR tag means:
|
||||||
|
|
||||||
- **Immutability** — the pipeline behavior you tested is the behavior you
|
- **Immutability** — the pipeline behavior you tested is the behavior you
|
||||||
|
|||||||
+74
-172
@@ -13,17 +13,18 @@ every deck and a presenter-ready cue sheet for delivery.
|
|||||||
|
|
||||||
```
|
```
|
||||||
Step 1: full markdown Step 2: Marp deck Step 3: HTML + PPTX Step 4: Talking points
|
Step 1: full markdown Step 2: Marp deck Step 3: HTML + PPTX Step 4: Talking points
|
||||||
(source of truth) ──► (lean, 10 slides) ──► (rendered) ──► (presenter cues)
|
(source of truth) ──► (lean, 21 slides) ──► (rendered) ──► (presenter cues)
|
||||||
*.md *-marp.md *.html / *.pptx *-talking-points.md
|
*.md *-marp.md *.html / *.pptx *-talking-points.md
|
||||||
+ speaker notes + embedded PNG diagrams + 3-6 bullets per slide
|
+ speaker notes + embedded PNG diagrams + 3-6 bullets per slide
|
||||||
+ mermaid code blocks + Marp frontmatter + key takeaway per slide
|
+ mermaid code blocks + Marp frontmatter + key takeaway per slide
|
||||||
+ maturity badges + indexed by Marp slide #
|
+ no speaker notes + indexed by Marp slide #
|
||||||
+ no speaker notes + content distilled from Step 1
|
+ no maturity badges + content distilled from Step 1
|
||||||
|
+ no version in footer
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 1 — Full markdown (source of truth)
|
### Step 1 — Full markdown (source of truth)
|
||||||
|
|
||||||
**File convention:** `<deck-name>.md` (e.g. `how-the-platform-works.md`).
|
**File convention:** `<deck-name>.md` (e.g. `nova-autonomous-cloud-delivery.md`).
|
||||||
|
|
||||||
Write the complete deck as a standard markdown file. This is the **source of
|
Write the complete deck as a standard markdown file. This is the **source of
|
||||||
truth** — it contains:
|
truth** — it contains:
|
||||||
@@ -34,9 +35,9 @@ truth** — it contains:
|
|||||||
the "who cares and why," and the honesty caveats.
|
the "who cares and why," and the honesty caveats.
|
||||||
- Mermaid diagrams as ```` ```mermaid ```` fenced code blocks (these render
|
- Mermaid diagrams as ```` ```mermaid ```` fenced code blocks (these render
|
||||||
on GitHub/Pages but not in Marp — Step 2 converts them to images).
|
on GitHub/Pages but not in Marp — Step 2 converts them to images).
|
||||||
- An honest "shipped vs. planned" framing: every "available today" claim is
|
- An honest "shipped vs. deferred" framing: every "available today" claim is
|
||||||
grounded in shipped/verified work; every "planned" item is explicitly
|
grounded in shipped/verified work; every "deferred" item is explicitly
|
||||||
marked.
|
marked with the blocking work in plain language.
|
||||||
|
|
||||||
**Why this file is the source of truth:** it is reviewable in any markdown
|
**Why this file is the source of truth:** it is reviewable in any markdown
|
||||||
viewer, diffs cleanly in git, and carries the full reasoning (speaker notes)
|
viewer, diffs cleanly in git, and carries the full reasoning (speaker notes)
|
||||||
@@ -45,13 +46,13 @@ fact is wrong, fix it here and re-run Steps 2 and 3.
|
|||||||
|
|
||||||
### Step 2 — Marp deck synthesis
|
### Step 2 — Marp deck synthesis
|
||||||
|
|
||||||
**File convention:** `<deck-name>-marp.md` (e.g. `how-the-platform-works-marp.md`).
|
**File convention:** `<deck-name>-marp.md` (e.g. `nova-autonomous-cloud-delivery-marp.md`).
|
||||||
|
|
||||||
Synthesize the full markdown into a lean Marp deck:
|
Synthesize the full markdown into a lean Marp deck:
|
||||||
|
|
||||||
- **Marp frontmatter** at the top: `marp: true`, `theme: default`,
|
- **Marp frontmatter** at the top: `marp: true`, `theme: nova-sp`,
|
||||||
`paginate: true`, `size: 16x9`, a header/footer, and an inline `style:`
|
`paginate: true`, `size: 16x9`, a header/footer, and an inline `style:`
|
||||||
block for fonts, colors, tables, badges.
|
block for fonts, colors, tables.
|
||||||
- **No speaker notes.** The Marp deck is what the audience sees; the
|
- **No speaker notes.** The Marp deck is what the audience sees; the
|
||||||
speaker notes live only in the Step 1 source of truth.
|
speaker notes live only in the Step 1 source of truth.
|
||||||
- **Mermaid diagrams → PNG images.** Marp does not render mermaid fenced
|
- **Mermaid diagrams → PNG images.** Marp does not render mermaid fenced
|
||||||
@@ -60,8 +61,10 @@ Synthesize the full markdown into a lean Marp deck:
|
|||||||
and embed it with ``.
|
and embed it with ``.
|
||||||
- **`<!-- _class: title -->` + `<!-- _paginate: false -->`** on title and
|
- **`<!-- _class: title -->` + `<!-- _paginate: false -->`** on title and
|
||||||
closing slides for the dark-background title style.
|
closing slides for the dark-background title style.
|
||||||
- **Maturity badges** using inline spans:
|
- **No maturity badges.** The deck no longer uses `<span class="badge">`
|
||||||
`<span class="badge planned">Planned</span>`
|
spans. Deferred items are named in plain language with their blocking
|
||||||
|
work, not tagged with a badge.
|
||||||
|
- **No version in the footer.** The footer carries the deck title only.
|
||||||
- **Tighter prose** than Step 1 — strip the speaker-note nuance; keep the
|
- **Tighter prose** than Step 1 — strip the speaker-note nuance; keep the
|
||||||
leadership-relevant selling points.
|
leadership-relevant selling points.
|
||||||
|
|
||||||
@@ -69,10 +72,8 @@ Synthesize the full markdown into a lean Marp deck:
|
|||||||
|
|
||||||
Both formats are derived from the Marp deck. **HTML is committed to the repo**
|
Both formats are derived from the Marp deck. **HTML is committed to the repo**
|
||||||
(viewable in any browser, self-contained with base64-embedded images). **PPTX
|
(viewable in any browser, self-contained with base64-embedded images). **PPTX
|
||||||
is uploaded to the Gitea release** as a downloadable attachment (binary, not
|
is also committed to the repo** as a first-class binary artifact and is
|
||||||
committed to git).
|
attached to the phase's release via `scripts/attach_release_asset.py`.
|
||||||
|
|
||||||
#### HTML export (committed to repo)
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
||||||
@@ -81,148 +82,67 @@ CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
|||||||
-o docs/presentations/<deck-name>.html
|
-o docs/presentations/<deck-name>.html
|
||||||
```
|
```
|
||||||
|
|
||||||
HTML export inlines images as base64 data URIs — no `--allow-local-files`
|
HTML export inlines images as base64 data URIs. PPTX export requires
|
||||||
needed for self-contained output, but it's required when the Marp deck
|
`--allow-local-files` so the local PNG diagrams are embedded in the file.
|
||||||
references local PNG assets. The resulting HTML is a single self-contained
|
The render + commit + attach pipeline is automated by `scripts/render_slides.sh`.
|
||||||
file that renders the full deck with the S&P Global Energy theme.
|
|
||||||
|
|
||||||
**Re-render the HTML whenever the Marp source changes.** The HTML files are
|
|
||||||
committed artifacts, not generated on-the-fly — they must be re-rendered and
|
|
||||||
re-committed when the Marp deck is updated.
|
|
||||||
|
|
||||||
#### PPTX export (uploaded to Gitea release)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
|
||||||
npx --yes @marp-team/marp-cli@latest --allow-local-files \
|
|
||||||
docs/presentations/<deck-name>-marp.md \
|
|
||||||
-o <output-path>.pptx
|
|
||||||
```
|
|
||||||
|
|
||||||
The `--allow-local-files` flag is **required** for PPTX export so the local
|
|
||||||
PNG diagrams are embedded in the file. PPTX files are not committed to the
|
|
||||||
repo (binary, no meaningful diffs) — they are uploaded to the Gitea release
|
|
||||||
as downloadable attachments.
|
|
||||||
|
|
||||||
### Step 4 — Talking points (presenter cues)
|
### Step 4 — Talking points (presenter cues)
|
||||||
|
|
||||||
**File convention:** `<deck-name>-talking-points.md` (e.g.
|
**File convention:** `<deck-name>-talking-points.md` (e.g.
|
||||||
`how-the-platform-works-talking-points.md`).
|
`nova-autonomous-cloud-delivery-talking-points.md`).
|
||||||
|
|
||||||
Distill the source of truth (Step 1) into presenter-ready cues, indexed by
|
Distill the source of truth (Step 1) into presenter-ready cues, indexed by
|
||||||
the Marp deck (Step 2) slide structure:
|
the Marp deck (Step 2) slide structure:
|
||||||
|
|
||||||
- **One section per Marp slide** — `## Slide N — Title`, matching the Marp
|
- **One section per Marp slide** — `## Slide N — Title`, matching the Marp
|
||||||
deck's 11 main + Appendix TOC + appendix slide structure exactly. The Marp deck
|
deck's 20 main + 1 appendix slide structure exactly.
|
||||||
provides the indexing and context (what the audience sees); the source
|
|
||||||
markdown provides the content (the speaker notes, the detail, the nuance).
|
|
||||||
- **3-6 talking point bullets per slide** — punchy, actionable cues distilled
|
- **3-6 talking point bullets per slide** — punchy, actionable cues distilled
|
||||||
from the source markdown's speaker notes. NOT the speaker notes verbatim
|
from the source markdown's speaker notes.
|
||||||
(those are too long and too contextual). These are prompts: "Land this
|
|
||||||
point," "Contrast with X," "Be honest about Y."
|
|
||||||
- **Key takeaway per slide** — the one memorable thing the audience should
|
- **Key takeaway per slide** — the one memorable thing the audience should
|
||||||
walk away with from that slide.
|
walk away with from that slide.
|
||||||
- **No content duplication** — the talking points reference the Marp slides
|
- **No content duplication** — the talking points reference the Marp slides
|
||||||
for visual context and the source markdown for full detail. They don't
|
for visual context and the source markdown for full detail.
|
||||||
repeat either; they bridge them.
|
|
||||||
|
|
||||||
**Why this file exists:** a presenter needs a cue sheet they can glance at
|
|
||||||
during delivery — not the full speaker notes (too long), not the Marp slides
|
|
||||||
(no detail). The talking points file is the middle layer: what to say, in
|
|
||||||
what order, with what emphasis, per slide.
|
|
||||||
|
|
||||||
**When to update:** re-distill the talking points whenever the Marp deck
|
|
||||||
structure changes (slides added, removed, merged, or re-ordered) or whenever
|
|
||||||
the source markdown's speaker notes are updated. The talking points are a
|
|
||||||
*derived artifact* — if a fact is wrong, fix it in the source markdown (Step 1)
|
|
||||||
and re-distill.
|
|
||||||
|
|
||||||
## Directory layout
|
## Directory layout
|
||||||
|
|
||||||
```
|
```
|
||||||
docs/presentations/
|
docs/presentations/
|
||||||
├── README.md ← this file
|
├── README.md ← this file
|
||||||
├── how-the-platform-works.md ← Step 1: full source of truth
|
├── nova-autonomous-cloud-delivery.md ← Step 1: full source of truth (20 main slides + speaker notes)
|
||||||
├── how-the-platform-works-marp.md ← Step 2: Marp deck (11 main + TOC + 8 appendix = 20)
|
├── nova-autonomous-cloud-delivery-marp.md ← Step 2: Marp deck (20 main + 1 appendix = 21 slides)
|
||||||
├── how-the-platform-works.html ← Step 3: rendered HTML (committed)
|
├── nova-autonomous-cloud-delivery.html ← Step 3: rendered HTML (committed, S&P-themed)
|
||||||
├── how-the-platform-works-talking-points.md ← Step 4: presenter cues (20 sections)
|
├── nova-autonomous-cloud-delivery.pptx ← Step 3: rendered PPTX (committed, S&P-themed)
|
||||||
├── the-developer-experience.md ← Step 1: full source of truth
|
├── nova-autonomous-cloud-delivery-talking-points.md ← Step 4: presenter cues (19 sections)
|
||||||
├── the-developer-experience-marp.md ← Step 2: Marp deck (11 main + TOC + 7 appendix = 19)
|
|
||||||
├── the-developer-experience.html ← Step 3: rendered HTML (committed)
|
|
||||||
├── the-developer-experience-talking-points.md ← Step 4: presenter cues (19 sections)
|
|
||||||
└── assets/
|
└── assets/
|
||||||
|
├── nova-sp-theme.css ← S&P Global Energy Marp theme (all slide chrome)
|
||||||
├── puppeteer-config.json ← no-sandbox config for mmdc
|
├── puppeteer-config.json ← no-sandbox config for mmdc
|
||||||
├── mmd/ ← mermaid source files (Step 2 input)
|
├── mmd/ ← mermaid source files (Step 2 input)
|
||||||
│ ├── sp-theme.json ← S&P Red/Black/White theme (mermaid-cli --configFile)
|
│ ├── sp-theme.json ← S&P Red/Black/White theme (mermaid-cli --configFile)
|
||||||
│ ├── platform-works-01-contract-driven.mmd
|
│ └── ... (per-slide .mmd files)
|
||||||
│ ├── platform-works-02-frictions.mmd
|
└── png/ ← rendered mermaid PNGs (committed, S&P-themed)
|
||||||
│ ├── platform-works-02-end-to-end-flow.mmd
|
|
||||||
│ ├── platform-works-03-north-star.mmd
|
|
||||||
│ ├── platform-works-03-scope-boundary.mmd
|
|
||||||
│ ├── platform-works-04-confidence-signal.mmd
|
|
||||||
│ ├── platform-works-05-attestation-flow.mmd
|
|
||||||
│ ├── platform-works-07-zero-trust.mmd
|
|
||||||
│ ├── developer-experience-01b-scope-boundary.mmd
|
|
||||||
│ ├── developer-experience-02-what-dev-does.mmd
|
|
||||||
│ ├── developer-experience-03-no-cloning.mmd
|
|
||||||
│ ├── developer-experience-04-promotion-journey.mmd
|
|
||||||
│ ├── developer-experience-05-catalog.mmd
|
|
||||||
│ ├── developer-experience-07-decommission.mmd
|
|
||||||
│ ├── developer-experience-08-semver.mmd
|
|
||||||
│ ├── platform-architecture.mmd ← shared high-level logical architecture (both decks)
|
|
||||||
│ └── road-to-north-star.mmd
|
|
||||||
└── png/ ← rendered PNGs (embedded in Marp)
|
|
||||||
├── platform-works-01-contract-driven.png
|
|
||||||
├── platform-works-02-frictions.png
|
|
||||||
├── platform-works-02-end-to-end-flow.png
|
|
||||||
├── platform-works-03-north-star.png
|
|
||||||
├── platform-works-03-scope-boundary.png
|
|
||||||
├── platform-works-04-confidence-signal.png
|
|
||||||
├── platform-works-05-attestation-flow.png
|
|
||||||
├── platform-works-07-zero-trust.png
|
|
||||||
├── developer-experience-01b-scope-boundary.png
|
|
||||||
├── developer-experience-02-what-dev-does.png
|
|
||||||
├── developer-experience-03-no-cloning.png
|
|
||||||
├── developer-experience-04-promotion-journey.png
|
|
||||||
├── developer-experience-05-catalog.png
|
|
||||||
├── developer-experience-07-decommission.png
|
|
||||||
├── developer-experience-08-semver.png
|
|
||||||
├── platform-architecture.png ← shared high-level logical architecture (both decks)
|
|
||||||
└── road-to-north-star.png
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Conventions
|
## Conventions
|
||||||
|
|
||||||
### Appendix structure
|
### Appendix structure
|
||||||
|
|
||||||
Each Marp deck has **11 main slides + an Appendix TOC + appendix slides**. The
|
Each Marp deck has **20 main slides + 1 appendix slide**. The main 20 are the
|
||||||
main 11 are the presentation; the appendix is for deep dives and Q&A backup.
|
presentation; the appendix is for Q&A backup. (v1.22 split slides 3 and 8
|
||||||
The platform-works deck has 8 appendix slides (A1–A8); the developer-experience
|
to relieve overflow, increasing the count from 18 to 20.)
|
||||||
deck has 7 appendix slides (A1–A7). Both include an Appendix TOC slide.
|
|
||||||
|
|
||||||
- **Main slides** (1-11): the story arc, high-impact, minimal text,
|
- **Main slides** (1-20): the story arc — Problem → Solution → Proof →
|
||||||
visual-heavy. These are what the audience sees during the talk.
|
Roadmap + Ask. These are what the audience sees during the talk.
|
||||||
- **Appendix slides** (TOC + A1..An): detail-heavy slides moved out of the
|
- **Appendix slide** (A1): the Metrics Glossary — detail-heavy reference for
|
||||||
main 10 to preserve the narrative flow. The appendix starts with a TOC
|
Q&A.
|
||||||
slide listing the contents, followed by detail slides and a glossary.
|
|
||||||
- **The Road to the North Star** is a required appendix slide in both decks
|
|
||||||
— a phased timeline from v1.0 demo to the North Star, annotated as
|
|
||||||
"proposed phasing, not formally planned."
|
|
||||||
- **The Glossary** is a required appendix slide in both decks — defines
|
|
||||||
acronyms (OIDC, ABAC, CMK, CMDB, RPO, HITL, VCS, NFR) for the audience.
|
|
||||||
|
|
||||||
### Maturity framing
|
### Honesty framing
|
||||||
|
|
||||||
Every capability claim in a deck is tagged with a `Planned` badge when the item is on the roadmap but not yet implemented:
|
Every capability claim in the deck is grounded, derived, or honestly
|
||||||
|
deferred with its blocking work named in plain language. Internal provenance
|
||||||
| Badge | Meaning |
|
(decision IDs, requirement IDs, internal file paths) is kept out of the
|
||||||
|---|---|
|
audience-facing slides — those live in the `.ciagent/` files only. When in
|
||||||
| `Planned` | On the roadmap, not yet implemented |
|
doubt, check `.ciagent/ROADMAP.md` and the milestone status in
|
||||||
|
`.ciagent/PROJECT.md`.
|
||||||
This is non-negotiable for a leadership audience: never present a roadmap
|
|
||||||
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`.
|
|
||||||
|
|
||||||
### Audience
|
### Audience
|
||||||
|
|
||||||
@@ -234,8 +154,10 @@ Head of Infrastructure, Head of DevOps. The framing rules:
|
|||||||
"composition."
|
"composition."
|
||||||
- **Selling points forward.** Each slide leads with the leadership-relevant
|
- **Selling points forward.** Each slide leads with the leadership-relevant
|
||||||
outcome; the mechanism follows.
|
outcome; the mechanism follows.
|
||||||
- **Zero-trust, security, observability, auditability, DX, citizen
|
- **Security, remediation velocity, reliability, lead time, observability,
|
||||||
developer** are the themes — not implementation details.
|
citizen developer** are the themes — not implementation details.
|
||||||
|
- **"Infrastructure operations become visible"** is the recurring theme across
|
||||||
|
the deck.
|
||||||
|
|
||||||
### Diagrams
|
### Diagrams
|
||||||
|
|
||||||
@@ -245,8 +167,7 @@ style (renders on GitHub/Pages). For the Marp deck (Step 2):
|
|||||||
1. Extract the mermaid block into `assets/mmd/<deck>-<slide>-<name>.mmd`.
|
1. Extract the mermaid block into `assets/mmd/<deck>-<slide>-<name>.mmd`.
|
||||||
2. Use **horizontal layouts** (`flowchart LR`) or **subgraph row-wrapping**
|
2. Use **horizontal layouts** (`flowchart LR`) or **subgraph row-wrapping**
|
||||||
for wide diagrams so the PNG fits a 16:9 slide without shrinking to
|
for wide diagrams so the PNG fits a 16:9 slide without shrinking to
|
||||||
illegibility. A 9-node sequential `flowchart TD` renders as a tall thin
|
illegibility.
|
||||||
strip — restructure it as 2-row subgraphs or `flowchart LR`.
|
|
||||||
3. Render with a 2x scale factor and transparent background for crisp slides.
|
3. Render with a 2x scale factor and transparent background for crisp slides.
|
||||||
4. Embed with `` (or `h:320` for tall images).
|
4. Embed with `` (or `h:320` for tall images).
|
||||||
|
|
||||||
@@ -274,42 +195,16 @@ for f in mmd/*.mmd; do
|
|||||||
done
|
done
|
||||||
```
|
```
|
||||||
|
|
||||||
The `puppeteer-config.json` passes `--no-sandbox` to the headless browser
|
### Render a Marp deck to HTML + PPTX (committed artifacts)
|
||||||
(required when running as root in this environment). The `--configFile
|
|
||||||
mmd/sp-theme.json` applies the S&P Global Red/Black/White theme (dark
|
|
||||||
`#1B1B1B` accent nodes with `#D6002A` red borders, white supporting nodes,
|
|
||||||
`#F0F0F0` subgraph backgrounds). Each `.mmd` file also carries the same
|
|
||||||
theme inline via a `%%{init:...}%%` block so it renders correctly even
|
|
||||||
without the `--configFile` flag.
|
|
||||||
|
|
||||||
### Export a Marp deck to HTML (committed to repo)
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
bash scripts/render_slides.sh nova-autonomous-cloud-delivery
|
||||||
npx --yes @marp-team/marp-cli@latest --allow-local-files \
|
|
||||||
docs/presentations/<deck-name>-marp.md \
|
|
||||||
-o docs/presentations/<deck-name>.html
|
|
||||||
```
|
```
|
||||||
|
|
||||||
HTML export inlines images as base64 data URIs. The `--allow-local-files`
|
This renders all mermaid PNGs, the HTML, and the PPTX, and stages them for
|
||||||
flag is needed when the Marp deck references local PNG assets (like the
|
commit. The `--allow-local-files` flag is required so local PNG diagrams are
|
||||||
diagram images in `assets/png/`). The resulting HTML is self-contained.
|
embedded. Both HTML and PPTX are committed to the repo; the PPTX is also
|
||||||
|
attached to the phase's release.
|
||||||
**The HTML files are committed artifacts** — re-render and re-commit whenever
|
|
||||||
the Marp source changes.
|
|
||||||
|
|
||||||
### Export a Marp deck to PPTX (uploaded to Gitea release)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
|
||||||
npx --yes @marp-team/marp-cli@latest --allow-local-files \
|
|
||||||
docs/presentations/<deck-name>-marp.md \
|
|
||||||
-o <output-path>.pptx
|
|
||||||
```
|
|
||||||
|
|
||||||
`--allow-local-files` is **required** for PPTX so local PNG diagrams are
|
|
||||||
embedded in the file. PPTX files are not committed to git — upload them as
|
|
||||||
attachments to the Gitea release.
|
|
||||||
|
|
||||||
## Adding a new presentation
|
## Adding a new presentation
|
||||||
|
|
||||||
@@ -319,16 +214,14 @@ attachments to the Gitea release.
|
|||||||
2. **Extract any mermaid diagrams** into `assets/mmd/<deck-name>-<slide>-<name>.mmd`
|
2. **Extract any mermaid diagrams** into `assets/mmd/<deck-name>-<slide>-<name>.mmd`
|
||||||
and render them to `assets/png/` (command above).
|
and render them to `assets/png/` (command above).
|
||||||
3. **Synthesize the Marp deck** as `<deck-name>-marp.md` with frontmatter,
|
3. **Synthesize the Marp deck** as `<deck-name>-marp.md` with frontmatter,
|
||||||
no speaker notes, embedded PNGs, and maturity badges.
|
no speaker notes, embedded PNGs, and no badges.
|
||||||
4. **Render to HTML** with `--allow-local-files` and commit the HTML to
|
4. **Render to HTML + PPTX** via `scripts/render_slides.sh <deck-name>` and
|
||||||
`docs/presentations/<deck-name>.html`.
|
commit both to `docs/presentations/`.
|
||||||
5. **Render to PPTX** with `--allow-local-files` and upload to the Gitea
|
5. **Distill the talking points** as `<deck-name>-talking-points.md` — one
|
||||||
release (do not commit PPTX to git).
|
|
||||||
6. **Distill the talking points** as `<deck-name>-talking-points.md` — one
|
|
||||||
section per Marp slide, 3-6 talking point bullets + key takeaway, content
|
section per Marp slide, 3-6 talking point bullets + key takeaway, content
|
||||||
distilled from the source markdown (Step 1), indexed by the Marp deck
|
distilled from the source markdown (Step 1), indexed by the Marp deck
|
||||||
(Step 2) slide structure.
|
(Step 2) slide structure.
|
||||||
7. **Verify** the PPTX slide count and that media files are embedded:
|
6. **Verify** the PPTX slide count and that media files are embedded:
|
||||||
```bash
|
```bash
|
||||||
python3 -c "
|
python3 -c "
|
||||||
import zipfile, re
|
import zipfile, re
|
||||||
@@ -341,7 +234,16 @@ attachments to the Gitea release.
|
|||||||
|
|
||||||
## Current decks
|
## Current decks
|
||||||
|
|
||||||
| Deck | Source of truth (Step 1) | Marp deck (Step 2) | Rendered HTML (Step 3) | Talking points (Step 4) | Slides | Audience |
|
| Deck | Source of truth (Step 1) | Marp deck (Step 2) | Rendered HTML + PPTX (Step 3) | Talking points (Step 4) | Slides | Audience |
|
||||||
|---|---|---|---|---|---|---|
|
|---|---|---|---|---|---|---|
|
||||||
| How the Platform Works | `how-the-platform-works.md` | `how-the-platform-works-marp.md` | `how-the-platform-works.html` | `how-the-platform-works-talking-points.md` | 11 main + TOC + 8 appendix (20) | CTO, Head of Cloud, Head of Infra, Head of DevOps |
|
| Nova — The Autonomous Cloud Delivery Platform | `nova-autonomous-cloud-delivery.md` | `nova-autonomous-cloud-delivery-marp.md` | `nova-autonomous-cloud-delivery.html` + `.pptx` (committed + release-attached) | `nova-autonomous-cloud-delivery-talking-points.md` | 20 main + 1 appendix (21) | CTO, Head of Cloud, Head of Infra, Head of DevOps |
|
||||||
| The Developer Experience | `the-developer-experience.md` | `the-developer-experience-marp.md` | `the-developer-experience.html` | `the-developer-experience-talking-points.md` | 11 main + TOC + 7 appendix (19) | CTO, Head of Cloud, Head of Infra, Head of DevOps |
|
|
||||||
|
> **v1.21:** the deck was renamed from "No-Humans Infrastructure Platform"
|
||||||
|
> to "Autonomous Cloud Delivery Platform" (professional framing; conveys
|
||||||
|
> autonomy without the provocative wording). The narrative restructured to
|
||||||
|
> a 4-beat arc (Problem → Solution → Proof → Roadmap + Ask). Internal
|
||||||
|
> provenance (decision IDs, requirement IDs, file paths) removed from
|
||||||
|
> audience-facing slides. Maturity badges removed. The RACI matrix expanded
|
||||||
|
> to four roles (Quality Engineering + SRE). The Atelier slide split into
|
||||||
|
> two. The pipeline hardened: Checkov on static code before the plan;
|
||||||
|
> Wiz-or-Checkov on the plan (never both).
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1B1B1B", "primaryBorderColor": "#D6002A", "primaryTextColor": "#fff", "secondaryColor": "#fff", "secondaryBorderColor": "#D6002A", "secondaryTextColor": "#1B1B1B", "tertiaryColor": "#F0F0F0", "clusterBkg": "#F0F0F0", "lineColor": "#1B1B1B", "fontFamily": "\"Akkurat Pro\", \"Helvetica Neue\", \"Arial\", sans-serif"}}}%%
|
||||||
|
|
||||||
|
flowchart TB
|
||||||
|
A["Contract → Resolver → Adapter"] --> D["Checkov (static code)"]
|
||||||
|
D --> E["Terraform plan"]
|
||||||
|
E --> F["Wiz (on plan) → Confidence signal → Stage gate"]
|
||||||
|
F --> I["Apply → Evidence + Ledger"]
|
||||||
|
classDef accent fill:#1B1B1B,color:#fff,stroke:#D6002A,stroke-width:2px
|
||||||
|
classDef supporting fill:#fff,color:#1B1B1B,stroke:#D6002A,stroke-width:1px
|
||||||
|
class D,E,F accent
|
||||||
|
class A,I supporting
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1B1B1B", "primaryBorderColor": "#D6002A", "primaryTextColor": "#fff", "secondaryColor": "#fff", "secondaryBorderColor": "#D6002A", "secondaryTextColor": "#1B1B1B", "tertiaryColor": "#F0F0F0", "clusterBkg": "#F0F0F0", "lineColor": "#1B1B1B", "fontFamily": "\"Akkurat Pro\", \"Helvetica Neue\", \"Arial\", sans-serif"}}}%%
|
||||||
|
|
||||||
|
flowchart TB
|
||||||
|
A["Platform<br/>components"] --> B["CloudEvents<br/>envelope"]
|
||||||
|
B --> C["Event log"]
|
||||||
|
B --> D["Decision<br/>ledger"]
|
||||||
|
B --> E["Run records"]
|
||||||
|
C --> F["Collector"]
|
||||||
|
D --> F
|
||||||
|
E --> F
|
||||||
|
F --> G["Cold store"]
|
||||||
|
G --> H["PowerBI<br/>views"]
|
||||||
|
H --> I["Live ops<br/>dashboard"]
|
||||||
|
classDef accent fill:#1B1B1B,color:#fff,stroke:#D6002A,stroke-width:2px
|
||||||
|
classDef supporting fill:#fff,color:#1B1B1B,stroke:#D6002A,stroke-width:1px
|
||||||
|
class B,F,G,H,I accent
|
||||||
|
class A,C,D,E supporting
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
/* @theme nova-sp */
|
||||||
|
/* Nova — S&P Global Energy theme for Marp decks.
|
||||||
|
*
|
||||||
|
* Palette: S&P Red (#D6002A), Black (#1B1B1B), White (#FFFFFF), Grey (#F0F0F0).
|
||||||
|
* Font: Akkurat Pro (fallback Helvetica Neue / Arial).
|
||||||
|
*
|
||||||
|
* This theme is a STANDALONE stylesheet (applied via `marp --theme
|
||||||
|
* nova-sp-theme.css`). It does NOT `@import "default"` because Marp's
|
||||||
|
* default theme applies `padding: 56px 64px` (which does not reserve
|
||||||
|
* header/footer space) and other base styles (font, color, list spacing)
|
||||||
|
* that would conflict with the S&P palette. Instead, this theme sets
|
||||||
|
* the padding explicitly: 48px top (reserves header space), 40px bottom
|
||||||
|
* (reserves footer space), 56px sides. This gives precise control over
|
||||||
|
* the padding budget. (GRILL revision 2 — @import rejection documented.)
|
||||||
|
*
|
||||||
|
* v1.22 (REQ-254,255,256): added section padding + overflow handling,
|
||||||
|
* aspect-ratio-aware image rules, title-slide chrome suppression,
|
||||||
|
* paragraph/list/table spacing tightening.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--sp-red: #D6002A;
|
||||||
|
--sp-black: #1B1B1B;
|
||||||
|
--sp-white: #FFFFFF;
|
||||||
|
--sp-grey: #F0F0F0;
|
||||||
|
--sp-dark-grey: #2E2E2E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base section — padding reserves header (top) + footer (bottom) space.
|
||||||
|
* REQ-254: zero padding was the root cause of "out of whack" layout.
|
||||||
|
* 48px top reserves header chrome; 40px bottom reserves footer chrome;
|
||||||
|
* 56px sides give breathing room. */
|
||||||
|
section {
|
||||||
|
font-family: "Akkurat Pro", "Helvetica Neue", "Arial", sans-serif;
|
||||||
|
font-size: 22px;
|
||||||
|
color: var(--sp-black);
|
||||||
|
background: var(--sp-white);
|
||||||
|
padding: 48px 56px 40px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Headings — S&P Red */
|
||||||
|
h1 { color: var(--sp-red); font-size: 34px; margin-bottom: 0.3em; }
|
||||||
|
h2 { color: var(--sp-red); font-size: 26px; margin-bottom: 0.2em; }
|
||||||
|
h3 { color: var(--sp-red); font-size: 22px; margin-bottom: 0.2em; }
|
||||||
|
h4 { color: var(--sp-dark-grey); font-size: 20px; margin-bottom: 0.15em; }
|
||||||
|
|
||||||
|
/* REQ-256: tighten h2 + lead-paragraph spacing (the deck's recurring
|
||||||
|
* `## Slide N — Title` + `**bold lead**` pattern). Default <p> margins
|
||||||
|
* waste ~44px per slide; this reclaims ~22px. */
|
||||||
|
section h2 + p { margin-top: 0.2em; }
|
||||||
|
section p { margin: 0.4em 0; }
|
||||||
|
|
||||||
|
/* Title slides — black background, red top border */
|
||||||
|
section.title {
|
||||||
|
background: var(--sp-black);
|
||||||
|
color: var(--sp-white);
|
||||||
|
border-top: 8px solid var(--sp-red);
|
||||||
|
}
|
||||||
|
section.title h1 { color: var(--sp-white); }
|
||||||
|
section.title h2 { color: var(--sp-white); }
|
||||||
|
|
||||||
|
/* REQ-256: suppress header/footer chrome on title slides. The
|
||||||
|
* `<!-- _class: title -->` + `<!-- _paginate: false -->` directives
|
||||||
|
* only suppress the page number, not the chrome. This prevents the
|
||||||
|
* header/footer from colliding with title/appendix content. */
|
||||||
|
section.title header, section.title footer { display: none; }
|
||||||
|
|
||||||
|
/* Tables — grey header with red underline, explicit white body for readability on any background */
|
||||||
|
table { font-size: 18px; width: 100%; border-collapse: collapse; background: var(--sp-white); }
|
||||||
|
th { background: var(--sp-grey); border-bottom: 2px solid var(--sp-red); padding: 4px 8px; text-align: left; }
|
||||||
|
td { background: var(--sp-white); color: var(--sp-black); border-bottom: 1px solid var(--sp-grey); padding: 4px 8px; }
|
||||||
|
/* Ensure tables on dark/title slides remain readable: white card with a subtle border */
|
||||||
|
section.title table, section table { background: var(--sp-white); }
|
||||||
|
section.title td, section td { background: var(--sp-white); color: var(--sp-black); }
|
||||||
|
section.title th, section th { background: var(--sp-grey); color: var(--sp-black); }
|
||||||
|
|
||||||
|
/* REQ-256: dense tables (≥8 rows) use tighter cell padding so 10-13 row
|
||||||
|
* tables (slides 8, 12, A1) fit. Apply via `table.dense` class in the
|
||||||
|
* marp deck. */
|
||||||
|
table.dense td, table.dense th { padding: 4px 8px; }
|
||||||
|
table.dense { font-size: 16px; }
|
||||||
|
|
||||||
|
/* Blockquotes — red left border */
|
||||||
|
blockquote { border-left: 4px solid var(--sp-red); color: var(--sp-dark-grey); font-size: 20px; padding-left: 12px; }
|
||||||
|
|
||||||
|
/* Code — dark background */
|
||||||
|
pre { background: var(--sp-black); color: var(--sp-white); border-radius: 4px; padding: 12px; font-size: 16px; }
|
||||||
|
code { background: var(--sp-grey); color: var(--sp-black); border-radius: 2px; padding: 1px 4px; font-size: 18px; }
|
||||||
|
pre code { background: transparent; color: inherit; }
|
||||||
|
|
||||||
|
/* REQ-255: aspect-ratio-aware image rules. The blunt `max-height: 320px`
|
||||||
|
* broke `w:` directives on tall images (slide 9) and did nothing for
|
||||||
|
* ultra-wide images (slide 6). The new rule uses `object-fit: contain`
|
||||||
|
* and `max-width: 100%` so images scale within the content area without
|
||||||
|
* ignoring explicit `w:`/`h:` directives. */
|
||||||
|
img { display: block; margin: 0 auto; max-width: 100%; max-height: 380px; object-fit: contain; }
|
||||||
|
/* Wide diagrams (ultra-wide aspect): tighter max-height so they don't
|
||||||
|
* render as a thin strip. Apply via `![w:1000 class:wide]` — or rely on
|
||||||
|
* the default max-height which is already tighter. */
|
||||||
|
img.wide { max-height: 280px; }
|
||||||
|
/* Tall diagrams: more vertical room. Apply via `![h:480 class:tall]`. */
|
||||||
|
img.tall { max-height: 480px; }
|
||||||
|
|
||||||
|
/* Header/footer — subtle grey */
|
||||||
|
header { color: var(--sp-dark-grey); border-bottom: 1px solid var(--sp-grey); }
|
||||||
|
footer { color: var(--sp-dark-grey); border-top: 1px solid var(--sp-grey); }
|
||||||
|
|
||||||
|
/* Maturity badges */
|
||||||
|
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 14px; font-weight: 600; }
|
||||||
|
.badge.today { background: #c6f6d5; color: #22543d; }
|
||||||
|
.badge.planned { background: #fef3c7; color: #78350f; }
|
||||||
|
|
||||||
|
/* Pagination — S&P Red progress bar */
|
||||||
|
.bespoke-progress-parent { background: var(--sp-grey); }
|
||||||
|
.bespoke-progress-bar { background: var(--sp-red) !important; }
|
||||||
|
|
||||||
|
/* Lists — tighter. REQ-256: add ol styling (match ul). */
|
||||||
|
ul { margin-top: 0.3em; }
|
||||||
|
ol { margin-top: 0.3em; }
|
||||||
|
li { margin-bottom: 0.2em; }
|
||||||
|
|
||||||
|
/* Strong — S&P Red for emphasis in lead lines */
|
||||||
|
strong { color: var(--sp-red); }
|
||||||
|
|
||||||
|
/* REQ-256: PPTX export fidelity — no scrollbars in exported slides.
|
||||||
|
* The `overflow: auto` above is an authoring-time signal; in print/PPTX
|
||||||
|
* we clamp to `hidden` so the exported slide is clean. */
|
||||||
|
@media print {
|
||||||
|
section { overflow: hidden; }
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
@@ -1,334 +0,0 @@
|
|||||||
---
|
|
||||||
marp: true
|
|
||||||
theme: default
|
|
||||||
paginate: true
|
|
||||||
size: 16x9
|
|
||||||
header: "How The Platform Works"
|
|
||||||
footer: "Internal"
|
|
||||||
style: |
|
|
||||||
section {
|
|
||||||
font-family: "Akkurat Pro", "Helvetica Neue", "Arial", sans-serif;
|
|
||||||
font-size: 26px;
|
|
||||||
color: #1B1B1B;
|
|
||||||
}
|
|
||||||
h1 { color: #D6002A; font-size: 40px; margin-bottom: 0.3em; }
|
|
||||||
h2 { color: #D6002A; font-size: 32px; margin-bottom: 0.2em; }
|
|
||||||
section.title { background: #1B1B1B; color: #fff; border-top: 8px solid #D6002A; }
|
|
||||||
section.title h1 { color: #fff; }
|
|
||||||
table { font-size: 22px; width: 100%; }
|
|
||||||
th { background: #F0F0F0; }
|
|
||||||
blockquote { border-left: 4px solid #D6002A; color: #2E2E2E; font-size: 24px; }
|
|
||||||
img { display: block; margin: 0 auto; max-height: 300px; }
|
|
||||||
.badge {
|
|
||||||
display: inline-block; padding: 2px 8px; border-radius: 4px;
|
|
||||||
font-size: 16px; font-weight: 600;
|
|
||||||
}
|
|
||||||
.planned { background: #fef3c7; color: #78350f; }
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# How The Platform Works
|
|
||||||
|
|
||||||
### Nova — The New Dawn of DevSecOps
|
|
||||||
|
|
||||||
<style>
|
|
||||||
section.title h1 { font-size: 44px; margin-bottom: 0.1em; }
|
|
||||||
section.title h3 { color: #F0F0F0; font-weight: 400; font-size: 22px; margin-top: 0; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Four frictions slow every team
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Cognitive load** — services inconsistent in security and observability
|
|
||||||
- **Operational work** — manual promotion scaling with the system
|
|
||||||
- **Red tape** — tickets and handoffs scaling with the organization
|
|
||||||
- **Scalability** — throughput without scaling platform engineers
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# The platform at a glance
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Consumer surfaces** — technical dev or citizen dev; both produce a contract
|
|
||||||
- **Central pipeline** — fixed stages, identical for every deployment: validate → resolve → security → plan → policy → confidence → evidence → apply
|
|
||||||
- **Module catalog + engine adapter** — security-reviewed blocks; the adapter is the only engine-specific code (Terraform today)
|
|
||||||
- **HITL gates + evidence stream** — human attestation for qa/prod/dr; every deployment writes a hash-chained event (RPO = 0)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Declare intent; the platform delivers safe production
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- A merged change progresses **without a ticket or thread**
|
|
||||||
- A **non-technical consumer** ships by declaring intent
|
|
||||||
- Every production change is **traceable to a human attestation**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Nova owns infrastructure, not your app
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Upstream is anything** — IDE, agentic SDLC, or vibe coding
|
|
||||||
- **Nova is infrastructure only** — provisions and governs AWS resources
|
|
||||||
- **Not a general-purpose AI** — autonomy is narrow, policy-bounded
|
|
||||||
- **Not a permissive highway** — no escape hatches
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# One YAML file. The platform owns everything else.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Module** — pre-built, security-reviewed building blocks
|
|
||||||
- **Environment** — `dev`, `qa`, `prod`, `dr`; bar rises with sensitivity
|
|
||||||
- **Inputs** — cpu, memory, port, desired_count
|
|
||||||
- Consumer provides **no AWS account, no VPC, no state backend**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Same stages, same checks, every deployment
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Security and policy checks run *before* any infra is created**
|
|
||||||
- **Every stage produces a record** — no "unchecked" path
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# No long-lived credentials. Blast radius contained.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **OIDC federation** — short-lived token per job, no stored credential <span class="badge planned">Planned: all runners</span>
|
|
||||||
- **ABAC, not role-based** — repo identity + resource tags scope every action
|
|
||||||
- **A consumer can only touch its own tagged resources.** One consumer can never affect another.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Safety is a measurable signal, not a black box
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Six weighted inputs** — manually tuned, auditable per-input breakdown
|
|
||||||
|
|
||||||
| Environment | Threshold | Attester |
|
|
||||||
|---|---|---|
|
|
||||||
| dev | ≥ 0.50 | No one — autonomous |
|
|
||||||
| qa | ≥ 0.75 | QA <span class="badge planned">Planned</span> |
|
|
||||||
| prod | ≥ 0.90 | SRE <span class="badge planned">Planned</span> |
|
|
||||||
|
|
||||||
- **A single critical finding hard-blocks** — not averaged away
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Every change traceable to a human attestation
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Dev is fully autonomous** — confidence signal is the only gate
|
|
||||||
- **qa, prod, dr require human attestation** — contract + plan + evidence <span class="badge planned">Planned</span>
|
|
||||||
- **Separation of duties** — QA approver ≠ prod approver; platform **blocks on a match** <span class="badge planned">Planned</span>
|
|
||||||
- **Hash-chained evidence event** — tampering breaks the chain. **RPO = 0**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# The vision realized
|
|
||||||
|
|
||||||
- **Velocity without sacrificing safety** — speed in ergonomics, safety in unbypassable gates
|
|
||||||
- **Security, observability, compliance as platform defaults** — not per-team effort
|
|
||||||
- **Auditability as a byproduct, not a project** — every change traceable to a human attestation
|
|
||||||
- **Blast radius contained by design** — OIDC + ABAC, only your own tagged resources
|
|
||||||
- **Infrastructure as a utility, not a craft** — consume, don't maintain
|
|
||||||
- **A path to the citizen developer** — same envelope, senior engineer or non-technical
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# Appendix
|
|
||||||
|
|
||||||
**Contents:**
|
|
||||||
|
|
||||||
1. Platform-Managed Environments (detail)
|
|
||||||
2. Observability Built In (detail)
|
|
||||||
3. Security by Construction (the full defaults inventory)
|
|
||||||
4. The Road to the North Star (phased roadmap)
|
|
||||||
5. Testing vs. Planned (full inventory)
|
|
||||||
6. Glossary
|
|
||||||
7. Operating Model & Cost (real AWS spend + pre-mortem)
|
|
||||||
8. Verified by Construction (the v1.11 architecture)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A1 — Platform-Managed Environments
|
|
||||||
|
|
||||||
A consumer provides **no AWS account, no VPC, no subnet, no state backend, no runner key.** The platform owns the blast radius.
|
|
||||||
|
|
||||||
A named environment is a platform-owned bundle of:
|
|
||||||
|
|
||||||
- An AWS account (or a scoped partition of one)
|
|
||||||
- A network (VPC + subnets)
|
|
||||||
- A state backend (S3 + DynamoDB for state + locking)
|
|
||||||
- An IAM role surfaced via ABAC, scoped to the consumer's identity and resource tags
|
|
||||||
|
|
||||||
The consumer selects an environment **by name** in their contract. The platform resolves it 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 planned">Self-service: planned</span>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A2 — Observability Built In
|
|
||||||
|
|
||||||
Monitoring is **a platform default, not a per-team project.**
|
|
||||||
|
|
||||||
- **Uptime monitoring deployed automatically with every stack** — separate state, feature flag to disable
|
|
||||||
- **Monitored endpoints passed from the deployment's own outputs** — no manual endpoint registration
|
|
||||||
- **Alert channels:** Microsoft Teams webhook, email, SMS, and GitHub issues
|
|
||||||
- **The uptime URL is published to the developer** via a PR comment
|
|
||||||
- **Roadmap:** deeper observability bootstrap (dashboards, runbooks, on-call bindings) <span class="badge planned">Planned</span>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A3 — Security by Construction
|
|
||||||
|
|
||||||
Security defaults that **do not require a team to opt in.** Checks run on **every** deployment, normalized to a single schema.
|
|
||||||
|
|
||||||
- **Policy checks** (Checkov, Wiz, Kyverno) — secrets, public ingress, IAM wildcards, **required tagging** — all run *before* infra is created
|
|
||||||
- **Encryption on every resource** — at-rest on by default; per-stack CMKs with 90-day rotation, **no shared keys across stacks**
|
|
||||||
- **Deletion protection on by default** — `prevent_destroy` on unless explicitly disabled via a documented flag
|
|
||||||
- **Safe decommission** — a 2-step pipeline with **two SRE attestation gates** and a **change-request validated against the CMDB**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# A4 — The Road to the North Star
|
|
||||||
|
|
||||||
*Proposed phasing — not formally planned.*
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# A5 — Testing vs. Planned (Full Inventory)
|
|
||||||
|
|
||||||
<style>
|
|
||||||
section { font-size: 18px; }
|
|
||||||
td { font-size: 16px; vertical-align: top; }
|
|
||||||
ul { margin: 0; padding-left: 1.2em; }
|
|
||||||
li { margin-bottom: 2px; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
**22/22 Verified** — the v1.11 lifecycle pipeline ran apply→modify→destroy against live AWS for every L1 + L2 module, then tore down to zero-cost (D-096). The v1.10 "6 deploy-unverified (IAM drift)" status is closed (CAP-013 fixed in P67).
|
|
||||||
|
|
||||||
<table style="width: 100%; border: none;">
|
|
||||||
<tr>
|
|
||||||
<td style="width: 52%; border: none; padding-right: 12px;">
|
|
||||||
|
|
||||||
**Testing** (22/22 Verified — works internally, dev pilot-ready)
|
|
||||||
|
|
||||||
- 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
|
|
||||||
- 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
|
|
||||||
- Engine-agnostic core (1 adapter: Terraform) + VCS-agnostic ingestion
|
|
||||||
|
|
||||||
</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)
|
|
||||||
- Pattern recognition compounds value over time
|
|
||||||
- Additional engine adapters (OpenTofu, Pulumi, Kubernetes CRDs)
|
|
||||||
- Deeper observability bootstrap (dashboards, runbooks, on-call)
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A6 — Glossary
|
|
||||||
|
|
||||||
| Term | Meaning |
|
|
||||||
|---|---|
|
|
||||||
| **OIDC** | OpenID Connect — federation protocol for short-lived tokens, no long-lived credentials |
|
|
||||||
| **ABAC** | Attribute-Based Access Control — access scoped by resource tags + repo identity, not roles |
|
|
||||||
| **CMK** | Customer-Managed Key — per-stack encryption key, 90-day rotation, no shared keys |
|
|
||||||
| **CMDB** | Configuration Management Database — validates change requests for decommission |
|
|
||||||
| **RPO** | Recovery Point Objective — RPO = 0 means evidence is written synchronously, no data loss |
|
|
||||||
| **HITL** | Human-in-the-Loop — deliberate human attestation required for qa/prod/dr environments |
|
|
||||||
| **VCS** | Version Control System — the git hosting platform (GitHub, Gitea, GitLab) |
|
|
||||||
| **NFR** | Non-Functional Requirement — encryption, tagging, observability standards |
|
|
||||||
| **IR** | Intermediate Representation — the engine-agnostic stack definition between contract and Terraform |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A7 — Operating Model & Cost
|
|
||||||
|
|
||||||
<style>
|
|
||||||
section { font-size: 20px; }
|
|
||||||
table { font-size: 18px; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
Nova runs at **zero cloud cost** for day-to-day development. AWS spend was measured via Cost Explorer (`COST.md`, 2026-07-28):
|
|
||||||
|
|
||||||
| Metric | Value |
|
|
||||||
|--------|-------|
|
|
||||||
| Total spend (8 days) | **$0.001883** |
|
|
||||||
| Daily average | $0.000235 |
|
|
||||||
| Projected monthly | ~$0.007 |
|
|
||||||
| Peak day | 2026-07-27 ($0.000867) |
|
|
||||||
|
|
||||||
- **S3 dominates** (98.8%, terraform state bucket) — no compute ran because v1.0→v1.10 was plan-only for IAM-gated capabilities
|
|
||||||
- **Local emulators are the primary tier** — the full pipeline runs in-process, no AWS credentials
|
|
||||||
- **Live-AWS verification is milestone-scoped, then torn down.** The pipeline now **defaults to plan-only** on every PR; `NOVA_LIFECYCLE_MODE=full` overrides to apply→destroy for milestone verification (REQ-134, v1.12).
|
|
||||||
- **Cost drivers** are spike-scoped: Terraform plan reads (free), S3 state storage (cents), DynamoDB outbox (cents). Any spike > $1/day is an anomaly.
|
|
||||||
|
|
||||||
**Pre-mortem (`PRE_MORTEM.md`):** the v1.10 decay incident (diff-scoped VERIFY missed 7 adapter defects) is the root pattern: *a claim outruns the verification that backs it.* Four forward failure modes + structural mitigations (regression-tested IAM baseline, mandatory teardown, verified-only deck claims, honest scope).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# A8 — Verified by Construction
|
|
||||||
|
|
||||||
<style>
|
|
||||||
section { font-size: 20px; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
Two architectural pillars make "Verified" a structural property, not a claim:
|
|
||||||
|
|
||||||
- **The stateless adapter (918 → ~80 lines).** The Terraform adapter was a 918-line monolith with 3 constant tables and 39 type-specific branches. It is now a ~80-line **stateless assembler**: it owns no module content — no resource shape, no nested HCL blocks, no defaults. Each L1 module ships a real `terraform/` module dir owning its shape, nested blocks, and defaults. The adapter reads the registry and emits `module "x" { source = ... }` blocks. A new module is a new terraform dir, not a code change. *(The v1.12 P67 fix closed a dedup defect for multi-resource L1s — ecs-service, alb; CAP-013 now Verified.)*
|
|
||||||
- **Pipeline-driven lifecycle testing.** A `modules-lifecycle` pipeline matrix-runs each L1 and L2 module's `examples/{simple,complex}.yml` contracts through apply→modify→destroy against live AWS. **The "test" = the pipeline cell going green.** Defaults to **plan-only** on every PR (fast, no AWS mutation, no cost); `NOVA_LIFECYCLE_MODE=full` overrides to the real apply→destroy for milestone verification (REQ-134, v1.12). The regression gate (D-091) re-runs all 22 capabilities at milestone completion — **22/22 Verified** as of v1.12.
|
|
||||||
|
|
||||||
The v1.10 lesson is the negative space: a 918-line adapter with type-specific branches decayed silently. The ~80-line stateless adapter + the milestone regression gate are the structural fix.
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
# How The Platform Works — Talking Points
|
|
||||||
|
|
||||||
> **Companion to:** `how-the-platform-works-marp.md` (11 main + Appendix TOC + 8 appendix = 20 slides)
|
|
||||||
> **Content source:** `how-the-platform-works.md` (full source of truth with speaker notes)
|
|
||||||
> **Purpose:** Presenter-ready cues — 3-6 talking points per slide + the one key takeaway the audience should remember.
|
|
||||||
> **Audience:** Senior Leadership — CTO, Head of Cloud, Head of Infrastructure, Head of DevOps
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 1 — Title
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Brief introduction — this deck explains *how* the platform works internally, not the developer experience (that's the companion deck)
|
|
||||||
- Set the frame: the platform is not a CI/CD tool — it's the organizational lever for shipping safely at the pace the business demands
|
|
||||||
- Every "Testing" claim is Verified — 22/22 capabilities via the v1.11 lifecycle pipeline (see A8)
|
|
||||||
|
|
||||||
**Key takeaway:** The platform is the organizational lever for safe, fast shipping.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 2 — Four frictions slow every team
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Open with the cost of the status quo — every team running its own pipeline, Terraform, and review checklist pays a tax that doesn't differentiate the business
|
|
||||||
- The four frictions are categorically parallel: cognitive load, operational work, red tape, scalability
|
|
||||||
- The platform absorbs all four — that is the value proposition in one sentence
|
|
||||||
- Don't dwell here; this is the setup for the before/after contrast on the next slide
|
|
||||||
|
|
||||||
**Key takeaway:** Four frictions slow every team. The platform absorbs all four.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 3 — The platform at a glance
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- One-slide map of the whole platform — use it to orient the audience before diving into any single component
|
|
||||||
- The leadership-relevant beats: (1) two surfaces, one pipeline, one evidence stream — the convergence is the design; (2) the pipeline stages are fixed and identical for every consumer; (3) the engine adapter is the only engine-specific code, which makes the catalog and confidence model portable
|
|
||||||
- Don't walk every node — point to the boundaries and say "the rest of this deck zooms into each of these"
|
|
||||||
- The contract schema is the boundary between upstream and Nova; everything left of it is the consumer's, everything right of it is the platform's
|
|
||||||
|
|
||||||
**Key takeaway:** Two surfaces, one pipeline, one evidence stream. The rest of the deck zooms in.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 4 — Declare intent; the platform delivers safe production
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Land the before/after contrast: today's queue vs. Nova's autonomous flow
|
|
||||||
- The litmus test: if a platform engineer still has to touch a ticket for a dev→qa promotion, we haven't delivered the vision
|
|
||||||
- The North Star is one sentence: "declare intent → safe production deployment"
|
|
||||||
- A non-technical consumer ships by declaring intent — no workflow, no config file, no module
|
|
||||||
|
|
||||||
**Key takeaway:** Declare intent; the platform delivers safe production — autonomously, with a complete audit trail.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 5 — Nova owns infrastructure, not your app
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- The platform is deliberately scoped — it is not trying to be everything
|
|
||||||
- The sovereign boundary: 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
|
|
||||||
- Upstream is anything: IDE, agentic SDLC, or vibe coding — Nova doesn't care how the contract was produced
|
|
||||||
|
|
||||||
**Key takeaway:** Nova is infrastructure only. App build/test/deploy is upstream.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 6 — One YAML file. The platform owns everything else.
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Hold this slide — emphasize the asymmetry. The consumer's surface is intentionally tiny; the platform's surface is large and opinionated
|
|
||||||
- The contract names three things: module, environment, inputs — that's the entire consumer-facing interface to production
|
|
||||||
- The contract shows infrastructure inputs (cpu, memory, desired_count, port) — not a container image. The image is upstream; the platform governs infrastructure
|
|
||||||
- The consumer provides no AWS account, no VPC, no state backend — the platform owns the blast radius
|
|
||||||
|
|
||||||
**Key takeaway:** One YAML file. The platform owns everything else.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 7 — Same stages, same checks, every deployment
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Walk left to right once — don't dwell on internals; the point is the flow is fixed, opinionated, and identical for every consumer
|
|
||||||
- The two leadership-relevant beats: (1) checks before creation, (2) every stage is evidenced
|
|
||||||
- No team-specific pipelines, no tribal runbooks — the flow is the contract
|
|
||||||
- The confidence signal (Slide 9) is where the "safety is computed" story lands
|
|
||||||
|
|
||||||
**Key takeaway:** Same stages, same checks, every deployment. No "unchecked" path.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 8 — No long-lived credentials. Blast radius contained.
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- This is the slide for the Head of Cloud/Security — the key phrase is "blast radius contained to the consumer's own stack"
|
|
||||||
- Contrast with the common failure mode of shared CI roles that can touch any account resource
|
|
||||||
- OIDC federation: short-lived token per job, no credential stored in the consumer repo or runner secret
|
|
||||||
- ABAC, not role-based: repo identity + resource tags scope every action — a consumer can only touch its own tagged resources
|
|
||||||
- The static-key override exists for edge cases but is rotated daily on platform runners; it is never the default
|
|
||||||
|
|
||||||
**Key takeaway:** No long-lived credentials. A consumer can only touch its own tagged resources.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 9 — Safety is a measurable signal, not a black box
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- This is the bet that separates this platform from "yet another CI/CD tool" — reliance on operator instinct or tenure is not a substitute
|
|
||||||
- The signal is auditable; the thresholds are tunable by Infra & Ops + SRE jointly, and any override is itself a confidence-event in the audit stream
|
|
||||||
- Six weighted inputs: policy, validation, freshness, provenance, history, NFRs — manually tuned, auditable per-input breakdown
|
|
||||||
- If a consumer asks "why 0.62?", the platform answers with a per-input breakdown — not a black box
|
|
||||||
- A single critical finding hard-blocks — critical findings are not averaged away
|
|
||||||
|
|
||||||
**Key takeaway:** Safety is a measurable, explainable signal — not a black box.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 10 — Every change traceable to a human attestation
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- The "lower environments autonomous, higher environments attested" tenet resolves the classic "move fast vs. be safe" false dichotomy
|
|
||||||
- Be honest: the separation-of-duties *mechanism* is designed and the dev path is wired; qa/prod/dr wiring is on the roadmap
|
|
||||||
- The audit trail is a byproduct of deployment, not a project — every production change is traceable to a human attestation
|
|
||||||
- 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
|
|
||||||
- RPO = 0 — the evidence write is synchronous; a deployment is not acknowledged until the evidence event is durably recorded
|
|
||||||
|
|
||||||
**Key takeaway:** Every change is traceable to a human attestation and a tamper-evident evidence event.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 11 — The vision realized
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Close on the strategic frame — the platform is not "a CI/CD tool," it's the organizational lever for shipping safely at the pace the business demands
|
|
||||||
- Velocity without sacrificing safety: speed is in the ergonomics, safety is in the unbypassable gates
|
|
||||||
- Security, observability, compliance as platform defaults — not per-team effort, not post-hoc remediation
|
|
||||||
- A path to the citizen developer: the same safety envelope serves a senior engineer and a non-technical consumer
|
|
||||||
- Invite questions; the companion deck ("The Developer Experience") covers who uses the platform and how fast/safe they ship
|
|
||||||
|
|
||||||
**Key takeaway:** Ship safely at the pace the business demands, with the security and audit posture the regulators require.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix TOC — Appendix
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- These are deep-dive slides for follow-up questions — don't walk them in the main 15-minute talk
|
|
||||||
- Pull them up when an audience member wants detail on a specific topic
|
|
||||||
- The appendix is indexed to match the Marp deck's A1-A8 structure
|
|
||||||
|
|
||||||
**Key takeaway:** Deep dives available — pull the relevant appendix slide when asked.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A1 — Platform-Managed Environments
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- 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
|
|
||||||
- Self-service environment provisioning is planned
|
|
||||||
|
|
||||||
**Key takeaway:** The consumer never sees raw credentials. The platform owns the blast radius.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A2 — Observability Built In
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- The Head of DevOps cares about this — "you don't deploy a service and *then* remember to set up monitoring; the platform does it as part of the deploy"
|
|
||||||
- Uptime monitoring deployed automatically with every stack — separate state, feature flag to disable
|
|
||||||
- The feature flag means teams with existing monitoring (e.g. Datadog) can opt out cleanly
|
|
||||||
- Deeper observability bootstrap (dashboards, runbooks, on-call bindings) is on the roadmap
|
|
||||||
|
|
||||||
**Key takeaway:** Monitoring is a platform default, not a per-team project.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A3 — Security by Construction
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- The phrase to land is "secure by default, not secure by effort"
|
|
||||||
- The selling point is *normalization* — we can add a new security tool without changing the confidence model or the evidence stream
|
|
||||||
- For the Head of Security: tagging standards are enforced, not advisory — a missing `nova:owner` tag fails the check, not a warning
|
|
||||||
- The decommission flow is the counter-argument to "deletion protection makes cleanup impossible" — it's a deliberate, gated, two-approval path
|
|
||||||
|
|
||||||
**Key takeaway:** Secure by default, not secure by effort. Checks run before infra is created.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A4 — The Road to the North Star
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Be clear with leadership: this is a proposed phasing, not a formally committed plan
|
|
||||||
- The phases are sequenced by dependency, not by calendar — each phase's items are gated on the prior phase's maturity
|
|
||||||
- Phase 1 is now fully Verified (22/22) and torn down to zero-cost — it is no longer aspirational
|
|
||||||
- Invite questions on any phase boundary
|
|
||||||
|
|
||||||
**Key takeaway:** Proposed phasing, not formally planned. Phase 1 is Verified; Phase 4 is the North Star.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A5 — Testing vs. Planned (Full Inventory)
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Close on honesty — the platform delivers real, verifiable value today: 22/22 auto-verifiable capabilities Verified via the v1.11 lifecycle pipeline
|
|
||||||
- The roadmap is concrete, not aspirational hand-waving — 9 planned items, each with a defined milestone and a clear reason it isn't shipped yet (usually an upstream dependency, not an engineering gap)
|
|
||||||
- Emphasize: 0 consumer adoption today — "Testing" means it works internally and is dev pilot-ready, not that it's released
|
|
||||||
- The lifecycle pipeline defaults to plan-only on every PR; `NOVA_LIFECYCLE_MODE=full` overrides for milestone verification
|
|
||||||
|
|
||||||
**Key takeaway:** 22/22 Verified today. 9 planned, each with a clear milestone and reason.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A6 — Glossary
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Use this slide as a reference when the audience asks for term definitions
|
|
||||||
- Don't read it aloud — point to it as a takeaway reference
|
|
||||||
- All acronyms used in the deck are defined here
|
|
||||||
|
|
||||||
**Key takeaway:** Reference slide — don't read aloud.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A7 — Operating Model & Cost
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- The headline for the Head of Cloud / Finance: less than one cent over 8 days of active development; zero BAU cloud spend
|
|
||||||
- The lifecycle pipeline defaults to plan-only so the PR-time cost is zero
|
|
||||||
- The pre-mortem is the credibility slide — we already asked "how does this fail?" and the mitigations are structural
|
|
||||||
- The v1.10 decay incident is disclosed honestly, not hidden — that disclosure IS the mitigation
|
|
||||||
|
|
||||||
**Key takeaway:** Zero BAU cloud cost. Pre-mortemed failure modes with structural mitigations.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A8 — Verified by Construction
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- This is the deep-dive slide for the Head of Engineering / Architecture — the two pillars answer "how do you keep the decks honest?"
|
|
||||||
- The adapter is simple enough to reason about (a stateless assembler); the lifecycle pipeline is the automated verification that backs every "Testing" claim
|
|
||||||
- The v1.10 lesson is the negative space: a 918-line adapter with type-specific branches decayed silently because the VERIFY gate was diff-scoped
|
|
||||||
- The ~80-line stateless adapter + the milestone regression gate are the structural fix
|
|
||||||
- The plan-only default (v1.12) means verification runs on every PR at zero cost, with the full apply→destroy gated behind a CI variable override
|
|
||||||
|
|
||||||
**Key takeaway:** "Verified" is a structural property, not a claim — the stateless adapter + lifecycle pipeline make it so.
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,488 +0,0 @@
|
|||||||
# How The Platform Works
|
|
||||||
|
|
||||||
> **Subtitle:** Nova — The New Dawn of DevSecOps
|
|
||||||
> **Audience:** Senior Leadership, CTO, Head of Cloud, Head of Infrastructure, Head of DevOps
|
|
||||||
> **Length:** ~16 minutes · 11 main + Appendix TOC + 8 appendix = 20 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:** "Testing" = works internally, dev pilot-ready. "Planned" = on the roadmap, not yet implemented. "Agentic" = involves AI agents or autonomous decision-making.
|
|
||||||
> **Re-verification (2026-07-29):** Every "Testing" claim in this deck was re-verified in v1.10 Phase 54 (D-093) and again in v1.11 via the pipeline-driven lifecycle tests (P59–P62). The headline E2E (contract → resolver → adapter → terraform init/validate/plan) passes against the live AWS account; the local emulating tier (Phase 53) runs the full E2E with no cloud credentials. **22/22 auto-verifiable capabilities Verified** (CAP-013 fixed in v1.12 P67 — the adapter's multi-resource L1 dedup defect is closed; CAP-017/018 probe bugs fixed). The v1.11 lifecycle pipeline ran apply→modify→destroy against live AWS and was then torn down to zero-cost (D-096). See `.ciagent/CAPABILITY_INVENTORY.md` and `.ciagent/PRE_MORTEM.md`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 1 — Title
|
|
||||||
|
|
||||||
# How The Platform Works
|
|
||||||
|
|
||||||
### Nova — The New Dawn of DevSecOps
|
|
||||||
|
|
||||||
**Security as a seamless enabler of fast deployments — not a bottleneck, not a "no" department.**
|
|
||||||
|
|
||||||
> **Speaker notes:** Brief introduction — this deck explains *how* the platform works internally, not what the developer experience is (that's the companion deck). Set the frame: the platform is not a CI/CD tool — it's the organizational lever for shipping safely at the pace the business demands.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 2 — Four frictions slow every team
|
|
||||||
|
|
||||||
Most teams can write code; far fewer get the infrastructure right. Delivery scales with the **coordination surface around it**, not the engineering inside it.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
subgraph ROW1 [" "]
|
|
||||||
direction LR
|
|
||||||
A["Cognitive load\nauthoring infra correctly"]
|
|
||||||
B["Operational work\nmerged → running"]
|
|
||||||
end
|
|
||||||
subgraph ROW2 [" "]
|
|
||||||
direction LR
|
|
||||||
C["Red tape\ntickets, approvals, handoffs"]
|
|
||||||
D["Scalability\nthroughput without headcount"]
|
|
||||||
end
|
|
||||||
A ~~~ B
|
|
||||||
C ~~~ D
|
|
||||||
A ~~~ C
|
|
||||||
B ~~~ D
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Cognitive load** — the long tail of services, inconsistent in security and observability.
|
|
||||||
- **Operational work** — manual promotion that scales with the system, not the change.
|
|
||||||
- **Red tape** — tickets and handoffs that scale with the organization.
|
|
||||||
- **Scalability** — throughput without linearly scaling platform engineers.
|
|
||||||
|
|
||||||
> **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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 3 — The platform at a glance
|
|
||||||
|
|
||||||
One picture of the whole platform — the components, how they connect, and where the boundaries are. The rest of this deck zooms into each piece.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart TD
|
|
||||||
subgraph UP ["Consumer surfaces — upstream"]
|
|
||||||
direction LR
|
|
||||||
U1["Technical dev\napp code + contract"]
|
|
||||||
U2["Citizen dev\nintent → AI agent → contract"]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph ACDL ["Nova — infrastructure only"]
|
|
||||||
direction TB
|
|
||||||
CS["Contract schema\n(validate + fail-fast)"]
|
|
||||||
subgraph PIPE ["Central pipeline — fixed stages, every deployment"]
|
|
||||||
direction LR
|
|
||||||
P1["Validate"] --> P2["Resolve\ntarget stack"] --> P3["Security\nchecks"] --> P4["Infra plan"] --> P5["Policy\nchecks"] --> P6["Confidence\nsignal"] --> P7["Evidence\nevent"] --> P8["Infra apply"]
|
|
||||||
end
|
|
||||||
CAT["Module catalog\nprimitives + modules\n(security-reviewed)"]
|
|
||||||
ADAPT["Engine adapter\n(stateless → Terraform)"]
|
|
||||||
ENV["Platform-managed\nenvironments\naccount · VPC · state · IAM"]
|
|
||||||
HITL["HITL gates\nqa · prod · dr"]
|
|
||||||
EVID["Evidence stream\nhash-chained outbox\n(RPO = 0)"]
|
|
||||||
CS --> PIPE
|
|
||||||
CAT --> P2
|
|
||||||
ADAPT --> P4
|
|
||||||
ADAPT --> P8
|
|
||||||
ENV --> P8
|
|
||||||
P6 --> HITL
|
|
||||||
HITL --> P8
|
|
||||||
P7 --> EVID
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph DOWN ["Downstream"]
|
|
||||||
direction LR
|
|
||||||
D1["AWS resources\nrunning\n(tagged, encrypted)"]
|
|
||||||
D2["Consumer pipeline\ndeploys image"]
|
|
||||||
end
|
|
||||||
|
|
||||||
U1 --> CS
|
|
||||||
U2 --> CS
|
|
||||||
P8 --> D1
|
|
||||||
D1 --> D2
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Consumer surfaces** — technical dev or citizen dev; both produce a contract. Upstream is anything.
|
|
||||||
- **Contract schema** — the boundary between upstream and Nova; validated fail-fast.
|
|
||||||
- **Central pipeline** — fixed stages, identical for every deployment: validate → resolve → security → plan → policy → confidence → evidence → apply.
|
|
||||||
- **Module catalog** — security-reviewed primitives + modules the resolver expands against.
|
|
||||||
- **Engine adapter** — stateless; the only engine-specific code (Terraform today).
|
|
||||||
- **Platform-managed environments** — account, VPC, state, IAM role; the platform owns the blast radius.
|
|
||||||
- **HITL gates** — human attestation for qa/prod/dr; dev is autonomous.
|
|
||||||
- **Evidence stream** — hash-chained outbox, RPO = 0, written by every deployment.
|
|
||||||
|
|
||||||
> **Speaker notes:** This is the one-slide map of the platform. Use it to orient the audience before diving into any single component. The leadership-relevant beats: (1) two surfaces, one pipeline, one evidence stream — the convergence is the design; (2) the pipeline stages are fixed and identical for every consumer — no team-specific pipelines; (3) the engine adapter is the only engine-specific code, which is what makes the catalog and confidence model portable. Don't walk every node; point to the boundaries and say "the rest of this deck zooms into each of these."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 4 — Declare intent; the platform delivers safe production
|
|
||||||
|
|
||||||
Consumers **declare intent**; the platform delivers **safe production deployment** — automatically, safely, with a complete audit trail.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
subgraph TODAY ["Today"]
|
|
||||||
direction TB
|
|
||||||
A["Merged change"]
|
|
||||||
B["Waits in queue"]
|
|
||||||
C["Ticket + approvals"]
|
|
||||||
D["Manual promotion"]
|
|
||||||
A --> B --> C --> D
|
|
||||||
end
|
|
||||||
subgraph ACDL ["With Nova"]
|
|
||||||
direction TB
|
|
||||||
E["Declare intent\n(one YAML contract)"]
|
|
||||||
F["Platform delivers\nsafely, autonomously"]
|
|
||||||
G["Traceable to\nhuman attestation"]
|
|
||||||
E --> F --> G
|
|
||||||
end
|
|
||||||
TODAY -.before.-> ACDL
|
|
||||||
```
|
|
||||||
|
|
||||||
- A merged change progresses **without a platform engineer joining a thread.**
|
|
||||||
- A **non-technical consumer** ships by declaring intent — no workflow, no config file, no module.
|
|
||||||
- Every production change is **traceable to a human attestation** and an immutable evidence stream.
|
|
||||||
|
|
||||||
> **Speaker notes:** Land the before/after contrast: today's queue vs. Nova's autonomous flow. The litmus test: if a platform engineer still has to touch a ticket for a dev→qa promotion, we haven't delivered the vision. The North Star is "declare intent → safe production deployment."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 5 — Nova owns infrastructure, not your app
|
|
||||||
|
|
||||||
The platform is deliberately scoped — it is not trying to be everything.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
subgraph UP ["Upstream — anything"]
|
|
||||||
direction TB
|
|
||||||
A["IDE / IDE + AI\n(dev writes contract)"]
|
|
||||||
B["Agentic SDLC\n(agent writes contract)"]
|
|
||||||
C["Citizen dev\n(vibe codes → AI agent\n→ contract)"]
|
|
||||||
end
|
|
||||||
subgraph ACDL ["Nova — infrastructure only"]
|
|
||||||
D["Contract\nvalidated"]
|
|
||||||
E["Resolve → Plan\nSecurity + Policy checks\nConfidence signal"]
|
|
||||||
F["Provision\nAWS resources"]
|
|
||||||
G["Evidence\nhash-chained"]
|
|
||||||
end
|
|
||||||
subgraph DOWN ["Downstream"]
|
|
||||||
H["AWS resources\nrunning"]
|
|
||||||
I["Consumer pipeline\ndeploys image"]
|
|
||||||
end
|
|
||||||
A --> D
|
|
||||||
B --> D
|
|
||||||
C --> D
|
|
||||||
D --> E
|
|
||||||
E --> F
|
|
||||||
E --> G
|
|
||||||
F --> H
|
|
||||||
H --> I
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Upstream is anything** — IDE, agentic SDLC, or vibe coding. Nova doesn't care how the contract was produced.
|
|
||||||
- **Nova is infrastructure only** — it provisions and governs AWS resources. App build/test/deploy is upstream.
|
|
||||||
- **Not a general-purpose AI** — autonomy is narrow, scoped to delivery, bounded by strict policy.
|
|
||||||
- **Not a permissive highway** — no escape hatches to bypass the confidence framework.
|
|
||||||
|
|
||||||
> **Speaker notes:** 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 6 — One YAML file. The platform owns everything else.
|
|
||||||
|
|
||||||
The contract is the boundary between upstream and Nova. It's all a consumer writes.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
A["Consumer<br/>writes a contract"] --> B["Platform resolves,<br/>compiles, checks,<br/>deploys, records"]
|
|
||||||
B --> C["Resources running in AWS<br/>+ tamper-evident evidence"]
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Which module** — a catalog of pre-built, security-reviewed building blocks.
|
|
||||||
- **Which environment** — `dev`, `qa`, `prod`, or `dr`. The bar rises automatically with sensitivity.
|
|
||||||
- **Which inputs** — infrastructure values that vary per deployment (cpu, memory, port, desired_count).
|
|
||||||
- The consumer provides **no AWS account, no VPC, no state backend** — the platform owns the blast radius.
|
|
||||||
|
|
||||||
> **Speaker notes:** Emphasize the asymmetry. The consumer's surface is intentionally tiny — a contract that fits on one screen. The platform's surface is large and opinionated. The contract examples show infrastructure inputs (cpu, memory, desired_count, port) — not a container image. The image is upstream; the platform governs infrastructure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 7 — Same stages, same checks, every deployment
|
|
||||||
|
|
||||||
Every deployment runs the same stages, in the same order, with the same checks — no team-specific pipelines, no tribal runbooks.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart TD
|
|
||||||
A["Consumer contract<br/>(module + environment + inputs)"] --> B["Validate contract<br/>against the schema"]
|
|
||||||
B --> C["Resolve to a target stack<br/>(expand the module's pattern)"]
|
|
||||||
C --> D["Security checks<br/>(before any infra is created)"]
|
|
||||||
D --> E["Infrastructure plan<br/>(platform compiles the stack)"]
|
|
||||||
E --> F["Policy checks<br/>(normalized results)"]
|
|
||||||
F --> G["Confidence signal<br/>(6 inputs → score + band)"]
|
|
||||||
G --> H["Evidence event<br/>(hash-chained, tamper-evident)"]
|
|
||||||
H --> I["Infrastructure apply<br/>(dev only — higher envs hold for attestation)"]
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Security and policy checks run *before* any infrastructure is created** — not as a post-deployment audit.
|
|
||||||
- **Every stage produces a record** that feeds the confidence signal and the evidence stream. No "unchecked" path.
|
|
||||||
|
|
||||||
> **Speaker notes:** Walk left to right once. Don't dwell on internals — the point is that the flow is fixed, opinionated, and identical for every consumer. The two leadership-relevant beats: (1) checks before creation, (2) every stage is evidenced. The confidence signal (Slide 9) is where the "safety is computed" story lands.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 8 — No long-lived credentials. Blast radius contained.
|
|
||||||
|
|
||||||
Consumer repositories hold **no long-lived cloud credentials.** Ever.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
A["Consumer repo\n(no credentials)"]
|
|
||||||
B["OIDC federation\nshort-lived token"]
|
|
||||||
C["ABAC session policy\nrepo identity + tags"]
|
|
||||||
D["Tagged resources\nonly"]
|
|
||||||
A --> B --> C --> D
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Authentication — OIDC federation.** Each job mints a short-lived token; no credential stored in the consumer repo or runner secret. <span class="badge planned">Planned: all runners</span>
|
|
||||||
- **Authorization — attribute-based (ABAC), not role-based.** Two attribute classes scope every action:
|
|
||||||
- **Repository identity** — trust policy binds to the exact consumer repo + branch.
|
|
||||||
- **Resource tags** — every resource tagged `nova:owner` + `nova:contract`; session policy grants access **only to matching tags.**
|
|
||||||
- **The effect:** a consumer can only touch the resources it created. One consumer can never affect another.
|
|
||||||
|
|
||||||
> **Speaker notes:** This is the slide for the Head of Cloud/Security. The key phrase is "blast radius contained to the consumer's own stack." Contrast with the common failure mode of shared CI roles that can touch any account resource. The static-key override exists for edge cases but is rotated daily on platform runners; it is never the default.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 9 — Safety is a measurable signal, not a black box
|
|
||||||
|
|
||||||
Every delivery action produces a **measurable, explainable confidence signal** — a weighted sum of observable facts, not a black box.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
P["Policy"] --> S["Score"]
|
|
||||||
V["Validation"] --> S
|
|
||||||
F["Freshness"] --> S
|
|
||||||
Pr["Provenance"] --> S
|
|
||||||
H["History"] --> S
|
|
||||||
N["NFRs"] --> S
|
|
||||||
S --> B["Band + threshold"]
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Six weighted inputs** — policy, validation, freshness, provenance, history, NFRs. Manually tuned, auditable. If a consumer asks "why 0.62?", the platform answers with a per-input breakdown.
|
|
||||||
- **Per-environment thresholds** that rise with sensitivity:
|
|
||||||
|
|
||||||
| Environment | Threshold | Attester |
|
|
||||||
|---|---|---|
|
|
||||||
| dev | ≥ 0.50 | No one — autonomous |
|
|
||||||
| qa | ≥ 0.75 | QA <span class="badge planned">Planned</span> |
|
|
||||||
| prod | ≥ 0.90 | SRE <span class="badge planned">Planned</span> |
|
|
||||||
|
|
||||||
- **A single critical finding hard-blocks** — critical findings are not averaged away.
|
|
||||||
|
|
||||||
> **Speaker notes:** This is the bet that separates this platform from "yet another CI/CD tool." Reliance on operator instinct or tenure is not a substitute. The signal is auditable; the thresholds are tunable by Infra & Ops + SRE jointly, and any override is itself a confidence-event in the audit stream. Leadership cares because it makes promotion decisions *reviewable*.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 10 — Every change traceable to a human attestation
|
|
||||||
|
|
||||||
Computed safety handles the gate. Humans still matter — here's how accountability works.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
subgraph DEV ["dev — autonomous"]
|
|
||||||
D1["Confidence ≥ 0.50\n→ apply"]
|
|
||||||
end
|
|
||||||
subgraph GATED ["qa / prod / dr — gated"]
|
|
||||||
G1["Confidence ≥ threshold"]
|
|
||||||
G2["Human attestation\nreviews contract\n+ plan + evidence"]
|
|
||||||
G3["Separation of duties\nQA ≠ prod approver"]
|
|
||||||
G1 --> G2 --> G3
|
|
||||||
end
|
|
||||||
DEV --> OUT["Hash-chained\nevidence event\n(RPO = 0)"]
|
|
||||||
GATED --> OUT
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Dev is fully autonomous.** The confidence signal (≥ 0.50) is the only gate.
|
|
||||||
- **qa, prod, dr require human attestation** — the approver reviews contract, planned Terraform, and accumulated evidence. <span class="badge planned">Planned</span>
|
|
||||||
- **Separation of duties is enforced** — the QA approver **cannot** be the prod approver. The platform **blocks on a match.** <span class="badge planned">Planned</span>
|
|
||||||
- **Every deployment writes a hash-chained evidence event** — tampering breaks the chain. **RPO = 0.**
|
|
||||||
|
|
||||||
> **Speaker notes:** The "lower environments autonomous, higher environments attested" tenet is the resolution to the classic "move fast vs. be safe" false dichotomy. Be honest: the separation-of-duties *mechanism* is designed and the dev path is wired; qa/prod/dr wiring is on the roadmap. The audit trail is a byproduct of deployment, not a project. 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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 11 — The vision realized
|
|
||||||
|
|
||||||
- **Velocity without sacrificing safety.** Speed is in the ergonomics; safety is in the gates the consumer cannot bypass.
|
|
||||||
- **Security, observability, and compliance as platform defaults** — not per-team effort, not post-hoc remediation.
|
|
||||||
- **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.
|
|
||||||
- **Infrastructure as a utility, not a craft.** Teams consume infrastructure, they don't maintain it.
|
|
||||||
- **A path to the citizen developer.** The same safety envelope serves a senior engineer and a non-technical consumer.
|
|
||||||
|
|
||||||
> **Speaker notes:** Close on the strategic frame. The platform is not "a CI/CD tool" — it's the organizational lever for shipping safely at the pace the business demands, with the security and audit posture the regulators require. The investment is in the abstraction, not the tool.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix — Table of Contents
|
|
||||||
|
|
||||||
For deep dives — these slides cover details omitted from the main 10.
|
|
||||||
|
|
||||||
**Contents:**
|
|
||||||
|
|
||||||
1. Platform-Managed Environments (detail)
|
|
||||||
2. Observability Built In (detail)
|
|
||||||
3. Security by Construction (the full defaults inventory)
|
|
||||||
4. The Road to the North Star (phased roadmap)
|
|
||||||
5. Testing vs. Planned (full inventory)
|
|
||||||
6. Glossary
|
|
||||||
7. Operating Model & Cost (real AWS spend + pre-mortem)
|
|
||||||
8. Verified by Construction (the v1.11 architecture)
|
|
||||||
|
|
||||||
> **Speaker notes:** These are deep-dive slides for follow-up questions. Don't walk them in the main 15-minute talk — pull them up when an audience member wants detail on a specific topic.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A1 — Platform-Managed Environments
|
|
||||||
|
|
||||||
A consumer provides **no AWS account, no VPC, no subnet, no state backend, no runner key.** The platform owns the blast radius.
|
|
||||||
|
|
||||||
A named environment is a platform-owned bundle of:
|
|
||||||
|
|
||||||
- An AWS account (or a scoped partition of one).
|
|
||||||
- A network (VPC + subnets).
|
|
||||||
- A state backend (S3 + DynamoDB for infrastructure state + locking).
|
|
||||||
- An IAM role surfaced to the consumer via ABAC, scoped to the consumer's repository identity and resource tags.
|
|
||||||
|
|
||||||
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. *(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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A2 — Observability Built In
|
|
||||||
|
|
||||||
Monitoring is **a platform default, not a per-team project.** *(Testing.)*
|
|
||||||
|
|
||||||
- **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.
|
|
||||||
- **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. *(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. *(Planned.)*
|
|
||||||
|
|
||||||
> **Speaker notes:** The Head of DevOps cares about this. The framing: "you don't deploy a service and *then* remember to set up monitoring — the platform does it as part of the deploy." The feature flag means teams with existing monitoring (e.g. Datadog) can opt out cleanly.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A3 — Security by Construction
|
|
||||||
|
|
||||||
Security defaults that **do not require a team to opt in.** Checks run on **every** deployment, normalized to a single schema regardless of which engine produced them. *(Testing.)*
|
|
||||||
|
|
||||||
- **Infrastructure-as-code policy** (Checkov) — secrets in plaintext, public ingress, IAM wildcards, KMS key references, **required tagging standards** (`nova:owner`, `nova:contract`, `nova:environment`, `nova:cost-center`). All run *before* infra is created.
|
|
||||||
- **Cloud security posture** (Wiz adapter) — translates cloud security findings into the same normalized record. *(Adapter testing; activates when a Wiz tenant is configured.)*
|
|
||||||
- **Kubernetes-native policy** (Kyverno adapter) — ready for the GitOps reconciler roadmap item. *(Adapter testing; inactive for Terraform-only stacks.)*
|
|
||||||
- **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. *(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 selling point is *normalization* — we can add a new security tool without changing the confidence model or the evidence stream. For the Head of Security: tagging standards are enforced, not advisory — a missing `nova:owner` tag fails the check, not a warning. 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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A4 — The Road to the North Star
|
|
||||||
|
|
||||||
*Proposed phasing — not formally planned.*
|
|
||||||
|
|
||||||
A phased roadmap from the current Testing baseline to the full North Star:
|
|
||||||
|
|
||||||
- **Phase 1 — Testing baseline (current, v1.12):** contract-driven deploys, zero-trust OIDC + ABAC on GitHub Actions, confidence signal gating, hash-chained evidence, encryption by default, deletion protection + safe decommission, uptime monitoring, platform-managed environments. **22/22 capabilities Verified** via the v1.11 lifecycle pipeline (apply→modify→destroy against live AWS, then torn down to zero-cost). The stateless adapter + lifecycle pipeline are the structural verification (see A8).
|
|
||||||
- **Phase 2 — Production readiness:** HITL wiring for qa/prod/dr, all-runner OIDC, full regulatory ledger (S3 Object Lock + JWS signatures + daily checkpoints), environment self-service.
|
|
||||||
- **Phase 3 — Compliance & expansion:** compliance milestone (GDPR, SOX, SOC2, DORA extension points), additional engine adapters (OpenTofu, Pulumi, Kubernetes CRDs), deeper observability bootstrap.
|
|
||||||
- **Phase 4 — Agentic frontier:** dynamic module creation from a contract (the agentic citizen-developer composition mechanism), pattern recognition that compounds value over time.
|
|
||||||
|
|
||||||
> **Speaker notes:** Be clear with leadership: this is a proposed phasing, not a formally committed plan. The phases are sequenced by dependency, not by calendar — each phase's items are gated on the prior phase's maturity. Phase 1 is now fully Verified (22/22) and torn down to zero-cost — it is no longer aspirational. Invite questions on any phase boundary.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A5 — Testing vs. Planned (Full Inventory)
|
|
||||||
|
|
||||||
> **Verification status (v1.12, 2026-07-29):** 22/22 auto-verifiable capabilities **Verified** — the v1.11 lifecycle pipeline ran apply→modify→destroy against live AWS for every L1 + L2 module, then tore down to zero-cost (D-096). The v1.10 "6 deploy-unverified (IAM drift)" status is closed (CAP-013 fixed in P67). See `CAPABILITY_INVENTORY.md`.
|
|
||||||
|
|
||||||
**Testing** (works internally, dev pilot-ready — 22/22 Verified via lifecycle pipeline + regression gate):
|
|
||||||
|
|
||||||
- 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 adapters ready).
|
|
||||||
- Confidence signal (6 inputs, per-env thresholds) gating promotion. *(Agentic.)*
|
|
||||||
- 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 + CMDB validation.
|
|
||||||
- Uptime monitoring deployed automatically with every stack.
|
|
||||||
- Platform-managed environments + friendly onboarding.
|
|
||||||
- Engine-agnostic core (1 adapter: Terraform) + VCS-agnostic ingestion (GitHub + Gitea).
|
|
||||||
|
|
||||||
**Planned** (on the roadmap, not yet implemented) — 9 capabilities:
|
|
||||||
|
|
||||||
- Real OIDC federation on all platform runners (Gitea Actions OIDC pending an upstream merge).
|
|
||||||
- HITL wiring for qa / prod / dr environments (design shipped; wiring is next).
|
|
||||||
- Full regulatory ledger: S3 Object Lock (7-yr compliance mode) + JWS detached signatures + daily checkpoints.
|
|
||||||
- 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). *(Agentic.)*
|
|
||||||
- Pattern recognition compounds value over time. *(Agentic.)*
|
|
||||||
- Additional engine adapters (OpenTofu, Pulumi, Kubernetes CRDs).
|
|
||||||
- Deeper observability bootstrap (dashboards, runbooks, on-call bindings).
|
|
||||||
|
|
||||||
> **Speaker notes:** Close on honesty. The platform delivers real, verifiable value today — 22/22 auto-verifiable capabilities are Verified via the v1.11 lifecycle pipeline (apply→modify→destroy against live AWS) + the D-091 regression gate. The roadmap is concrete, not aspirational hand-waving — 9 planned items, each with a defined milestone and a clear reason it isn't shipped yet (usually an upstream dependency, not an engineering gap). Emphasize: 0 consumer adoption today — "Testing" means it works internally and is dev pilot-ready, not that it's released. The lifecycle pipeline defaults to **plan-only** on every PR (fast, no AWS mutation, no cost); a CI variable (`NOVA_LIFECYCLE_MODE=full`) overrides to the real apply→destroy for milestone verification (REQ-134, v1.12).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A6 — Glossary
|
|
||||||
|
|
||||||
| Term | Meaning |
|
|
||||||
|---|---|
|
|
||||||
| **OIDC** | OpenID Connect — federation protocol for short-lived tokens, no long-lived credentials |
|
|
||||||
| **ABAC** | Attribute-Based Access Control — access scoped by resource tags + repo identity, not roles |
|
|
||||||
| **CMK** | Customer-Managed Key — per-stack encryption key, 90-day rotation, no shared keys |
|
|
||||||
| **CMDB** | Configuration Management Database — validates change requests for decommission |
|
|
||||||
| **RPO** | Recovery Point Objective — RPO = 0 means evidence is written synchronously, no data loss |
|
|
||||||
| **HITL** | Human-in-the-Loop — deliberate human attestation required for qa/prod/dr environments |
|
|
||||||
| **VCS** | Version Control System — the git hosting platform (GitHub, Gitea, GitLab) |
|
|
||||||
| **NFR** | Non-Functional Requirement — encryption, tagging, observability standards |
|
|
||||||
| **IR** | Intermediate Representation — the engine-agnostic stack definition between contract and Terraform |
|
|
||||||
|
|
||||||
> **Speaker notes:** Use this slide as a reference when the audience asks for term definitions. Don't read it aloud — point to it as a takeaway reference.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A7 — Operating Model & Cost (real AWS spend + pre-mortem)
|
|
||||||
|
|
||||||
Nova runs at **zero cloud cost** for day-to-day development. The v1.0→v1.10 AWS spend was measured directly via Cost Explorer (`COST.md`, 2026-07-28):
|
|
||||||
|
|
||||||
| Metric | Value |
|
|
||||||
|--------|-------|
|
|
||||||
| Total spend (8 days) | **$0.001883** |
|
|
||||||
| Daily average | $0.000235 |
|
|
||||||
| Projected monthly | ~$0.007 |
|
|
||||||
| Peak day | 2026-07-27 ($0.000867 — v1.10 regression + verify run) |
|
|
||||||
|
|
||||||
- **S3 dominates** (98.8%, terraform state bucket) — no compute (ECS/Lambda) ran because v1.0→v1.10 was plan-only for IAM-gated capabilities.
|
|
||||||
- **Local emulators are the primary tier** — the full pipeline runs in-process, no AWS credentials, no Checkov, no DynamoDB. *(Testing.)*
|
|
||||||
- **Live-AWS verification is milestone-scoped, then torn down.** The v1.11 lifecycle pipeline ran apply→modify→destroy for every module, then tore down to zero-cost steady state (D-096 — teardown mandatory before milestone COMPLETE; no merge to main until `terraform show` confirms no resources). The lifecycle pipeline now **defaults to plan-only** on every PR (fast, no AWS mutation, no cost); a CI variable (`NOVA_LIFECYCLE_MODE=full`) overrides to the real apply→destroy for milestone verification (REQ-134, v1.12).
|
|
||||||
- **Cost drivers** are spike-scoped: Terraform plan reads (free), S3 state storage (cents), DynamoDB outbox (cents). Any cost spike > $1/day is an anomaly.
|
|
||||||
|
|
||||||
**Pre-mortem (`PRE_MORTEM.md`):** the project's failure modes were pre-mortemed before the leadership pitch. The v1.10 decay incident (diff-scoped VERIFY missed 7 adapter defects across 8 NFR-patch phases — decks advertised capability that wasn't reproducible) is the root pattern: *a claim outruns the verification that backs it.* Four forward failure modes + structural mitigations: (FM-1) IAM-drift recurrence → IAM policy baseline is regression-tested; (FM-2) cost spike from un-torn-down stacks → D-096 mandatory teardown; (FM-3) deck overstates capability → verified-only claims + decks unfrozen only after re-verification; (FM-4) pilot contract gap → honest scope (microservice + static-assets today; the L2 pattern is extensible). All mitigations are structural, not procedural.
|
|
||||||
|
|
||||||
> **Speaker notes:** This is the slide for the Head of Cloud / Finance. The headline: less than one cent over 8 days of active development; zero BAU cloud spend; the lifecycle pipeline defaults to plan-only so the PR-time cost is zero. The pre-mortem is the credibility slide — we have already asked "how does this fail?" and the mitigations are structural (regression-tested baselines, mandatory teardown, verified-only deck claims). The v1.10 decay incident is disclosed honestly, not hidden — that disclosure IS the mitigation.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A8 — Verified by Construction (the v1.11 architecture)
|
|
||||||
|
|
||||||
v1.11 rebuilt the platform on two architectural pillars that make "Verified" a structural property, not a claim:
|
|
||||||
|
|
||||||
- **The stateless adapter (REQ-123, 918 → ~80 lines).** The Terraform adapter was a 918-line monolith with 3 constant tables and 39 type-specific branches. It is now a ~80-line **stateless assembler**: it owns no module content — no resource shape, no nested HCL blocks, no defaults, no type-specific logic. Each L1 module ships a real `terraform/` module dir owning its resource shape, nested blocks, and defaults (centralized in `locals.tf`). The adapter reads the registry and emits `module "x" { source = ... }` blocks. No type-specific logic in the adapter means a new module is a new terraform dir, not a code change. *(The v1.12 P67 fix closed a dedup defect where multi-resource L1s — ecs-service, alb — produced invalid Terraform; CAP-013 now Verified.)*
|
|
||||||
- **Pipeline-driven lifecycle testing (REQ-127/128).** A `modules-lifecycle` pipeline matrix-runs each L1 and L2 module's `examples/{simple,complex}.yml` contracts through apply→modify→destroy against live AWS. No per-module Python. **The "test" = the pipeline cell going green.** Defaults to **plan-only** on every PR (fast, no AWS mutation, no cost); `NOVA_LIFECYCLE_MODE=full` runs the real apply→destroy for milestone verification (REQ-134, v1.12). The regression gate (D-091) re-runs all 22 capabilities at milestone completion — 22/22 Verified as of v1.12.
|
|
||||||
|
|
||||||
> **Speaker notes:** This is the deep-dive slide for the Head of Engineering / Architecture. The two pillars are the answer to "how do you keep the decks honest?" The adapter is simple enough to reason about (a stateless assembler), and the lifecycle pipeline is the automated verification that backs every "Testing" claim. The v1.10 lesson is the negative space: a 918-line adapter with type-specific branches decayed silently because the VERIFY gate was diff-scoped. The ~80-line stateless adapter + the milestone regression gate are the structural fix. The plan-only default (v1.12) means this verification runs on every PR at zero cost, with the full apply→destroy gated behind a CI variable override.
|
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
---
|
||||||
|
marp: true
|
||||||
|
theme: nova-sp
|
||||||
|
paginate: true
|
||||||
|
size: 16x9
|
||||||
|
footer: 'Nova — The Autonomous Cloud Delivery Platform'
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- _class: title -->
|
||||||
|
<!-- _paginate: false -->
|
||||||
|
|
||||||
|
# Nova — The Autonomous Cloud Delivery Platform
|
||||||
|
|
||||||
|
**Shifting from Operational Overhead to Strategic Value**
|
||||||
|
|
||||||
|
Product Development & Citizen Developer Overview
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 1 — The Problem
|
||||||
|
|
||||||
|
**Product teams now own their cloud infrastructure — but ownership without discipline is destroying value.**
|
||||||
|
|
||||||
|
- **No lifecycle planning.** Resources are authored for creation, not for patching, decommissioning, or rollback — so changes are destructive.
|
||||||
|
- **Proactive scanning is not part of authoring.** AI-frontier models exploit zero-days at a rapid pace; teams cannot keep up by reacting. Modules must be scanned as code and at runtime — and remediated at the pace the threat moves.
|
||||||
|
- **Bandwidth gaps in infrastructure operations.** Time spent on remediation + the push for innovation leaves operations chronically under-resourced; detections are missed, incidents grow.
|
||||||
|
- **Tribal knowledge and the rockstar-operator problem.** Operations depend on a handful of administrators; when they leave, the knowledge leaves with them. The platform should encode the discipline, not the person.
|
||||||
|
|
||||||
|
Every hour a developer spends writing, deploying, fixing, or remediating infrastructure is an hour not spent releasing features to production.
|
||||||
|
|
||||||
|
**Benefit:** the answer is an autonomous cloud delivery platform that encodes discipline as policy, scans proactively, remediates rapidly, and makes operations visible to leadership rather than hidden in tribal knowledge.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 2 — Nova's Vision
|
||||||
|
|
||||||
|
> **Infrastructure operations become visible. Every environment provisioned, every incident healed, every risk remediated — by an autonomous system whose trustworthiness is provable, not promised. Human attestation remains required at stage gates; the operator is never in the loop of normal operations.**
|
||||||
|
|
||||||
|
- **Visibility is the recurring theme** — security posture, remediation velocity, reliability, and lead time as queryable signals
|
||||||
|
- **Provable, not promised** — trust established by deterministic scripts that calculate a score; the platform functions without AI
|
||||||
|
- **Autonomy in operations, human at stage gates** — QA signs off for production; SRE greenlights operational readiness
|
||||||
|
|
||||||
|
**Benefit:** the destination is autonomous operations with provable trust — security, remediation velocity, reliability, and lead time made visible to leadership, not promised to them.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 3 — Strategic Objectives
|
||||||
|
|
||||||
|
**4 Strategic Objectives:**
|
||||||
|
1. **Zero-touch operations** — autonomy as the default, not the demo; stage-gate attestation (QA, SRE) remains human by design
|
||||||
|
2. **Provable trust in automated decisions** — deterministic scripts calculate a score; the platform functions without AI; Decision Ledger, confidence scoring, circuit breakers, blast-radius controls
|
||||||
|
3. **Compounding, quantifiable ROI** — four CTO-grade metrics, all flowing into PowerBI:
|
||||||
|
- **Lead Time** (PR → Production) · **Infrastructure Vulnerability Count** (trend) · **MTTR** · **Cloud Spend Reduction**
|
||||||
|
4. **Integrate with externally owned development platforms — regardless of source** — PDLC, SDLC, Agentic, or Citizen Developer; Nova provides skills + MCP endpoints; all prod intents go through the same controls and quality gates
|
||||||
|
|
||||||
|
**Benefit:** the scope is explicit — Nova governs infrastructure and delivery, integrates with any upstream source through one validated contract, and measures success on four metrics a CTO can repeat back.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 4 — Anti-Goals (What Nova Is NOT)
|
||||||
|
|
||||||
|
1. Not a general-purpose AI agent platform
|
||||||
|
2. Not a system that removes humans from accountability — only from normal operations
|
||||||
|
3. Not an upstream development platform (no product backlogs, IDE, code authorship)
|
||||||
|
4. Not a replacement for the Product Development Lifecycle (PDLC)
|
||||||
|
|
||||||
|
**Benefit:** the boundaries are explicit — Nova is purpose-built for infrastructure operations and delivery, not a general-purpose AI agent or an upstream development platform.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 5 — Scope: Downstream of PDLC
|
||||||
|
|
||||||
|
**Nova governs infrastructure and delivery. The PDLC is upstream — Nova never penetrates it. Integration is through one validated contract.**
|
||||||
|
|
||||||
|
- **The PDLC is upstream:** product backlog, code authorship (AI agent, IDE, agentic SDLC), sprint planning, application business logic
|
||||||
|
- **Nova is downstream:** contract ingestion → submission-readiness gate → policy enforcement → cloud resource lifecycle → environment progression (dev → qa → prod → dr) → immutable audit + attestation
|
||||||
|
- **The integration point is one contract** — any upstream source (AI agent, agentic SDLC, dev platform) produces submissions subject to the same compliance standards
|
||||||
|
- **Nova validates the submission, not the author** — the audit trail, the policy envelope, and the evidence stream are the same regardless of source
|
||||||
|
|
||||||
|
**Benefit:** a clean scope boundary — Nova is purpose-built for infrastructure operations and integrates with any upstream source through one validated contract, so the platform team's surface area stays bounded.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 6 — RACI: Who Owns What
|
||||||
|
|
||||||
|
**Four roles, one matrix — citizen developer owns FRs + UAT, platform owns NFRs + infra, quality engineering owns the gate evidence, SRE owns operational readiness.**
|
||||||
|
|
||||||
|
| Work Category | Citizen Dev | Platform | Quality Eng | SRE |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| Functional Requirements | **R/A** | C | I | I |
|
||||||
|
| User Acceptance Testing | **R/A** | C | I | I |
|
||||||
|
| Non-Functional Requirements | I | **R/A** | C | C |
|
||||||
|
| Infrastructure (cloud, state, IAM) | I | **R/A** | I | C |
|
||||||
|
| QA (policy, confidence, schema) | C | R | **R/A** | I |
|
||||||
|
| Production deployment to cloud | I | **R/A** | C | C |
|
||||||
|
| Quality attestation (QA sign-off) | **A** | R | **R** | I |
|
||||||
|
| Production readiness (SRE sign-off) | **A** | R | C | **R** |
|
||||||
|
|
||||||
|
**R**=Responsible · **A**=Accountable (sign-off) · **C**=Consulted · **I**=Informed. Production readiness is co-owned: the platform runs attestations agentically; the citizen developer authorizes the promotion at the stage gate.
|
||||||
|
|
||||||
|
**Benefit:** every party knows what they bring, what the platform provides, what quality engineering guards, and where SRE signs off — accountability is explicit, never diffuse.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 7 — The Platform Pipeline
|
||||||
|
|
||||||
|
**How intent becomes verified infrastructure — fail-fast policy scanning before the plan, runtime scanning after it.**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- **Contract → resolver → adapter → Checkov on static code (before plan) → terraform plan → Wiz on the plan → confidence signal → stage gate → apply → evidence + ledger**
|
||||||
|
- **Fail-fast, quick feedback** — Checkov runs on the authored Terraform code before `terraform plan` so developers get immediate policy feedback
|
||||||
|
- **Wiz on the plan when configured; Checkov as a drop-in otherwise** — Wiz scans the plan output; when Wiz credentials are absent, Checkov runs against the plan. **Wiz and Checkov are never both run on the plan.**
|
||||||
|
|
||||||
|
**Benefit:** two layers of scanning, zero operator involvement in normal operations — fast deterministic feedback at authoring time and a runtime scan on the resolved plan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 8 — The Decision Ledger
|
||||||
|
|
||||||
|
**Every automated decision is captured, immutable, queryable — and accountable.**
|
||||||
|
|
||||||
|
- **What is captured:** the chosen action, the confidence score, the alternatives considered, whether a human overrode it, and the outcome (backfilled once the apply completes). Every stage-gate attestation (QA, SRE) is captured with approver identity and the evidence presented.
|
||||||
|
- **"AI decisions" are really automated decisions** — made by deterministic scripts that calculate a score and a band; the platform functions without AI. When an LLM planner is added later, it will emit richer alternatives without breaking the schema.
|
||||||
|
- **The value is accountability, not the storage engine** — the ledger is append-only and tamper-evident; every decision is queryable for auditing, traceable to an outcome, and impossible to rewrite after the fact.
|
||||||
|
|
||||||
|
**Benefit:** "autonomous" is defensible because every decision is immutable, queryable, and accountable — and the audience knows exactly what "automated" means here: deterministic scoring, not a black-box LLM.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 9 — Attestation Matrix: QA
|
||||||
|
|
||||||
|
**The designed controls that keep humans at stage gates — QA concerns, freshness-validated.**
|
||||||
|
|
||||||
|
| Concern | Env | Freshness | Description |
|
||||||
|
|---------|-----|-----------|-------------|
|
||||||
|
| Functional correctness | qa | 24h | The application behaves as specified; evidence accepted from the consumer's UAT. |
|
||||||
|
| Performance baseline | qa | 7d | The deployment meets its performance envelope vs. the agreed baseline. |
|
||||||
|
| Security posture | qa | 24h | The deployment's security findings have been reviewed and accepted. |
|
||||||
|
|
||||||
|
**Benefit:** QA signs off on quality before any promotion — the gate is explicit, not implicit.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 10 — Attestation Matrix: Prod/DR
|
||||||
|
|
||||||
|
**Production and DR controls — operational readiness, resilience, and disaster recovery.**
|
||||||
|
|
||||||
|
| Concern | Env | Freshness | Description |
|
||||||
|
|---------|-----|-----------|-------------|
|
||||||
|
| Operational readiness | prod | 30d | SRE confirms the deployment is operable: runbooks, dashboards, on-call. |
|
||||||
|
| Incident response | prod | 90d | The on-call path has been exercised; a working incident-response plan exists. |
|
||||||
|
| Capacity & cost | prod | 30d | Capacity headroom and monthly cost are within the agreed envelope. |
|
||||||
|
| Resilience: DR drill | prod | 180d | A DR drill has been run and recovery met the RTO. |
|
||||||
|
| Resilience: chaos | prod | 90d | A chaos exercise has been run and the deployment absorbed the failure. |
|
||||||
|
| Resilience: backup | prod | 30d | Backups are restorable and tested within the freshness window. |
|
||||||
|
| DR region deploy | dr | 180d | The DR region can be deployed and is reachable. |
|
||||||
|
|
||||||
|
Separation-of-duties on prod: the approver cannot be the same person who built the deployment.
|
||||||
|
|
||||||
|
**Benefit:** the gate model is explicit — autonomy in operations, human in accountability, by design. The matrix is what makes autonomous operations safe enough to trust in production.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 11 — Telemetry & Live Ops
|
||||||
|
|
||||||
|
**Every metric in this deck is traceable to a real emitted signal — the live-ops dashboard makes operations visible in PowerBI.**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- **Platform components → CloudEvents envelope → event log + decision ledger + run records → collector → cold store → PowerBI views → live ops dashboard**
|
||||||
|
- **The live ops dashboard (PowerBI)** surfaces the four CTO-grade metrics (Lead Time, Vulnerability Count, MTTR, Cloud Spend) alongside trust metrics (Decision Ledger coverage, Attestation coverage) and efficiency metrics (touchless resolution, escalation frequency)
|
||||||
|
- **Every number is traceable to a signal** — when a CFO asks "where does this number come from?", the answer is a query against the cold store, not a Slack thread
|
||||||
|
|
||||||
|
**Benefit:** the architecture is the trust substrate — leadership sees the same numbers the platform produces, in PowerBI, with full traceability. Operations become visible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 12 — Decision Ledger + Attestation Coverage
|
||||||
|
|
||||||
|
**By design, no change reaches production without a ledger entry and a human attestation — both queryable for auditing, with full traceability.**
|
||||||
|
|
||||||
|
- **Decision Ledger coverage: 100%** — every platform run emits a decision record with outcome backfill; no automated decision is ever lost
|
||||||
|
- **Attestation coverage: 100%** — every prod/dr promotion is attested by a human (QA for quality, SRE for production readiness), recorded with approver identity, separation-of-duties check, and the evidence matrix
|
||||||
|
- **No change to production without both** — the ledger entry and the human attestation are mandatory, enforced by the pipeline, not by policy
|
||||||
|
- **Full traceability** — a production change is traceable from the contract that declared intent, through the policy scan, the confidence score, the attestation, to the applied outcome
|
||||||
|
|
||||||
|
**Benefit:** trust is provable — not a marketing claim, a queryable record. An auditor answers "who approved this, when, on what evidence?" in one query; a CTO answers "how many of last quarter's prod changes were touchless?" in one query.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 13 — Cost & ROI
|
||||||
|
|
||||||
|
**The ROI formula and the cost estimates — grounded, with the production denominator honestly flagged.**
|
||||||
|
|
||||||
|
- **Cost estimates are pre-apply and offline** — the platform reads the terraform plan and estimates cost before anything is applied; a cost regression is caught before the spend happens
|
||||||
|
- **The ROI formula:**
|
||||||
|
`Platform ROI = (FTE hours saved × blended rate + cloud savings + avoided downtime) ÷ platform op cost`
|
||||||
|
- **The four CTO-grade metrics are the ROI proof:** Lead Time (PR → Prod), Infrastructure Vulnerability Count (trend), MTTR, Cloud Spend Reduction — all flow into PowerBI
|
||||||
|
- **Honest caveat:** derived metrics are computed on internal runs today; the production-denominator activates when a pilot estate runs. The formula is grounded; the production numbers are not yet.
|
||||||
|
|
||||||
|
**Benefit:** the ROI is not a black box — the formula is shown, the four metrics are committed, and the production-denominator caveat is stated up front. The CFO sees exactly what is real today and what activates with a pilot.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 14 — What's Deferred — and Why
|
||||||
|
|
||||||
|
**Honesty about what is not measured yet — and the blocking work for each.**
|
||||||
|
|
||||||
|
To be clear: these deferrals are *measurement infrastructure*, not the autonomy itself. The platform runs without an operator in the loop of normal operations. What is deferred is the evidence pipeline for certain metrics — not the autonomy.
|
||||||
|
|
||||||
|
| # | Deferred metric | Blocking work |
|
||||||
|
|---|-----------------|---------------|
|
||||||
|
| 1 | Live infra health, outbox write rate, SLA | Live AWS re-provisioning (currently torn down to zero-cost steady state) |
|
||||||
|
| 2 | Tamper-evident ledger checkpoints | Audit-ledger build-out (Object Lock + signed checkpoints) |
|
||||||
|
| 3 | Onboarding funnel (requested → granted) | Auto-grant implementation |
|
||||||
|
| 4 | Drift auto-reversal | Drift-detection scheduler (not yet built) |
|
||||||
|
| 5 | Live cost reconciliation | Live AWS re-provisioning + actual-spend feed |
|
||||||
|
| 6 | Predictive vs reactive ratio | ML anomaly-forecasting service (not yet built) |
|
||||||
|
|
||||||
|
**Benefit:** the boundaries are explicit — what Nova measures today, and exactly what blocks the rest. The autonomy is real; the measurement gaps are documented with the work that unblocks each one.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 15 — Roadmap to the North Star
|
||||||
|
|
||||||
|
**The path from the grounded metrics to the 12–18 month targets — each deferred metric has an unblock path and a timeframe.**
|
||||||
|
|
||||||
|
| Timeframe | Work | Unblocks |
|
||||||
|
|-----------|------|----------|
|
||||||
|
| Near-term | Live AWS re-provisioning | Live infra health, outbox write rate, live cost reconciliation, SLA |
|
||||||
|
| Near-term | Auto-grant implementation | Onboarding funnel (requested → granted) |
|
||||||
|
| Mid-term | Drift-detection scheduler | Drift auto-reversal |
|
||||||
|
| Mid-term | Audit-ledger build-out (Object Lock + signed checkpoints) | Tamper-evident ledger checkpoints |
|
||||||
|
| Mid-term | Hot-path activation (batch → near-real-time) | Live-ops dashboard freshness |
|
||||||
|
| Longer-term | ML anomaly-forecasting service | Predictive vs reactive ratio |
|
||||||
|
|
||||||
|
Re-evaluation triggers: each blocking piece of work lifts on its own schedule; the metrics layer evolves as each one lands.
|
||||||
|
|
||||||
|
**Benefit:** every deferred metric has an unblock path — nothing is hand-waved; everything has a plan and a timeframe.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 16 — 12-Month Product Roadmap
|
||||||
|
|
||||||
|
**The product arc from pilot activation to integration — four quarters, four outcomes.**
|
||||||
|
|
||||||
|
| Quarter | Theme | Board-level outcome |
|
||||||
|
|---------|-------|---------------------|
|
||||||
|
| **Q1** | Pilot Activation | Nova runs a real customer estate end-to-end, autonomously, with a measurable zero-touch rate. |
|
||||||
|
| **Q2** | Provable Trust | Every automated decision lands in a tamper-evident ledger; the CFO sees real cloud-spend reconciliation. |
|
||||||
|
| **Q3** | Compounding ROI | Quarter-over-quarter cloud spend drops; drift is detected and reversed without a human. |
|
||||||
|
| **Q4** | Integration & Predictive | AI agents deploy through Nova by default; the ML anomaly-forecasting service goes live. |
|
||||||
|
|
||||||
|
Grounded in the four strategic objectives (autonomy, provable trust, ROI, integration) and the deferred-metric unblock paths.
|
||||||
|
|
||||||
|
**Benefit:** the 12-month product arc — each quarter activates a strategic objective and its corresponding board-level metric, from pilot activation through integration leadership.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 17 — Quarter-by-Quarter Outcomes
|
||||||
|
|
||||||
|
| Quarter | Product theme | Key deliverable | Target metric |
|
||||||
|
|---------|---------------|-----------------|---------------|
|
||||||
|
| **Q1** | Pilot Activation | Re-provision live AWS; activate first pilot estate; onboarding auto-grant | Touchless ≥ 99% · Escalation < 0.1% · Accuracy ≥ 99.5% |
|
||||||
|
| **Q2** | Provable Trust | Tamper-evident ledger (Object Lock + signed checkpoints); daily checkpoints; live cost reconciliation | Decision Ledger Coverage 100% · Cost Savings ≥ 25% |
|
||||||
|
| **Q3** | Compounding ROI + Drift | Drift-detection scheduler; auto-reversal; pre-apply → actual-spend reconciliation on the pilot estate | Drift Auto-Reversal ≥ 95% · Spend Reduction ≥ 25% |
|
||||||
|
| **Q4** | Integration + Predictive | ML anomaly-forecasting; AI-agent intent surface; multi-cloud (Azure/GCP) preview | Predictive:Reactive ≥ 3:1 · AI-Agent Intent Share (first measurement) |
|
||||||
|
|
||||||
|
**Month-18 destination:** *"Nova is the layer enterprise leadership points to when they say 'we don't have an infrastructure ops team anymore, and the audit trail is stronger than it ever was.'"*
|
||||||
|
|
||||||
|
**Benefit:** each quarter has a concrete deliverable, a target metric grounded in a strategic objective, and a path from "honestly deferred" to "shipped and measured."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 18 — Production-Grade Guidance via Atelier (1/2)
|
||||||
|
|
||||||
|
**Nova instructs the citizen developer's AI agent on production-grade engineering — a set of skills and an MCP server.**
|
||||||
|
|
||||||
|
- **Skills** — markdown files keyed to production-grade engineering domains (API, security, data, testing, observability, errors, DevOps, infrastructure-as-code, compliance); the skills extend the baseline catalog with Nova-specific production-grade principles
|
||||||
|
- **MCP server** — a plugin-registry, stdio server exposing four tools: `lookup_principle`, `list_domains`, `matrix_lookup`, `validate_against_principles`. The developer's AI agent (or any agentic SDLC platform) calls these tools to look up the principles that apply to its submission
|
||||||
|
- **The integration point is the same regardless of source** — whether the submission comes from an AI coding agent, an agentic SDLC platform, or a traditional IDE, the same skills and MCP server apply. This is how Nova makes the citizen developer production-grade without owning the PDLC
|
||||||
|
|
||||||
|
**Benefit:** the citizen developer's AI agent is not unguided — Nova provides production-grade engineering principles as skills and as an MCP surface, so submissions arrive at the contract boundary already aligned with the platform's standards.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 19 — Production-Grade Guidance via Atelier (2/2)
|
||||||
|
|
||||||
|
**Agentic validation catches engineering-discipline gaps that deterministic scanners miss — and the validation is reproducible.**
|
||||||
|
|
||||||
|
- **Beyond deterministic scanners** — Wiz, Checkmarx, and Mend check policy and secrets; they do not check engineering discipline. The Atelier MCP server catches correctness, clarity, and observability gaps that deterministic tools cannot: "is this service observable?", "is this error path handled?", "is this API contract clear?"
|
||||||
|
- **Agentic validation, not a second policy engine** — the MCP server gives the AI agent the principles to validate against; the agent does the validation. The agent reasons about the submission against the principles, not a second static scan
|
||||||
|
- **Vendored for audit reproducibility** — Atelier is vendored at a pinned tag. A validation result is replayable against the exact principles that produced it, so an audit can reproduce a validation months later, not just trust a log line
|
||||||
|
|
||||||
|
**Benefit:** the citizen developer's submission is checked for engineering discipline, not just policy compliance — and the check is reproducible for audit. That is what makes the submission production-grade, regardless of which upstream platform produced it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 20 — Recap + Ask
|
||||||
|
|
||||||
|
**The 4-beat recap + the business decision.**
|
||||||
|
|
||||||
|
**Recap:**
|
||||||
|
- **Problem:** product teams own infrastructure without the discipline and lifecycle planning it requires; bandwidth gaps and tribal knowledge leave operations exposed
|
||||||
|
- **Solution:** autonomous cloud delivery — operations become visible, trust is provable (deterministic scoring), humans at stage gates
|
||||||
|
- **Proof:** 100% ledger coverage, 100% attestation coverage, grounded ROI formula, four CTO-grade metrics flowing into PowerBI
|
||||||
|
- **Roadmap:** deferred metrics have unblock paths; the 12-month product arc activates one strategic objective per quarter
|
||||||
|
|
||||||
|
**The ask:** "Approve a pilot estate to activate the production-denominator metrics (Lead Time, Vulnerability Count, MTTR, Cloud Spend), and approve the tamper-evident ledger build-out to move from the local hash-chain to S3 Object Lock + signed checkpoints. These two decisions move Nova from 'pipeline-ready' to 'production-proven.'"
|
||||||
|
|
||||||
|
**Benefit:** a clear business decision — approve a pilot and the ledger build-out — with the confidence that every claim in this deck is grounded, derived, or honestly deferred.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- _class: title -->
|
||||||
|
<!-- _paginate: false -->
|
||||||
|
|
||||||
|
## Appendix A1 — Metrics Glossary
|
||||||
|
|
||||||
|
| KPI | Definition | Status |
|
||||||
|
|-----|-----------|--------|
|
||||||
|
| Touchless Resolution Rate | runs without operational stage-gate block ÷ total | partial (Post-Pilot) |
|
||||||
|
| Human Escalation Frequency | operational stage-gate blocks ÷ total | partial (Post-Pilot) |
|
||||||
|
| Automated Decision Accuracy | decisions not followed by failure within 5min | partial (Post-Pilot) |
|
||||||
|
| MTTR (p95) | apply.failed → successful retry | grounded |
|
||||||
|
| Confidence-Gate Halt Rate | runs with band=block ÷ total | grounded |
|
||||||
|
| Provisioning Lead Time | run.completed − run.started | grounded |
|
||||||
|
| Deployment Frequency | count(run.completed) per day | grounded |
|
||||||
|
| Cost Savings (pre-apply) | sum(delta_usd where delta < 0) | partial (live reconciliation deferred) |
|
||||||
|
| FTE Hours Saved | run count × manual baseline × rate | derived (N=0 caveat) |
|
||||||
|
| Platform ROI | (labor + cloud + avoided downtime) ÷ op cost | derived (N=0 caveat) |
|
||||||
|
| Decision Ledger Coverage | decisions with outcome ÷ total | grounded |
|
||||||
|
| Attestation Coverage | prod/dr attested ÷ total prod/dr | grounded |
|
||||||
|
| Policy Compliance Rate | 1 − failed_assets ÷ total | grounded |
|
||||||
|
|
||||||
|
**Benefit:** a reference for every metric mentioned in the deck.
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
# Nova — The Autonomous Cloud Delivery Platform: Talking Points
|
||||||
|
|
||||||
|
> Step 4 of the 4-step deck process. Presenter cues distilled from the
|
||||||
|
> source of truth (`nova-autonomous-cloud-delivery.md`). 3-6 bullets per
|
||||||
|
> slide + key takeaway. Indexed by Marp slide #.
|
||||||
|
> v1.21 — REQ-245
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Slide 1 — The Problem
|
||||||
|
- Open with the shift: "you build it, you run it" put Terraform into product teams — ownership without discipline is destroying value
|
||||||
|
- Land the lifecycle-planning gap: resources authored for creation, not for patching/rollback → destructive changes
|
||||||
|
- Land the urgency: AI-era 0-day pace demands proactive scanning as code + at runtime, remediated at threat pace
|
||||||
|
- Call out tribal knowledge / the rockstar-operator problem — the platform should encode the discipline, not the person
|
||||||
|
- Do NOT frame this as "humans are the problem" — the problem is ownership without the discipline and tooling
|
||||||
|
- **Key takeaway:** the problem is infrastructure ownership without discipline; the answer is an autonomous platform that encodes the discipline
|
||||||
|
|
||||||
|
### Slide 2 — Nova's Vision
|
||||||
|
- Read the vision verbatim — "infrastructure operations become visible" is the operative phrase
|
||||||
|
- Emphasize "provable, not promised" — trust established by deterministic scripts; the platform functions without AI
|
||||||
|
- State the attestation model up front: QA for production, SRE for operational readiness
|
||||||
|
- **Key takeaway:** autonomous operations with provable trust — security, remediation velocity, reliability, lead time made visible, not promised
|
||||||
|
|
||||||
|
### Slide 3 — Strategic Objectives
|
||||||
|
- Objective #1: zero-touch operations — autonomy as the default, not the demo; stage-gate attestation (QA, SRE) remains human by design
|
||||||
|
- Objective #2 is the one to land carefully: trust = deterministic scoring, not an LLM; the platform functions without AI
|
||||||
|
- Objective #3: four CTO-grade metrics (Lead Time, Vuln Count, MTTR, Spend) — all flow into PowerBI
|
||||||
|
- Objective #4 is the integration thesis: Nova integrates with any upstream source; provides skills + MCP; all prod intents go through the same controls
|
||||||
|
- **Key takeaway:** the scope is explicit — Nova governs infra + delivery, integrates with any source through one contract, measures success on four CTO metrics
|
||||||
|
|
||||||
|
### Slide 4 — Anti-Goals (What Nova Is NOT)
|
||||||
|
- Not a general-purpose AI agent platform
|
||||||
|
- Not a system that removes humans from accountability — only from normal operations
|
||||||
|
- Not an upstream development platform (no product backlogs, IDE, code authorship)
|
||||||
|
- Not a replacement for the Product Development Lifecycle (PDLC)
|
||||||
|
- Anti-goals #3 and #4 protect the scope boundary — Nova will not become an IDE or a product-planning tool
|
||||||
|
- **Key takeaway:** the boundaries are explicit — Nova is purpose-built for infra ops + delivery, not a general-purpose AI agent or an upstream dev platform
|
||||||
|
|
||||||
|
### Slide 5 — Scope: Downstream of PDLC
|
||||||
|
- Nova governs infra + delivery only; the PDLC (backlog, code authorship, IDE) is upstream — Nova never penetrates it
|
||||||
|
- Integration is only through the validated contract boundary
|
||||||
|
- Any upstream source (AI agent, agentic SDLC, dev platform) produces submissions subject to the same compliance standards
|
||||||
|
- Nova validates the submission, not the author
|
||||||
|
- **Key takeaway:** Nova is purpose-built for infrastructure operations; the scope boundary is clean and bounded
|
||||||
|
|
||||||
|
### Slide 6 — RACI: Who Owns What
|
||||||
|
- Four roles now: Citizen Developer, Platform, Quality Engineering, SRE
|
||||||
|
- Quality attestation is owned by Quality Engineering (not the Platform); Production readiness is owned by SRE
|
||||||
|
- The Platform runs the checks agentically but is never the Accountable party for the gate — that separation keeps the platform honest
|
||||||
|
- Production readiness is co-owned: the platform runs attestations; the citizen developer authorizes the promotion at the stage gate
|
||||||
|
- **Key takeaway:** you bring FRs + UAT; Nova provides NFRs + infra; QE guards the gate evidence; SRE signs off on production readiness
|
||||||
|
|
||||||
|
### Slide 7 — The Platform Pipeline
|
||||||
|
- Walk the pipeline left-to-right: contract → resolver → adapter → Checkov (static) → plan → Wiz (on plan) → confidence → gate → apply
|
||||||
|
- Two-stage scan: Checkov on static code BEFORE the plan (fail-fast dev feedback); Wiz on the plan (or Checkov as drop-in if no Wiz creds)
|
||||||
|
- Never both Wiz + Checkov on the plan — avoid duplicate noise
|
||||||
|
- Dev is autonomous; qa/prod/dr require attestation (QA for quality, SRE for production readiness)
|
||||||
|
- **Key takeaway:** two layers of scanning, zero operator involvement in normal operations
|
||||||
|
|
||||||
|
### Slide 8 — The Decision Ledger
|
||||||
|
- "AI decisions" are really automated decisions — deterministic scripts calculate a score; the platform functions without AI
|
||||||
|
- Do not dwell on the storage substrate — the value is accountability (immutable, queryable, traceable to outcome), not the database
|
||||||
|
- Every stage-gate attestation is captured with approver identity and the evidence presented
|
||||||
|
- When an LLM planner is added later, it emits richer alternatives without breaking the schema
|
||||||
|
- **Key takeaway:** autonomous is defensible because every decision is immutable, queryable, accountable — and "automated" means deterministic scoring, not a black-box LLM
|
||||||
|
|
||||||
|
### Slide 9 — Attestation Matrix: QA
|
||||||
|
- The matrix is not a rubber stamp — structured, freshness-validated
|
||||||
|
- Each concern now has a plain-language description of what is being attested (the old "operator-supplied" label is gone)
|
||||||
|
- Three QA concerns: functional correctness (24h), performance baseline (7d), security posture (24h)
|
||||||
|
- Each concern has a freshness window — evidence older than the window does not satisfy the gate
|
||||||
|
- **Key takeaway:** QA signs off on quality before any promotion — the gate is explicit, not implicit
|
||||||
|
|
||||||
|
### Slide 10 — Attestation Matrix: Prod/DR
|
||||||
|
- Seven prod/DR concerns: operational readiness, incident response, capacity & cost, DR drill, chaos, backup, DR region deploy
|
||||||
|
- SRE signs off on operability (runbooks, dashboards, on-call), incident response, capacity, and the three resilience checks
|
||||||
|
- Each concern has a freshness window — 30d/90d/180d depending on the control
|
||||||
|
- SoD on prod: the approver can't be the same person who built it — the rule that keeps the gate honest
|
||||||
|
- **Key takeaway:** autonomy in operations, human in accountability, by design — the matrix is what makes autonomous operations safe enough to trust in production
|
||||||
|
|
||||||
|
### Slide 11 — Telemetry & Live Ops
|
||||||
|
- Deliberately minimal: Nova-native CloudEvents; no Kafka/Prometheus/ClickHouse
|
||||||
|
- The live-ops dashboard is built in PowerBI on top of the exported views — leadership sees the same numbers the platform produces
|
||||||
|
- Every number in the Proof slides is traceable to a signal — "where does this number come from?" → a query against the cold store
|
||||||
|
- This is where the "infrastructure operations become visible" theme lands concretely
|
||||||
|
- **Key takeaway:** the architecture is the trust substrate — operations become visible in PowerBI, with full traceability
|
||||||
|
|
||||||
|
### Slide 12 — Decision Ledger + Attestation Coverage
|
||||||
|
- Both 100% — no automated decision is ever lost; no prod/dr promotion lands without a human sign-off
|
||||||
|
- The mandatory-by-design point: the ledger entry + the human attestation are a gate, not a best-effort feature
|
||||||
|
- Easily queried: by run, by environment, by approver, by outcome — the audit trail is a query, not a forensic exercise
|
||||||
|
- **Key takeaway:** trust is provable — not a marketing claim, a queryable record; no change to production without both the ledger entry and the human attestation
|
||||||
|
|
||||||
|
### Slide 13 — Cost & ROI
|
||||||
|
- The ROI formula is shown inline — not hidden in a footnote
|
||||||
|
- The four CTO-grade metrics are the ROI proof — Lead Time, Vuln Count, MTTR, Cloud Spend
|
||||||
|
- The N=0 caveat is stated explicitly: the formula is grounded; the production numbers activate with a pilot
|
||||||
|
- **Key takeaway:** the ROI is not a black box — the formula is shown, the four metrics are committed, the production-denominator caveat is up front
|
||||||
|
|
||||||
|
### Slide 14 — What's Deferred — and Why
|
||||||
|
- The preempt is critical: these deferrals are measurement infrastructure, not autonomy — the platform IS autonomous in operations
|
||||||
|
- The blocking work is named in plain language (no decision IDs) — "live AWS re-provisioning", "drift-detection scheduler", "ML service"
|
||||||
|
- Showing this to leadership demonstrates honesty, not weakness
|
||||||
|
- **Key takeaway:** the autonomy is real; the measurement gaps are documented with the work that unblocks each one
|
||||||
|
|
||||||
|
### Slide 15 — Roadmap to the North Star
|
||||||
|
- Each deferred metric has an unblock path and a timeframe — near-term, mid-term, longer-term
|
||||||
|
- No status column: most of it is not implemented yet, so status would be noise
|
||||||
|
- Re-evaluation triggers: each blocking piece of work lifts on its own schedule
|
||||||
|
- **Key takeaway:** every deferred metric has a plan and a timeframe — nothing is hand-waved
|
||||||
|
|
||||||
|
### Slide 16 — 12-Month Product Roadmap
|
||||||
|
- This is the *product* roadmap, forward-looking only
|
||||||
|
- Q1 Pilot Activation → Q2 Provable Trust → Q3 Compounding ROI → Q4 Integration & Predictive
|
||||||
|
- Each quarter activates one strategic objective from the North Star
|
||||||
|
- **Key takeaway:** the 12-month product arc — each quarter activates a strategic objective and its board-level metric
|
||||||
|
|
||||||
|
### Slide 17 — Quarter-by-Quarter Outcomes
|
||||||
|
- Q1: three post-pilot metrics go live (Touchless ≥99%, Escalation <0.1%, Accuracy ≥99.5%) — denominator activates with the pilot
|
||||||
|
- Q2: Decision Ledger Coverage was already grounded — tamper-evidence is the Q2 upgrade (local hash-chain → Object Lock + signed checkpoints)
|
||||||
|
- Q3: Drift Auto-Reversal ≥95% unblocks when the drift scheduler ships; Spend Reduction ≥25% measured against the pilot baseline
|
||||||
|
- Q4: Predictive:Reactive ≥3:1 requires the ML forecasting service; AI-Agent Intent Share is a first measurement (aspirational-metric)
|
||||||
|
- **Key takeaway:** each quarter has a concrete deliverable, a target metric grounded in a strategic objective, and a path from deferred to shipped
|
||||||
|
|
||||||
|
### Slide 18 — Production-Grade Guidance via Atelier (1/2)
|
||||||
|
- Nova instructs the citizen developer's AI agent via skills (markdown, keyed to engineering domains) + an MCP server (4 tools, plugin-registry, stdio)
|
||||||
|
- The integration point is the same regardless of source — AI agent, agentic SDLC, traditional IDE all get the same skills + MCP
|
||||||
|
- This is how Nova makes the citizen developer production-grade without owning the PDLC
|
||||||
|
- **Key takeaway:** the citizen developer's AI agent is not unguided — Nova provides engineering principles as skills + MCP
|
||||||
|
|
||||||
|
### Slide 19 — Production-Grade Guidance via Atelier (2/2)
|
||||||
|
- The value is the gap deterministic scanners leave: engineering discipline (Wiz/Checkmarx/Mend check policy/secrets, not discipline)
|
||||||
|
- The MCP server catches "is this service observable?", "is this error path handled?", "is this API contract clear?"
|
||||||
|
- Vendored at a pinned tag → audit reproducibility — a validation result is replayable months later
|
||||||
|
- **Key takeaway:** submissions are checked for engineering discipline, not just policy compliance — and the check is reproducible for audit
|
||||||
|
|
||||||
|
### Slide 20 — Recap + Ask
|
||||||
|
- Recap the 4-beat arc so the audience leaves with the structure
|
||||||
|
- The ask is a business decision: approve a pilot estate + the tamper-evident ledger build-out
|
||||||
|
- "Pipeline-ready" → "production-proven" is the value proposition
|
||||||
|
- **Key takeaway:** approve a pilot + the ledger build-out to move from pipeline-ready to production-proven
|
||||||
|
|
||||||
|
### Appendix A1 — Metrics Glossary
|
||||||
|
- Reference for every metric mentioned in the deck
|
||||||
|
- Use if the audience asks "what does X mean?"
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,747 @@
|
|||||||
|
# Nova — The Autonomous Cloud Delivery Platform
|
||||||
|
|
||||||
|
> **Source of truth** (Step 1 of the 4-step deck process).
|
||||||
|
> Unified narrative deck. 4-beat arc: Problem → Solution → Proof →
|
||||||
|
> Roadmap + Ask. x3 structure at deck level (opening = the problem + the
|
||||||
|
> arc, body = tell them, closing = recap + ask) AND per slide (opens with
|
||||||
|
> what it covers, delivers, closes with a benefit callout written for a
|
||||||
|
> tech-leadership audience).
|
||||||
|
>
|
||||||
|
> **Honesty model:** every metric cited is grounded (cites a source),
|
||||||
|
> derived (documented formula), or deferred (cites the blocking work).
|
||||||
|
> No fabricated numbers. Internal provenance (decision IDs, requirement
|
||||||
|
> IDs, internal file paths) is kept out of the audience-facing slides —
|
||||||
|
> those live in the appendix and the `.ciagent/` files only.
|
||||||
|
>
|
||||||
|
> v1.21 — Deck Refinement & Pipeline Hardening
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 1 — The Problem
|
||||||
|
|
||||||
|
**Product teams now own their cloud infrastructure — but ownership without
|
||||||
|
discipline is destroying value.**
|
||||||
|
|
||||||
|
The broad shift to "you build it, you run it" put Terraform into the hands
|
||||||
|
of product teams. The intention was right: teams that own their stack ship
|
||||||
|
faster. The reality is that infrastructure-as-code is a different craft
|
||||||
|
from software development, and the engineering standards that teams apply
|
||||||
|
to application code are rarely applied to the infrastructure that carries
|
||||||
|
it.
|
||||||
|
|
||||||
|
- **No lifecycle planning.** Resources are authored for creation, not for
|
||||||
|
patching, decommissioning, or rollback. When a change is needed, the
|
||||||
|
change is destructive — because no one planned the lifecycle.
|
||||||
|
- **Proactive scanning is not part of authoring.** In a year where
|
||||||
|
AI-frontier models discover and exploit zero-day vulnerabilities at a
|
||||||
|
rapid pace, teams cannot keep up by reacting. Infrastructure modules
|
||||||
|
must be scanned as code and at runtime, post-deployment — and remediated
|
||||||
|
at the pace the threat moves, not the pace a sprint allows.
|
||||||
|
- **Bandwidth gaps in infrastructure operations.** An unusual amount of
|
||||||
|
time is spent on remediation, the push for innovation does not pause,
|
||||||
|
and the result is that operational work is chronically under-resourced.
|
||||||
|
Gaps open. Detections are missed. Incidents grow.
|
||||||
|
- **Tribal knowledge and the rockstar-operator problem.** Operations
|
||||||
|
depend on a handful of administrators who hold the infrastructure in
|
||||||
|
their heads. When they leave, the knowledge leaves with them. The
|
||||||
|
platform should encode the discipline, not the person.
|
||||||
|
|
||||||
|
Every hour a developer spends writing, deploying, fixing, or remediating
|
||||||
|
infrastructure is an hour not spent releasing features to production and
|
||||||
|
generating value.
|
||||||
|
|
||||||
|
> **Benefit:** the rest of this deck shows the answer — an autonomous
|
||||||
|
> cloud delivery platform that encodes infrastructure discipline as
|
||||||
|
> policy, scans proactively, remediates rapidly, and makes operations
|
||||||
|
> visible to leadership rather than hidden in tribal knowledge.
|
||||||
|
|
||||||
|
> **Speaker notes:** Do not frame this as "humans are the problem." The
|
||||||
|
> problem is that ownership was granted without the discipline, tooling,
|
||||||
|
> and lifecycle planning that infrastructure requires. The operator is
|
||||||
|
> not the bottleneck because operators exist — the bottleneck is that
|
||||||
|
> operations depend on a few individuals instead of an encoded system.
|
||||||
|
|
||||||
|
> **Transition:** "Here is the destination Nova is building toward."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 2 — Nova's Vision
|
||||||
|
|
||||||
|
**Infrastructure operations become visible. Every environment provisioned,
|
||||||
|
every incident healed, every risk remediated — by an autonomous system
|
||||||
|
whose trustworthiness is provable, not promised. Human attestation remains
|
||||||
|
required at stage gates; the operator is never in the loop of normal
|
||||||
|
operations.**
|
||||||
|
|
||||||
|
- **Visibility is the recurring theme.** Security posture, remediation
|
||||||
|
velocity, reliability, and lead time are surfaced as queryable signals —
|
||||||
|
not hidden in a person's head or a Slack thread.
|
||||||
|
- **Provable, not promised.** Trust is established by deterministic
|
||||||
|
scripts that calculate a score and gate the action. The platform
|
||||||
|
functions without AI. "AI decisions" are really automated decisions.
|
||||||
|
- **Autonomy in operations, human at stage gates.** QA signs off for
|
||||||
|
production; SRE greenlights based on operational readiness. The
|
||||||
|
absence of an operator in the loop is never the absence of a record.
|
||||||
|
|
||||||
|
> **Benefit:** the destination is autonomous operations with provable
|
||||||
|
> trust — security, remediation velocity, reliability, and lead time made
|
||||||
|
> visible to leadership, not promised to them.
|
||||||
|
|
||||||
|
> **Speaker notes:** "Visible" is the operative word. The vision is not
|
||||||
|
> just that operations run without an operator — it is that operations
|
||||||
|
> become observable, queryable, and accountable. That is what makes the
|
||||||
|
> trust defensible.
|
||||||
|
|
||||||
|
> **Transition:** "The vision is ambitious — here are the strategic
|
||||||
|
> objectives that make it concrete, and the anti-goals that keep it
|
||||||
|
> focused."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 3 — Strategic Objectives
|
||||||
|
|
||||||
|
**4 Strategic Objectives:**
|
||||||
|
1. **Demonstrate production-grade zero-touch operations** — autonomy as
|
||||||
|
the default, not the demo. Stage-gate attestation (QA, SRE) remains
|
||||||
|
human by design.
|
||||||
|
2. **Establish provable trust in automated decisions** — deterministic
|
||||||
|
scripts calculate a score; a band outcome gates the action. The
|
||||||
|
platform functions without AI. The Decision Ledger, confidence
|
||||||
|
scoring, circuit breakers, and blast-radius controls make
|
||||||
|
"autonomous" a defensible claim, not a marketing one.
|
||||||
|
3. **Deliver compounding, quantifiable ROI** — measured on four CTO-grade
|
||||||
|
metrics, all flowing into PowerBI:
|
||||||
|
- **Lead Time** (PR → Production) — downward trend.
|
||||||
|
- **Infrastructure Vulnerability Count** — downward trend
|
||||||
|
(proactive scanning keeps up with the AI-era 0-day pace).
|
||||||
|
- **MTTR** — for platform-detected and platform-remediated incidents.
|
||||||
|
- **Cloud Spend Reduction** — on pilot estates vs. the pre-Nova
|
||||||
|
baseline.
|
||||||
|
4. **Integrate with externally owned development platforms — regardless
|
||||||
|
of source.** Nova integrates with externally owned PDLC, SDLC,
|
||||||
|
Agentic, and Citizen Developer platforms. Nova provides skills and
|
||||||
|
MCP endpoints that help the developer or AI agent make their
|
||||||
|
application production-grade. Regardless of the source, all intents
|
||||||
|
to deploy to production go through the same rigorous controls,
|
||||||
|
quality gates, attestation, and evidence stream.
|
||||||
|
|
||||||
|
> **Benefit:** the scope is explicit — Nova governs infrastructure and
|
||||||
|
> delivery, integrates with any upstream source through one validated
|
||||||
|
> contract, and measures success on four metrics a CTO can repeat back.
|
||||||
|
|
||||||
|
> **Speaker notes:** Objective #2 is the one to land carefully: trust is
|
||||||
|
> established by deterministic scoring, not by an LLM. The platform
|
||||||
|
> functions without AI.
|
||||||
|
|
||||||
|
> **Transition:** "The objectives are concrete — here is what Nova is
|
||||||
|
> NOT, to keep it focused."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 4 — Anti-Goals (What Nova Is NOT)
|
||||||
|
|
||||||
|
1. Not a general-purpose AI agent platform.
|
||||||
|
2. Not a system that removes humans from accountability — only from
|
||||||
|
normal operations.
|
||||||
|
3. Not an upstream development platform (no product backlogs, IDE, code
|
||||||
|
authorship).
|
||||||
|
4. Not a replacement for the Product Development Lifecycle (PDLC).
|
||||||
|
|
||||||
|
> **Benefit:** the boundaries are explicit — Nova is purpose-built for
|
||||||
|
> infrastructure operations and delivery, not a general-purpose AI agent
|
||||||
|
> or an upstream development platform.
|
||||||
|
|
||||||
|
> **Speaker notes:** Anti-goals #3 and #4 protect the scope boundary —
|
||||||
|
> Nova will not become an IDE or a product-planning tool.
|
||||||
|
|
||||||
|
> **Transition:** "The scope boundary is explicit — here is exactly
|
||||||
|
> where Nova sits relative to the product development lifecycle."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 5 — Scope: Downstream of PDLC
|
||||||
|
|
||||||
|
**Nova governs infrastructure and delivery. The PDLC is upstream — Nova
|
||||||
|
never penetrates it. Integration is through one validated contract.**
|
||||||
|
|
||||||
|
- **The PDLC is upstream:** product backlog, code authorship (AI agent,
|
||||||
|
IDE, agentic SDLC), sprint planning, application business logic.
|
||||||
|
- **Nova is downstream:** contract ingestion → submission-readiness gate
|
||||||
|
→ policy enforcement → cloud resource lifecycle → environment
|
||||||
|
progression (dev → qa → prod → dr) → immutable audit + attestation.
|
||||||
|
- **The integration point is one contract.** The citizen developer's AI
|
||||||
|
coding agent, an upstream agentic SDLC platform, or any development
|
||||||
|
platform may all produce submissions — the source does not matter
|
||||||
|
because all are subject to the same compliance standards.
|
||||||
|
- **Nova validates the submission, not the author.** The audit trail is
|
||||||
|
the same; the policy envelope is the same; the evidence stream is the
|
||||||
|
same.
|
||||||
|
|
||||||
|
> **Benefit:** a clean scope boundary — Nova is purpose-built for
|
||||||
|
> infrastructure operations and integrates with any upstream source
|
||||||
|
> through one validated contract, so the platform team's surface area
|
||||||
|
> stays bounded.
|
||||||
|
|
||||||
|
> **Speaker notes:** This slide protects the scope. The moment Nova
|
||||||
|
> starts owning the PDLC, it loses focus. The contract boundary is what
|
||||||
|
> keeps Nova deep on infrastructure and delivery rather than shallow on
|
||||||
|
> everything.
|
||||||
|
|
||||||
|
> **Transition:** "With the scope clear, here is who owns what across the
|
||||||
|
> delivery lifecycle."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 6 — RACI: Who Owns What
|
||||||
|
|
||||||
|
**Four roles, one matrix — the citizen developer owns FRs + UAT, the
|
||||||
|
platform owns NFRs + infra, quality engineering owns the gate evidence,
|
||||||
|
and SRE owns operational readiness.**
|
||||||
|
|
||||||
|
| Work Category | Citizen Dev | Platform | Quality Eng | SRE |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| Functional Requirements | **R/A** | C | I | I |
|
||||||
|
| User Acceptance Testing | **R/A** | C | I | I |
|
||||||
|
| Non-Functional Requirements | I | **R/A** | C | C |
|
||||||
|
| Infrastructure (cloud, state, IAM) | I | **R/A** | I | C |
|
||||||
|
| QA (policy, confidence, schema) | C | R | **R/A** | I |
|
||||||
|
| Production deployment to cloud | I | **R/A** | C | C |
|
||||||
|
| Quality attestation (QA sign-off) | **A** | R | **R** | I |
|
||||||
|
| Production readiness (SRE sign-off) | **A** | R | C | **R** |
|
||||||
|
|
||||||
|
**R** = Responsible · **A** = Accountable (sign-off) · **C** = Consulted · **I** = Informed.
|
||||||
|
|
||||||
|
- **Compliance-standard equivalence:** FRs + UAT may come from any
|
||||||
|
upstream source (AI agent, agentic SDLC, dev platform) — all pass the
|
||||||
|
same submission-readiness gate.
|
||||||
|
- **Production readiness is co-owned:** the platform runs the
|
||||||
|
attestations agentically; the citizen developer authorizes the
|
||||||
|
promotion at the stage gate.
|
||||||
|
|
||||||
|
> **Benefit:** every party knows what they bring, what the platform
|
||||||
|
> provides, what quality engineering guards, and where SRE signs off —
|
||||||
|
> accountability is explicit, never diffuse.
|
||||||
|
|
||||||
|
> **Speaker notes:** Quality attestation is now owned by Quality
|
||||||
|
> Engineering (not the Platform), and Production readiness is owned by
|
||||||
|
> SRE. The Platform runs the checks agentically but is never the
|
||||||
|
> Accountable party for the gate — that separation keeps the platform
|
||||||
|
> honest.
|
||||||
|
|
||||||
|
> **Transition:** "With ownership clear, here is how the pipeline
|
||||||
|
> enforces it."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 7 — The Platform Pipeline
|
||||||
|
|
||||||
|
**How intent becomes verified infrastructure — with fail-fast policy
|
||||||
|
scanning before the plan and runtime scanning after it.**
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
A[Contract] --> B[Resolver]
|
||||||
|
B --> C[Adapter]
|
||||||
|
C --> D["Checkov (static code)"]
|
||||||
|
D --> E[Terraform Plan]
|
||||||
|
E --> F["Wiz (on plan)"]
|
||||||
|
F --> G[Confidence Signal]
|
||||||
|
G --> H{Stage Gate}
|
||||||
|
H -->|dev: autonomous| I[Apply]
|
||||||
|
H -->|qa/prod/dr: attested| I
|
||||||
|
I --> J[Evidence + Ledger]
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Contract → resolver → adapter → Checkov on static code (before the
|
||||||
|
plan) → terraform plan → Wiz on the plan → confidence signal → stage
|
||||||
|
gate → apply → evidence + ledger.**
|
||||||
|
- **Fail-fast, quick feedback.** Checkov runs on the authored Terraform
|
||||||
|
code before `terraform plan` so developers get immediate policy
|
||||||
|
feedback, not a delayed plan-stage failure.
|
||||||
|
- **Wiz on the plan when configured; Checkov as a drop-in otherwise.**
|
||||||
|
Wiz scans the terraform plan output. When Wiz credentials are not
|
||||||
|
available, Checkov runs against the plan as a drop-in replacement. Wiz
|
||||||
|
and Checkov are never both run on the plan.
|
||||||
|
- **Dev is autonomous** (no stage gate); **qa/prod/dr require human
|
||||||
|
attestation** (QA for quality, SRE for production readiness).
|
||||||
|
|
||||||
|
> **Benefit:** the pipeline gives developers fast, deterministic feedback
|
||||||
|
> on policy at authoring time and gives the platform a runtime scan on the
|
||||||
|
> resolved plan — two layers of scanning, zero operator involvement in
|
||||||
|
> normal operations.
|
||||||
|
|
||||||
|
> **Speaker notes:** The two-stage scan is the key design: static code
|
||||||
|
> scanning catches policy violations before the cost of a plan; runtime
|
||||||
|
> plan scanning catches what the static code cannot (resolved values,
|
||||||
|
cross-resource issues). The platform picks the runtime scanner based on
|
||||||
|
configuration — never both, to avoid duplicate noise.
|
||||||
|
|
||||||
|
> **Transition:** "The pipeline produces decisions — here is how every
|
||||||
|
> decision is captured and made accountable."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 8 — The Decision Ledger
|
||||||
|
|
||||||
|
**Every automated decision is captured, immutable, queryable — and
|
||||||
|
accountable.**
|
||||||
|
|
||||||
|
- **What is captured:** every action the platform takes — the chosen
|
||||||
|
action, the confidence score, the alternatives considered, whether a
|
||||||
|
human overrode it, and the outcome (backfilled once the apply
|
||||||
|
completes). Every stage-gate attestation (QA sign-off, SRE
|
||||||
|
production-readiness sign-off) is captured with approver identity and
|
||||||
|
the evidence that was presented.
|
||||||
|
- **"AI decisions" are really automated decisions.** The decisions are
|
||||||
|
made by deterministic scripts that calculate a score and a band; the
|
||||||
|
platform functions without AI. The ledger captures the real decision
|
||||||
|
path — not a fabricated "AI agent." When an LLM planner is added later,
|
||||||
|
it will emit richer alternatives without breaking the schema.
|
||||||
|
- **The value is accountability, not the storage engine.** The ledger is
|
||||||
|
an append-only, tamper-evident record. The point is not which database
|
||||||
|
it lives in — the point is that every decision is queryable for
|
||||||
|
auditing, traceable to an outcome, and impossible to rewrite after the
|
||||||
|
fact.
|
||||||
|
|
||||||
|
> **Benefit:** "autonomous" is defensible because every decision the
|
||||||
|
> platform makes is immutable, queryable, and accountable — and the
|
||||||
|
> audience knows exactly what "automated" means here: deterministic
|
||||||
|
> scoring, not a black-box LLM.
|
||||||
|
|
||||||
|
> **Speaker notes:** Do not dwell on the storage substrate. The audience
|
||||||
|
> cares that the ledger is append-only, queryable, and tied to outcomes —
|
||||||
|
> not that it is a hash-chain in a SQLite file. The D-122 honesty point
|
||||||
|
> is restated without the decision ID: the platform's decisions are
|
||||||
|
> deterministic; the ledger captures that real path.
|
||||||
|
|
||||||
|
> **Transition:** "Decisions are captured — here is how stage-gate
|
||||||
|
> attestation keeps humans in accountability."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 9 — Attestation Matrix: QA
|
||||||
|
|
||||||
|
**The designed controls that keep humans at stage gates — QA concerns,
|
||||||
|
freshness-validated.**
|
||||||
|
|
||||||
|
| Concern | Env | Freshness | Description |
|
||||||
|
|---------|-----|-----------|-------------|
|
||||||
|
| Functional correctness | qa | 24h | The application behaves as specified; evidence accepted from the consumer's UAT. |
|
||||||
|
| Performance baseline | qa | 7d | The deployment meets its performance envelope vs. the agreed baseline. |
|
||||||
|
| Security posture | qa | 24h | The deployment's security findings have been reviewed and accepted. |
|
||||||
|
|
||||||
|
- Each concern has a freshness window — evidence older than the window
|
||||||
|
does not satisfy the gate.
|
||||||
|
- Concerns that are offline-testable run for real; concerns that require
|
||||||
|
external evidence accept signed artifacts.
|
||||||
|
|
||||||
|
> **Benefit:** QA signs off on quality before any promotion — the gate
|
||||||
|
> is explicit, not implicit.
|
||||||
|
|
||||||
|
> **Speaker notes:** The matrix is not a rubber stamp. Each concern has a
|
||||||
|
> freshness window and a plain-language description of what is being
|
||||||
|
> attested. The "operator-supplied" label from the prior deck was
|
||||||
|
> dropped — every concern now has a plain-language description.
|
||||||
|
|
||||||
|
> **Transition:** "QA is half the matrix — here are the production and
|
||||||
|
> DR controls."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 10 — Attestation Matrix: Prod/DR
|
||||||
|
|
||||||
|
**Production and DR controls — operational readiness, resilience, and
|
||||||
|
disaster recovery.**
|
||||||
|
|
||||||
|
| Concern | Env | Freshness | Description |
|
||||||
|
|---------|-----|-----------|-------------|
|
||||||
|
| Operational readiness | prod | 30d | SRE confirms the deployment is operable: runbooks, dashboards, on-call coverage. |
|
||||||
|
| Incident response | prod | 90d | The on-call path has been exercised; the deployment has a working incident-response plan. |
|
||||||
|
| Capacity & cost | prod | 30d | Capacity headroom and monthly cost are within the agreed envelope. |
|
||||||
|
| Resilience: DR drill | prod | 180d | A DR drill has been run and the deployment recovered within the RTO. |
|
||||||
|
| Resilience: chaos | prod | 90d | A chaos exercise has been run and the deployment absorbed the failure. |
|
||||||
|
| Resilience: backup | prod | 30d | Backups are restorable and have been tested within the freshness window. |
|
||||||
|
| DR region deploy | dr | 180d | The DR region can be deployed and the deployment is reachable from it. |
|
||||||
|
|
||||||
|
- Each concern has a freshness window — evidence older than the window
|
||||||
|
does not satisfy the gate.
|
||||||
|
- **Separation-of-duties on prod:** the approver cannot be the same
|
||||||
|
person who built the deployment.
|
||||||
|
|
||||||
|
> **Benefit:** the gate model is explicit — autonomy in operations,
|
||||||
|
> human in accountability, by design. The matrix is what makes autonomous
|
||||||
|
> operations safe enough to trust in production.
|
||||||
|
|
||||||
|
> **Speaker notes:** The prod/DR rows are the operational-readiness and
|
||||||
|
> resilience gates — SRE signs off on operability, incident response,
|
||||||
|
> capacity, and the three resilience checks (DR drill, chaos, backup).
|
||||||
|
> Separation-of-duties on prod is the rule that keeps the gate honest:
|
||||||
|
> the approver cannot be the same person who built the deployment.
|
||||||
|
|
||||||
|
> **Transition:** "You've seen how Nova works — the pipeline, the ledger,
|
||||||
|
> the attestation gates. Here is how Nova instruments itself so that
|
||||||
|
> every claim in this deck is traceable to a real signal."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 11 — Telemetry & Live Ops
|
||||||
|
|
||||||
|
**Every metric in this deck is traceable to a real emitted signal — and
|
||||||
|
the live-ops dashboard makes operations visible in PowerBI.**
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TB
|
||||||
|
A[Platform components] --> B[CloudEvents envelope]
|
||||||
|
B --> C[Event log]
|
||||||
|
B --> D[Decision ledger]
|
||||||
|
B --> E[Run records]
|
||||||
|
C --> F[Collector]
|
||||||
|
D --> F
|
||||||
|
E --> F
|
||||||
|
F --> G[Cold store]
|
||||||
|
G --> H[PowerBI views]
|
||||||
|
H --> I[Live ops dashboard]
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Platform components emit a CloudEvents envelope** → event log,
|
||||||
|
decision ledger, and run records → collector → cold store → PowerBI
|
||||||
|
views → **live ops dashboard.**
|
||||||
|
- **The live ops dashboard (PowerBI)** surfaces the four CTO-grade
|
||||||
|
metrics — Lead Time, Infrastructure Vulnerability Count, MTTR, Cloud
|
||||||
|
Spend — alongside the trust metrics (Decision Ledger coverage,
|
||||||
|
Attestation coverage) and the efficiency metrics (touchless
|
||||||
|
resolution, escalation frequency).
|
||||||
|
- **The architecture is deliberately minimal.** Nova-native envelopes;
|
||||||
|
no Kafka, no Prometheus, no ClickHouse. The cold store is sufficient
|
||||||
|
for batch and historical analysis; the live-ops surface is built in
|
||||||
|
PowerBI on top of the exported views.
|
||||||
|
- **Every number in the Proof slides is traceable to a signal.** When a
|
||||||
|
CFO asks "where does this number come from?", the answer is a query
|
||||||
|
against the cold store, not a Slack thread.
|
||||||
|
|
||||||
|
> **Benefit:** the architecture is the trust substrate — leadership sees
|
||||||
|
> the same numbers the platform produces, in PowerBI, with full
|
||||||
|
> traceability to the emitted signal. Operations become visible.
|
||||||
|
|
||||||
|
> **Speaker notes:** The value is not the plumbing — it is that the
|
||||||
|
> platform's metrics surface in a tool leadership already uses (PowerBI),
|
||||||
|
> and every number is traceable. The live-ops dashboard is where the
|
||||||
|
> "infrastructure operations become visible" theme lands concretely.
|
||||||
|
|
||||||
|
> **Transition:** "The architecture is sound — here is the measured
|
||||||
|
> proof."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 12 — Decision Ledger + Attestation Coverage
|
||||||
|
|
||||||
|
**By design, no change reaches production without a ledger entry and a
|
||||||
|
human attestation — both queryable for auditing, with full
|
||||||
|
traceability.**
|
||||||
|
|
||||||
|
- **Decision Ledger coverage: 100%.** Every platform run emits a
|
||||||
|
decision record with outcome backfill. No automated decision is ever
|
||||||
|
lost.
|
||||||
|
- **Attestation coverage: 100%.** Every prod/dr promotion is attested by
|
||||||
|
a human — QA for quality, SRE for production readiness — recorded with
|
||||||
|
approver identity, separation-of-duties check, and the evidence matrix.
|
||||||
|
- **No change to production without both.** The ledger entry and the
|
||||||
|
human attestation are mandatory, not optional. This is enforced by the
|
||||||
|
pipeline, not by policy.
|
||||||
|
- **Easily queried for auditing.** The ledger and the attestation
|
||||||
|
records are queryable by run, by environment, by approver, and by
|
||||||
|
outcome — the audit trail is a query, not a forensic exercise.
|
||||||
|
- **Full traceability.** A production change is traceable from the
|
||||||
|
contract that declared intent, through the policy scan, the confidence
|
||||||
|
score, the attestation, to the applied outcome. Nothing is opaque.
|
||||||
|
|
||||||
|
> **Benefit:** trust is provable — not a marketing claim, a queryable
|
||||||
|
> record. An auditor can answer "who approved this, when, on what
|
||||||
|
> evidence?" in one query; a CTO can answer "how many of last quarter's
|
||||||
|
> prod changes were touchless?" in one query.
|
||||||
|
|
||||||
|
> **Speaker notes:** The mandatory-by-design point is the one to land.
|
||||||
|
> The ledger + attestation are not a best-effort feature; they are a
|
||||||
|
> gate. No change reaches production without both. That is what makes
|
||||||
|
> the 100% numbers credible — they are enforced, not aspirational.
|
||||||
|
|
||||||
|
> **Transition:** "Trust is provable — here is the cost side of the ROI."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 13 — Cost & ROI
|
||||||
|
|
||||||
|
**The ROI formula and the cost estimates — grounded, with the production
|
||||||
|
denominator honestly flagged.**
|
||||||
|
|
||||||
|
- **Cost estimates are pre-apply and offline.** The platform reads the
|
||||||
|
terraform plan and estimates cost before anything is applied — so a
|
||||||
|
regression in cost is caught before the spend happens, not after.
|
||||||
|
- **The ROI formula:**
|
||||||
|
`Platform ROI = (FTE hours saved × blended rate + cloud savings + avoided downtime) ÷ platform op cost`
|
||||||
|
- **The four CTO-grade metrics (from Slide 3) are the ROI proof:**
|
||||||
|
Lead Time (PR → Prod), Infrastructure Vulnerability Count (trend), MTTR,
|
||||||
|
Cloud Spend Reduction. All flow into PowerBI.
|
||||||
|
- **Honest caveat:** the derived metrics are computed on internal runs
|
||||||
|
today; the production-denominator activates when a pilot estate runs.
|
||||||
|
The formula is grounded; the production numbers are not yet.
|
||||||
|
|
||||||
|
> **Benefit:** the ROI is not a black box — the formula is shown, the
|
||||||
|
> four metrics are committed, and the production-denominator caveat is
|
||||||
|
> stated up front. The CFO can see exactly what is real today and what
|
||||||
|
> activates with a pilot.
|
||||||
|
|
||||||
|
> **Speaker notes:** The formula is shown inline, not hidden. The
|
||||||
|
> "no fabrication" constraint in action: show the formula, show the
|
||||||
|
> caveat, do not pretend the production numbers exist.
|
||||||
|
|
||||||
|
> **Transition:** "The proof is grounded — here is what is honestly
|
||||||
|
> deferred, and why."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 14 — What's Deferred — and Why
|
||||||
|
|
||||||
|
**Honesty about what is not measured yet — and the blocking work for
|
||||||
|
each.**
|
||||||
|
|
||||||
|
To be clear: these deferrals are measurement infrastructure, not the
|
||||||
|
autonomy itself. The platform runs without an operator in the loop of
|
||||||
|
normal operations. What is deferred is the evidence pipeline for certain
|
||||||
|
metrics — not the autonomy.
|
||||||
|
|
||||||
|
| # | Deferred metric | Blocking work |
|
||||||
|
|---|-----------------|---------------|
|
||||||
|
| 1 | Live infrastructure health | Live AWS re-provisioning (currently torn down to a zero-cost steady state) |
|
||||||
|
| 2 | Live outbox write rate | Live AWS re-provisioning |
|
||||||
|
| 3 | Tamper-evident ledger checkpoints | Audit-ledger build-out (S3 Object Lock + signed checkpoints) |
|
||||||
|
| 4 | Onboarding funnel (requested → granted) | Auto-grant implementation |
|
||||||
|
| 5 | Drift auto-reversal | Drift-detection scheduler (not yet built) |
|
||||||
|
| 6 | Live cost reconciliation | Live AWS re-provisioning + actual-spend feed |
|
||||||
|
| 7 | SLA / unplanned downtime | Live AWS re-provisioning |
|
||||||
|
| 8 | Predictive vs reactive ratio | ML anomaly-forecasting service (not yet built) |
|
||||||
|
|
||||||
|
> **Benefit:** the boundaries are explicit — what Nova measures today,
|
||||||
|
> and exactly what blocks the rest. The autonomy is real; the measurement
|
||||||
|
> gaps are documented with the work that unblocks each one.
|
||||||
|
|
||||||
|
> **Speaker notes:** The preempt is critical: these deferrals are
|
||||||
|
> measurement infrastructure, not autonomy. The platform runs without an
|
||||||
|
> operator in the loop. What is deferred is the evidence pipeline for
|
||||||
|
> live-infra health, drift, predictive remediation — not the autonomy
|
||||||
|
> itself.
|
||||||
|
|
||||||
|
> **Transition:** "The proof is honest — here is the roadmap from here to
|
||||||
|
> the targets."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 15 — Roadmap to the North Star
|
||||||
|
|
||||||
|
**The path from the grounded metrics to the 12–18 month targets — each
|
||||||
|
deferred metric has an unblock path and a candidate milestone.**
|
||||||
|
|
||||||
|
| Timeframe | Work | Unblocks |
|
||||||
|
|-----------|------|----------|
|
||||||
|
| Near-term | Live AWS re-provisioning | Live infra health, live outbox write rate, live cost reconciliation, SLA |
|
||||||
|
| Near-term | Auto-grant implementation | Onboarding funnel (requested → granted) |
|
||||||
|
| Mid-term | Drift-detection scheduler | Drift auto-reversal |
|
||||||
|
| Mid-term | Audit-ledger build-out (Object Lock + signed checkpoints) | Tamper-evident ledger checkpoints |
|
||||||
|
| Mid-term | Hot-path activation (live-ops dashboard goes from batch to near-real-time) | Live-ops dashboard freshness |
|
||||||
|
| Longer-term | ML anomaly-forecasting service | Predictive vs reactive ratio |
|
||||||
|
|
||||||
|
- Each deferred metric has a specific unblock requirement and a
|
||||||
|
candidate future milestone.
|
||||||
|
- Re-evaluation triggers: each blocking piece of work lifts on its own
|
||||||
|
schedule; the metrics layer evolves as each one lands.
|
||||||
|
|
||||||
|
> **Benefit:** every deferred metric has an unblock path — nothing is
|
||||||
|
> hand-waved; everything has a plan and a timeframe.
|
||||||
|
|
||||||
|
> **Speaker notes:** This is the bridge from "honestly deferred" to
|
||||||
|
> "here is how we get there." The roadmap uses timeframes, not status —
|
||||||
|
> most of it is not implemented yet, so a status column would be noise.
|
||||||
|
|
||||||
|
> **Transition:** "The unblock path is clear — here is the 12-month
|
||||||
|
> product arc."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 16 — 12-Month Product Roadmap
|
||||||
|
|
||||||
|
**The product arc from pilot activation to integration — four quarters,
|
||||||
|
four outcomes.**
|
||||||
|
|
||||||
|
| Quarter | Theme | Board-level outcome |
|
||||||
|
|---------|-------|---------------------|
|
||||||
|
| **Q1** | Pilot Activation | Nova runs a real customer estate end-to-end, autonomously, with a measurable zero-touch rate. |
|
||||||
|
| **Q2** | Provable Trust | Every automated decision lands in a tamper-evident ledger; the CFO sees real cloud-spend reconciliation. |
|
||||||
|
| **Q3** | Compounding ROI | Quarter-over-quarter cloud spend drops; drift is detected and reversed without a human. |
|
||||||
|
| **Q4** | Integration & Predictive | AI agents deploy through Nova by default; the ML anomaly-forecasting service goes live. |
|
||||||
|
|
||||||
|
Grounded in the four strategic objectives (autonomy, provable trust, ROI,
|
||||||
|
integration) and the deferred-metric unblock paths.
|
||||||
|
|
||||||
|
> **Benefit:** the 12-month product arc — each quarter activates a
|
||||||
|
> strategic objective and its corresponding board-level metric, from
|
||||||
|
> pilot activation through integration leadership.
|
||||||
|
|
||||||
|
> **Speaker notes:** The roadmap is organized by product outcome, not
|
||||||
|
> by technical milestone. Each quarter activates one strategic
|
||||||
|
> objective from the North Star.
|
||||||
|
|
||||||
|
> **Transition:** "Here is the quarter-by-quarter detail."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 17 — Quarter-by-Quarter Outcomes
|
||||||
|
|
||||||
|
| Quarter | Product theme | Key deliverable | Target metric | Grounding |
|
||||||
|
|---------|---------------|-----------------|---------------|-----------|
|
||||||
|
| **Q1** | Pilot Activation | Re-provision live AWS; activate first pilot estate; onboarding auto-grant | Touchless ≥ 99% · Escalation < 0.1% · Accuracy ≥ 99.5% | Objective #1 — autonomy as the default |
|
||||||
|
| **Q2** | Provable Trust | Tamper-evident ledger (Object Lock + signed checkpoints); daily checkpoints; live cost reconciliation | Decision Ledger Coverage 100% · Cost Savings ≥ 25% | Objective #2 — trust is the moat |
|
||||||
|
| **Q3** | Compounding ROI + Drift | Drift-detection scheduler; auto-reversal; pre-apply → actual-spend reconciliation on the pilot estate | Drift Auto-Reversal ≥ 95% · Spend Reduction ≥ 25% | Objective #3 — CFO-pointable numbers |
|
||||||
|
| **Q4** | Integration + Predictive | ML anomaly-forecasting; AI-agent intent surface; multi-cloud (Azure/GCP) preview | Predictive:Reactive ≥ 3:1 · AI-Agent Intent Share (first measurement) | Objective #4 — default substrate for agents |
|
||||||
|
|
||||||
|
**Month-18 destination:** *"Nova is the layer enterprise leadership
|
||||||
|
points to when they say 'we don't have an infrastructure ops team
|
||||||
|
anymore, and the audit trail is stronger than it ever was.'"*
|
||||||
|
|
||||||
|
> **Benefit:** each quarter has a concrete deliverable, a target metric
|
||||||
|
> grounded in a strategic objective, and a path from "honestly deferred"
|
||||||
|
> to "shipped and measured."
|
||||||
|
|
||||||
|
> **Speaker notes:** Q1–Q3 are committed (grounded pipeline + known
|
||||||
|
> unblock paths). Q4 targets are committed-deliverable,
|
||||||
|
> aspirational-metric — the ML service ships, the intent-share number is
|
||||||
|
> a first measurement (we do not control adoption rate).
|
||||||
|
|
||||||
|
> **Transition:** "Production-grade guidance is how Nova helps the
|
||||||
|
> citizen developer's AI agent meet the bar — here is the first half."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 18 — Production-Grade Guidance via Atelier (1/2)
|
||||||
|
|
||||||
|
**Nova instructs the citizen developer's AI agent on production-grade
|
||||||
|
engineering — a set of skills and an MCP server.**
|
||||||
|
|
||||||
|
- **Skills** — markdown files keyed to production-grade engineering
|
||||||
|
domains (API, security, data, testing, observability, errors, DevOps,
|
||||||
|
infrastructure-as-code, compliance). The skills extend the baseline
|
||||||
|
catalog with Nova-specific production-grade principles.
|
||||||
|
- **MCP server** — a plugin-registry, stdio server exposing four tools:
|
||||||
|
`lookup_principle`, `list_domains`, `matrix_lookup`, and
|
||||||
|
`validate_against_principles`. The developer's AI agent (or any
|
||||||
|
agentic SDLC platform) calls these tools to look up the principles
|
||||||
|
that apply to its submission.
|
||||||
|
- **The integration point is the same regardless of source.** Whether
|
||||||
|
the submission comes from an AI coding agent, an agentic SDLC
|
||||||
|
platform, or a traditional IDE, the same skills and MCP server apply.
|
||||||
|
This is how Nova makes the citizen developer production-grade without
|
||||||
|
owning the PDLC.
|
||||||
|
|
||||||
|
> **Benefit:** the citizen developer's AI agent is not unguided — Nova
|
||||||
|
> provides production-grade engineering principles as skills and as an
|
||||||
|
> MCP surface, so submissions arrive at the contract boundary already
|
||||||
|
> aligned with the platform's standards.
|
||||||
|
|
||||||
|
> **Speaker notes:** This is the first half of the Atelier story — the
|
||||||
|
> surface (skills + MCP). The next slide is what the surface catches
|
||||||
|
> that deterministic scanners cannot.
|
||||||
|
|
||||||
|
> **Transition:** "Here is what that guidance catches that deterministic
|
||||||
|
> scanners cannot."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 19 — Production-Grade Guidance via Atelier (2/2)
|
||||||
|
|
||||||
|
**Agentic validation catches engineering-discipline gaps that deterministic
|
||||||
|
scanners miss — and the validation is reproducible.**
|
||||||
|
|
||||||
|
- **Beyond deterministic scanners.** Wiz, Checkmarx, and Mend check
|
||||||
|
policy and secrets — they do not check engineering discipline. The
|
||||||
|
Atelier MCP server catches correctness, clarity, and observability gaps
|
||||||
|
that deterministic tools cannot: "is this service observable?",
|
||||||
|
"is this error path handled?", "is this API contract clear?"
|
||||||
|
- **Agentic validation, not a second policy engine.** The MCP server
|
||||||
|
gives the AI agent the principles to validate against; the agent does
|
||||||
|
the validation. This is agentic validation — the agent reasons about
|
||||||
|
the submission against the principles, not a second static scan.
|
||||||
|
- **Vendored for audit reproducibility.** Atelier is vendored at a
|
||||||
|
pinned tag. A validation result is replayable against the exact
|
||||||
|
principles that produced it — so an audit can reproduce a validation
|
||||||
|
months later, not just trust a log line.
|
||||||
|
|
||||||
|
> **Benefit:** the citizen developer's submission is checked for
|
||||||
|
> engineering discipline, not just policy compliance — and the check is
|
||||||
|
> reproducible for audit. That is what makes the submission
|
||||||
|
> production-grade, regardless of which upstream platform produced it.
|
||||||
|
|
||||||
|
> **Speaker notes:** The value is the gap deterministic scanners leave:
|
||||||
|
engineering discipline. Policy scanners catch "is this S3 bucket
|
||||||
|
public?"; the MCP server catches "is this service observable if that
|
||||||
|
bucket fails?". The vendoring point is audit reproducibility — the
|
||||||
|
validation is not a black box.
|
||||||
|
|
||||||
|
> **Transition:** "You've seen the problem, the solution, and the proof.
|
||||||
|
> Here is the recap and the ask."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 20 — Recap + Ask
|
||||||
|
|
||||||
|
**The 4-beat recap + the business decision.**
|
||||||
|
|
||||||
|
**Recap:**
|
||||||
|
- **Problem:** product teams own infrastructure without the discipline
|
||||||
|
and lifecycle planning it requires; bandwidth gaps and tribal
|
||||||
|
knowledge leave operations exposed.
|
||||||
|
- **Solution:** autonomous cloud delivery — operations become visible,
|
||||||
|
trust is provable (deterministic scoring), humans at stage gates.
|
||||||
|
- **Proof:** 100% ledger coverage, 100% attestation coverage, grounded
|
||||||
|
ROI formula, four CTO-grade metrics flowing into PowerBI.
|
||||||
|
- **Roadmap:** deferred metrics have unblock paths; the 12-month product
|
||||||
|
arc activates one strategic objective per quarter.
|
||||||
|
|
||||||
|
**The ask:** "Approve a pilot estate to activate the production-denominator
|
||||||
|
metrics (Lead Time, Vulnerability Count, MTTR, Cloud Spend), and approve
|
||||||
|
the tamper-evident ledger build-out to move from the local hash-chain to
|
||||||
|
S3 Object Lock + signed checkpoints. These two decisions move Nova from
|
||||||
|
'pipeline-ready' to 'production-proven.'"
|
||||||
|
|
||||||
|
> **Benefit:** a clear business decision — approve a pilot and the ledger
|
||||||
|
> build-out — with the confidence that every claim in this deck is
|
||||||
|
> grounded, derived, or honestly deferred.
|
||||||
|
|
||||||
|
> **Speaker notes:** The ask is a business decision, not insider
|
||||||
|
> language. "Approve a pilot estate" is a C-suite decision. "Approve the
|
||||||
|
> ledger build-out" is a budget decision. The recap reinforces the 4-beat
|
||||||
|
> arc — the audience leaves with the structure, not a pile of facts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix A1 — Metrics Glossary
|
||||||
|
|
||||||
|
| KPI | Definition | Status |
|
||||||
|
|-----|-----------|--------|
|
||||||
|
| Touchless Resolution Rate | runs without operational stage-gate block ÷ total | partial (Post-Pilot) |
|
||||||
|
| Human Escalation Frequency | operational stage-gate blocks ÷ total | partial (Post-Pilot) |
|
||||||
|
| Automated Decision Accuracy | decisions not followed by failure within 5min | partial (Post-Pilot) |
|
||||||
|
| MTTR (p95) | apply.failed → successful retry | grounded |
|
||||||
|
| Confidence-Gate Halt Rate | runs with band=block ÷ total | grounded |
|
||||||
|
| Provisioning Lead Time | run.completed − run.started | grounded |
|
||||||
|
| Deployment Frequency | count(run.completed) per day | grounded |
|
||||||
|
| Cost Savings (pre-apply) | sum(delta_usd where delta < 0) | partial (live reconciliation deferred) |
|
||||||
|
| FTE Hours Saved | run count × manual baseline × rate | derived (N=0 caveat) |
|
||||||
|
| Platform ROI | (labor + cloud + avoided downtime) ÷ op cost | derived (N=0 caveat) |
|
||||||
|
| Decision Ledger Coverage | decisions with outcome ÷ total | grounded |
|
||||||
|
| Attestation Coverage | prod/dr attested ÷ total prod/dr | grounded |
|
||||||
|
| Policy Compliance Rate | 1 − failed_assets ÷ total | grounded |
|
||||||
|
|
||||||
|
> **Benefit:** a reference for every metric mentioned in the deck.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> **End of deck.** 20 main slides + 1 appendix slide = 21 total.
|
||||||
Binary file not shown.
@@ -1,321 +0,0 @@
|
|||||||
---
|
|
||||||
marp: true
|
|
||||||
theme: default
|
|
||||||
paginate: true
|
|
||||||
size: 16x9
|
|
||||||
header: "The Developer Experience"
|
|
||||||
footer: "Internal"
|
|
||||||
style: |
|
|
||||||
section {
|
|
||||||
font-family: "Akkurat Pro", "Helvetica Neue", "Arial", sans-serif;
|
|
||||||
font-size: 26px;
|
|
||||||
color: #1B1B1B;
|
|
||||||
}
|
|
||||||
h1 { color: #D6002A; font-size: 40px; margin-bottom: 0.3em; }
|
|
||||||
h2 { color: #D6002A; font-size: 32px; margin-bottom: 0.2em; }
|
|
||||||
section.title { background: #1B1B1B; color: #fff; border-top: 8px solid #D6002A; }
|
|
||||||
section.title h1 { color: #fff; }
|
|
||||||
table { font-size: 22px; width: 100%; }
|
|
||||||
th { background: #F0F0F0; }
|
|
||||||
blockquote { border-left: 4px solid #D6002A; color: #2E2E2E; font-size: 24px; }
|
|
||||||
pre { font-size: 16px; line-height: 1.3; }
|
|
||||||
code { font-size: 16px; }
|
|
||||||
img { display: block; margin: 0 auto; max-height: 280px; }
|
|
||||||
.badge {
|
|
||||||
display: inline-block; padding: 2px 8px; border-radius: 4px;
|
|
||||||
font-size: 16px; font-weight: 600;
|
|
||||||
}
|
|
||||||
.planned { background: #fef3c7; color: #78350f; }
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# The Developer Experience
|
|
||||||
|
|
||||||
### Nova — The New Dawn of DevSecOps
|
|
||||||
|
|
||||||
<style>
|
|
||||||
section.title h1 { font-size: 44px; margin-bottom: 0.1em; }
|
|
||||||
section.title h3 { color: #F0F0F0; font-weight: 400; font-size: 22px; margin-top: 0; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Two consumer paths, one safety envelope
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Technical developer** — owns app code + a contract + a thin CI definition
|
|
||||||
- **Citizen developer** — declares intent; an AI agent produces a contract that passes the **same** safety envelope
|
|
||||||
- **Upstream is anything** — IDE, agentic SDLC, or vibe coding. Nova doesn't care how the contract was produced
|
|
||||||
- **Nova is infrastructure only** — provisions and governs AWS resources. Application deployment is upstream
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# The platform at a glance
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **You own the left edge** — app code and a contract. That is the entire consumer surface
|
|
||||||
- **The platform owns the middle** — pipeline, catalog, adapter, environments, gates, evidence
|
|
||||||
- **Two surfaces, one pipeline, one evidence stream** — senior engineer and citizen dev converge on the same safety envelope
|
|
||||||
- **The bar rises automatically** — confidence signal + HITL gates scale with the target environment, not a ticket
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Three things. The entire consumer surface.
|
|
||||||
|
|
||||||
<img src="assets/png/developer-experience-02-what-dev-does.png" style="float: right; width: 38%; margin-left: 20px; margin-bottom: 10px;" />
|
|
||||||
|
|
||||||
- **1. App code** — the consumer's service, at the top level of the repo
|
|
||||||
- **2. A contract** — a single YAML file: id, name, environment, infrastructure
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
id: msvc
|
|
||||||
name: microservice
|
|
||||||
environment: dev
|
|
||||||
infrastructure:
|
|
||||||
microservice:
|
|
||||||
version: "1.0.0"
|
|
||||||
inputs:
|
|
||||||
cpu: 256
|
|
||||||
memory: 512
|
|
||||||
desired_count: 2
|
|
||||||
port: 8080
|
|
||||||
```
|
|
||||||
|
|
||||||
- **3. A one-line CI definition** — a thin `uses:` wrapper pointing at a versioned platform workflow
|
|
||||||
- The developer does **not**: write modules, clone the platform repo, hold cloud credentials, or maintain a state backend
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# See what the platform does, in real time
|
|
||||||
|
|
||||||
- **Streamed output by default** — the plan, policy results, and each check record flow to stdout
|
|
||||||
- **PR comments after every successful pipeline stage** — always know where you stand
|
|
||||||
- **Clear, explainable halt reasons** — a policy violation, an insufficient signal, or a missing attestation. **Never opaque.**
|
|
||||||
- **Connection strings posted as PR comments** — human-readable, no hunting. Runtime secrets go to encrypted Parameter Store, never to logs
|
|
||||||
- **Errors become GitHub issues, automatically** — a failed deploy opens an issue on the platform repo
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Pick from pre-built, security-reviewed blocks
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Primitives** — single-purpose resources (S3, VPC, ECS, IAM, ALB, ECR, CloudFront, WAF, RDS)
|
|
||||||
- **Modules** — composed patterns (static site with CDN + WAF; microservice with VPC + ECS + ALB + ECR)
|
|
||||||
- **Validated examples per module** — `simple.yaml` + `complex.yaml`, validated against the contract schema in CI
|
|
||||||
- **Auto-promotion of patterns** — after 3 observed usages <span class="badge planned">Planned</span>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# The bar rises automatically with sensitivity
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
| Environment | What the platform adds | Maturity |
|
|
||||||
|---|---|---|
|
|
||||||
| dev | Confidence ≥ 0.50, fully autonomous | — |
|
|
||||||
| qa | QA human attestation + confidence ≥ 0.75 | <span class="badge planned">Planned</span> |
|
|
||||||
| prod | SRE human attestation + confidence ≥ 0.90 | <span class="badge planned">Planned</span> |
|
|
||||||
| dr | SRE human attestation + confidence ≥ 0.95 + DR drill | <span class="badge planned">Planned</span> |
|
|
||||||
|
|
||||||
- **No staging environment** — dev is the only autonomous environment
|
|
||||||
- **Separation of duties** — the QA approver cannot be the prod approver
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Tearing down is as gated as deploying
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
<style>
|
|
||||||
section { font-size: 22px; }
|
|
||||||
pre { font-size: 13px; line-height: 1.2; }
|
|
||||||
code { font-size: 13px; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.12
|
|
||||||
with:
|
|
||||||
contract: .nova/contract.yml
|
|
||||||
mode: decommission
|
|
||||||
changeRequestId: "CHG0678912"
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Validate the change request** — platform queries the CMDB; CR must be `approved` and match the consumer repo
|
|
||||||
- **Two SRE human-attestation gates** — disable protection → SRE approves → zero counts + destroy → second SRE approves
|
|
||||||
- **Per-stack encryption key enters a grace window** (default 30 days) so encrypted data remains recoverable
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# You control when you absorb improvements
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- **Floating MAJOR + MINOR tags** (e.g. `@v1.12`) — automatically receive patch updates within the line
|
|
||||||
- **Semantic versioning with a clear contract:** interface → MAJOR, behavior → MINOR, lifecycle → PATCH
|
|
||||||
- **Pin to an exact version** for stability, or float on MAJOR only (`@v1`) to absorb new features on your 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 floating tags
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Fails gracefully, not opaquely
|
|
||||||
|
|
||||||
First impressions of a platform are made **when it fails for the first time.** The platform fails gracefully.
|
|
||||||
|
|
||||||
When no environment is bound, the platform emits a **user-friendly onboarding prompt** instead of failing opaquely:
|
|
||||||
|
|
||||||
1. That no environment is bound to their repo yet
|
|
||||||
2. What the platform will provision on their behalf (account, network, state, role)
|
|
||||||
3. The expected turnaround for the platform team to grant the environment
|
|
||||||
4. How to request an environment
|
|
||||||
|
|
||||||
The pipeline then **exits without attempting a deployment** — no partial state, no confusing errors.
|
|
||||||
|
|
||||||
<span class="badge planned">Citizen developer onboarding path: planned</span>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# The desired outcomes
|
|
||||||
|
|
||||||
- **Velocity without sacrificing safety** — speed in ergonomics, safety in unbypassable gates
|
|
||||||
- **Security, observability, compliance as platform defaults** — not per-team effort, not post-hoc remediation
|
|
||||||
- **Auditability as a byproduct, not a project** — every change traceable to a human attestation and a tamper-evident evidence event
|
|
||||||
- **Blast radius contained by design** — OIDC + ABAC, only your own tagged resources
|
|
||||||
- **The bottleneck moves off the platform team's ticket queue** — a merged change progresses without a platform engineer joining a thread
|
|
||||||
- **Infrastructure as a utility, not a craft** — consume, don't maintain
|
|
||||||
- **A path to the citizen developer** — same envelope, senior engineer or non-technical
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# Appendix
|
|
||||||
|
|
||||||
**Contents:**
|
|
||||||
|
|
||||||
1. The Citizen Developer Experience (full)
|
|
||||||
2. No Platform Code, No Cloning (detail)
|
|
||||||
3. Local Reproducibility (detail)
|
|
||||||
4. The Road to the North Star (phased roadmap)
|
|
||||||
5. Glossary
|
|
||||||
6. Operating Model & Cost
|
|
||||||
7. Verified by Construction
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A1 — The Citizen Developer Experience
|
|
||||||
|
|
||||||
A non-technical consumer ships a production deployment **by declaring intent** — without authoring a workflow, a configuration file, or an infrastructure module.
|
|
||||||
|
|
||||||
- The consumer opens an issue describing what they need (e.g. "a web API for the pricing service")
|
|
||||||
- An AI agent maps the intent to a contract referencing a module from the **reviewed skill catalog**
|
|
||||||
- The contract enters the **same pipeline** and must clear the **same confidence gate** before promotion
|
|
||||||
|
|
||||||
**Guardrails that make this safe:**
|
|
||||||
|
|
||||||
- Skills are **versioned, signed, and reviewed for sensitive data before release** (Infra & Ops owns the review)
|
|
||||||
- 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>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A2 — No Platform Code, No Cloning
|
|
||||||
|
|
||||||
Consumers `uses:` a **versioned** central workflow. The platform fetches itself at run time. The consumer **never touches platform internals.**
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- The consumer's CI definition is a thin wrapper — one `uses:` line
|
|
||||||
- The runner checks out the consumer repo, then checks out the platform repo into the workspace
|
|
||||||
- The platform installs its own runtime dependencies — the consumer installs nothing
|
|
||||||
- When the platform ships a fix, every consumer on a floating tag gets it on their next run
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A3 — Local Reproducibility
|
|
||||||
|
|
||||||
The entire CI pipeline runs **from the shell**, not just in CI.
|
|
||||||
|
|
||||||
- `scripts/run_ci.sh` mirrors the CI pipeline locally — the same three stages (lint → test → check-only) in sequence
|
|
||||||
- `scripts/run_platform.sh --check-only` runs the platform **offline** — no AWS, no policy engine, no outbox required. Validates a contract end-to-end before pushing
|
|
||||||
- `--plan-only` runs through the infrastructure plan without applying
|
|
||||||
- The CI and deploy pipelines are defined by **declarative contracts** (YAML instances validated against JSON Schemas) — a single source of truth that both workflows implement
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# A4 — The Road to the North Star
|
|
||||||
|
|
||||||
*Proposed phasing — not formally planned.*
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A5 — Glossary
|
|
||||||
|
|
||||||
| Term | Meaning |
|
|
||||||
|---|---|
|
|
||||||
| **OIDC** | OpenID Connect — federation protocol for short-lived tokens, no long-lived credentials |
|
|
||||||
| **ABAC** | Attribute-Based Access Control — access scoped by resource tags + repo identity, not roles |
|
|
||||||
| **CMK** | Customer-Managed Key — per-stack encryption key, 90-day rotation, no shared keys |
|
|
||||||
| **CMDB** | Configuration Management Database — validates change requests for decommission |
|
|
||||||
| **RPO** | Recovery Point Objective — RPO = 0 means evidence is written synchronously, no data loss |
|
|
||||||
| **HITL** | Human-in-the-Loop — deliberate human attestation required for qa/prod/dr environments |
|
|
||||||
| **VCS** | Version Control System — the git hosting platform (GitHub, Gitea, GitLab) |
|
|
||||||
| **NFR** | Non-Functional Requirement — encryption, tagging, observability standards |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# A6 — Operating Model & Cost
|
|
||||||
|
|
||||||
<style>
|
|
||||||
section { font-size: 20px; }
|
|
||||||
table { font-size: 18px; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
Nova runs at **zero cloud cost** for day-to-day development. AWS spend was measured via Cost Explorer (`COST.md`, 2026-07-28):
|
|
||||||
|
|
||||||
| Metric | Value |
|
|
||||||
|--------|-------|
|
|
||||||
| Total spend (8 days) | **$0.001883** |
|
|
||||||
| Daily average | $0.000235 |
|
|
||||||
| Projected monthly | ~$0.007 |
|
|
||||||
| Peak day | 2026-07-27 ($0.000867) |
|
|
||||||
|
|
||||||
- **Local emulators are the primary tier** — the full pipeline runs in-process, no AWS credentials
|
|
||||||
- **Live-AWS verification is milestone-scoped, then torn down.** The pipeline now **defaults to plan-only** on every PR; `NOVA_LIFECYCLE_MODE=full` overrides to apply→destroy for milestone verification (REQ-134, v1.12).
|
|
||||||
- **Cost drivers** are spike-scoped: Terraform plan reads (free), S3 state storage (cents), DynamoDB outbox (cents). No running infrastructure between milestones.
|
|
||||||
|
|
||||||
**Pre-mortem (`PRE_MORTEM.md`):** the v1.10 decay incident (diff-scoped VERIFY missed 7 adapter defects) is the root pattern: *a claim outruns the verification that backs it.* Four forward failure modes + structural mitigations (regression-tested IAM baseline, mandatory teardown, verified-only deck claims, honest scope).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- _class: title -->
|
|
||||||
<!-- _paginate: false -->
|
|
||||||
|
|
||||||
# A7 — Verified by Construction
|
|
||||||
|
|
||||||
<style>
|
|
||||||
section { font-size: 20px; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
Two architectural pillars make "Verified" a structural property, not a claim:
|
|
||||||
|
|
||||||
- **The stateless adapter (918 → ~80 lines).** The Terraform adapter was a 918-line monolith with 3 constant tables and 39 type-specific branches. It is now a ~80-line **stateless assembler**: it owns no module content — no resource shape, no nested HCL blocks, no defaults. Each L1 module ships a real `terraform/` module dir owning its shape, nested blocks, and defaults. The adapter reads the registry and emits `module "x" { source = ... }` blocks. A new module is a new terraform dir, not a code change. *(The v1.12 P67 fix closed a dedup defect for multi-resource L1s — ecs-service, alb; CAP-013 now Verified.)*
|
|
||||||
- **Pipeline-driven lifecycle testing.** A `modules-lifecycle` pipeline matrix-runs each L1 and L2 module's contracts through apply→modify→destroy against live AWS. **The "test" = the pipeline cell going green.** Defaults to **plan-only** on every PR (fast, no AWS mutation, no cost); `NOVA_LIFECYCLE_MODE=full` overrides to the real apply→destroy for milestone verification (REQ-134, v1.12). The regression gate (D-091) re-runs all 22 capabilities at milestone completion — **22/22 Verified** as of v1.12.
|
|
||||||
|
|
||||||
The v1.10 lesson is the negative space: a 918-line adapter with type-specific branches decayed silently. The ~80-line stateless adapter + the milestone regression gate are the structural fix.
|
|
||||||
@@ -1,253 +0,0 @@
|
|||||||
# The Developer Experience — Talking Points
|
|
||||||
|
|
||||||
> **Companion to:** `the-developer-experience-marp.md` (11 main + Appendix TOC + 7 appendix = 19 slides)
|
|
||||||
> **Content source:** `the-developer-experience.md` (full source of truth with speaker notes)
|
|
||||||
> **Purpose:** Presenter-ready cues — 3-6 talking points per slide + the one key takeaway the audience should remember.
|
|
||||||
> **Audience:** Senior Leadership — CTO, Head of Cloud, Head of Infrastructure, Head of DevOps
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 1 — Title
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Brief introduction — this deck covers *who uses the platform and how fast/safe they ship*, not the internal mechanics (that's the companion deck)
|
|
||||||
- Set the frame: velocity without sacrificing safety, and security/observability/compliance as platform defaults rather than per-team effort
|
|
||||||
- v1.12 re-verification: every "Testing" claim in this deck is now Verified — 22/22 capabilities via the v1.11 lifecycle pipeline (see A7)
|
|
||||||
|
|
||||||
**Key takeaway:** The consumer surface is intentionally tiny. The platform's surface is large and opinionated.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 2 — Two consumer paths, one safety envelope
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- This is the scope-boundary slide — here's who uses the platform, and here's where Nova's responsibility starts and stops
|
|
||||||
- Two consumer paths converge on the same contract: **technical** developer writes the contract directly; **citizen** developer declares intent and an AI agent produces a contract that passes the same safety envelope
|
|
||||||
- Upstream is anything — your IDE, an agentic SDLC, or vibe coding on a laptop. Nova doesn't care how the contract was produced
|
|
||||||
- Nova is infrastructure only — it provisions and governs AWS resources. Application deployment is upstream of the contract
|
|
||||||
- The two surfaces are *parallel*, not a progression. A citizen developer doesn't "graduate" to the developer surface. There is no "citizen developer mode" with weaker checks
|
|
||||||
|
|
||||||
**Key takeaway:** Two consumer paths, one safety envelope. Nova is infra only — anything upstream is fair game.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 3 — The platform at a glance
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- One-slide map — frame it from the left edge: "this is what you touch, this is what the platform owns for you"
|
|
||||||
- The leadership beat: the convergence — two surfaces, one pipeline, one evidence stream — is the design point that lets us expand who can ship safely without lowering the bar
|
|
||||||
- Don't walk every node — point to the contract boundary and say "the rest of this deck zooms into the developer-facing pieces"
|
|
||||||
- The bar rises automatically — the confidence signal and HITL gates scale with the target environment, not with a ticket
|
|
||||||
|
|
||||||
**Key takeaway:** You own the left edge (app + contract). The platform owns everything else, end to end.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 4 — Three things. The entire consumer surface.
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Hold this slide — the audience should sit with how small the consumer surface is. Three things: app code, a contract, a one-line CI definition
|
|
||||||
- The contract is a single YAML file: module, environment, inputs. That's the entire consumer-facing interface to production
|
|
||||||
- The contract example shows **infrastructure inputs** (cpu, memory, desired_count, port) — not an `image:` field. The consumer declares capacity and shape; the platform resolves the rest
|
|
||||||
- Walk the "does not" list quickly — no infrastructure modules, no platform repo cloning, no cloud credentials, no state backends. Every item is a category of toil the platform removes
|
|
||||||
- For the Head of DevOps: this is the lever for throughput — the bottleneck moves off the platform team's ticket queue
|
|
||||||
|
|
||||||
**Key takeaway:** Three things. That's the entire consumer-side surface. Everything else is the platform's job.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 5 — See what the platform does, in real time
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- This directly answers "but developers hate platforms that hide what they're doing" — the platform is opinionated about *what* runs, not *opaque* about *that* it runs
|
|
||||||
- Streamed output by default — the plan, policy results, and each check record flow to stdout
|
|
||||||
- PR comments after every successful pipeline stage — a developer always knows where they stand without refreshing a dashboard
|
|
||||||
- Connection strings posted as PR comments — human-readable, no hunting. Runtime secrets go to encrypted Parameter Store (KMS-encrypted, namespaced), never to logs
|
|
||||||
- The "errors become GitHub 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
|
|
||||||
- Clear, explainable halt reasons — a policy violation, an insufficient confidence signal, or a missing attestation. Never an opaque debugging exercise
|
|
||||||
|
|
||||||
**Key takeaway:** The platform closes the feedback loop — streamed output, PR comments, clear halt reasons, no secrets in logs.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 6 — Pick from pre-built, security-reviewed blocks
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- The catalog is what makes "declare intent" practical — you can only declare a module that exists
|
|
||||||
- For leadership: the catalog is the leverage. One well-reviewed module serves every consumer; a fix to the module serves every consumer on the next run. This is the compounding asset
|
|
||||||
- Primitives are single-purpose resources (S3, VPC, ECS, IAM, ALB, ECR, CloudFront, WAF, RDS) — each with documented inputs/outputs and versioning
|
|
||||||
- Modules are composed patterns — a static site with CDN + WAF; a microservice with VPC + ECS + ALB + ECR
|
|
||||||
- Validated examples per module (`simple.yaml` + `complex.yaml`) are validated against the contract schema in CI — examples cannot drift from the schema silently
|
|
||||||
- Auto-promotion of patterns (after 3 observed usages) and compliance extension points (GDPR, SOX, SOC2, DORA) are on the roadmap
|
|
||||||
|
|
||||||
**Key takeaway:** You don't author infrastructure — you pick from pre-built, security-reviewed building blocks. The catalog is the compounding asset.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 7 — The bar rises automatically with sensitivity
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Promotion is a workflow choice, not a contract edit — a promotion can be reviewed as a *diff in the workflow*, not as a rewritten contract
|
|
||||||
- The DX win: the contract stays stable across environments; the safety win: the platform raises the threshold and attestation bar automatically based on the target environment
|
|
||||||
- The consumer can't bypass the gates — they pick *which* environment to target, and the platform applies the right bar
|
|
||||||
- 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
|
|
||||||
- Be honest about maturity: dev is tested and pilot-ready; qa/prod/dr wiring is planned
|
|
||||||
|
|
||||||
**Key takeaway:** The bar rises automatically with sensitivity. The consumer picks the environment; the platform applies the right gate.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 8 — Tearing down is as gated as deploying
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- The counter-argument to "deletion protection makes cleanup impossible" is this slide. Decommission is a first-class, gated, two-approval flow — not a lock with no key, and not an ungated `terraform destroy`
|
|
||||||
- The CMDB validation means decommission is auditable, not just possible — the platform queries the CMDB and asserts the CR is `approved` and matches the consumer repo
|
|
||||||
- Two SRE human-attestation gates: disable protection → SRE approves → zero all counts + destroy → a second SRE approves
|
|
||||||
- The per-stack encryption key enters a grace window (default 30 days) so encrypted data remains recoverable during decommission
|
|
||||||
- For the Head of Infrastructure: this is what makes deletion protection safe to ship by default — cleanup is a deliberate, gated path, not an impossible one
|
|
||||||
|
|
||||||
**Key takeaway:** Tearing down is as deliberate as deploying — two SRE attestation gates + CMDB-validated change request.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 9 — You control when you absorb improvements
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- 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
|
|
||||||
- Floating MAJOR + MINOR tags (e.g. `@v1.12`) — a consumer automatically receives patch updates within the line
|
|
||||||
- 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 a consumer has
|
|
||||||
- The automated release job computes the next semver on merge to main, creates the tag, and updates the floating tags
|
|
||||||
|
|
||||||
**Key takeaway:** You control when you absorb platform improvements — no surprise upgrades, no forced forks.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 10 — Fails gracefully, not opaquely
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- This looks like a small thing; it's actually a cultural one. The platform's posture is "help me get started," not "you should have known"
|
|
||||||
- For the Head of DevOps: this is what drives adoption. Platforms that fail opaquely on first run get routed around
|
|
||||||
- When no environment is bound, the platform emits a user-friendly onboarding prompt — not an opaque failure
|
|
||||||
- The prompt tells the consumer: no environment bound, what the platform will provision, expected turnaround, how to request an environment
|
|
||||||
- The pipeline then exits without attempting a deployment — no partial state, no confusing errors
|
|
||||||
- The citizen developer onboarding path is planned
|
|
||||||
|
|
||||||
**Key takeaway:** The platform fails gracefully, not opaquely — first impressions are made when it fails for the first time.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 11 — The desired outcomes
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- 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
|
|
||||||
- Velocity without sacrificing safety: speed is in the ergonomics (a simple contract, a one-line `uses:`); safety is in the gates the consumer cannot bypass
|
|
||||||
- Security, observability, and compliance as platform defaults — not per-team effort, not post-hoc remediation
|
|
||||||
- Auditability as a byproduct, not a project — every production change is traceable to a human attestation and a tamper-evident evidence event
|
|
||||||
- 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 serves a senior engineer and a non-technical consumer
|
|
||||||
- Invite questions; the companion deck ("How the Platform Works") covers the internal mechanics in more depth
|
|
||||||
|
|
||||||
**Key takeaway:** Ship safely at the pace the business demands, with the security and audit posture the regulators require.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix TOC — Appendix
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- These are backup slides for Q&A. Use them when the audience asks for the detail behind a main-slide claim
|
|
||||||
- Don't walk through them in the main talk unless time permits
|
|
||||||
- The appendix is indexed to match the Marp deck's A1-A7 structure
|
|
||||||
|
|
||||||
**Key takeaway:** Backup slides for Q&A — pull the relevant appendix slide when asked.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A1 — The Citizen Developer Experience
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Be honest about maturity: the *mechanism* (agent → contract → same pipeline) is designed and the stub was proven in the v1.0 demo; the full skill catalog and real agent runtime are planned
|
|
||||||
- The "vibe coding on a laptop" framing is intentional — it meets the citizen developer where they already are, but every submission still passes the same safety envelope
|
|
||||||
- The design point matters to leadership now: we are building for a world where more of the org can ship safely, not where more of the org has to become a platform engineer
|
|
||||||
- Guardrails: skills are versioned, signed, reviewed for sensitive data; agents are stateless; the platform trusts and always verifies
|
|
||||||
- The agent's trace and submission confidence are captured in the contract (`profile: agentic`) for review
|
|
||||||
|
|
||||||
**Key takeaway:** A non-technical consumer ships by declaring intent — same pipeline, same safety envelope, no weaker checks.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A2 — No Platform Code, No Cloning
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- The Head of Cloud cares about this: there is no "platform code in every consumer repo" problem
|
|
||||||
- The version-pinned `uses:` line is the *only* coupling, and it's a coupling that updates itself within the line
|
|
||||||
- The runner checks out the consumer repo, then checks out the platform repo into the workspace — the consumer never clones the platform repo
|
|
||||||
- The platform installs its own runtime dependencies — the consumer installs nothing
|
|
||||||
- When the platform ships a fix, every consumer on a floating tag gets it on their next run — no per-repo upgrade project
|
|
||||||
|
|
||||||
**Key takeaway:** The consumer never touches platform internals. The versioned `uses:` line is the only coupling.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A3 — Local Reproducibility
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- This is the "no surprises before you push" story. A consumer can validate their contract offline, run the plan offline, and only push when they're confident
|
|
||||||
- `scripts/run_ci.sh` mirrors the CI pipeline locally — the same three stages (lint → test → check-only) in sequence
|
|
||||||
- `scripts/run_platform.sh --check-only` runs the platform offline — no AWS, no policy engine, no outbox required
|
|
||||||
- The same declarative contract drives both the local tooling and CI — there's no "works on my machine, fails in CI" gap
|
|
||||||
|
|
||||||
**Key takeaway:** The entire CI pipeline runs from the shell — no surprises before you push.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A4 — The Road to the North Star
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- This is a proposed phasing, not a formally committed plan — call that out explicitly
|
|
||||||
- Phase 1 is what's tested and Verified today (22/22 capabilities, torn down to zero-cost)
|
|
||||||
- Phase 2 is the next milestone (qa/prod/dr wiring)
|
|
||||||
- Phase 3 introduces the agentic surface (skill catalog + agents)
|
|
||||||
- Phase 4 is the north star: citizen developer GA on the same safety envelope
|
|
||||||
- Use this only when an audience member asks "how do you get from here to there"
|
|
||||||
|
|
||||||
**Key takeaway:** Proposed phasing — Phase 1 Verified, Phase 4 is the North Star (citizen developer GA).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A5 — Glossary
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- Keep this slide in your back pocket for the audience member who asks "what does ABAC actually mean?"
|
|
||||||
- Don't read it aloud
|
|
||||||
- All acronyms used in the deck are defined here
|
|
||||||
|
|
||||||
**Key takeaway:** Reference slide — don't read aloud.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A6 — Operating Model & Cost
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- The headline for the Head of Cloud / Finance: less than one cent over 8 days of active development; zero BAU cloud spend
|
|
||||||
- The lifecycle pipeline defaults to plan-only so the PR-time cost is zero; `NOVA_LIFECYCLE_MODE=full` overrides for milestone verification
|
|
||||||
- The pre-mortem is the credibility slide — we already asked "how does this fail?" and the mitigations are structural
|
|
||||||
- The v1.10 decay incident is disclosed honestly, not hidden — that disclosure IS the mitigation
|
|
||||||
- Cost drivers are spike-scoped: Terraform plan reads (free), S3 state storage (cents), DynamoDB outbox (cents). No running infrastructure between milestones
|
|
||||||
|
|
||||||
**Key takeaway:** Zero BAU cloud cost. Pre-mortemed failure modes with structural mitigations.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A7 — Verified by Construction
|
|
||||||
|
|
||||||
**Talking points:**
|
|
||||||
- This is the deep-dive slide for the Head of Engineering / Architecture — the two pillars answer "how do you keep the decks honest?"
|
|
||||||
- The adapter is simple enough to reason about (a stateless assembler); the lifecycle pipeline is the automated verification that backs every "Testing" claim
|
|
||||||
- The v1.10 lesson is the negative space: a 918-line adapter with type-specific branches decayed silently because the VERIFY gate was diff-scoped
|
|
||||||
- The ~80-line stateless adapter + the milestone regression gate are the structural fix
|
|
||||||
- The plan-only default (v1.12) means verification runs on every PR at zero cost, with the full apply→destroy gated behind a CI variable override
|
|
||||||
|
|
||||||
**Key takeaway:** "Verified" is a structural property, not a claim — the stateless adapter + lifecycle pipeline make it so.
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,457 +0,0 @@
|
|||||||
# The Developer Experience
|
|
||||||
|
|
||||||
> **Subtitle:** Nova — The New Dawn of DevSecOps
|
|
||||||
> **Audience:** Senior Leadership, CTO, Head of Cloud, Head of Infrastructure, Head of DevOps
|
|
||||||
> **Length:** ~16 minutes · 11 main + Appendix TOC + 7 appendix = 19 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:** "Testing" = works internally, dev pilot-ready. "Planned" = on the roadmap. "Agentic" = involves AI agents or autonomous decision-making.
|
|
||||||
> **Re-verification (2026-07-29):** Every "Testing" claim in this deck was re-verified in v1.10 Phase 54 (D-093) and again in v1.11 via the pipeline-driven lifecycle tests (P59–P62). The headline E2E (contract → resolver → adapter → terraform init/validate/plan) passes against the live AWS account; the local emulating tier (Phase 53) runs the full E2E with no cloud credentials. **22/22 auto-verifiable capabilities Verified** (CAP-013 fixed in v1.12 P67 — the adapter's multi-resource L1 dedup defect is closed). The v1.11 lifecycle pipeline ran apply→modify→destroy against live AWS and was then torn down to zero-cost (D-096). See `.ciagent/CAPABILITY_INVENTORY.md` and `.ciagent/PRE_MORTEM.md`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 1 — Title
|
|
||||||
|
|
||||||
**Nova — The New Dawn of DevSecOps.** Security as a seamless enabler of fast deployments — not a bottleneck, not a "no" department.
|
|
||||||
|
|
||||||
The consumer surface is intentionally tiny. The platform's surface is large and opinionated.
|
|
||||||
|
|
||||||
> **Speaker notes:** Brief introduction — this deck covers *who uses the platform and how fast/safe they ship*, not the internal mechanics (that's the companion deck). Set the frame: velocity without sacrificing safety, and security/observability/compliance as platform defaults rather than per-team effort.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 2 — Two consumer paths, one safety envelope
|
|
||||||
|
|
||||||
The platform serves **two kinds of consumer** through two coordinated paths — but both converge on the **same contract, the same policy envelope, and the same evidence stream.**
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
subgraph UP ["Upstream — anything"]
|
|
||||||
direction TB
|
|
||||||
A["Technical dev\n(app code + contract)"]
|
|
||||||
B["Citizen dev\n(intent → AI agent\n→ contract)"]
|
|
||||||
end
|
|
||||||
subgraph ACDL ["Nova — infrastructure only"]
|
|
||||||
C["Same contract\nSame pipeline\nSame safety"]
|
|
||||||
D["Provision\nAWS resources"]
|
|
||||||
E["Evidence\nhash-chained"]
|
|
||||||
end
|
|
||||||
subgraph DOWN ["Downstream"]
|
|
||||||
F["AWS resources\nrunning"]
|
|
||||||
G["Consumer pipeline\ndeploys image"]
|
|
||||||
end
|
|
||||||
A --> C
|
|
||||||
B --> C
|
|
||||||
C --> D
|
|
||||||
C --> E
|
|
||||||
D --> F
|
|
||||||
F --> G
|
|
||||||
```
|
|
||||||
|
|
||||||
- **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.
|
|
||||||
- **Upstream is anything** — IDE, agentic SDLC, or vibe coding. Nova doesn't care how the contract was produced.
|
|
||||||
- **Nova is infrastructure only** — it provisions and governs AWS resources. Application deployment is upstream.
|
|
||||||
|
|
||||||
> **Speaker notes:** This is the thesis of the deck. The two surfaces are *parallel*, not a progression — a citizen developer doesn't "graduate" to the developer surface. Both produce a contract; both get the same treatment. The scope boundary matters: anything upstream of the contract is out of Nova's concern. The leadership takeaway: we expand who can ship safely without lowering the bar.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 3 — The platform at a glance
|
|
||||||
|
|
||||||
One picture of the whole platform — what you touch, what the platform owns, and where the safety lives. The rest of this deck zooms into the developer-facing pieces.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart TD
|
|
||||||
subgraph UP ["Consumer surfaces — upstream"]
|
|
||||||
direction LR
|
|
||||||
U1["Technical dev\napp code + contract"]
|
|
||||||
U2["Citizen dev\nintent → AI agent → contract"]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph ACDL ["Nova — infrastructure only"]
|
|
||||||
direction TB
|
|
||||||
CS["Contract schema\n(validate + fail-fast)"]
|
|
||||||
subgraph PIPE ["Central pipeline — fixed stages, every deployment"]
|
|
||||||
direction LR
|
|
||||||
P1["Validate"] --> P2["Resolve\ntarget stack"] --> P3["Security\nchecks"] --> P4["Infra plan"] --> P5["Policy\nchecks"] --> P6["Confidence\nsignal"] --> P7["Evidence\nevent"] --> P8["Infra apply"]
|
|
||||||
end
|
|
||||||
CAT["Module catalog\nprimitives + modules\n(security-reviewed)"]
|
|
||||||
ADAPT["Engine adapter\n(stateless → Terraform)"]
|
|
||||||
ENV["Platform-managed\nenvironments\naccount · VPC · state · IAM"]
|
|
||||||
HITL["HITL gates\nqa · prod · dr"]
|
|
||||||
EVID["Evidence stream\nhash-chained outbox\n(RPO = 0)"]
|
|
||||||
CS --> PIPE
|
|
||||||
CAT --> P2
|
|
||||||
ADAPT --> P4
|
|
||||||
ADAPT --> P8
|
|
||||||
ENV --> P8
|
|
||||||
P6 --> HITL
|
|
||||||
HITL --> P8
|
|
||||||
P7 --> EVID
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph DOWN ["Downstream"]
|
|
||||||
direction LR
|
|
||||||
D1["AWS resources\nrunning\n(tagged, encrypted)"]
|
|
||||||
D2["Consumer pipeline\ndeploys image"]
|
|
||||||
end
|
|
||||||
|
|
||||||
U1 --> CS
|
|
||||||
U2 --> CS
|
|
||||||
P8 --> D1
|
|
||||||
D1 --> D2
|
|
||||||
```
|
|
||||||
|
|
||||||
- **You own the left edge** — app code and a contract. That is the entire consumer surface.
|
|
||||||
- **The platform owns everything in the middle** — the pipeline, the catalog, the adapter, the environments, the gates, the evidence.
|
|
||||||
- **Two surfaces, one pipeline, one evidence stream** — a senior engineer and a citizen developer converge on the same safety envelope.
|
|
||||||
- **The bar rises automatically** — the confidence signal and HITL gates scale with the target environment, not with a ticket.
|
|
||||||
|
|
||||||
> **Speaker notes:** This is the one-slide map. For a developer-experience audience, frame it from the left edge: "this is what you touch, this is what the platform owns for you." The leadership beat: the convergence — two surfaces, one pipeline, one evidence stream — is the design point that lets us expand who can ship safely without lowering the bar. Don't walk every node; point to the contract boundary and say "the rest of this deck zooms into the developer-facing pieces."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 4 — Three things. The entire consumer surface.
|
|
||||||
|
|
||||||
Three things. That is the entire consumer-side surface.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
id: msvc
|
|
||||||
name: microservice
|
|
||||||
environment: dev
|
|
||||||
infrastructure:
|
|
||||||
microservice:
|
|
||||||
version: "1.0.0"
|
|
||||||
inputs:
|
|
||||||
cpu: 256
|
|
||||||
memory: 512
|
|
||||||
desired_count: 2
|
|
||||||
port: 8080
|
|
||||||
```
|
|
||||||
|
|
||||||
1. **App code** — the consumer's service, at the top level of the repo
|
|
||||||
2. **A contract** — a single YAML file: id, name, environment, infrastructure
|
|
||||||
3. **A one-line CI definition** — a thin `uses:` wrapper pointing at a versioned platform workflow
|
|
||||||
|
|
||||||
The developer does **not**: write infrastructure modules, clone the platform repo, hold cloud credentials, or maintain a state backend.
|
|
||||||
|
|
||||||
> **Speaker notes:** Hold this slide. The audience should sit with how small the consumer surface is. Every item in the "does not" list is a category of toil the platform removes. The contract is the API — deliberately tiny so that it can be reviewed, validated, and audited. For the Head of DevOps: this is the lever for throughput — the bottleneck moves off the platform team's ticket queue.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 5 — See what the platform does, in real time
|
|
||||||
|
|
||||||
Developers see **what the platform is doing**, in real time.
|
|
||||||
|
|
||||||
- **Streamed output by default** — the plan, policy-check results, and each check record flow to stdout.
|
|
||||||
- **PR comments after every successful pipeline stage** — a developer always knows where they stand.
|
|
||||||
- **Clear, explainable halt reasons** — a policy violation, an insufficient confidence signal, or a missing attestation. **Never an opaque debugging exercise.**
|
|
||||||
- **Connection strings posted as PR comments** — human-readable, no hunting. Runtime secrets go to encrypted Parameter Store (KMS-encrypted, namespaced), never to logs.
|
|
||||||
- **Errors become GitHub issues, automatically** — a failed deploy opens an issue on the platform repo.
|
|
||||||
|
|
||||||
> **Speaker notes:** This directly answers "but developers hate platforms that hide what they're doing." The platform is opinionated about *what* runs, not *opaque* about *that* it runs. The PR-comment-after-each-stage pattern is a small thing that compounds into trust. 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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 6 — Pick from pre-built, security-reviewed blocks
|
|
||||||
|
|
||||||
Developers pick from **pre-built, security-reviewed building blocks.**
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
subgraph PRIM ["Primitives"]
|
|
||||||
direction TB
|
|
||||||
P1["S3"]
|
|
||||||
P2["VPC"]
|
|
||||||
P3["ECS"]
|
|
||||||
P4["IAM"]
|
|
||||||
P5["ALB"]
|
|
||||||
P6["ECR"]
|
|
||||||
P7["CloudFront"]
|
|
||||||
P8["WAF"]
|
|
||||||
P9["RDS"]
|
|
||||||
end
|
|
||||||
subgraph MOD ["Modules — composed patterns"]
|
|
||||||
direction TB
|
|
||||||
M1["Static site\nCDN + WAF + S3"]
|
|
||||||
M2["Microservice\nVPC + ECS + ALB + ECR"]
|
|
||||||
end
|
|
||||||
PRIM --> MOD
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Primitives** — single-purpose resources (S3, VPC, ECS, IAM, ALB, ECR, CloudFront, WAF, RDS), each with documented inputs/outputs and versioning.
|
|
||||||
- **Modules** — composed patterns (a static site with CDN + WAF; a microservice with VPC + ECS + ALB + ECR).
|
|
||||||
- **Validated examples per module** — `simple.yaml` + `complex.yaml`, validated against the contract schema in CI. Examples cannot drift from the schema silently.
|
|
||||||
- **Auto-promotion of patterns** — auto-promoted to the catalog after 3 observed usages. <span class="badge planned">Planned</span>
|
|
||||||
- **Compliance extension points** — each module lists where GDPR, SOX, SOC2, DORA controls will wire in. <span class="badge planned">Planned</span>
|
|
||||||
|
|
||||||
> **Speaker notes:** The catalog is what makes "declare intent" practical — you can only declare a module that exists. For leadership: the catalog is the leverage. One well-reviewed module serves every consumer; a fix to the module serves every consumer on the next run. This is the compounding asset.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 7 — The bar rises automatically with sensitivity
|
|
||||||
|
|
||||||
The contract is environment-agnostic. The platform raises the bar automatically.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
DEV["dev<br/>autonomous"] -->|raise the bar| QA["qa<br/>QA attests"]
|
|
||||||
QA -->|raise the bar| PROD["prod<br/>SRE attests"]
|
|
||||||
PROD -->|raise the bar| DR["dr<br/>SRE attests + DR drill"]
|
|
||||||
```
|
|
||||||
|
|
||||||
| Environment | What the platform adds | Maturity |
|
|
||||||
|---|---|---|
|
|
||||||
| dev | Confidence ≥ 0.50, fully autonomous | — |
|
|
||||||
| qa | QA human attestation + confidence ≥ 0.75 | <span class="badge planned">Planned</span> |
|
|
||||||
| prod | SRE human attestation + confidence ≥ 0.90 | <span class="badge planned">Planned</span> |
|
|
||||||
| dr | SRE human attestation + confidence ≥ 0.95 + DR drill reference | <span class="badge planned">Planned</span> |
|
|
||||||
|
|
||||||
- **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.
|
|
||||||
- **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. The DX win: the contract stays stable across environments; the safety win: the platform raises the threshold and attestation bar automatically based on the target environment. The consumer can't bypass the gates — they pick *which* environment to target, and the platform applies the right bar. Be honest about maturity: dev is tested and pilot-ready; qa/prod/dr wiring is planned.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 8 — Tearing down is as gated as deploying
|
|
||||||
|
|
||||||
Tearing down a stack is **as deliberate as deploying one.**
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
A["Validate CR\n(CMDB)"]
|
|
||||||
B["Disable\nprevent_destroy"]
|
|
||||||
C["SRE\napprove"]
|
|
||||||
D["Zero counts\n+ destroy"]
|
|
||||||
E["SRE\napprove"]
|
|
||||||
F["Key enters\ngrace window"]
|
|
||||||
A --> B --> C --> D --> E --> F
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
uses: acdl/.github/workflows/deploy.yml@v1.12
|
|
||||||
with:
|
|
||||||
contract: .nova/contract.yml
|
|
||||||
mode: decommission
|
|
||||||
changeRequestId: "CHG0678912"
|
|
||||||
```
|
|
||||||
|
|
||||||
A 2-step pipeline with **two SRE human-attestation gates**:
|
|
||||||
|
|
||||||
1. **Validate the change request** — the platform queries the CMDB and asserts the CR is `approved` and matches the consumer repo. No CR, no decommission.
|
|
||||||
2. **Disable deletion protection** → **SRE approves** → **Zero all counts + destroy** → **a second SRE approves.**
|
|
||||||
|
|
||||||
The per-stack encryption key enters a **grace window** (default 30 days) so encrypted data remains recoverable.
|
|
||||||
|
|
||||||
> **Speaker notes:** The counter-argument to "deletion protection makes cleanup impossible" is this slide. Decommission is a first-class, gated, two-approval flow — not a lock with no key, and not an ungated `terraform destroy`. For the Head of Infrastructure: the CMDB validation means decommission is auditable, not just possible.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 9 — You control when you absorb improvements
|
|
||||||
|
|
||||||
Consumers control **when** they absorb platform improvements.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
subgraph FLOAT ["@v1.12 — floating MAJOR+MINOR"]
|
|
||||||
direction LR
|
|
||||||
F1["v1.12.0"]
|
|
||||||
F2["v1.12.1"]
|
|
||||||
F3["v1.12.2"]
|
|
||||||
F1 --> F2 --> F3
|
|
||||||
end
|
|
||||||
subgraph PIN ["@v1.12.2 — pinned exact"]
|
|
||||||
direction LR
|
|
||||||
P1["v1.12.2"]
|
|
||||||
P2["v1.12.2"]
|
|
||||||
P3["v1.12.2"]
|
|
||||||
P1 --> P2 --> P3
|
|
||||||
end
|
|
||||||
subgraph MAJ ["@v1 — float MAJOR only"]
|
|
||||||
direction LR
|
|
||||||
M1["v1.12.0"]
|
|
||||||
M2["v1.13.0"]
|
|
||||||
M3["v1.14.0"]
|
|
||||||
M1 --> M2 --> M3
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Floating MAJOR + MINOR tags** (e.g. `@v1.12`) — automatically receive patch updates within the line.
|
|
||||||
- **Semantic versioning with a clear contract:** interface → MAJOR, behavior → MINOR, lifecycle → PATCH.
|
|
||||||
- **Pin to an exact version** for maximum stability, or float on MAJOR only (`@v1`) to absorb new features on your 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.
|
|
||||||
|
|
||||||
> **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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 10 — Fails gracefully, not opaquely
|
|
||||||
|
|
||||||
First impressions of a platform are made **when it fails for the first time.** The platform fails gracefully.
|
|
||||||
|
|
||||||
When no environment is bound, the platform emits a **user-friendly onboarding prompt** instead of failing opaquely. 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).
|
|
||||||
3. The expected turnaround for the platform team to grant the environment.
|
|
||||||
4. How to request an environment.
|
|
||||||
|
|
||||||
The pipeline then **exits without attempting a deployment** — no partial state, no confusing errors.
|
|
||||||
|
|
||||||
<span class="badge planned">Citizen developer onboarding path: planned</span>
|
|
||||||
|
|
||||||
> **Speaker notes:** This looks like a small thing; it's actually a cultural one. The platform's posture is "help me get started," not "you should have known." For the Head of DevOps: this is what drives adoption. Platforms that fail opaquely on first run get routed around.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 11 — The desired outcomes
|
|
||||||
|
|
||||||
- **Velocity without sacrificing safety.** Speed is in the ergonomics; safety is in the gates the consumer cannot bypass.
|
|
||||||
- **Security, observability, and compliance as platform defaults** — not per-team effort, not post-hoc remediation.
|
|
||||||
- **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.
|
|
||||||
- **Infrastructure as a utility, not a craft.** Teams consume infrastructure, they don't maintain it.
|
|
||||||
- **A path to the citizen developer.** The same safety envelope serves a senior engineer and a non-technical consumer.
|
|
||||||
|
|
||||||
> **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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix — Contents
|
|
||||||
|
|
||||||
For deep dives — these slides cover details omitted from the main 10.
|
|
||||||
|
|
||||||
1. **A1 — The Citizen Developer Experience** (full)
|
|
||||||
2. **A2 — No Platform Code, No Cloning** (detail)
|
|
||||||
3. **A3 — Local Reproducibility** (detail)
|
|
||||||
4. **A4 — The Road to the North Star** (phased roadmap)
|
|
||||||
5. **A5 — Glossary**
|
|
||||||
6. **A6 — Operating Model & Cost** (real AWS spend + pre-mortem)
|
|
||||||
7. **A7 — Verified by Construction** (the v1.11 architecture)
|
|
||||||
|
|
||||||
> **Speaker notes:** These are backup slides for Q&A. Use them when the audience asks for the detail behind a main-slide claim. Don't walk through them in the main talk unless time permits.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A1 — The Citizen Developer Experience
|
|
||||||
|
|
||||||
A non-technical consumer ships a production deployment **by declaring intent** — without authoring a workflow, a configuration file, or an infrastructure module. Think of this as **vibe coding on a laptop** — the consumer describes what they want; an AI agent turns that into a contract that the platform treats identically to a senior engineer's.
|
|
||||||
|
|
||||||
- The consumer opens an issue describing what they need (e.g. "a web API for the pricing service").
|
|
||||||
- An AI agent maps the intent to a contract referencing a module from the **reviewed skill catalog.**
|
|
||||||
- The contract enters the **same pipeline** and must clear the **same confidence gate** before promotion.
|
|
||||||
|
|
||||||
**Guardrails that make this safe:**
|
|
||||||
|
|
||||||
- Skills are **versioned, signed, and reviewed for sensitive data before release** (Infra & Ops owns the review — it is the mandatory release gate).
|
|
||||||
- Agents are **stateless** — all state lives in the platform. The platform does not run the skill blindly; it trusts and **always verifies** on the platform side.
|
|
||||||
- The agent's trace and submission confidence are captured in the contract (`profile: agentic`), so a reviewer can see *how* the contract was produced.
|
|
||||||
- **Initial skill catalog:** web API, worker, scheduled job, static asset, basic observability bootstrap.
|
|
||||||
|
|
||||||
<span class="badge planned">Skill catalog + real agent runtime: planned</span>
|
|
||||||
|
|
||||||
> **Speaker notes:** Be honest about maturity: the *mechanism* (agent → contract → same pipeline) is designed and the stub was proven in the v1.0 demo; the full skill catalog and real agent runtime are planned. The "vibe coding on a laptop" framing is intentional — it meets the citizen developer where they already are, but every submission still passes the same safety envelope. The design point matters to leadership now: we are building for a world where more of the org can ship safely, not where more of the org has to become a platform engineer.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A2 — No Platform Code, No Cloning
|
|
||||||
|
|
||||||
Consumers `uses:` a **versioned** central workflow. The platform fetches itself at run time. The consumer **never touches platform internals.**
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
A["Consumer repo<br/>app + contract + 'uses:'"] -->|triggers on push to main| B["Platform runner"]
|
|
||||||
B -->|checks out the consumer repo| A
|
|
||||||
B -->|checks out the Nova platform repo<br/>into the workspace| C["Platform code<br/>(modules, adapters, schemas)"]
|
|
||||||
C --> B
|
|
||||||
B -->|runs the pipeline against<br/>the consumer's contract| D["Consumer's resources in AWS"]
|
|
||||||
```
|
|
||||||
|
|
||||||
- The consumer's CI definition is a thin wrapper — one `uses:` line pointing at a versioned tag.
|
|
||||||
- The runner checks out the consumer repo, then checks out the platform repo into the workspace.
|
|
||||||
- The platform installs its own runtime dependencies. The consumer installs nothing.
|
|
||||||
- The consumer **never clones the platform repo, never invokes platform scripts locally** (optional `--check-only` validation is available but not required for the happy path).
|
|
||||||
- When the platform ships a fix, every consumer on a floating MAJOR.MINOR tag gets it on their next run — no per-repo upgrade project.
|
|
||||||
|
|
||||||
> **Speaker notes:** The Head of Cloud cares about this: there is no "platform code in every consumer repo" problem. The version-pinned `uses:` line is the *only* coupling, and it's a coupling that updates itself within the line.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A3 — Local Reproducibility
|
|
||||||
|
|
||||||
The entire CI pipeline runs **from the shell**, not just in CI.
|
|
||||||
|
|
||||||
- `scripts/run_ci.sh` mirrors the CI pipeline locally — the same three stages (lint → test → check-only) in sequence.
|
|
||||||
- `scripts/run_platform.sh --check-only` runs the platform **offline** — no AWS, no policy engine, no outbox required. Validates a contract end-to-end before pushing.
|
|
||||||
- `--plan-only` runs through the infrastructure plan without applying.
|
|
||||||
- The CI and deploy pipelines are defined by **declarative contracts** (YAML instances validated against JSON Schemas) — a single source of truth that both workflows implement.
|
|
||||||
|
|
||||||
> **Speaker notes:** This is the "no surprises before you push" story. A consumer can validate their contract offline, run the plan offline, and only push when they're confident. The same declarative contract drives both the local tooling and CI — there's no "works on my machine, fails in CI" gap.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A4 — The Road to the North Star
|
|
||||||
|
|
||||||
*Proposed phasing — not formally planned.*
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
P1["Phase 1<br/>Core platform<br/>(22/22 Verified)"] --> P2["Phase 2<br/>Safe promotion<br/>qa/prod/dr wiring"]
|
|
||||||
P2 --> P3["Phase 3<br/>Agentic surface<br/>(skill catalog + agents)"]
|
|
||||||
P3 --> P4["Phase 4<br/>North star<br/>citizen developer GA"]
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Speaker notes:** This is a proposed phasing, not a formally committed plan — call that out explicitly. Phase 1 is what's tested and Verified today (22/22 capabilities, torn down to zero-cost). Phase 2 is the next milestone (qa/prod/dr wiring). Phase 3 introduces the agentic surface. Phase 4 is the north star: citizen developer GA on the same safety envelope. Use this only when an audience member asks "how do you get from here to there."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A5 — Glossary
|
|
||||||
|
|
||||||
| Term | Meaning |
|
|
||||||
|---|---|
|
|
||||||
| **OIDC** | OpenID Connect — federation protocol for short-lived tokens, no long-lived credentials |
|
|
||||||
| **ABAC** | Attribute-Based Access Control — access scoped by resource tags + repo identity, not roles |
|
|
||||||
| **CMK** | Customer-Managed Key — per-stack encryption key, 90-day rotation, no shared keys |
|
|
||||||
| **CMDB** | Configuration Management Database — validates change requests for decommission |
|
|
||||||
| **RPO** | Recovery Point Objective — RPO = 0 means evidence is written synchronously, no data loss |
|
|
||||||
| **HITL** | Human-in-the-Loop — deliberate human attestation required for qa/prod/dr environments |
|
|
||||||
| **VCS** | Version Control System — the git hosting platform (GitHub, Gitea, GitLab) |
|
|
||||||
| **NFR** | Non-Functional Requirement — encryption, tagging, observability standards |
|
|
||||||
|
|
||||||
> **Speaker notes:** Keep this slide in your back pocket for the audience member who asks "what does ABAC actually mean?" Don't read it aloud.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A6 — Operating Model & Cost
|
|
||||||
|
|
||||||
Nova runs at **zero cloud cost** for day-to-day development. The v1.0→v1.10 AWS spend was measured directly via Cost Explorer (`COST.md`, 2026-07-28):
|
|
||||||
|
|
||||||
| Metric | Value |
|
|
||||||
|--------|-------|
|
|
||||||
| Total spend (8 days) | **$0.001883** |
|
|
||||||
| Daily average | $0.000235 |
|
|
||||||
| Projected monthly | ~$0.007 |
|
|
||||||
| Peak day | 2026-07-27 ($0.000867 — v1.10 regression + verify run) |
|
|
||||||
|
|
||||||
- **Local emulators are the primary tier** — the full pipeline runs in-process, no AWS credentials, no Checkov, no DynamoDB.
|
|
||||||
- **Live-AWS verification is milestone-scoped, then torn down.** The v1.11 lifecycle pipeline ran apply→modify→destroy for every module, then tore down to zero-cost steady state (D-096 — teardown mandatory before milestone COMPLETE). The lifecycle pipeline now **defaults to plan-only** on every PR (fast, no AWS mutation, no cost); a CI variable (`NOVA_LIFECYCLE_MODE=full`) overrides to the real apply→destroy for milestone verification (REQ-134, v1.12).
|
|
||||||
- **Cost drivers** are spike-scoped: Terraform plan reads (free), S3 state storage (cents), DynamoDB outbox (cents). No running infrastructure between milestones.
|
|
||||||
|
|
||||||
**Pre-mortem (`PRE_MORTEM.md`):** the project's failure modes were pre-mortemed before the leadership pitch. The v1.10 decay incident (diff-scoped VERIFY missed 7 adapter defects — decks advertised capability that wasn't reproducible) is the root pattern: *a claim outruns the verification that backs it.* Four forward failure modes + structural mitigations (regression-tested IAM baseline, mandatory teardown, verified-only deck claims, honest scope).
|
|
||||||
|
|
||||||
> **Speaker notes:** The headline for the Head of Cloud / Finance: less than one cent over 8 days of active development; zero BAU cloud spend; the lifecycle pipeline defaults to plan-only so the PR-time cost is zero. The pre-mortem is the credibility slide — we already asked "how does this fail?" and the mitigations are structural.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## A7 — Verified by Construction (the v1.11 architecture)
|
|
||||||
|
|
||||||
v1.11 rebuilt the platform on two architectural pillars that make "Verified" a structural property, not a claim:
|
|
||||||
|
|
||||||
- **The stateless adapter (918 → ~80 lines).** The Terraform adapter was a 918-line monolith with 3 constant tables and 39 type-specific branches. It is now a ~80-line **stateless assembler**: it owns no module content. Each L1 module ships a real `terraform/` module dir owning its resource shape, nested blocks, and defaults. A new module is a new terraform dir, not a code change. *(The v1.12 P67 fix closed a dedup defect for multi-resource L1s — ecs-service, alb; CAP-013 now Verified.)*
|
|
||||||
- **Pipeline-driven lifecycle testing.** A `modules-lifecycle` pipeline matrix-runs each L1 and L2 module's contracts through apply→modify→destroy against live AWS. **The "test" = the pipeline cell going green.** Defaults to **plan-only** on every PR (fast, no AWS mutation, no cost); `NOVA_LIFECYCLE_MODE=full` runs the real apply→destroy for milestone verification (REQ-134, v1.12). The regression gate (D-091) re-runs all 22 capabilities at milestone completion — 22/22 Verified as of v1.12.
|
|
||||||
|
|
||||||
> **Speaker notes:** This is the deep-dive slide for the Head of Engineering / Architecture. The two pillars answer "how do you keep the decks honest?" The adapter is simple enough to reason about (a stateless assembler); the lifecycle pipeline is the automated verification that backs every "Testing" claim. The v1.10 lesson is the negative space: a 918-line adapter with type-specific branches decayed silently. The ~80-line stateless adapter + the milestone regression gate are the structural fix. The plan-only default (v1.12) means verification runs on every PR at zero cost, with the full apply→destroy gated behind a CI variable override.
|
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
# RACI — Who Owns What
|
||||||
|
|
||||||
|
> This page is the citizen-developer-facing copy.
|
||||||
|
|
||||||
|
Nova's delivery lifecycle has four roles. This page clarifies who owns
|
||||||
|
what — so the citizen developer knows what they bring, what the platform
|
||||||
|
provides, what quality engineering guards, and what is co-owned with SRE.
|
||||||
|
|
||||||
|
## The Four Roles
|
||||||
|
|
||||||
|
### Citizen Developer (CD)
|
||||||
|
|
||||||
|
That's you — the consumer (technical developer L3A or non-technical L3B).
|
||||||
|
You are **Responsible** for all **Functional Requirements (FRs)** and
|
||||||
|
**User Acceptance Testing (UAT)**. You produce the FRs + UAT via your AI
|
||||||
|
coding agent, an upstream agentic SDLC platform, or any upstream
|
||||||
|
development platform. **The source does not matter** — all are subject to
|
||||||
|
the same compliance standards (the submission-readiness gate, the
|
||||||
|
contract schema, the policy envelope, the immutable audit stream). Nova
|
||||||
|
validates the submission, not the author.
|
||||||
|
|
||||||
|
### Platform (Nova)
|
||||||
|
|
||||||
|
Nova is **Responsible** for all **Non-Functional Requirements (NFRs)**,
|
||||||
|
**Infrastructure** (cloud resource lifecycle, state, IAM), and
|
||||||
|
**Production deployments to cloud** (the apply path, the pipeline, the
|
||||||
|
release mechanics).
|
||||||
|
|
||||||
|
### Quality Engineering (QE)
|
||||||
|
|
||||||
|
Quality Engineering is **Responsible** for the platform-side quality
|
||||||
|
checks: policy enforcement, confidence scoring, schema validation, and
|
||||||
|
the functional/contract/non-functional evidence that feeds attestation.
|
||||||
|
QE owns the **quality** of what the platform produces — the gate
|
||||||
|
evidence, not the gate decision.
|
||||||
|
|
||||||
|
### SRE — co-owned with you
|
||||||
|
|
||||||
|
Production readiness is **co-owned**. SRE owns operational readiness:
|
||||||
|
the operational attestation (incident response, capacity, resilience,
|
||||||
|
DR). The platform performs the QA + SRE attestations agentically (it
|
||||||
|
runs the confidence signal, the policy checks, the
|
||||||
|
separation-of-duties). The citizen developer **oversees and triggers**
|
||||||
|
the actual release — the human attestation at the stage gate is your
|
||||||
|
authorization. The platform runs the checks; you authorize the promotion.
|
||||||
|
This is the "autonomy in operations, human at stage gates" model.
|
||||||
|
|
||||||
|
## The Matrix
|
||||||
|
|
||||||
|
| Work Category | Citizen Developer | Platform | Quality Engineering | SRE |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| **Functional Requirements (FRs)** | **R/A** | C | I | I |
|
||||||
|
| **User Acceptance Testing (UAT)** | **R/A** | C | I | I |
|
||||||
|
| **Non-Functional Requirements (NFRs)** | I | **R/A** | C | C |
|
||||||
|
| **Infrastructure (cloud, state, IAM)** | I | **R/A** | I | C |
|
||||||
|
| **QA (policy, confidence, schema checks)** | C | R | **R/A** | I |
|
||||||
|
| **Production deployment to cloud** | I | **R/A** | C | C |
|
||||||
|
| **Quality attestation (QA sign-off)** | **A** | R | **R** | I |
|
||||||
|
| **Production readiness (SRE sign-off)** | **A** | R | C | **R** |
|
||||||
|
|
||||||
|
**Key:** **R** = Responsible (does the work) · **A** = Accountable (owns
|
||||||
|
the outcome, sign-off) · **C** = Consulted · **I** = Informed.
|
||||||
|
|
||||||
|
## What This Means in Practice
|
||||||
|
|
||||||
|
**You (Citizen Developer) bring:**
|
||||||
|
- Your application code + a contract that declares intent.
|
||||||
|
- Your FRs (what the application does).
|
||||||
|
- Your UAT (you accept the deployment when it meets your FRs).
|
||||||
|
|
||||||
|
**Nova (Platform) provides:**
|
||||||
|
- The NFRs (security, observability, compliance — baked into the
|
||||||
|
pipeline, not your concern).
|
||||||
|
- The infrastructure (cloud resources, state management, IAM scoping).
|
||||||
|
- The production deployment (the apply path, the pipeline, the release).
|
||||||
|
|
||||||
|
**Quality Engineering guards:**
|
||||||
|
- The policy enforcement, confidence scoring, schema validation.
|
||||||
|
- The quality attestation evidence that feeds the stage gates.
|
||||||
|
|
||||||
|
**You co-own production readiness with SRE:**
|
||||||
|
- Nova + SRE run the attestations (QA quality sign-off, SRE operational
|
||||||
|
readiness).
|
||||||
|
- You authorize the promotion at the stage gate. No promotion happens
|
||||||
|
without your recorded attestation.
|
||||||
|
|
||||||
|
## Compliance Standards Apply Equally
|
||||||
|
|
||||||
|
Your FRs + UAT may come from any source — an AI coding agent, an
|
||||||
|
agentic SDLC platform, or a traditional IDE. Nova does not
|
||||||
|
differentiate. All submissions pass through the same gate
|
||||||
|
(`schemas/submission-readiness.schema.json`): tags, environment
|
||||||
|
metadata, policy preconditions, profile markers. The compliance
|
||||||
|
standards are the same regardless of how the code was authored. This is
|
||||||
|
by design: the audit trail is the same, the policy envelope is the
|
||||||
|
same, the evidence stream is the same. The source does not matter; the
|
||||||
|
submission does.
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# Scope — Nova is Downstream of PDLC
|
||||||
|
|
||||||
|
> This page is the citizen-developer-facing copy.
|
||||||
|
|
||||||
|
## The Boundary
|
||||||
|
|
||||||
|
The **Product Development Lifecycle (PDLC)** is **upstream** of Nova. The
|
||||||
|
PDLC includes:
|
||||||
|
|
||||||
|
- Product backlog / roadmap planning
|
||||||
|
- Code authorship (via AI coding agent, IDE, or agentic SDLC platform)
|
||||||
|
- Sprint planning / issue tracking
|
||||||
|
- Application business logic
|
||||||
|
- IDE workflows / developer experience
|
||||||
|
|
||||||
|
Nova never penetrates the PDLC. Nova's domain is **infrastructure +
|
||||||
|
delivery only**. Nova integrates with externally owned PDLC, SDLC,
|
||||||
|
Agentic, and Citizen Developer platforms with no regard for the source
|
||||||
|
of the intent: Nova provides a set of skills and MCP endpoints that help
|
||||||
|
the developer or AI agent make their application production-grade, and
|
||||||
|
all intents to deploy to production go through the same rigorous
|
||||||
|
controls, quality gates, attestation, and evidence stream.
|
||||||
|
|
||||||
|
## What Nova Does
|
||||||
|
|
||||||
|
Nova governs the downstream half:
|
||||||
|
|
||||||
|
- **Contract ingestion** — the validated entry point
|
||||||
|
- **Submission-readiness gate** — what is acceptable to start
|
||||||
|
(`schemas/submission-readiness.schema.json`)
|
||||||
|
- **Policy enforcement** — the confidence signal, Checkov, tagging
|
||||||
|
- **Cloud resource lifecycle** — Terraform plan/apply, state, IAM
|
||||||
|
- **Environment progression** — dev (autonomous) → qa (QA attestation) →
|
||||||
|
prod (SRE attestation) → dr (SRE attestation)
|
||||||
|
- **Immutable audit + attestation** — the Decision Ledger, the evidence
|
||||||
|
stream, the HITL gates
|
||||||
|
|
||||||
|
## The Integration Point
|
||||||
|
|
||||||
|
Integration between the PDLC and Nova is **only** through the validated,
|
||||||
|
published contract boundary:
|
||||||
|
|
||||||
|
```
|
||||||
|
PDLC (upstream) Nova (downstream)
|
||||||
|
───────────────── ─────────────────
|
||||||
|
product backlog contract ingestion
|
||||||
|
code authorship (AI agent / IDE / SDLC) → submission-readiness gate
|
||||||
|
sprint planning → policy enforcement
|
||||||
|
application business logic → cloud resource lifecycle
|
||||||
|
→ environment progression (dev→qa→prod→dr)
|
||||||
|
→ immutable audit + attestation
|
||||||
|
```
|
||||||
|
|
||||||
|
The citizen developer's AI coding agent, an upstream agentic SDLC
|
||||||
|
platform, or any upstream development platform may all produce
|
||||||
|
submissions. **The source does not matter** — all are subject to the
|
||||||
|
same compliance standards. Nova validates the submission, not the
|
||||||
|
author.
|
||||||
|
|
||||||
|
## What Nova is Not
|
||||||
|
|
||||||
|
- Not an upstream development platform (no product backlogs, IDE, code
|
||||||
|
authorship).
|
||||||
|
- Not a general-purpose AI agent platform (autonomy is narrow, bounded
|
||||||
|
by policy envelopes).
|
||||||
|
- Not a legacy infrastructure bridge (no VMs/bare metal/OS).
|
||||||
|
- Not a permissive delivery highway (no escape hatches past confidence
|
||||||
|
or HITL).
|
||||||
|
- Not a mutable audit log (VCS history ≠ regulatory evidence).
|
||||||
|
|
||||||
|
These anti-goals (from `docs/vision.md` §7 and Core Tenet #2) are
|
||||||
|
promoted here from buried tenets to an unmissable scope statement.
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# Skills — Production-Grade Guidance for the Citizen Developer
|
||||||
|
|
||||||
|
> **Source of truth (v1.18, REQ-221, REQ-222).** The Nova skill catalog
|
||||||
|
> extends the BA.A 5-skill catalog (web API, worker, scheduled job, static
|
||||||
|
> asset, basic observability bootstrap) with Atelier-derived production-
|
||||||
|
> grade engineering principles. Each skill is a markdown file under
|
||||||
|
> `skills/` keyed to an Atelier domain path.
|
||||||
|
|
||||||
|
## How the Citizen Developer's AI Agent Consumes Skills
|
||||||
|
|
||||||
|
1. **Before completing a task**, read the relevant skill file(s) that
|
||||||
|
match the task's domain.
|
||||||
|
2. **Run `review/agent-checklist.md`** (from Atelier) before finishing —
|
||||||
|
the checklist items are the gate between "the code is written" and
|
||||||
|
"the task is done."
|
||||||
|
3. **Use the Atelier MCP server** (`mcp/atelier/server.py`, P5) for
|
||||||
|
agentic validation — the `atelier.validate_against_principles` tool
|
||||||
|
catches correctness/clarity/simplicity/observability gaps that
|
||||||
|
deterministic scanners (Wiz, Checkmarx, Mend) cannot.
|
||||||
|
|
||||||
|
## The 9 Skills
|
||||||
|
|
||||||
|
| Skill | Atelier Source | Core Principles | BA.A Mapping |
|
||||||
|
|---|---|---|---|
|
||||||
|
| [`api.md`](../skills/api.md) | `domains/api/` | C1, C2, C6 | web API |
|
||||||
|
| [`security.md`](../skills/security.md) | `domains/security/` | C1 | cross-cutting (all 5) |
|
||||||
|
| [`data.md`](../skills/data.md) | `domains/data/` | C1, C4, C6 | web API, worker, scheduled job |
|
||||||
|
| [`testing.md`](../skills/testing.md) | `domains/testing/` | C1, C5 | UAT (citizen-dev RACI) |
|
||||||
|
| [`observability.md`](../skills/observability.md) | `domains/observability/` | C7 | basic observability bootstrap |
|
||||||
|
| [`errors.md`](../skills/errors.md) | `domains/errors/` | C1, C7 | web API, worker, scheduled job |
|
||||||
|
| [`devops.md`](../skills/devops.md) | `domains/devops/` | C5, C7, C8 | scheduled job, worker |
|
||||||
|
| [`infrastructure-as-code.md`](../skills/infrastructure-as-code.md) | `domains/infrastructure-as-code/` | C1, C5, C8 | static asset |
|
||||||
|
| [`compliance.md`](../skills/compliance.md) | `domains/compliance/` | C1, C5 | cross-cutting (all 5) |
|
||||||
|
|
||||||
|
## Atelier Provenance
|
||||||
|
|
||||||
|
The skills are derived from [Atelier](https://example.com/atelier)
|
||||||
|
— a first-principles docs-as-code engineering framework with 8 core
|
||||||
|
principles (C1–C8) and 19 domains, each with 10 derived P-rules. The
|
||||||
|
skills distill the citizen-developer-relevant subset of each domain's
|
||||||
|
first-principles, link to the agent-checklist triggers, and map to the
|
||||||
|
existing BA.A catalog.
|
||||||
|
|
||||||
|
Atelier is vendored under `mcp/atelier/vendor/` (pinned tag) for
|
||||||
|
audit reproducibility — an agentic validation result is replayable
|
||||||
|
against the exact principles that produced it.
|
||||||
|
|
||||||
|
## The 8 Core Principles (from Atelier)
|
||||||
|
|
||||||
|
| # | Principle | One-line |
|
||||||
|
|---|---|---|
|
||||||
|
| C1 | Correctness | The system does what it is supposed to do, and nothing else. |
|
||||||
|
| C2 | Clarity | The intent of the code is obvious to its reader. |
|
||||||
|
| C3 | Simplicity | The solution is as simple as possible, and no simpler. |
|
||||||
|
| C4 | Locality | Decisions and their consequences live near each other. |
|
||||||
|
| C5 | Reversibility | Every decision can be undone, and the cost of undoing is known. |
|
||||||
|
| C6 | Composability | Parts combine into wholes, and the parts are reusable. |
|
||||||
|
| C7 | Observability | The system's behavior is visible to those who must understand it. |
|
||||||
|
| C8 | Economy | The system uses no more resources than the task requires. |
|
||||||
|
|
||||||
|
Precedence: C1 > C2 > C3 > C4 > C5 > C6 > C7 > C8. Correctness is never
|
||||||
|
sacrificed.
|
||||||
|
|
||||||
|
## Reference-Only Domains (cited inside skills, not elevated to skill files)
|
||||||
|
|
||||||
|
These 4 Atelier domains are relevant to a citizen developer but are cited
|
||||||
|
inside the 9 skills above rather than getting their own skill file:
|
||||||
|
|
||||||
|
- **Performance** (`domains/performance/`) — cited in `observability.md` +
|
||||||
|
`devops.md` (bounded operations, timeouts, N+1)
|
||||||
|
- **Documentation** (`domains/documentation/`) — the runbook requirement
|
||||||
|
(W3.E prod mandatory) is the documentation skill in practice
|
||||||
|
- **Concurrency** (`domains/concurrency/`) — cited in `errors.md` +
|
||||||
|
`devops.md` (bounded queues, cancellation, timeout)
|
||||||
|
- **AI/ML** (`domains/ai-ml/`) — scope: engineering discipline (data
|
||||||
|
versioning, evaluation, serving, drift), not algorithm design
|
||||||
|
|
||||||
|
## Excluded Domains (not relevant to Nova citizen developer)
|
||||||
|
|
||||||
|
6 Atelier domains are excluded from the Nova skill catalog (not relevant
|
||||||
|
to a citizen developer building on Nova's infrastructure platform):
|
||||||
|
|
||||||
|
- UI/UX — Nova has no frontend (frontend-engineer deactivated, PERSONAS.md)
|
||||||
|
- Kubernetes — Nova is AWS-only this milestone (NORTH_STAR Non-Goal #7)
|
||||||
|
- GitOps + Operators — future roadmap (no GitOps reconciler today)
|
||||||
|
- Edge — not in scope (Nova is cloud, not edge)
|
||||||
|
- Messaging — not in scope (Nova deploys infra, not message brokers)
|
||||||
|
- i18n — application-level concern, not infrastructure
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
# Submission Readiness — What is Acceptable to Start
|
||||||
|
|
||||||
|
> **Source of truth:** `schemas/submission-readiness.schema.json` (v1.18,
|
||||||
|
> REQ-217). The validator is `core/submission_readiness.py` (REQ-218),
|
||||||
|
> invoked as `python3 -m core.lambda.contract_ingestor --check-readiness
|
||||||
|
> <submission.json>` (D-133).
|
||||||
|
|
||||||
|
Nova's submission-readiness gate defines what is **acceptable to start**.
|
||||||
|
It is a superset gate *above* contract-schema validity: the contract schema
|
||||||
|
(`schemas/contract.schema.json`) defines the **shape** (id / name /
|
||||||
|
environment / infrastructure); the readiness schema defines the **gate**
|
||||||
|
(tags, per-env mandatory metadata, policy preconditions, profile markers,
|
||||||
|
appSource). Both must pass before ingestion proceeds.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
```
|
||||||
|
citizen developer submits
|
||||||
|
↓
|
||||||
|
contract.schema.json validation (shape) ← the existing check
|
||||||
|
↓
|
||||||
|
submission-readiness.schema.json (gate) ← the new check
|
||||||
|
├── contractId present (non-empty)
|
||||||
|
├── environment valid (dev/qa/prod/dr)
|
||||||
|
├── tags: all 5 Nova tags present (D-054)
|
||||||
|
├── policyPreconditions declared
|
||||||
|
├── profile: developer or agentic
|
||||||
|
│ └── if agentic: naturalLanguageIntent + confidenceAtSubmission + agentTrace
|
||||||
|
├── appSource: repo + ref (for runtime fetch)
|
||||||
|
└── per-env mandatory (W3.E):
|
||||||
|
dev → stack + environment
|
||||||
|
qa → + validation.e2eSuite + validation.loadTest
|
||||||
|
prod → + runbook + dashboard + oncall
|
||||||
|
dr → + drDrillRef
|
||||||
|
↓
|
||||||
|
ready → proceed to contract ingestion
|
||||||
|
not ready → reject with citizen-developer-facing error (reason code)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reason Codes
|
||||||
|
|
||||||
|
When a submission is not ready, the validator returns one or more reason
|
||||||
|
codes. These are citizen-developer-facing — no stack traces.
|
||||||
|
|
||||||
|
| Code | Meaning |
|
||||||
|
|---|---|
|
||||||
|
| `MISSING_TAGS:<tag1>,<tag2>` | One or more required Nova tags are absent |
|
||||||
|
| `ENV_MISSING_MANDATORY:<env>:<field>` | A per-env mandatory field (W3.E) is missing |
|
||||||
|
| `AGENTIC_MISSING_INTENT:<marker>` | profile=agentic but a required marker is absent |
|
||||||
|
| `MISSING_APP_SOURCE` | appSource (repo + ref) is missing |
|
||||||
|
| `POLICY_PRECONDITION_MISSING` | No policy preconditions declared |
|
||||||
|
| `CONTRACT_SCHEMA_INVALID:<detail>` | The contract shape failed contract.schema.json |
|
||||||
|
| `READINESS_SCHEMA_INVALID:<detail>` | The submission failed the readiness schema |
|
||||||
|
|
||||||
|
## Good Example
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"contractId": "uuid-1234",
|
||||||
|
"id": "webapi",
|
||||||
|
"name": "Customer Web API",
|
||||||
|
"environment": "dev",
|
||||||
|
"tags": {
|
||||||
|
"nova:owner": "consumer-repo",
|
||||||
|
"nova:contract": "uuid-1234",
|
||||||
|
"nova:environment": "dev",
|
||||||
|
"nova:cost-center": "nova-default",
|
||||||
|
"nova:ref": "CHG0678912"
|
||||||
|
},
|
||||||
|
"policyPreconditions": {
|
||||||
|
"public-ingress": false,
|
||||||
|
"encryption_enabled": true,
|
||||||
|
"deletion_protection": true
|
||||||
|
},
|
||||||
|
"profile": "developer",
|
||||||
|
"appSource": {
|
||||||
|
"repo": "consumer/web-api",
|
||||||
|
"ref": "main"
|
||||||
|
},
|
||||||
|
"infrastructure": {
|
||||||
|
"static-assets": {
|
||||||
|
"inputs": {
|
||||||
|
"bucket_name": "webapi-assets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Result: **READY** — passes the shape + the gate.
|
||||||
|
|
||||||
|
## Rejected Examples
|
||||||
|
|
||||||
|
### Missing Tags
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"contractId": "uuid-1234",
|
||||||
|
"environment": "dev",
|
||||||
|
"tags": {
|
||||||
|
"nova:owner": "consumer-repo"
|
||||||
|
},
|
||||||
|
"policyPreconditions": {"public-ingress": false},
|
||||||
|
"profile": "developer",
|
||||||
|
"appSource": {"repo": "consumer/repo", "ref": "main"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Result: `NOT READY — MISSING_TAGS:nova:contract,nova:environment,nova:cost-center,nova:ref`
|
||||||
|
|
||||||
|
### Agentic Missing Intent
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"contractId": "uuid-1234",
|
||||||
|
"environment": "qa",
|
||||||
|
"tags": { "nova:owner": "x", "nova:contract": "x", "nova:environment": "qa", "nova:cost-center": "x", "nova:ref": "x" },
|
||||||
|
"policyPreconditions": {"public-ingress": false},
|
||||||
|
"profile": "agentic",
|
||||||
|
"appSource": {"repo": "x", "ref": "x"},
|
||||||
|
"validation": {"e2eSuite": true, "loadTest": true}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Result: `NOT READY — AGENTIC_MISSING_INTENT:naturalLanguageIntent; AGENTIC_MISSING_INTENT:confidenceAtSubmission; AGENTIC_MISSING_INTENT:agentTrace`
|
||||||
|
|
||||||
|
### Env Missing Mandatory (prod without runbook)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"contractId": "uuid-1234",
|
||||||
|
"environment": "prod",
|
||||||
|
"tags": { "nova:owner": "x", "nova:contract": "x", "nova:environment": "prod", "nova:cost-center": "x", "nova:ref": "x" },
|
||||||
|
"policyPreconditions": {"public-ingress": false},
|
||||||
|
"profile": "developer",
|
||||||
|
"appSource": {"repo": "x", "ref": "x"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Result: `NOT READY — ENV_MISSING_MANDATORY:prod:runbook; ENV_MISSING_MANDATORY:prod:dashboard; ENV_MISSING_MANDATORY:prod:oncall`
|
||||||
|
|
||||||
|
## Compliance-Standard Equivalence
|
||||||
|
|
||||||
|
The submission-readiness gate applies **equally** to all upstream sources.
|
||||||
|
Whether the citizen developer's submission originated from an AI coding
|
||||||
|
agent, an agentic SDLC platform, or a traditional development platform —
|
||||||
|
the same tags, the same env mandatory, the same policy preconditions, the
|
||||||
|
same profile markers are required. The source does not matter; the
|
||||||
|
submission does. This is the RACI compliance-standard equivalence note
|
||||||
|
(`docs/raci.md`) made machine-checkable.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# mcp/atelier — Nova Atelier MCP server package (v1.18)
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# Nova Atelier MCP Server
|
||||||
|
|
||||||
|
> exposes Atelier engineering principles to the citizen developer's AI
|
||||||
|
> agent. Plugin-registry architecture; stdio transport;
|
||||||
|
> vendored Atelier for audit reproducibility.
|
||||||
|
|
||||||
|
## What This Is
|
||||||
|
|
||||||
|
The server exposes 4 tools that let a citizen developer's AI coding agent
|
||||||
|
look up production-grade engineering principles and validate code against
|
||||||
|
them — agentic validation that goes **beyond deterministic scanners**
|
||||||
|
(Wiz, Checkmarx, Mend) by catching correctness, clarity, simplicity, and
|
||||||
|
observability gaps.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|---|---|
|
||||||
|
| `atelier.lookup_principle(domain, principle_id)` | Look up a principle by domain + P-rule ID (e.g., `security`, `P4`). Returns the principle text + the core C-rule it derives from. |
|
||||||
|
| `atelier.list_domains()` | List the 19 Atelier domains with P-rule counts + Nova-relevance. |
|
||||||
|
| `atelier.matrix_lookup(domain)` | Look up the domain→core principle mapping for a given domain. |
|
||||||
|
| `atelier.validate_against_principles(snippet, domains?)` | Validate a code/diff snippet against the Atelier agent-checklist. Returns pass/fail per check item with the principle citation. |
|
||||||
|
|
||||||
|
## Architecture — Plugin Registry
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp/atelier/
|
||||||
|
├── server.py # entrypoint: loads plugins, starts server
|
||||||
|
├── plugins/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── principles.py # lookup_principle, list_domains, matrix_lookup
|
||||||
|
│ └── validation.py # validate_against_principles
|
||||||
|
├── vendor/ # pinned Atelier snapshot
|
||||||
|
│ ├── VERSION.md # pinned tag + upgrade instructions
|
||||||
|
│ ├── core/first-principles.md
|
||||||
|
│ ├── domains/security/first-principles.md
|
||||||
|
│ ├── review/agent-checklist.md
|
||||||
|
│ └── matrix/principles-matrix.md
|
||||||
|
└── README.md # this file
|
||||||
|
```
|
||||||
|
|
||||||
|
Each plugin module exposes `register(mcp) -> None` and calls `@mcp.tool()`
|
||||||
|
for its tools. `server.py` scans `plugins/` and calls `register` on each.
|
||||||
|
**Future capabilities drop in as a new plugin file — no `server.py` edits.**
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
### With the MCP Python SDK installed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install "mcp[cli]"
|
||||||
|
python3 -m mcp.atelier.server
|
||||||
|
```
|
||||||
|
|
||||||
|
The server runs over stdio. An MCP client (e.g., the citizen developer's
|
||||||
|
AI coding agent) spawns it as a subprocess and calls tools via JSON-RPC.
|
||||||
|
|
||||||
|
### Without the SDK (fallback / test mode)
|
||||||
|
|
||||||
|
The server degrades to a plain-Python tool registry. Tools are callable
|
||||||
|
directly — this is how tests run without the SDK installed:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from mcp.atelier.server import NovaAtelierServer
|
||||||
|
s = NovaAtelierServer()
|
||||||
|
s.load_plugins()
|
||||||
|
result = s.call_tool("atelier_lookup_principle", {"domain": "security", "principle_id": "P4"})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Vendoring
|
||||||
|
|
||||||
|
Atelier is vendored under `vendor/` at a pinned tag (`v0.3.6`, see
|
||||||
|
`vendor/VERSION.md`). An agentic validation result is only reproducible if
|
||||||
|
the principles that produced it are pinned. Live-fetch breaks replayability
|
||||||
|
(Atelier `main` drifts). To upgrade:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/update_atelier_vendor.sh <new-tag>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Extensibility
|
||||||
|
|
||||||
|
To add a new tool (e.g., a cost-estimation tool, a policy-as-code
|
||||||
|
evaluator): create `plugins/<name>.py`, expose `register(mcp)`, and call
|
||||||
|
`@mcp.tool()` on your function. The server picks it up automatically. No
|
||||||
|
`server.py` edit. This is the extensibility insurance for future
|
||||||
|
capabilities.
|
||||||
|
|
||||||
|
## Transport
|
||||||
|
|
||||||
|
- **Now:** stdio (local agent consumption — the citizen developer's AI
|
||||||
|
agent spawns the server as a subprocess).
|
||||||
|
- **Future:** Streamable HTTP (the MCP SDK supports it on the same
|
||||||
|
`MCPServer` object; adding it is a transport-only change in `server.py`,
|
||||||
|
not a rewrite).
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# mcp/atelier package
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# mcp/atelier/plugins package
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
"""mcp/atelier/plugins/principles.py — principle lookup, domain listing, matrix lookup.
|
||||||
|
|
||||||
|
Implements 3 MCP tools (REQ-223):
|
||||||
|
- atelier.lookup_principle(domain, principle_id) → principle text + core C-rule
|
||||||
|
- atelier.list_domains() → 19 domains with P-rule counts + Nova-relevance
|
||||||
|
- atelier.matrix_lookup(domain) → domain→core principle mapping
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
_VENDOR = Path(__file__).resolve().parent.parent / "vendor"
|
||||||
|
|
||||||
|
DOMAINS = [
|
||||||
|
{"domain": "api", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "security", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "data", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "testing", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "performance", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "observability", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "errors", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "documentation", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "concurrency", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "devops", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "infrastructure-as-code", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "kubernetes", "p_rules": 10, "nova_relevant": False},
|
||||||
|
{"domain": "gitops-operators", "p_rules": 10, "nova_relevant": False},
|
||||||
|
{"domain": "ai-ml", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "i18n", "p_rules": 10, "nova_relevant": False},
|
||||||
|
{"domain": "compliance", "p_rules": 10, "nova_relevant": True},
|
||||||
|
{"domain": "edge", "p_rules": 10, "nova_relevant": False},
|
||||||
|
{"domain": "messaging", "p_rules": 10, "nova_relevant": False},
|
||||||
|
{"domain": "ui-ux", "p_rules": 10, "nova_relevant": False},
|
||||||
|
]
|
||||||
|
|
||||||
|
_MATRIX = {
|
||||||
|
"security": [
|
||||||
|
{"p": "P1", "core": "C1", "title": "Boundary Validation"},
|
||||||
|
{"p": "P2", "core": "C1, C8", "title": "Least Privilege"},
|
||||||
|
{"p": "P3", "core": "C1", "title": "Defense in Depth"},
|
||||||
|
{"p": "P4", "core": "C1, C7", "title": "Secrets Never Exposed"},
|
||||||
|
{"p": "P5", "core": "C1", "title": "Authenticated by Default"},
|
||||||
|
{"p": "P6", "core": "C1", "title": "Encrypted in Transit and at Rest"},
|
||||||
|
{"p": "P7", "core": "C1, C7", "title": "Auditable Actions"},
|
||||||
|
{"p": "P8", "core": "C1, C8", "title": "Patched Dependencies"},
|
||||||
|
{"p": "P9", "core": "C1, C6", "title": "Isolated Blast Radius"},
|
||||||
|
{"p": "P10", "core": "C1", "title": "Secure by Default"},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def register(mcp: Any) -> None:
|
||||||
|
"""Register the principles tools with the MCP server (or fallback registry)."""
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def atelier_lookup_principle(domain: str, principle_id: str) -> dict[str, Any]:
|
||||||
|
"""Look up an Atelier principle by domain + P-rule ID (e.g., 'security', 'P4').
|
||||||
|
|
||||||
|
Returns the principle title, text, and the core C-rule(s) it derives from.
|
||||||
|
"""
|
||||||
|
fp = _VENDOR / "domains" / domain / "first-principles.md"
|
||||||
|
if not fp.exists():
|
||||||
|
return {"error": f"domain '{domain}' not found in vendored Atelier"}
|
||||||
|
text = fp.read_text()
|
||||||
|
# Parse the P-rule section
|
||||||
|
pattern = rf"## ({principle_id}\s*—\s*.+?)\n(.+?)(?=\n## |\Z)"
|
||||||
|
match = re.search(pattern, text, re.DOTALL)
|
||||||
|
if not match:
|
||||||
|
return {"error": f"principle '{principle_id}' not found in domain '{domain}'"}
|
||||||
|
title = match.group(1).strip()
|
||||||
|
body = match.group(2).strip()
|
||||||
|
# Find core C-rule from matrix
|
||||||
|
matrix_entry = next(
|
||||||
|
(e for e in _MATRIX.get(domain, []) if e["p"] == principle_id),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
core = matrix_entry["core"] if matrix_entry else "unknown"
|
||||||
|
return {
|
||||||
|
"domain": domain,
|
||||||
|
"principle_id": principle_id,
|
||||||
|
"title": title,
|
||||||
|
"body": body,
|
||||||
|
"core_c_rule": core,
|
||||||
|
}
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def atelier_list_domains() -> list[dict[str, Any]]:
|
||||||
|
"""List the 19 Atelier domains with P-rule counts + Nova-relevance."""
|
||||||
|
return DOMAINS
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def atelier_matrix_lookup(domain: str) -> dict[str, Any]:
|
||||||
|
"""Look up the domain→core principle mapping for a given domain."""
|
||||||
|
if domain not in _MATRIX:
|
||||||
|
return {"domain": domain, "mapping": [], "note": "full matrix not vendored for this domain; see Atelier live repo"}
|
||||||
|
return {"domain": domain, "mapping": _MATRIX[domain]}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
"""mcp/atelier/plugins/validation.py — agentic validation against Atelier principles.
|
||||||
|
|
||||||
|
Implements 1 MCP tool (REQ-223):
|
||||||
|
- atelier.validate_against_principles(snippet, domains) → pass/fail per
|
||||||
|
checklist item with the principle citation. This is the agentic
|
||||||
|
validation BEYOND deterministic scanners (Wiz/Checkmarx/Mend) — it
|
||||||
|
catches correctness/clarity/simplicity/observability gaps that
|
||||||
|
deterministic tools cannot.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
# Condensed checklist: core C1-C8 + security domain. Each item is a
|
||||||
|
# (check_id, description, heuristic_pattern, principle_citation).
|
||||||
|
_CHECKLIST = [
|
||||||
|
# C1 Correctness
|
||||||
|
{"id": "C1.1", "desc": "Does the code do what the task asked, completely?", "heuristic": r"TODO|FIXME|pass\s*$", "principle": "C1 Correctness", "neg": True},
|
||||||
|
{"id": "C1.2", "desc": "Does it handle failure cases? (errors, timeouts)", "heuristic": r"except\s*:?\s*pass", "principle": "C1 Correctness", "neg": True},
|
||||||
|
{"id": "C1.3", "desc": "Is there a test that would fail if the code were wrong?", "heuristic": r"def test_|describe\(", "principle": "C1 Correctness", "neg": False, "optional": True},
|
||||||
|
# C2 Clarity
|
||||||
|
{"id": "C2.1", "desc": "Are names intent-revealing? (no 'data', 'temp', 'x')", "heuristic": r"\b(data|temp|x|foo|bar|doStuff)\b", "principle": "C2 Clarity", "neg": True},
|
||||||
|
# C3 Simplicity
|
||||||
|
{"id": "C3.1", "desc": "Is there dead code? (unreachable branches)", "heuristic": r"return\s+\w+\s*$.*return", "principle": "C3 Simplicity", "neg": True, "multiline": True},
|
||||||
|
# C7 Observability
|
||||||
|
{"id": "C7.1", "desc": "Are there logs for significant events?", "heuristic": r"log(ger|ging)?|print\(|console\.", "principle": "C7 Observability", "neg": False, "optional": True},
|
||||||
|
{"id": "C7.2", "desc": "Are there secrets in logs?", "heuristic": r"password|secret|token|api_key", "principle": "C7 Observability + Security P4", "neg": True},
|
||||||
|
# Security
|
||||||
|
{"id": "SEC.1", "desc": "No secrets in code/logs/URLs", "heuristic": r"(password|secret|token|api_key)\s*=\s*['\"]", "principle": "Security P4 Secrets Never Exposed", "neg": True},
|
||||||
|
{"id": "SEC.2", "desc": "Input validated at the boundary", "heuristic": r"validate|schema|assert", "principle": "Security P1 Boundary Validation", "neg": False, "optional": True},
|
||||||
|
{"id": "SEC.3", "desc": "Authorization checked, not assumed", "heuristic": r"auth|permission|rbac|authorize", "principle": "Security P5 Authenticated by Default", "neg": False, "optional": True},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def register(mcp: Any) -> None:
|
||||||
|
"""Register the validation tools with the MCP server (or fallback registry)."""
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def atelier_validate_against_principles(snippet: str, domains: list[str] | None = None) -> dict[str, Any]:
|
||||||
|
"""Validate a code/diff snippet against Atelier principles.
|
||||||
|
|
||||||
|
Runs the agent-checklist items against the snippet and returns
|
||||||
|
pass/fail per item with the principle citation. This is the
|
||||||
|
agentic validation BEYOND deterministic scanners (Wiz/Checkmarx/
|
||||||
|
Mend) — it catches correctness/clarity/simplicity/observability
|
||||||
|
gaps that deterministic tools cannot.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
snippet: The code or diff text to validate.
|
||||||
|
domains: Optional list of domains to include (default: core + security).
|
||||||
|
"""
|
||||||
|
results: list[dict[str, Any]] = []
|
||||||
|
for check in _CHECKLIST:
|
||||||
|
pattern = check["heuristic"]
|
||||||
|
flags = re.DOTALL if check.get("multiline") else 0
|
||||||
|
found = bool(re.search(pattern, snippet, flags))
|
||||||
|
# neg=True means finding the pattern is a FAIL; neg=False means finding is a PASS
|
||||||
|
if check.get("neg"):
|
||||||
|
status = "FAIL" if found else "PASS"
|
||||||
|
else:
|
||||||
|
if check.get("optional"):
|
||||||
|
status = "PASS" if found else "WARN"
|
||||||
|
else:
|
||||||
|
status = "PASS" if found else "WARN"
|
||||||
|
results.append({
|
||||||
|
"check_id": check["id"],
|
||||||
|
"description": check["desc"],
|
||||||
|
"status": status,
|
||||||
|
"principle": check["principle"],
|
||||||
|
})
|
||||||
|
all_pass = all(r["status"] == "PASS" for r in results)
|
||||||
|
return {
|
||||||
|
"overall": "PASS" if all_pass else "FAIL",
|
||||||
|
"results": results,
|
||||||
|
"domains_checked": domains or ["core", "security"],
|
||||||
|
"note": "Agentic validation beyond Wiz/Checkmarx/Mend — catches correctness, clarity, simplicity, observability gaps.",
|
||||||
|
}
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
"""mcp/atelier/server.py — Nova Atelier MCP server (REQ-223, D-135, D-137, D-140).
|
||||||
|
|
||||||
|
Plugin-registry architecture (D-140): plugins/<name>.py modules each expose
|
||||||
|
``register(mcp) -> None`` and call ``@mcp.tool()`` for their tools. This file
|
||||||
|
scans ``plugins/`` and calls ``register`` on each. Future capabilities drop
|
||||||
|
in as new plugin files — no server.py edits.
|
||||||
|
|
||||||
|
Transport: stdio (D-135). The MCP Python SDK v2 (``modelcontextprotocol/
|
||||||
|
python-sdk``, D-137) is the target. If the SDK is not installed, the server
|
||||||
|
degrades to a plain-Python tool registry that can be tested directly — the
|
||||||
|
tools are callable without MCP. This makes the server testable in CI
|
||||||
|
without the SDK installed.
|
||||||
|
|
||||||
|
Usage (with SDK):
|
||||||
|
python3 -m mcp.atelier.server
|
||||||
|
|
||||||
|
Usage (without SDK, for testing):
|
||||||
|
from mcp.atelier.server import NovaAtelierServer
|
||||||
|
s = NovaAtelierServer()
|
||||||
|
s.load_plugins()
|
||||||
|
result = s.call_tool("atelier.lookup_principle", {"domain": "security", "principle_id": "P4"})
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
_PLUGIN_DIR = pathlib.Path(__file__).parent / "plugins"
|
||||||
|
_VENDOR_DIR = pathlib.Path(__file__).parent / "vendor"
|
||||||
|
|
||||||
|
|
||||||
|
class _ToolRegistry:
|
||||||
|
"""A minimal tool registry that mimics the MCP ``@mcp.tool()`` decorator.
|
||||||
|
|
||||||
|
When the MCP SDK is available, ``NovaAtelierServer`` wraps a real
|
||||||
|
``MCPServer`` and the decorator registers tools with the SDK. When the
|
||||||
|
SDK is absent, this registry is the fallback — tools are callable via
|
||||||
|
``call_tool()`` for testing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._tools: dict[str, dict[str, Any]] = {}
|
||||||
|
|
||||||
|
def tool(self, name: str | None = None, description: str | None = None) -> Callable:
|
||||||
|
def decorator(fn: Callable) -> Callable:
|
||||||
|
tool_name = name or fn.__name__
|
||||||
|
self._tools[tool_name] = {
|
||||||
|
"fn": fn,
|
||||||
|
"description": description or fn.__doc__ or "",
|
||||||
|
"name": tool_name,
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
def list_tools(self) -> list[dict[str, str]]:
|
||||||
|
return [{"name": t["name"], "description": t["description"]} for t in self._tools.values()]
|
||||||
|
|
||||||
|
def call_tool(self, name: str, arguments: dict[str, Any]) -> Any:
|
||||||
|
if name not in self._tools:
|
||||||
|
raise KeyError(f"Unknown tool: {name}")
|
||||||
|
return self._tools[name]["fn"](**arguments)
|
||||||
|
|
||||||
|
|
||||||
|
class NovaAtelierServer:
|
||||||
|
"""The Nova Atelier MCP server.
|
||||||
|
|
||||||
|
Wraps an MCP SDK ``MCPServer`` if available; otherwise uses the
|
||||||
|
``_ToolRegistry`` fallback. Plugins are loaded from ``plugins/``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.registry = _ToolRegistry()
|
||||||
|
self._mcp = None
|
||||||
|
try:
|
||||||
|
from mcp.server import MCPServer # type: ignore[import-not-found]
|
||||||
|
self._mcp = MCPServer("atelier")
|
||||||
|
except ImportError:
|
||||||
|
pass # SDK not installed — fallback to _ToolRegistry
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mcp(self) -> Any:
|
||||||
|
"""The object plugins register tools on (real MCPServer or fallback)."""
|
||||||
|
return self._mcp if self._mcp is not None else self.registry
|
||||||
|
|
||||||
|
def load_plugins(self) -> list[str]:
|
||||||
|
"""Scan plugins/ and call ``register(mcp)`` on each. Returns loaded names."""
|
||||||
|
loaded: list[str] = []
|
||||||
|
for p in sorted(_PLUGIN_DIR.glob("*.py")):
|
||||||
|
if p.stem == "__init__":
|
||||||
|
continue
|
||||||
|
mod_name = f"mcp.atelier.plugins.{p.stem}"
|
||||||
|
mod = importlib.import_module(mod_name)
|
||||||
|
if hasattr(mod, "register"):
|
||||||
|
mod.register(self.mcp if self._mcp else self.registry)
|
||||||
|
loaded.append(p.stem)
|
||||||
|
return loaded
|
||||||
|
|
||||||
|
def list_tools(self) -> list[dict[str, str]]:
|
||||||
|
if self._mcp is not None:
|
||||||
|
return [{"name": t.name, "description": t.description} for t in self._mcp._tools.values()] # type: ignore[attr-defined]
|
||||||
|
return self.registry.list_tools()
|
||||||
|
|
||||||
|
def call_tool(self, name: str, arguments: dict[str, Any]) -> Any:
|
||||||
|
if self._mcp is not None:
|
||||||
|
raise RuntimeError("MCP SDK call_tool not supported in fallback mode — use the MCP client")
|
||||||
|
return self.registry.call_tool(name, arguments)
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
"""Run the server over stdio (requires the MCP SDK)."""
|
||||||
|
if self._mcp is None:
|
||||||
|
raise RuntimeError("MCP SDK not installed — cannot run server. Install: pip install mcp")
|
||||||
|
self._mcp.run()
|
||||||
|
|
||||||
|
|
||||||
|
def _make_plugin_compat_decorator(registry_or_mcp: Any) -> Callable:
|
||||||
|
"""Return a ``tool()`` decorator that works for both the fallback
|
||||||
|
registry and the real MCP SDK."""
|
||||||
|
if hasattr(registry_or_mcp, "tool"):
|
||||||
|
return registry_or_mcp.tool
|
||||||
|
# Fallback: wrap registry.tool() as a decorator factory
|
||||||
|
return registry_or_mcp.tool
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
server = NovaAtelierServer()
|
||||||
|
loaded = server.load_plugins()
|
||||||
|
print(f"Atelier MCP server — {len(loaded)} plugins loaded: {', '.join(loaded)}", file=sys.stderr)
|
||||||
|
if server._mcp is None:
|
||||||
|
print("MCP SDK not installed — server is in fallback (test) mode.", file=sys.stderr)
|
||||||
|
print("Tools: " + ", ".join(t["name"] for t in server.list_tools()), file=sys.stderr)
|
||||||
|
else:
|
||||||
|
server.run()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Vendored
+21
@@ -0,0 +1,21 @@
|
|||||||
|
# Vendored Atelier — Version Pin
|
||||||
|
|
||||||
|
> **Pinned tag:** `v0.3.6` (the v0.4 milestone release, 2026-08-05)
|
||||||
|
> **Commit:** `666b137dbb3c00e81f8740d18b639bc67587d29f`
|
||||||
|
> **P-rule count:** 190 (19 domains × 10 P-rules)
|
||||||
|
> **Vendor date:** 2026-08-06
|
||||||
|
> **Vendor reason:** audit reproducibility (D-136) — an agentic validation
|
||||||
|
> result is only replayable if the principles that produced it are pinned.
|
||||||
|
|
||||||
|
## Upgrade
|
||||||
|
|
||||||
|
To bump the vendored Atelier to a new tag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/update_atelier_vendor.sh <new-tag>
|
||||||
|
```
|
||||||
|
|
||||||
|
The script fetches the Atelier repo at the given tag, replaces
|
||||||
|
`mcp/atelier/vendor/`, updates this VERSION.md, and commits the change.
|
||||||
|
Upgrades are **intentional** — never automatic. Atelier `main` is a
|
||||||
|
moving target; pinning is required for audit reproducibility.
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
# Core First Principles
|
||||||
|
|
||||||
|
The 8 universal axioms. Every domain principle derives from one or more
|
||||||
|
of these. Precedence: C1 > C2 > C3 > C4 > C5 > C6 > C7 > C8.
|
||||||
|
|
||||||
|
## C1 — Correctness
|
||||||
|
The system does what it is supposed to do, and nothing else.
|
||||||
|
|
||||||
|
## C2 — Clarity
|
||||||
|
The intent of the code is obvious to its reader.
|
||||||
|
|
||||||
|
## C3 — Simplicity
|
||||||
|
The solution is as simple as possible, and no simpler.
|
||||||
|
|
||||||
|
## C4 — Locality
|
||||||
|
Decisions and their consequences live near each other.
|
||||||
|
|
||||||
|
## C5 — Reversibility
|
||||||
|
Every decision can be undone, and the cost of undoing is known.
|
||||||
|
|
||||||
|
## C6 — Composability
|
||||||
|
Parts combine into wholes, and the parts are reusable.
|
||||||
|
|
||||||
|
## C7 — Observability
|
||||||
|
The system's behavior is visible to those who must understand it.
|
||||||
|
|
||||||
|
## C8 — Economy
|
||||||
|
The system uses no more resources than the task requires.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Security — First Principles
|
||||||
|
|
||||||
|
## P1 — Boundary Validation
|
||||||
|
All input is validated at the trust boundary. (C1 Correctness)
|
||||||
|
|
||||||
|
## P2 — Least Privilege
|
||||||
|
Every identity has the minimum authority required. (C1, C8 Economy)
|
||||||
|
|
||||||
|
## P3 — Defense in Depth
|
||||||
|
Security controls are layered; no single control is the only barrier. (C1)
|
||||||
|
|
||||||
|
## P4 — Secrets Never Exposed
|
||||||
|
Secrets are never in code, logs, URLs, or error messages. (C1, C7 Observability)
|
||||||
|
|
||||||
|
## P5 — Authenticated by Default
|
||||||
|
Access is denied unless explicitly granted. (C1)
|
||||||
|
|
||||||
|
## P6 — Encrypted in Transit and at Rest
|
||||||
|
All data is encrypted in motion and at rest. (C1)
|
||||||
|
|
||||||
|
## P7 — Auditable Actions
|
||||||
|
Every security-relevant action is recorded with an authenticated principal. (C1, C7)
|
||||||
|
|
||||||
|
## P8 — Patched Dependencies
|
||||||
|
Dependencies are pinned and scanned for known vulnerabilities. (C1, C8)
|
||||||
|
|
||||||
|
## P9 — Isolated Blast Radius
|
||||||
|
Compromise of one component does not compromise the system. (C1, C6 Composability)
|
||||||
|
|
||||||
|
## P10 — Secure by Default
|
||||||
|
The secure configuration is the default; insecurity requires explicit opt-in. (C1)
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
# Principles Matrix (Vendored Stub)
|
||||||
|
|
||||||
|
Maps every domain P-rule back to the core C-rule(s) it derives from.
|
||||||
|
Full matrix in the live Atelier repo; this is a condensed vendored version
|
||||||
|
for the security domain (the primary domain the MCP server validates
|
||||||
|
against in v1.18).
|
||||||
|
|
||||||
|
| Domain | P-rule | Core C-rule(s) |
|
||||||
|
|---|---|---|
|
||||||
|
| security | P1 Boundary Validation | C1 Correctness |
|
||||||
|
| security | P2 Least Privilege | C1, C8 Economy |
|
||||||
|
| security | P3 Defense in Depth | C1 |
|
||||||
|
| security | P4 Secrets Never Exposed | C1, C7 Observability |
|
||||||
|
| security | P5 Authenticated by Default | C1 |
|
||||||
|
| security | P6 Encrypted in Transit and at Rest | C1 |
|
||||||
|
| security | P7 Auditable Actions | C1, C7 |
|
||||||
|
| security | P8 Patched Dependencies | C1, C8 |
|
||||||
|
| security | P9 Isolated Blast Radius | C1, C6 Composability |
|
||||||
|
| security | P10 Secure by Default | C1 |
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
# Agent Pre-Completion Checklist (Vendored)
|
||||||
|
|
||||||
|
Every AI agent runs this checklist before completing a task.
|
||||||
|
|
||||||
|
## Core Principles Checklist (C1–C8)
|
||||||
|
|
||||||
|
### C1 Correctness
|
||||||
|
- Does the code do what the task asked, completely?
|
||||||
|
- Does it handle the specified edge cases? (nulls, empties, max, min)
|
||||||
|
- Does it handle the failure cases? (errors, timeouts, invalid input)
|
||||||
|
- Is there a test that would fail if the code were wrong?
|
||||||
|
|
||||||
|
### C2 Clarity
|
||||||
|
- Can a stranger read this and understand it without asking you?
|
||||||
|
- Are names intent-revealing? (No `data`, `temp`, `x`, `doStuff`)
|
||||||
|
- Do comments explain *why*, not *what*?
|
||||||
|
|
||||||
|
### C3 Simplicity
|
||||||
|
- Is this the simplest solution that is complete?
|
||||||
|
- Is there dead code? (Unreachable branches, unused variables)
|
||||||
|
- Is there premature abstraction? (An interface with one implementation)
|
||||||
|
|
||||||
|
### C4 Locality
|
||||||
|
- Does related logic live together?
|
||||||
|
- Are side effects near their causes?
|
||||||
|
|
||||||
|
### C5 Reversibility
|
||||||
|
- Is this change undoable? (migration has a `down`, deploy has a rollback)
|
||||||
|
- Did I avoid irreversible actions without explicit confirmation?
|
||||||
|
|
||||||
|
### C6 Composability
|
||||||
|
- Does this component/function do one thing?
|
||||||
|
- Is the boundary (props/args/return) explicit and typed?
|
||||||
|
|
||||||
|
### C7 Observability
|
||||||
|
- Are there logs for significant events?
|
||||||
|
- Do errors carry enough context to debug? (request ID, user, action)
|
||||||
|
- Are there no secrets in logs?
|
||||||
|
|
||||||
|
### C8 Economy
|
||||||
|
- Is memory bounded? (No unbounded growth, no loading everything)
|
||||||
|
- Is time bounded? (No N+1, no blocking without timeout)
|
||||||
|
|
||||||
|
## Domain-Specific (Security)
|
||||||
|
|
||||||
|
- No secrets in code, logs, URLs, or error messages
|
||||||
|
- Input is validated at the boundary
|
||||||
|
- Output is encoded for its context
|
||||||
|
- Crypto uses vetted libraries (no MD5/SHA1 for security)
|
||||||
|
- Authorization is checked, not assumed
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
# Nova Metrics Directory
|
# Nova Metrics Directory
|
||||||
|
|
||||||
> v1.17 — Strategic Direction, Leadership Metrics & Unified Story (D-128)
|
|
||||||
|
|
||||||
This directory holds Nova's telemetry/observability artifacts. The
|
This directory holds Nova's telemetry/observability artifacts. The
|
||||||
metrics layer is **Nova-native** (D-120): JSONL event log + SQLite cold
|
metrics layer is **Nova-native** (D-120): JSONL event log + SQLite cold
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Nova Trust Snapshot — 2026-08-04T20:05:00Z
|
||||||
|
|
||||||
|
> v1.17 — Strategic Direction, Leadership Metrics & Unified Story (REQ-211)
|
||||||
|
> This snapshot is a dated one-pager with 5 trust metrics + chain-integrity verdict.
|
||||||
|
|
||||||
|
## Trust Metrics
|
||||||
|
|
||||||
|
| Metric | Value | Details |
|
||||||
|
|--------|-------|---------|
|
||||||
|
| **Decision Ledger Coverage** | 0.0% | 0 entries, 0 broken |
|
||||||
|
| **Attestation Coverage** | 0.0% | 0 attestation events |
|
||||||
|
| **Capability Health** | 18V / 4S / 0B / 0D | from REGRESSION_REPORT.json |
|
||||||
|
| **AI Decision Accuracy** | 0.0% | 0/0 succeeded |
|
||||||
|
| **Confidence-Gate Halt Rate** | 0.0% | 0/0 halted |
|
||||||
|
|
||||||
|
## Chain Integrity
|
||||||
|
|
||||||
|
- **Verdict:** INTACT
|
||||||
|
- **Broken entries:** 0
|
||||||
|
|
||||||
|
## Snapshot Hash
|
||||||
|
|
||||||
|
`a3c59eda5d569a5d`
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# Nova PowerBI Dashboard — Import Guide
|
||||||
|
|
||||||
|
|
||||||
|
This guide documents how to import Nova's metrics views into PowerBI
|
||||||
|
via the folder connector, and suggests a starter visual model.
|
||||||
|
|
||||||
|
## Import via folder connector
|
||||||
|
|
||||||
|
1. Open PowerBI Desktop.
|
||||||
|
2. **Get Data** → **Folder** → navigate to `metrics/powerbi/`.
|
||||||
|
3. PowerBI discovers all CSV/JSON files in the folder.
|
||||||
|
4. Combine the files — PowerBI creates a single query per file.
|
||||||
|
|
||||||
|
## Starter visual model
|
||||||
|
|
||||||
|
### Suggested joins
|
||||||
|
- `fact_run` ←→ `fact_decision` on `run_id` (run-level decision path)
|
||||||
|
- `fact_run` ←→ `fact_cost_estimate` on `run_id` (run-level cost)
|
||||||
|
- `fact_capability` ←→ `dim_capability` on `capability_id` (capability lookup)
|
||||||
|
- `fact_capability` ←→ `dim_milestone` on `milestone` (milestone lookup)
|
||||||
|
|
||||||
|
### Suggested visuals (4 starter visuals)
|
||||||
|
|
||||||
|
1. **Capability Health over Time** — bar chart: `fact_capability.status`
|
||||||
|
grouped by `run_at_utc`. Shows Verified/Skipped/Broken/Decayed trend.
|
||||||
|
Source: `fact_capability.csv`.
|
||||||
|
|
||||||
|
2. **Confidence Distribution** — histogram: `fact_confidence.score`.
|
||||||
|
Shows the distribution of confidence scores across all runs.
|
||||||
|
Source: `fact_confidence.csv`.
|
||||||
|
|
||||||
|
3. **Decision Accuracy** — KPI card: count of `fact_decision` where
|
||||||
|
`outcome = 'succeeded'` ÷ total `fact_decision` rows. Shows AI
|
||||||
|
Decision Accuracy (NORTH_STAR target ≥99.5%).
|
||||||
|
Source: `fact_decision.csv`.
|
||||||
|
|
||||||
|
4. **Cost Trend** — line chart: `fact_cost_estimate.delta_usd` over
|
||||||
|
`estimated_at`. Shows pre-apply cost estimate trend (Infracost).
|
||||||
|
Source: `fact_cost_estimate.csv`.
|
||||||
|
|
||||||
|
## Placeholder views (deferred metrics)
|
||||||
|
|
||||||
|
The 8 `placeholder_*.csv` files contain headers only (no data rows).
|
||||||
|
Each has a companion `placeholder_*.json` with the schema metadata
|
||||||
|
(columns, blocking decision, description). When the blocking decision
|
||||||
|
lifts (e.g., D-096 for live AWS), the collector will populate these
|
||||||
|
views and PowerBI will automatically pick up the data.
|
||||||
|
|
||||||
|
## Data refresh
|
||||||
|
|
||||||
|
The export is regenerated by running:
|
||||||
|
```bash
|
||||||
|
python3 core/metrics/collector.py # rebuilds nova_metrics.db
|
||||||
|
python3 core/metrics/powerbi_export.py # exports to metrics/powerbi/
|
||||||
|
```
|
||||||
|
|
||||||
|
In PowerBI, click **Refresh** to pick up the updated CSV/JSON files.
|
||||||
|
|
||||||
|
## Honesty model
|
||||||
|
|
||||||
|
Every metric in the export is `grounded` (cites a source file), `derived`
|
||||||
|
(documented formula), or `deferred` (cites a blocking decision ID). See
|
||||||
|
`docs/METRICS.md` (P4) for the canonical catalog and `docs/METRICS_VIEWS.md`
|
||||||
|
for the column-level data dictionary.
|
||||||
@@ -48,6 +48,11 @@
|
|||||||
"description": "Target group target type (ip or instance).",
|
"description": "Target group target type (ip or instance).",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "ip"
|
"default": "ip"
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": {
|
"outputs": {
|
||||||
@@ -85,20 +90,42 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:elbv2:loadbalancer",
|
"type": "aws:elbv2:loadbalancer",
|
||||||
"description": "Application load balancer in the VPC subnets.",
|
"description": "Application load balancer in the VPC subnets.",
|
||||||
"inputs": ["name", "subnets", "security_group", "load_balancer_type"],
|
"inputs": [
|
||||||
"outputs": ["lb_arn"]
|
"name",
|
||||||
|
"subnets",
|
||||||
|
"security_group",
|
||||||
|
"load_balancer_type"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"lb_arn"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "aws:elbv2:targetgroup",
|
"type": "aws:elbv2:targetgroup",
|
||||||
"description": "Target group for the ECS service tasks.",
|
"description": "Target group for the ECS service tasks.",
|
||||||
"inputs": ["name", "port", "protocol", "vpc_id", "target_type"],
|
"inputs": [
|
||||||
"outputs": ["target_group_arn"]
|
"name",
|
||||||
|
"port",
|
||||||
|
"protocol",
|
||||||
|
"vpc_id",
|
||||||
|
"target_type"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"target_group_arn"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "aws:elbv2:listener",
|
"type": "aws:elbv2:listener",
|
||||||
"description": "Listener forwarding the LB port to the target group.",
|
"description": "Listener forwarding the LB port to the target group.",
|
||||||
"inputs": ["lb_arn", "port", "protocol", "target_group_arn"],
|
"inputs": [
|
||||||
"outputs": ["listener_arn"]
|
"lb_arn",
|
||||||
|
"port",
|
||||||
|
"protocol",
|
||||||
|
"target_group_arn"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"listener_arn"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
resource "aws_lb" "this" {
|
resource "aws_lb" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
name = var.name
|
name = var.name
|
||||||
load_balancer_type = var.load_balancer_type
|
load_balancer_type = var.load_balancer_type
|
||||||
subnets = local.subnet_list
|
subnets = local.subnet_list
|
||||||
@@ -6,6 +7,7 @@ resource "aws_lb" "this" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_lb_target_group" "this" {
|
resource "aws_lb_target_group" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
name_prefix = "${var.name}-"
|
name_prefix = "${var.name}-"
|
||||||
port = var.port
|
port = var.port
|
||||||
protocol = var.protocol
|
protocol = var.protocol
|
||||||
@@ -18,13 +20,14 @@ resource "aws_lb_target_group" "this" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_lb_listener" "this" {
|
resource "aws_lb_listener" "this" {
|
||||||
load_balancer_arn = aws_lb.this.id
|
count = var.enabled ? 1 : 0
|
||||||
|
load_balancer_arn = aws_lb.this[0].id
|
||||||
port = var.port
|
port = var.port
|
||||||
protocol = var.protocol
|
protocol = var.protocol
|
||||||
|
|
||||||
default_action {
|
default_action {
|
||||||
type = "forward"
|
type = "forward"
|
||||||
target_group_arn = aws_lb_target_group.this.arn
|
target_group_arn = aws_lb_target_group.this[0].arn
|
||||||
}
|
}
|
||||||
|
|
||||||
depends_on = [aws_lb_target_group.this]
|
depends_on = [aws_lb_target_group.this]
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
output "lb_arn" {
|
output "lb_arn" {
|
||||||
value = aws_lb.this.id
|
value = aws_lb.this[0].id
|
||||||
description = "The load balancer ARN."
|
description = "The load balancer ARN."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "listener_arn" {
|
output "listener_arn" {
|
||||||
value = aws_lb_listener.this.arn
|
value = aws_lb_listener.this[0].arn
|
||||||
description = "The listener ARN."
|
description = "The listener ARN."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "target_group_arn" {
|
output "target_group_arn" {
|
||||||
value = aws_lb_target_group.this.arn
|
value = aws_lb_target_group.this[0].arn
|
||||||
description = "The target group ARN."
|
description = "The target group ARN."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,3 +50,9 @@ variable "vpc_id" {
|
|||||||
description = "VPC ID for the target group (ref to vpc or platform VPC)."
|
description = "VPC ID for the target group (ref to vpc or platform VPC)."
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "AWS region (CloudFront is global but the provider region is used for the OAC).",
|
"description": "AWS region (CloudFront is global but the provider region is used for the OAC).",
|
||||||
"required": true
|
"required": true
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": {
|
"outputs": {
|
||||||
@@ -75,17 +80,37 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cloudfront:distribution",
|
"type": "aws:cloudfront:distribution",
|
||||||
"description": "CloudFront distribution with S3 origin via OAC.",
|
"description": "CloudFront distribution with S3 origin via OAC.",
|
||||||
"inputs": ["bucket_regional_domain_name", "price_class", "viewer_protocol_policy", "default_ttl", "max_ttl", "waf_web_acl_arn", "oac_id"],
|
"inputs": [
|
||||||
"outputs": ["distribution_arn", "distribution_domain_name"]
|
"bucket_regional_domain_name",
|
||||||
|
"price_class",
|
||||||
|
"viewer_protocol_policy",
|
||||||
|
"default_ttl",
|
||||||
|
"max_ttl",
|
||||||
|
"waf_web_acl_arn",
|
||||||
|
"oac_id"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"distribution_arn",
|
||||||
|
"distribution_domain_name"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "aws:cloudfront:originaccesscontrol",
|
"type": "aws:cloudfront:originaccesscontrol",
|
||||||
"description": "Origin Access Control for the S3 origin.",
|
"description": "Origin Access Control for the S3 origin.",
|
||||||
"inputs": ["name", "origin_type", "signing_behavior"],
|
"inputs": [
|
||||||
"outputs": ["oac_id"]
|
"name",
|
||||||
|
"origin_type",
|
||||||
|
"signing_behavior"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"oac_id"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"intra_refs": [
|
"intra_refs": [
|
||||||
{"from": "aws:cloudfront:distribution.oac_id", "to": "aws:cloudfront:originaccesscontrol.oac_id"}
|
{
|
||||||
|
"from": "aws:cloudfront:distribution.oac_id",
|
||||||
|
"to": "aws:cloudfront:originaccesscontrol.oac_id"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user