Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 707a7dbe9b | |||
| e7866fda84 | |||
| 2efed26bb6 | |||
| 5c07e29b90 | |||
| aa868c97ef | |||
| e4a9915891 | |||
| 0ca383dae6 | |||
| ed5ea90654 | |||
| 2273009b95 | |||
| 0d2cbdb423 | |||
| b418d429b5 | |||
| dcba380b52 | |||
| f0bc3be92c | |||
| 0b79b16715 | |||
| 90624be63f | |||
| be51fc15fa |
@@ -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,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
"phase": 1,
|
"phase": 0,
|
||||||
"stage": "execute",
|
"stage": "plan",
|
||||||
"milestone": "v1.19",
|
"milestone": "v1.21",
|
||||||
"phase_role": "execution",
|
"phase_role": "pre_execution",
|
||||||
"attempts": 0,
|
"attempts": 0,
|
||||||
"updated_at": "2026-08-06T19:30:00Z",
|
"updated_at": "2026-08-11T00:01:00Z",
|
||||||
"milestone_complete": false,
|
"milestone_complete": false,
|
||||||
"tag": null,
|
"requirements": ["REQ-245","REQ-246","REQ-247","REQ-248","REQ-249","REQ-250","REQ-251","REQ-252","REQ-253"],
|
||||||
"requirements": ["REQ-229"],
|
"notes": "v1.21 P0 plan stage complete. PLAN.md v1.21 section written. 5 execution phases (P1 strategic-docs, P2 slides, P3 marp+talking-points+README, P4 pipeline-hardening, P5 render+verify) + P6 final-review-ship. Wave 1 (P1/P2/P4 parallelizable), Wave 2 (P3), Wave 3 (P5), Wave 4 (P6). CLARIFY+RESEARCH minimal at full autonomy — domain known, requirements confirmed with user. Proceeding to P0 ship then execution."
|
||||||
"notes": "v1.19 P1 complete: scripts/sync_to_nova.sh replaces sync_to_gl.sh. Manual-only 2nd-release pipeline into ~/nova (separate GitLab repo, consumer/platform-team audience). Consumer subset rsync, 13 fixed-order domain commits via positional -m, conventional-commit validation. 8 new tests pass (TestSyncToNovaScript). Pre-existing test_attestation_event_emission failure (env-dependent: NOVA_ATTESTATION_SIGNING_KEY_ID unset, D-089) reproduced on clean main — unrelated. Next: P2 final-review-ship -> tag v1.18.0."
|
|
||||||
}
|
}
|
||||||
+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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,157 @@
|
|||||||
|
# Nova — Phase Plan v1.21 (Nova Deck Refinement & Pipeline Hardening)
|
||||||
|
|
||||||
|
> **Milestone:** v1.21 — Nova Deck Refinement & Pipeline Hardening
|
||||||
|
> **Branch:** `milestone/v1.21-deck-refinement` (flat workflow: commits on
|
||||||
|
> main, tags on the v1.20.x line per branch-strategy)
|
||||||
|
> **Tag line:** `v1.20.x` patch line — `v1.20.0` (P0) → `v1.20.1..v1.20.5`
|
||||||
|
> (P1–P5) → `v1.20.6` (P6 final = milestone release). v1.21 is an NFR
|
||||||
|
> milestone (all phases are docs/test/chore/refactor) → progressive patches.
|
||||||
|
> **Phase count:** 7 (P0 pre-execution [DONE] + 5 execution + 1 final).
|
||||||
|
> **Source of truth for requirements:** `.ciagent/REQUIREMENTS.md` §v1.21
|
||||||
|
> (REQ-245..253, 9 requirements).
|
||||||
|
> **Source of truth for decisions:** the 33 review notes in the v1.21
|
||||||
|
> run context (encoded as REQ-245..253).
|
||||||
|
> **Source of truth for research:** existing deck + pipeline + strategic
|
||||||
|
> docs (the domain is known; no new research needed at full autonomy).
|
||||||
|
|
||||||
|
## Wave Ordering
|
||||||
|
|
||||||
|
All 5 execution phases are **sequenced** (flat workflow). The theoretical
|
||||||
|
parallelism is documented for future parallelization-enabled runs.
|
||||||
|
|
||||||
|
| Wave | Phases | Rationale |
|
||||||
|
|------|--------|-----------|
|
||||||
|
| Wave 1 | P1, P2, P4 (**parallelizable**) | P1 (strategic docs: NORTH_STAR, AUTONOMY_THESIS, PROJECT, scope, raci), P2 (slides source-of-truth rewrite + rename), P4 (pipeline hardening: Checkov/Wiz flow). Zero file overlap: P1 touches `.ciagent/` + `docs/scope.md` + `docs/raci.md`; P2 touches `docs/presentations/*.md`; P4 touches `scripts/run_*.sh` + `adapters/wiz/` + `tests/test_pipeline*.py`. In a parallelization-enabled run these three could execute concurrently. |
|
||||||
|
| Wave 2 | P3 | Marp deck + talking points + README synthesis. Depends on P2's updated source-of-truth. Re-renders HTML+PPTX via `render_slides.sh`. Also fixes theme CSS A1 table + footer cleanup (REQ-251). |
|
||||||
|
| Wave 3 | P5 | Render + verify. Depends on P2 (source), P3 (marp), P4 (pipeline). Re-renders mermaid PNGs (slide 1 new diagram, slide 9 expand, Atelier split), HTML, PPTX. Runs `test_slides_pipeline.py`, `test_no_forge_mentions.py`, full `pytest`, `run_platform.sh --check-only`. |
|
||||||
|
| Wave 4 | P6 | Final review + audit + milestone ship. Merge to main, tag `v1.20.6`, create release, attach PPTX. |
|
||||||
|
|
||||||
|
## Phase Summaries
|
||||||
|
|
||||||
|
### Phase P0 — pre-execution (DONE)
|
||||||
|
SPECIFY → CLARIFY → RESEARCH → PLAN. Validated v1.21 requirements
|
||||||
|
(REQ-245..253). Established `active_milestone: "v1.21"`. Synced
|
||||||
|
PROJECT.md strategic-direction pillar. No new research (domain known).
|
||||||
|
|
||||||
|
### Phase P1 — strategic-docs (Wave 1)
|
||||||
|
- `NORTH_STAR.md`: vision polish (item 11); obj #2 deterministic-scoring
|
||||||
|
reword (item 13); obj #3 four CTO metrics (item 14); obj #4 replaced
|
||||||
|
with integration objective (item 17); drop anti-goals 1,4,5; add 2 new
|
||||||
|
anti-goals (item 16); anti-goal #3 reworded (item 7).
|
||||||
|
- `git mv .ciagent/NO_HUMANS_THESIS.md .ciagent/AUTONOMY_THESIS.md` +
|
||||||
|
reframe content (items 7, 8).
|
||||||
|
- `PROJECT.md`: mission/scope sync for item 17 (already partially done
|
||||||
|
in P0; finalize here).
|
||||||
|
- `docs/scope.md`: light sync.
|
||||||
|
- `docs/raci.md`: rename Release Mgmt → SRE; add Quality Engineering role.
|
||||||
|
- **REQs:** REQ-246, REQ-247 (partial).
|
||||||
|
|
||||||
|
### Phase P2 — slides source-of-truth (Wave 1)
|
||||||
|
- `git mv` all 5 deck files `nova-no-humans-platform*` →
|
||||||
|
`nova-autonomous-cloud-delivery*`.
|
||||||
|
- Rewrite `nova-autonomous-cloud-delivery.md` (source of truth):
|
||||||
|
- Slide 1 "The Problem" (items 3,4,5,7,9): broader problem (devs writing
|
||||||
|
terraform, destructive changes, AI-era 0-day pace, bandwidth gaps,
|
||||||
|
tribal knowledge/rockstar operator); no arc; no "18 capabilities
|
||||||
|
verified"; not "humans are the problem".
|
||||||
|
- Slide 2 "Nova's Vision" (item 11): polish for technical audience;
|
||||||
|
"infrastructure operations become visible" as recurring theme.
|
||||||
|
- Slide 3 "Strategic Objectives + Anti-Goals" (items 12,13,14,15,16,17,
|
||||||
|
18): only Obj+Anti-Goals; provable trust = deterministic scripts
|
||||||
|
(functions without AI); ROI = Lead Time + Vuln Trend + MTTR + Spend;
|
||||||
|
drop anti-goals 1,4,5; add "not upstream dev platform", "not PDLC
|
||||||
|
replacement"; replace obj #4 with integration objective; reword benefit.
|
||||||
|
- Slide 4 "Scope" (item 29): refine (moved up).
|
||||||
|
- Slide 5 "RACI" (item 30): add QE column; reassign A from Platform →
|
||||||
|
QA/SRE; rename Release Mgmt → SRE; split release attestation (SRE =
|
||||||
|
Production Readiness); shrink to fit (moved up).
|
||||||
|
- Slide 6 "Pipeline" (item 20): Checkov on static code before plan;
|
||||||
|
Wiz on plan; no Wiz → Checkov on plan; never both.
|
||||||
|
- Slide 7 "Decision Ledger" (items 21,22): drop D-121/122/132; "AI
|
||||||
|
decisions = automated decisions"; focus on value (immutable,
|
||||||
|
queryable, accountable), not sqlite/hash-chain implementation.
|
||||||
|
- Slide 8 "Attestation Matrix" (item 23): drop bullets below table;
|
||||||
|
add Description column per concern; rethink "operator-supplied"
|
||||||
|
label; reword benefit.
|
||||||
|
- Slide 9 "Telemetry & Live Ops" (item 25): expand on value; keep
|
||||||
|
metric flow; drop D-120/125/126; expand on PowerBI live ops
|
||||||
|
dashboard; reword benefit.
|
||||||
|
- Slide 10 "Decision Ledger + Attestation Coverage" (item 27):
|
||||||
|
mandatory by design; no prod change without ledger + human
|
||||||
|
attestation; queryable for auditing; full traceability; improve
|
||||||
|
benefit.
|
||||||
|
- Slide 11 "Cost & ROI": minor polish.
|
||||||
|
- Slide 12 "What's Deferred — and Why" (items 10,19): remove all D-IDs;
|
||||||
|
plain-language blockers.
|
||||||
|
- Slide 13 "Roadmap to the North Star" (items 10,19): drop D-IDs; no
|
||||||
|
status column; roadmap with timelines.
|
||||||
|
- Slide 14 "12-Month Product Roadmap" (item 24): drop `planned` badges.
|
||||||
|
- Slide 15 "Quarter-by-Quarter Outcomes" (item 24): drop badges.
|
||||||
|
- Slide 16 "Production-Grade Guidance via Atelier (1/2)" (item 31):
|
||||||
|
split — Skills + MCP server overview.
|
||||||
|
- Slide 17 "Production-Grade Guidance via Atelier (2/2)" (item 31):
|
||||||
|
split — agentic validation beyond deterministic scanners + vendoring.
|
||||||
|
- Slide 18 "Recap + Ask": refresh recap to match new structure.
|
||||||
|
- Appendix A1 "Metrics Glossary" (item 32): table readability fixed
|
||||||
|
in P3 theme CSS.
|
||||||
|
- Global (items 6,10,24,2): tech-leadership benefits; no D-###/REQ-###/
|
||||||
|
.py paths in audience slides; no badges; no version in footer; final
|
||||||
|
"less is more / no fluff" prose pass.
|
||||||
|
- **REQs:** REQ-245, REQ-248, REQ-249, REQ-252 (partial).
|
||||||
|
|
||||||
|
### Phase P3 — marp deck + talking points + README (Wave 2)
|
||||||
|
- `nova-autonomous-cloud-delivery-marp.md`: synthesize 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.
|
||||||
|
- `nova-autonomous-cloud-delivery-talking-points.md`: re-distill to
|
||||||
|
18-slide structure.
|
||||||
|
- `docs/presentations/README.md`: update deck title, audience, slide
|
||||||
|
count (18 main + 1 appendix), directory layout, remove badge docs,
|
||||||
|
update deck table + render commands + filenames.
|
||||||
|
- `docs/presentations/assets/nova-sp-theme.css`: fix Appendix A1 table
|
||||||
|
background (item 32); footer chrome no version.
|
||||||
|
- Update `scripts/render_slides.sh`, `scripts/render_deck.sh`,
|
||||||
|
`workflows-src/slides.yml`, `.github/workflows/slides.yml`,
|
||||||
|
`tests/test_slides_pipeline.py` filename refs.
|
||||||
|
- **REQs:** REQ-251, REQ-252 (partial).
|
||||||
|
|
||||||
|
### Phase P4 — pipeline hardening (Wave 1)
|
||||||
|
- `scripts/run_platform.sh` + `scripts/run_postapply.sh`: item 20 flow —
|
||||||
|
1. Checkov on static code (`main.tf`/TF dir) **before** `terraform
|
||||||
|
plan` → fail-fast dev feedback.
|
||||||
|
2. After plan: if `WIZ_API_TOKEN`+`WIZ_API_URL` → **Wiz against plan**;
|
||||||
|
else **Checkov against plan** (drop-in). **Never both.**
|
||||||
|
- `adapters/wiz/wiz_adapter.py`: support plan-mode input if needed.
|
||||||
|
- Tests: `tests/test_pipeline.py`, `tests/test_pipeline_contract.py`,
|
||||||
|
`tests/test_slides_pipeline.py`, checkov/wiz tests.
|
||||||
|
- `docs/scope.md` policy-enforcement line + slide 6 reflect new flow.
|
||||||
|
- `docs/METRICS.md` policy-stage description if changed.
|
||||||
|
- **REQs:** REQ-250.
|
||||||
|
|
||||||
|
### Phase P5 — render + verify (Wave 3)
|
||||||
|
- Re-render changed/new mermaid diagrams (slide 1 new diagram, slide 9
|
||||||
|
expand, Atelier split) via `scripts/render_slides.sh`.
|
||||||
|
- Render HTML + PPTX.
|
||||||
|
- `tests/test_slides_pipeline.py` passes: 18 main + 1 appendix; no badges;
|
||||||
|
no version in footer; no D-###/REQ-###/.py paths in audience slides;
|
||||||
|
filename refs updated.
|
||||||
|
- `tests/test_no_forge_mentions.py` passes.
|
||||||
|
- Full `pytest` passes (pipeline-hardening tests green).
|
||||||
|
- `run_platform.sh --check-only` passes.
|
||||||
|
- **REQs:** REQ-253 (partial).
|
||||||
|
|
||||||
|
### Phase P6 — final-review-ship (Final Phase, Wave 4)
|
||||||
|
- Multi-persona code review across P1–P5.
|
||||||
|
- Audit: git log vs `.ciagent/` discipline.
|
||||||
|
- Ship: merge to main, tag `v1.20.6` (final patch = milestone release),
|
||||||
|
create release, attach PPTX.
|
||||||
|
- Update `REQUIREMENTS.md` (v1.21 REQs complete) + `ROADMAP.md` (v1.21
|
||||||
|
complete). Clear `CHECKPOINT.json`.
|
||||||
|
- **REQs:** REQ-253 (complete).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Nova — Phase Plan v1.18 (Citizen Developer & Production-Grade Guidance)
|
# Nova — Phase Plan v1.18 (Citizen Developer & Production-Grade Guidance)
|
||||||
|
|
||||||
> **Milestone:** v1.18 — Citizen Developer & Production-Grade Guidance
|
> **Milestone:** v1.18 — Citizen Developer & Production-Grade Guidance
|
||||||
|
|||||||
+17
-4
@@ -1266,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
|
||||||
@@ -1334,7 +1347,7 @@ constraints or user-directed scope). New v1.18 decisions:
|
|||||||
| 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-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-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. |
|
| 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 (active — Nova 2nd-Release Sync)
|
## Objective for Milestone v1.19 (complete — Nova 2nd-Release Sync)
|
||||||
|
|
||||||
> **NFR-only chore milestone.** Ships a patch on the v1.18.x line (tag
|
> **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
|
> `v1.18.0`). Single execution phase. Establishes the manual-only "2nd
|
||||||
|
|||||||
@@ -1395,3 +1395,324 @@ with documented schemas.
|
|||||||
| REQ | Phase | Status |
|
| REQ | Phase | Status |
|
||||||
|-----|-------|--------|
|
|-----|-------|--------|
|
||||||
| REQ-229 | P1 | complete |
|
| 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 | pending |
|
||||||
|
| REQ-246 | P1 | pending |
|
||||||
|
| REQ-247 | P1 | pending |
|
||||||
|
| REQ-248 | P2 | pending |
|
||||||
|
| REQ-249 | P2 | pending |
|
||||||
|
| REQ-250 | P4 | pending |
|
||||||
|
| REQ-251 | P3 | pending |
|
||||||
|
| REQ-252 | P2 | pending |
|
||||||
|
| REQ-253 | P5 | pending |
|
||||||
|
|||||||
+98
-2
@@ -1756,7 +1756,7 @@ locked (D-133..D-142).
|
|||||||
Ship tag at milestone COMPLETE: `v1.17.7` (feature milestone; final patch
|
Ship tag at milestone COMPLETE: `v1.17.7` (feature milestone; final patch
|
||||||
IS the release). **DONE.**
|
IS the release). **DONE.**
|
||||||
|
|
||||||
## v1.19 (active — Nova 2nd-Release Sync, tag line `v1.18.x`)
|
## v1.19 (complete — Nova 2nd-Release Sync, tag line `v1.18.x`)
|
||||||
|
|
||||||
> **NFR-only chore milestone.** Single execution phase. Establishes the
|
> **NFR-only chore milestone.** Single execution phase. Establishes the
|
||||||
> manual-only "2nd release" pipeline `~/acdl → ~/nova` (GitLab
|
> manual-only "2nd release" pipeline `~/acdl → ~/nova` (GitLab
|
||||||
@@ -1787,7 +1787,7 @@ IS the release). **DONE.**
|
|||||||
### Phase P2 — final-review-ship (Final Phase)
|
### Phase P2 — final-review-ship (Final Phase)
|
||||||
- **Description:** Final review + audit + milestone ship. Merge to main, tag
|
- **Description:** Final review + audit + milestone ship. Merge to main, tag
|
||||||
`v1.18.0` (first patch on the v1.18.x line), create Gitea release.
|
`v1.18.0` (first patch on the v1.18.x line), create Gitea release.
|
||||||
- **Status:** pending
|
- **Status:** complete
|
||||||
- **Depends on:** [P1]
|
- **Depends on:** [P1]
|
||||||
- **Requirements:** REQ-229
|
- **Requirements:** REQ-229
|
||||||
- **Success Criteria:**
|
- **Success Criteria:**
|
||||||
@@ -1796,3 +1796,99 @@ IS the release). **DONE.**
|
|||||||
`main`.
|
`main`.
|
||||||
- Tag `v1.18.0` created; release notes summarize REQ-229.
|
- Tag `v1.18.0` created; release notes summarize REQ-229.
|
||||||
- Milestone branches deleted; CHECKPOINT cleared.
|
- 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.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
],
|
],
|
||||||
"active_project": "acdl",
|
"active_project": "acdl",
|
||||||
"active_projects": ["acdl"],
|
"active_projects": ["acdl"],
|
||||||
"active_milestone": "v1.19",
|
"active_milestone": "v1.21",
|
||||||
"autonomy": {
|
"autonomy": {
|
||||||
"level": "full",
|
"level": "full",
|
||||||
"escalation_hooks": ["deploy", "delete_data", "merge_to_main"],
|
"escalation_hooks": ["deploy", "delete_data", "merge_to_main"],
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -41,3 +41,4 @@ metrics/lifecycle/
|
|||||||
*.crt
|
*.crt
|
||||||
*.jks
|
*.jks
|
||||||
*.keystore.coverage
|
*.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).
|
||||||
@@ -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"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
# Nova Metrics Catalog
|
# Nova Metrics Catalog
|
||||||
|
|
||||||
> v1.17 — Strategic Direction, Leadership Metrics & Unified Story (REQ-195)
|
|
||||||
> Generated: 2026-08-04
|
|
||||||
|
|
||||||
This is the canonical catalog of every executive KPI in Nova's
|
This is the canonical catalog of every executive KPI in Nova's
|
||||||
leadership metrics layer. Each metric carries a **status**:
|
leadership metrics layer. Each metric carries a **status**:
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
# Nova Deferred Metrics Activation Roadmap
|
# Nova Deferred Metrics Activation Roadmap
|
||||||
|
|
||||||
> v1.17 — Strategic Direction, Leadership Metrics & Unified Story (REQ-210)
|
|
||||||
> Generated: 2026-08-04
|
|
||||||
|
|
||||||
This document lists all 8 deferred metrics + the onboarding-funnel
|
This document lists all 8 deferred metrics + the onboarding-funnel
|
||||||
"granted" half, with their blocking decisions, unblock requirements,
|
"granted" half, with their blocking decisions, unblock requirements,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
# Nova Metrics Views — PowerBI Data Dictionary
|
# Nova Metrics Views — PowerBI Data Dictionary
|
||||||
|
|
||||||
> v1.17 — Strategic Direction, Leadership Metrics & Unified Story (REQ-190, REQ-209)
|
|
||||||
> Generated: 2026-08-04
|
|
||||||
|
|
||||||
This document is the column-level data dictionary for the PowerBI export
|
This document is the column-level data dictionary for the PowerBI export
|
||||||
views in `metrics/powerbi/`. Each fact/dimension table and placeholder
|
views in `metrics/powerbi/`. Each fact/dimension table and placeholder
|
||||||
|
|||||||
@@ -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.
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
# Nova — The No-Humans Infrastructure Platform: Thesis Defensibility Brief
|
|
||||||
|
|
||||||
> v1.17 — Strategic Direction, Leadership Metrics & Unified Story (REQ-213)
|
|
||||||
> Generated: 2026-08-04
|
|
||||||
|
|
||||||
## The thesis
|
|
||||||
|
|
||||||
Nova is the autonomous infrastructure layer that lets product teams
|
|
||||||
ship without engaging an operator, and lets executives trust the AI
|
|
||||||
not because it never fails but because every decision is captured,
|
|
||||||
scored, and accountable.
|
|
||||||
|
|
||||||
**Autonomy in operations; human at stage gates.** The operator is
|
|
||||||
removed from the loop of normal operations. Human attestation remains
|
|
||||||
required at stage gates — QA signs off for production, SRE greenlights
|
|
||||||
based on operational readiness. The absence of an operator is never
|
|
||||||
the absence of a record.
|
|
||||||
|
|
||||||
## Grounded proof (measurable today)
|
|
||||||
|
|
||||||
| Proof | Source | Status |
|
|
||||||
|-------|--------|--------|
|
|
||||||
| 18 capabilities verified, 4 honestly skipped (0 broken) | `REGRESSION_REPORT.json` | grounded |
|
|
||||||
| Decision Ledger captures 100% of AI decisions with outcome backfill | `metrics/decision_ledger.db` | grounded (this milestone) |
|
|
||||||
| Attestation Coverage: 100% of prod/dr promotions attested by a human | `hitl_gates.py` + outbox `approver_*` | grounded |
|
|
||||||
| Confidence-gated policy engine (not an LLM) — 6 weighted inputs, band outcome | `confidence_signal.py` | grounded |
|
|
||||||
| 8-concern attestation matrix with separation-of-duties on prod | `attestation_matrix.py` + `separation_of_duties.py` | grounded |
|
|
||||||
| Pre-apply cost estimates (Infracost, offline) | `infracost_adapter.py` | grounded |
|
|
||||||
| Test suite passes (~656 tests) | `metrics/test-results.xml` | grounded |
|
|
||||||
|
|
||||||
## Deferred proof (measurable when blocking decisions lift)
|
|
||||||
|
|
||||||
| Proof | Blocking Decision | Unblock Requirement |
|
|
||||||
|-------|-------------------|---------------------|
|
|
||||||
| Touchless Resolution Rate ≥99% across production estates | 0 consumers today | Pilot estate activation |
|
|
||||||
| Live infrastructure health (ECS, ALB, RPS) | D-096 | Live AWS re-provisioning |
|
|
||||||
| Onboarding funnel: requested → granted | D-113/D-114/D-119 | Auto-grant implementation |
|
|
||||||
| Drift auto-reversal rate ≥95% | D-096 + no scheduler | Drift detection scheduler |
|
|
||||||
| Predictive vs reactive ratio ≥3:1 | future emitter | ML anomaly-forecasting service |
|
|
||||||
| Tamper-evident ledger checkpoints (S3 Object Lock + JWS) | D-083 | Audit ledger build-out |
|
|
||||||
|
|
||||||
## Anti-claims (what Nova is NOT)
|
|
||||||
|
|
||||||
1. **Nova's "AI" is NOT an LLM planner.** It is a confidence-gated
|
|
||||||
policy engine (confidence_signal + HITL gate). The Decision Ledger
|
|
||||||
captures this real decision path — not a fabricated "AI agent" that
|
|
||||||
doesn't exist yet (D-122). 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
|
|
||||||
operations. Every stage-gate promotion (qa/prod/dr) requires a human
|
|
||||||
attestation recorded with approver identity, separation-of-duties
|
|
||||||
check, and the 8-concern evidence matrix (NORTH_STAR Anti-Goal #3).
|
|
||||||
3. **Nova is NOT for legacy, untagged, or freeform infrastructure.** It
|
|
||||||
requires Terraform-managed, policy-aligned, fully-tagged inputs
|
|
||||||
(NORTH_STAR Anti-Goal #4).
|
|
||||||
4. **Nova does NOT fabricate metrics.** Every metric is grounded (cites
|
|
||||||
a source file), derived (documented formula), or deferred (cites a
|
|
||||||
blocking decision ID). No fabricated numbers in any deck slide or
|
|
||||||
METRICS.md 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 default
|
|
||||||
substrate their AI engineering teams reach for first when an agent needs
|
|
||||||
to deploy.
|
|
||||||
+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.
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ Step 1: full markdown Step 2: Marp deck Step 3: HTML + PPTX
|
|||||||
|
|
||||||
### 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-no-humans-platform.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:
|
||||||
@@ -45,7 +45,7 @@ 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-no-humans-platform-marp.md`).
|
||||||
|
|
||||||
Synthesize the full markdown into a lean Marp deck:
|
Synthesize the full markdown into a lean Marp deck:
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ 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 uploaded to the release** as a downloadable attachment (binary, not
|
||||||
committed to git).
|
committed to git).
|
||||||
|
|
||||||
#### HTML export (committed to repo)
|
#### HTML export (committed to repo)
|
||||||
@@ -90,7 +90,7 @@ file that renders the full deck with the S&P Global Energy theme.
|
|||||||
committed artifacts, not generated on-the-fly — they must be re-rendered and
|
committed artifacts, not generated on-the-fly — they must be re-rendered and
|
||||||
re-committed when the Marp deck is updated.
|
re-committed when the Marp deck is updated.
|
||||||
|
|
||||||
#### PPTX export (uploaded to Gitea release)
|
#### PPTX export (uploaded to release)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
||||||
@@ -102,14 +102,14 @@ CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
|||||||
The `--allow-local-files` flag is **required** for PPTX export so the local
|
The `--allow-local-files` flag is **required** for PPTX export so the local
|
||||||
PNG diagrams are embedded in the file. As of v1.18 (REQ-228, D-141), PPTX
|
PNG diagrams are embedded in the file. As of v1.18 (REQ-228, D-141), PPTX
|
||||||
files **are committed to the repo** as first-class binary artifacts (no LFS)
|
files **are committed to the repo** as first-class binary artifacts (no LFS)
|
||||||
and are also attached to the phase's Gitea release via
|
and are also attached to the phase's release via
|
||||||
`scripts/attach_release_asset.py`. The render + commit + attach pipeline is
|
`scripts/attach_release_asset.py`. The render + commit + attach pipeline is
|
||||||
automated by `scripts/render_deck.sh`.
|
automated by `scripts/render_deck.sh`.
|
||||||
|
|
||||||
### 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-no-humans-platform-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:
|
||||||
@@ -144,35 +144,20 @@ and re-distill.
|
|||||||
```
|
```
|
||||||
docs/presentations/
|
docs/presentations/
|
||||||
├── README.md ← this file
|
├── README.md ← this file
|
||||||
├── how-the-platform-works.md ← Step 1: full source of truth
|
├── nova-no-humans-platform.md ← Step 1: full source of truth (19 main slides + speaker notes)
|
||||||
├── how-the-platform-works-marp.md ← Step 2: Marp deck (11 main + TOC + 8 appendix = 20)
|
├── nova-no-humans-platform-marp.md ← Step 2: Marp deck (19 main + 2 appendix = 21 slides)
|
||||||
├── how-the-platform-works.html ← Step 3: rendered HTML (committed)
|
├── nova-no-humans-platform.html ← Step 3: rendered HTML (committed, S&P-themed)
|
||||||
├── how-the-platform-works-talking-points.md ← Step 4: presenter cues (20 sections)
|
├── nova-no-humans-platform.pptx ← Step 3: rendered PPTX (committed, S&P-themed)
|
||||||
├── the-developer-experience.md ← Step 1: full source of truth
|
├── nova-no-humans-platform-talking-points.md ← Step 4: presenter cues (21 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
|
│ ├── platform-architecture.mmd
|
||||||
│ ├── platform-works-02-frictions.mmd
|
│ ├── road-to-north-star.mmd
|
||||||
│ ├── platform-works-02-end-to-end-flow.mmd
|
│ └── ... (per-slide .mmd files)
|
||||||
│ ├── platform-works-03-north-star.mmd
|
└── png/ ← rendered mermaid PNGs (committed, S&P-themed)
|
||||||
│ ├── 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)
|
└── png/ ← rendered PNGs (embedded in Marp)
|
||||||
├── platform-works-01-contract-driven.png
|
├── platform-works-01-contract-driven.png
|
||||||
├── platform-works-02-frictions.png
|
├── platform-works-02-frictions.png
|
||||||
@@ -300,7 +285,7 @@ diagram images in `assets/png/`). The resulting HTML is self-contained.
|
|||||||
**The HTML files are committed artifacts** — re-render and re-commit whenever
|
**The HTML files are committed artifacts** — re-render and re-commit whenever
|
||||||
the Marp source changes.
|
the Marp source changes.
|
||||||
|
|
||||||
### Export a Marp deck to PPTX (uploaded to Gitea release)
|
### Export a Marp deck to PPTX (uploaded to release)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
||||||
@@ -311,7 +296,7 @@ CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \
|
|||||||
|
|
||||||
`--allow-local-files` is **required** for PPTX so local PNG diagrams are
|
`--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
|
embedded in the file. PPTX files are not committed to git — upload them as
|
||||||
attachments to the Gitea release.
|
attachments to the release.
|
||||||
|
|
||||||
## Adding a new presentation
|
## Adding a new presentation
|
||||||
|
|
||||||
@@ -324,7 +309,7 @@ attachments to the Gitea release.
|
|||||||
no speaker notes, embedded PNGs, and maturity badges.
|
no speaker notes, embedded PNGs, and maturity badges.
|
||||||
4. **Render to HTML** with `--allow-local-files` and commit the HTML to
|
4. **Render to HTML** with `--allow-local-files` and commit the HTML to
|
||||||
`docs/presentations/<deck-name>.html`.
|
`docs/presentations/<deck-name>.html`.
|
||||||
5. **Render to PPTX** with `--allow-local-files` and upload to the Gitea
|
5. **Render to PPTX** with `--allow-local-files` and upload to the release
|
||||||
release (do not commit PPTX to git).
|
release (do not commit PPTX to git).
|
||||||
6. **Distill the talking points** as `<deck-name>-talking-points.md` — one
|
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
|
||||||
@@ -352,4 +337,4 @@ attachments to the Gitea release.
|
|||||||
> deck with a 5-act arc (Problem → Vision → How → Proof → Roadmap). v1.18
|
> deck with a 5-act arc (Problem → Vision → How → Proof → Roadmap). v1.18
|
||||||
> (REQ-226) adds 3 slides (17 Scope, 18 RACI, 19 Atelier) → 21 total. The
|
> (REQ-226) adds 3 slides (17 Scope, 18 RACI, 19 Atelier) → 21 total. The
|
||||||
> S&P Global Energy theme is restored (REQ-214, P1). PPTX is committed to
|
> S&P Global Energy theme is restored (REQ-214, P1). PPTX is committed to
|
||||||
> git + attached to the Gitea release (REQ-228, D-141).
|
> git + attached to the release (REQ-228, D-141).
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/* @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 extends Marp's default and applies the S&P palette to ALL slide
|
||||||
|
* chrome — backgrounds, headers/footers, pagination, tables, blockquotes,
|
||||||
|
* code blocks — not just headings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--sp-red: #D6002A;
|
||||||
|
--sp-black: #1B1B1B;
|
||||||
|
--sp-white: #FFFFFF;
|
||||||
|
--sp-grey: #F0F0F0;
|
||||||
|
--sp-dark-grey: #2E2E2E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base section */
|
||||||
|
section {
|
||||||
|
font-family: "Akkurat Pro", "Helvetica Neue", "Arial", sans-serif;
|
||||||
|
font-size: 22px;
|
||||||
|
color: var(--sp-black);
|
||||||
|
background: var(--sp-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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; }
|
||||||
|
|
||||||
|
/* 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); }
|
||||||
|
|
||||||
|
/* Tables — grey header with red underline */
|
||||||
|
table { font-size: 18px; width: 100%; border-collapse: collapse; }
|
||||||
|
th { background: var(--sp-grey); border-bottom: 2px solid var(--sp-red); padding: 6px 10px; text-align: left; }
|
||||||
|
td { border-bottom: 1px solid var(--sp-grey); padding: 6px 10px; }
|
||||||
|
|
||||||
|
/* 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; }
|
||||||
|
|
||||||
|
/* Images — centered, max height */
|
||||||
|
img { display: block; margin: 0 auto; max-height: 320px; }
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
ul { margin-top: 0.3em; }
|
||||||
|
li { margin-bottom: 0.2em; }
|
||||||
|
|
||||||
|
/* Strong — S&P Red for emphasis in lead lines */
|
||||||
|
strong { color: var(--sp-red); }
|
||||||
+40
-23
@@ -1,30 +1,10 @@
|
|||||||
---
|
---
|
||||||
marp: true
|
marp: true
|
||||||
theme: default
|
theme: nova-sp
|
||||||
paginate: true
|
paginate: true
|
||||||
size: 16x9
|
size: 16x9
|
||||||
header: 'Nova — The No-Humans Infrastructure Platform'
|
header: 'Nova — The No-Humans Infrastructure Platform'
|
||||||
footer: 'Act %{page}/5 — v1.17'
|
footer: 'Act %{page}/5 — v1.20'
|
||||||
style: |
|
|
||||||
section {
|
|
||||||
font-family: "Akkurat Pro", "Helvetica Neue", "Arial", sans-serif;
|
|
||||||
font-size: 22px;
|
|
||||||
color: #1B1B1B;
|
|
||||||
}
|
|
||||||
h1 { color: #D6002A; font-size: 34px; margin-bottom: 0.3em; }
|
|
||||||
h2 { color: #D6002A; font-size: 26px; margin-bottom: 0.2em; }
|
|
||||||
section.title { background: #1B1B1B; color: #fff; border-top: 8px solid #D6002A; }
|
|
||||||
section.title h1 { color: #fff; }
|
|
||||||
table { font-size: 18px; width: 100%; }
|
|
||||||
th { background: #F0F0F0; }
|
|
||||||
blockquote { border-left: 4px solid #D6002A; color: #2E2E2E; font-size: 20px; }
|
|
||||||
img { display: block; margin: 0 auto; max-height: 320px; }
|
|
||||||
.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; }
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- _class: title -->
|
<!-- _class: title -->
|
||||||
@@ -383,4 +363,41 @@ From `docs/METRICS_DEFERRED_ROADMAP.md`.
|
|||||||
- **Zero-cost steady state:** all resources torn down post-v1.11 (D-096); the platform runs offline
|
- **Zero-cost steady state:** all resources torn down post-v1.11 (D-096); the platform runs offline
|
||||||
- References the pre-mortem (`PRE_MORTEM.md`: v1.10 decay root cause + structural mitigations)
|
- References the pre-mortem (`PRE_MORTEM.md`: v1.10 decay root cause + structural mitigations)
|
||||||
|
|
||||||
**Benefit:** you now know the operating cost is negligible — and the structural mitigation that prevents decay.
|
**Benefit:** you now know the operating cost is negligible — and the structural mitigation that prevents decay.
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- _class: title -->
|
||||||
|
<!-- _paginate: false -->
|
||||||
|
|
||||||
|
## Slide 20 — 12-Month Product Roadmap
|
||||||
|
|
||||||
|
**The product arc from pilot activation to agentic substrate — four quarters, four outcomes.**
|
||||||
|
|
||||||
|
| Quarter | Theme | Board-level outcome |
|
||||||
|
|---------|-------|---------------------|
|
||||||
|
| **Q1** | <span class="badge planned">Pilot Activation</span> | Nova runs a real customer estate end-to-end, autonomously, with a measurable zero-touch rate |
|
||||||
|
| **Q2** | <span class="badge planned">Provable Trust</span> | Every AI decision lands in a tamper-evident ledger; CFO sees real cloud-spend reconciliation |
|
||||||
|
| **Q3** | <span class="badge planned">Compounding ROI</span> | Quarter-over-quarter cloud spend drops; drift is detected and reversed without a human |
|
||||||
|
| **Q4** | <span class="badge planned">Agentic Substrate</span> | AI agents deploy through Nova by default; Nova is the substrate, not a vendor arriving late |
|
||||||
|
|
||||||
|
**Grounded in:** the 4 strategic objectives (autonomy, provable trust, ROI, agentic substrate) + the deferred-metric unblock paths.
|
||||||
|
|
||||||
|
**Benefit:** you now know the 12-month product arc — each quarter activates a strategic objective and its corresponding board-level metric, from pilot activation through agentic substrate leadership.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- _class: title -->
|
||||||
|
<!-- _paginate: false -->
|
||||||
|
|
||||||
|
## Slide 21 — 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 Resolution ≥ 99% · Escalation < 0.1% · AI Accuracy ≥ 99.5% | Strategic Objective #1 — autonomy as the default |
|
||||||
|
| **Q2** | Provable Trust | Tamper-evident ledger (Object Lock + JWS); daily checkpoints; live cost reconciliation (CUR) | Decision Ledger Coverage 100% · Cost Savings ≥ 25% | Strategic Objective #2 — trust is the moat |
|
||||||
|
| **Q3** | Compounding ROI + Drift | Drift detection scheduler; auto-reversal; Infracost→CUR reconciliation on pilot estate | Drift Auto-Reversal ≥ 95% · Spend Reduction ≥ 25% | Strategic Objective #3 — CFO-pointable numbers |
|
||||||
|
| **Q4** | Agentic Substrate + Predictive | ML anomaly-forecasting; AI-agent intent surface; multi-cloud (Azure/GCP) preview | Predictive:Reactive ≥ 3:1 · AI-Agent Intent Share ≥ 40% (first measurement) | Strategic 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:** you now know the quarter-by-quarter detail — each quarter has a concrete deliverable, a target metric grounded in a strategic objective, and a path from "honestly deferred" to "shipped and measured."
|
||||||
+31
-1
@@ -131,4 +131,34 @@
|
|||||||
### Appendix A2 — Operating Model & Cost
|
### Appendix A2 — Operating Model & Cost
|
||||||
- The operating cost is negligible (~$0.007/month)
|
- The operating cost is negligible (~$0.007/month)
|
||||||
- The zero-cost steady state (D-096 teardown) is the structural mitigation
|
- The zero-cost steady state (D-096 teardown) is the structural mitigation
|
||||||
- References the pre-mortem for the decay-prevention story
|
- References the pre-mortem for the decay-prevention story
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 20 — 12-Month Product Roadmap
|
||||||
|
|
||||||
|
**Key takeaway:** The next 12 months have a clear product arc — pilot activation → provable trust → compounding ROI → agentic substrate. Each quarter activates one strategic objective.
|
||||||
|
|
||||||
|
- This is the *product* roadmap, not the technical roadmap. The technical milestones (v1.0–v1.19) are behind us; this is forward-looking.
|
||||||
|
- Q1 (Pilot Activation): re-provision live AWS, activate the first pilot estate, light up the three post-pilot metrics. Onboarding auto-grant ships.
|
||||||
|
- Q2 (Provable Trust): tamper-evident ledger (Object Lock + JWS), daily checkpoints, live cost reconciliation. Trust is the moat — features can be copied; an immutable decision history cannot.
|
||||||
|
- Q3 (Compounding ROI + Drift): drift detection + auto-reversal, Infracost→CUR reconciliation on the pilot estate. This is the quarter the CFO points to a number that improves quarter-over-quarter.
|
||||||
|
- Q4 (Agentic Substrate + Predictive): ML anomaly-forecasting, AI-agent intent surface, multi-cloud preview. The Future Horizon target moves from aspiration to first measurement.
|
||||||
|
- The roadmap is grounded in the four strategic objectives from the North Star — autonomy, provable trust, ROI, agentic substrate — and the deferred-metric unblock paths from Slide 15.
|
||||||
|
|
||||||
|
**If asked "what about multi-cloud?"**: Q4 preview. AWS-only through Q3; Azure/GCP enters preview in Q4. We optimize for depth first, breadth second.
|
||||||
|
|
||||||
|
**If asked "what about the ML service?"**: Q4. The predictive-vs-reactive ≥3:1 target requires an ML anomaly-forecasting emitter — the most technically ambitious deliverable on the roadmap.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Slide 21 — Quarter-by-Quarter Outcomes
|
||||||
|
|
||||||
|
**Key takeaway:** Each quarter has a concrete deliverable, a target metric, and a strategic-objective grounding. Nothing is hand-waved.
|
||||||
|
|
||||||
|
- Q1: three post-pilot metrics go live (Touchless ≥99%, Escalation <0.1%, Accuracy ≥99.5%). The measurement pipeline is already grounded; the denominator activates when the pilot estate runs.
|
||||||
|
- Q2: Decision Ledger Coverage was already grounded — the *tamper-evidence* is the Q2 upgrade (SQLite hash-chain → S3 Object Lock + JWS). Cost Savings ≥25% becomes CFO-grade with live CUR reconciliation.
|
||||||
|
- Q3: Drift Auto-Reversal ≥95% unblocks when the drift scheduler ships. Spend Reduction ≥25% is the same target, now measured against the pilot baseline.
|
||||||
|
- Q4: Predictive:Reactive ≥3:1 requires the ML forecasting service. AI-Agent Intent Share ≥40% moves from aspiration to first measurement.
|
||||||
|
- The 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.'"
|
||||||
|
|
||||||
|
**If asked "are these committed or aspirational?"**: Q1–Q3 are committed (grounded pipeline + known unblock paths). Q4 targets are committed-deliverable, aspirational-metric — the ML service ships, the ≥40% intent share is first measurement (we don't control adoption rate).
|
||||||
+131
-891
File diff suppressed because one or more lines are too long
@@ -0,0 +1,713 @@
|
|||||||
|
# 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 + Anti-Goals
|
||||||
|
|
||||||
|
**Four objectives Nova is building toward; four anti-goals that keep it
|
||||||
|
focused.**
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
**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 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. 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 4 — 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 5 — 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 6 — 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 7 — 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 8 — The Attestation Matrix
|
||||||
|
|
||||||
|
**The designed controls that keep humans at stage gates — structured,
|
||||||
|
freshness-validated, and separation-of-duties-enforced.**
|
||||||
|
|
||||||
|
| 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. |
|
||||||
|
| 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.
|
||||||
|
- Concerns that are offline-testable run for real; concerns that require
|
||||||
|
external evidence accept signed artifacts.
|
||||||
|
|
||||||
|
> **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 matrix is not a rubber stamp. Each concern has a
|
||||||
|
> freshness window, a description, and a separation-of-duties rule. The
|
||||||
|
> "operator-supplied" label from the prior deck was dropped — every
|
||||||
|
> concern now has a plain-language description of what is being attested.
|
||||||
|
|
||||||
|
> **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 9 — 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 10 — 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 11 — 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 12 — 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 13 — 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 14 — 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 15 — 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 16 — 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 17 — 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 18 — 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.** 18 main slides + 1 appendix slide = 19 total.
|
||||||
Binary file not shown.
@@ -1,417 +0,0 @@
|
|||||||
# Nova — The No-Humans Infrastructure Platform
|
|
||||||
|
|
||||||
> **Source of truth** (Step 1 of the 4-step deck process).
|
|
||||||
> Unified narrative deck merging `how-the-platform-works` + `the-developer-experience`.
|
|
||||||
> 5-act arc: Problem → Vision → How → Proof → Roadmap.
|
|
||||||
> x3 structure at deck level (opening = arc preview, body = tell them, closing = recap + ask)
|
|
||||||
> AND per slide (opens with what it covers, delivers, closes with benefit callout).
|
|
||||||
> Act indicator in the Marp footer: `Act N/5: <act name>`.
|
|
||||||
>
|
|
||||||
> **Honesty model:** every metric cited is grounded (cites a source file),
|
|
||||||
> derived (documented formula), or deferred (cites a blocking decision ID).
|
|
||||||
> No fabricated numbers. Deferred metrics marked `<span class="badge planned">Planned</span>`.
|
|
||||||
>
|
|
||||||
> v1.17 — Strategic Direction, Leadership Metrics & Unified Story (REQ-196, REQ-197)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 1 — Arc Preview (the "what I'm going to tell you" deck-level opening)
|
|
||||||
|
|
||||||
This deck proves Nova is the no-humans infrastructure platform — and shows you the metrics that make the claim defensible.
|
|
||||||
|
|
||||||
**Today:** 18 capabilities verified, 0 consumer estates in production. This deck shows what's proven, what's pipeline-ready, and what's honestly deferred.
|
|
||||||
|
|
||||||
The 5-act arc:
|
|
||||||
1. **Problem** — why the operator is the bottleneck
|
|
||||||
2. **Vision** — Nova's strategic direction (NORTH_STAR)
|
|
||||||
3. **How** — the pipeline, Decision Ledger, attestation gates
|
|
||||||
4. **Proof** — grounded metrics that make the claim defensible
|
|
||||||
5. **Roadmap** — deferred metrics with unblock paths + the ask
|
|
||||||
|
|
||||||
> **Benefit:** you leave this deck knowing which claims are proven today, which are pipeline-ready, and which are deferred with a documented unblock path — no marketing, just grounded evidence.
|
|
||||||
|
|
||||||
> **Speaker notes:** The stake line (18V + 0 consumers) sets the honesty frame. The audience knows from slide 1 that this is not a hype deck — it's an evidence deck. The arc preview orients them for the next 15 slides.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 2 — The No-Humans Imperative
|
|
||||||
|
|
||||||
This slide shows why the operator is the bottleneck — and why removing them from operations (not accountability) is the imperative.
|
|
||||||
|
|
||||||
- **The cost of humans-in-the-loop:** L1/L2 ops hours, escalation latency, the trust gap (autonomous claims without proof)
|
|
||||||
- **The operator is the bottleneck:** provisioning takes days, not minutes; escalations pile up; the trust gap means "autonomous" is a marketing claim, not a defensible one
|
|
||||||
- **The attestation model:** autonomy in operations, human at stage gates — not "no humans ever"
|
|
||||||
- Cites `docs/NO_HUMANS_THESIS.md` (the thesis, grounded proof, deferred proof, anti-claims)
|
|
||||||
|
|
||||||
> **Benefit:** you now know the problem framing — autonomy in operations, human at stage gates, is the path forward.
|
|
||||||
|
|
||||||
> **Speaker notes:** The key reframing: "no-humans" means no human in the loop of *normal operations*. Stage-gate attestation (QA for production, SRE for operational readiness) remains human by design. This is not about removing humans from accountability — only from operations.
|
|
||||||
|
|
||||||
> **Transition:** "Having defined the problem, here is Nova's strategic direction toward solving it."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 3 — Nova's Vision
|
|
||||||
|
|
||||||
This slide states Nova's vision — infrastructure operations become invisible, with provable trust.
|
|
||||||
|
|
||||||
> **Infrastructure operations become invisible. 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 — QA signs off for production, SRE greenlights based on operational readiness — but the operator is never in the loop of normal operations.**
|
|
||||||
|
|
||||||
- The attestation model: human attestation required at stage gates (QA for production, SRE for operational readiness); autonomy in operations, not in accountability
|
|
||||||
- Cites `docs/NO_HUMANS_THESIS.md` (the thesis, grounded proof, deferred proof, anti-claims incl. D-122 honesty)
|
|
||||||
|
|
||||||
> **Benefit:** you now know the destination — invisible operations with provable trust, not promised trust. And you know the attestation model: humans at stage gates, not in the ops loop.
|
|
||||||
|
|
||||||
> **Speaker notes:** The vision is ambitious but precise. "Provable, not promised" is the key phrase — it's the difference between a marketing claim and a defensible one. The attestation clarification is stated up front so the audience doesn't mishear "no-humans" as "no accountability."
|
|
||||||
|
|
||||||
> **Transition:** "The vision is ambitious — here are the 4 strategic objectives that make it concrete."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 4 — Strategic Objectives + Anti-Goals
|
|
||||||
|
|
||||||
This slide pairs what Nova is building toward (4 objectives) with what Nova refuses to build (5 anti-goals).
|
|
||||||
|
|
||||||
**4 Strategic Objectives:**
|
|
||||||
1. **Demonstrate production-grade zero-touch operations** — autonomy as the default, not the demo
|
|
||||||
2. **Establish provable trust in AI decisions** — Decision Ledger, confidence scoring, circuit breakers, blast-radius controls
|
|
||||||
3. **Deliver compounding, quantifiable ROI** — each quarter must reduce spend, free hours, avoid downtime measurably
|
|
||||||
4. **Become the default substrate for agentic infrastructure consumption** — the platform AI agents reach for first
|
|
||||||
|
|
||||||
**5 Anti-Goals (what Nova is NOT):**
|
|
||||||
1. Not a Terraform, Kubernetes, or hyperscaler competitor
|
|
||||||
2. Not a general-purpose AI agent platform
|
|
||||||
3. Not a system that removes humans from accountability
|
|
||||||
4. Not for legacy, untagged, or freeform infrastructure
|
|
||||||
5. Not sold to operators
|
|
||||||
|
|
||||||
From `NORTH_STAR.md`.
|
|
||||||
|
|
||||||
> **Benefit:** you now know the scope boundaries — Nova is purpose-built for infrastructure operations, sold to leadership on outcomes, and explicitly not a general-purpose AI platform or a hyperscaler competitor.
|
|
||||||
|
|
||||||
> **Speaker notes:** The anti-goals are as important as the objectives. They tell the audience what Nova will NOT be distracted by. Anti-goal #3 (not removing humans from accountability) reinforces the attestation model from slide 3.
|
|
||||||
|
|
||||||
> **Transition:** "The objectives are committed to measurable targets — here is the 12–18 month scorecard, with honest grounding status."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 5 — 12–18 Month Targets (the scorecard)
|
|
||||||
|
|
||||||
This slide shows the committed targets — numbers a board member can repeat back — with their grounding status.
|
|
||||||
|
|
||||||
**Current-milestone targets (grounded or derived this milestone):**
|
|
||||||
|
|
||||||
| Domain | Target | Status |
|
|
||||||
|---|---|---|
|
|
||||||
| MTTR (p95) | < 60 seconds | grounded (platform-run) |
|
|
||||||
| Cloud Spend Reduction | ≥ 25% on pilot estates | partial (Infracost grounded; CUR deferred D-096) |
|
|
||||||
| L1/L2 Ops Hours Avoided | ≥ 70% of pre-Nova FTE | derived (N internal runs; prod activates post-pilot) |
|
|
||||||
| Platform ROI | ≥ 250% annually | derived (formula; N internal runs caveat) |
|
|
||||||
| Decision Ledger Coverage | 100% of AI actions | grounded (this milestone builds it) |
|
|
||||||
| Attestation Coverage | 100% of prod/dr promotions | grounded |
|
|
||||||
|
|
||||||
**Post-Pilot targets (pipeline grounded; denominator activates with a pilot estate):**
|
|
||||||
|
|
||||||
| Domain | Target | Status |
|
|
||||||
|---|---|---|
|
|
||||||
| Touchless Resolution Rate | ≥ 99% | partial (pipeline grounded; 0 consumers today) |
|
|
||||||
| Human Escalation Frequency | < 0.1% | partial (pipeline grounded; 0 consumers today) |
|
|
||||||
| AI Decision Accuracy | ≥ 99.5% | partial (pipeline grounded; 0 consumers today) |
|
|
||||||
|
|
||||||
**Deferred targets:** Predictive vs Reactive ≥3:1 <span class="badge planned">Planned</span> · Drift Auto-Reversal ≥95% <span class="badge planned">Planned</span>
|
|
||||||
|
|
||||||
> **Benefit:** you now know the destination numbers — and which ones are measurable today vs deferred honestly. The Post-Pilot targets are committed; the pipeline works; the numbers fill when a pilot estate runs.
|
|
||||||
|
|
||||||
> **Speaker notes:** The three-section split (current / post-pilot / deferred) is the honesty model. The "partial" status means the measurement pipeline is grounded but the denominator is zero (0 consumers). This is the same honesty as Cloud Spend (Infracost grounded, CUR deferred). A board member can see exactly which numbers are real today and which are waiting for a pilot.
|
|
||||||
|
|
||||||
> **Transition:** "The targets are committed — here is how Nova works to achieve them."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 6 — The Platform Pipeline
|
|
||||||
|
|
||||||
This slide shows the contract-to-evidence pipeline — how intent becomes verified infrastructure without an operator.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
graph LR
|
|
||||||
A[Contract] --> B[Resolver]
|
|
||||||
B --> C[Adapter]
|
|
||||||
C --> D[Terraform Plan]
|
|
||||||
D --> E[Checkov Policy]
|
|
||||||
E --> F[Confidence Signal]
|
|
||||||
F --> G{HITL Gate}
|
|
||||||
G -->|dev: autonomous| H[Apply]
|
|
||||||
G -->|qa/prod/dr: attested| H
|
|
||||||
H --> I[Evidence + Outbox]
|
|
||||||
```
|
|
||||||
|
|
||||||
- Contract → resolver → adapter → terraform plan → Checkov (policy) → confidence signal → HITL gate (dev autonomous; qa/prod/dr attested) → apply → evidence
|
|
||||||
- Grounded in `scripts/run_platform.sh` + `core/contract_resolver.py` + `adapters/terraform/adapter.py` + `core/confidence_signal.py`
|
|
||||||
|
|
||||||
> **Benefit:** you now know the path from intent to evidence — and where the human appears (stage gates only, not in the ops loop).
|
|
||||||
|
|
||||||
> **Speaker notes:** The pipeline is the engine. The key insight: dev is autonomous (no HITL gate); qa/prod/dr require human attestation. The confidence signal is the "AI" — it's a 6-input weighted score, not an LLM. The HITL gate is where the human appears, but only for qa/prod/dr, not for dev.
|
|
||||||
|
|
||||||
> **Transition:** "The pipeline produces decisions — here is how every decision is captured and made accountable."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 7 — The Decision Ledger
|
|
||||||
|
|
||||||
This slide shows the Decision Ledger — every AI decision captured with confidence, alternatives, and outcome.
|
|
||||||
|
|
||||||
- **Architecture:** `outbox_writer.py` extended → SQLite append-only hash-chain table
|
|
||||||
- **`ai.decision.made` events:** decision_id=run_id, chosen_action=band, confidence=score, alternatives=perInput, human_override=HITL block, outcome backfilled from apply.completed
|
|
||||||
- **`attestation.recorded` events:** qa/prod/dr sign-offs (approver, env, concerns, result)
|
|
||||||
- D-121, D-122, D-132. Honors D-083 (no S3 Object Lock/JWS — local hash-chain this milestone)
|
|
||||||
|
|
||||||
**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" that doesn't exist yet.
|
|
||||||
|
|
||||||
> **Benefit:** you now know why 'autonomous' is defensible — every decision is immutable, queryable, and accountable. And you know exactly what 'AI' means here: a confidence-gated policy engine, not a black-box LLM.
|
|
||||||
|
|
||||||
> **Speaker notes:** The D-122 honesty sentence is critical. If the audience walks away thinking Nova has an LLM planner, we've violated the "no fabrication" constraint. The Decision Ledger is the trust substrate (NORTH_STAR Objective #2) — it's the moat. Features can be copied; an immutable, queryable decision history cannot.
|
|
||||||
|
|
||||||
> **Transition:** "Decisions are captured — here is how stage-gate attestation keeps humans in accountability."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 8 — The 8-Concern Attestation Matrix
|
|
||||||
|
|
||||||
This slide shows the 8-concern attestation matrix — the designed controls that keep humans at stage gates.
|
|
||||||
|
|
||||||
| Concern | Env | Freshness | Type |
|
|
||||||
|---------|-----|-----------|------|
|
|
||||||
| functional_correctness | qa | 24h | operator-supplied |
|
|
||||||
| performance_baseline | qa | 7d | operator-supplied |
|
|
||||||
| security_posture | qa | 24h | operator-supplied |
|
|
||||||
| contract_nfrs | qa/prod/dr | — | offline-testable |
|
|
||||||
| operational_readiness | prod | 30d | operator-supplied |
|
|
||||||
| incident_response | prod | 90d | operator-supplied |
|
|
||||||
| capacity_cost | prod | 30d | operator-supplied |
|
|
||||||
| resilience_dr_drill | prod | 180d | operator-supplied |
|
|
||||||
| resilience_chaos | prod | 90d | operator-supplied |
|
|
||||||
| resilience_backup | prod | 30d | operator-supplied |
|
|
||||||
| dr_region_deploy | dr | 180d | operator-supplied |
|
|
||||||
|
|
||||||
- Offline-testable concerns run for real; operator-supplied concerns accept signed evidence artifacts
|
|
||||||
- Separation-of-duties on prod (the approver can't be the same person who built it)
|
|
||||||
- Grounded in `core/attestation_matrix.py` + `core/hitl_gates.py`
|
|
||||||
|
|
||||||
> **Benefit:** you now know the gate model — autonomy in operations, human in accountability, by design. The 8-concern matrix is what makes "no-humans in ops" safe.
|
|
||||||
|
|
||||||
> **Speaker notes:** The attestation matrix is the human-in-the-loop safeguard. It's not a rubber stamp — it's a structured, freshness-validated, separation-of-duties-enforced gate. This is what Anti-Goal #3 means: "not a system that removes humans from accountability."
|
|
||||||
|
|
||||||
> **Transition:** "You've now seen how Nova works — the pipeline, the Decision Ledger, the attestation gates. But 'how it works' is not 'proof it works.' The next four slides show the measured evidence: capability health, trust metrics, efficiency, and cost — every number grounded in a real file, not a marketing claim."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 9 — Telemetry Architecture
|
|
||||||
|
|
||||||
This slide shows how Nova instruments itself — the CloudEvents envelope, the cold store, and the PowerBI export.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
graph TB
|
|
||||||
A[Platform components] --> B[CloudEvents 1.0 envelope]
|
|
||||||
B --> C[metrics/events.jsonl]
|
|
||||||
B --> D[metrics/decision_ledger.db]
|
|
||||||
B --> E[metrics/runs/]
|
|
||||||
C --> F[Collector]
|
|
||||||
D --> F
|
|
||||||
E --> F
|
|
||||||
F --> G[metrics/nova_metrics.db]
|
|
||||||
G --> H[metrics/powerbi/]
|
|
||||||
H --> I[PowerBI dashboards]
|
|
||||||
```
|
|
||||||
|
|
||||||
- Platform components → CloudEvents 1.0 envelope → `metrics/events.jsonl` + `metrics/runs/` + `metrics/decision_ledger.db` → collector → `metrics/nova_metrics.db` (SQLite cold store) → `metrics/powerbi/` (CSV/JSON views) → PowerBI
|
|
||||||
- D-120 (Nova-native), D-125 (hybrid events/files), D-126 (cold-only)
|
|
||||||
- <span class="badge planned">Planned</span>: Hot-path (live ops dashboard) — D-126
|
|
||||||
|
|
||||||
> **Benefit:** you now know that every metric in this deck is traceable to a real emitted event — the architecture IS the trust substrate. When a CFO asks 'where does this number come from?', the answer is a file path, not a Slack thread.
|
|
||||||
|
|
||||||
> **Speaker notes:** The architecture is deliberately minimal (Nova-native, no Kafka/Prometheus/ClickHouse). The hot path is deferred (D-126) — the cold store is sufficient for batch/historical analysis. The key point: every number in the Proof act is traceable to a file path. This is the "no fabrication" constraint made architectural.
|
|
||||||
|
|
||||||
> **Transition:** "The architecture is sound — here is the measured proof."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 10 — Capability Health + Confidence Distribution
|
|
||||||
|
|
||||||
This slide shows the grounded proof: capability health and confidence distribution from real runs.
|
|
||||||
|
|
||||||
**Capability Health:** 18 Verified + 4 Skipped (post-D-096 teardown) from `.ciagent/REGRESSION_REPORT.json`
|
|
||||||
|
|
||||||
| Status | Count |
|
|
||||||
|--------|-------|
|
|
||||||
| Verified | 18 |
|
|
||||||
| Skipped | 4 |
|
|
||||||
| Broken | 0 |
|
|
||||||
| Decayed | 0 |
|
|
||||||
|
|
||||||
- The 4 Skipped are live-AWS capabilities (CAP-013..016) — honestly skipped because resources are torn down (D-096), not a failure
|
|
||||||
- Confidence distribution: from `metrics/nova_metrics.db` `fact_confidence` — score histogram, band breakdown (pass/halt)
|
|
||||||
|
|
||||||
> **Benefit:** you now know the platform is verified — 18 capabilities pass, 4 are honestly skipped, 0 broken. The honesty model (Skipped ≠ failure) is what makes the Verified count credible.
|
|
||||||
|
|
||||||
> **Speaker notes:** The 18V+4S number is the single most important proof point. It says "the platform works, and we're honest about what we can't test." The 4 Skipped are live-AWS capabilities — they're skipped because the live AWS resources are torn down (D-096), not because they're broken. When live AWS is re-provisioned, they reactivate.
|
|
||||||
|
|
||||||
> **Transition:** "Capability health is necessary — here is the trust substrate that makes autonomy defensible."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 11 — Decision Ledger + Attestation Coverage
|
|
||||||
|
|
||||||
This slide shows the trust metrics — Decision Ledger coverage and attestation coverage, both 100%.
|
|
||||||
|
|
||||||
- **Decision Ledger Coverage:** 100% of platform runs emit `ai.decision.made` with outcome backfill (source: `metrics/decision_ledger.db`)
|
|
||||||
- **Attestation Coverage:** 100% of prod/dr promotions attested by a human (source: `hitl_gates.py` + outbox `approver_*` attributes)
|
|
||||||
- **AI Decision Accuracy:** decisions not followed by apply.failed/incident within 5min
|
|
||||||
- The trust-snapshot report (`metrics/TRUST_SNAPSHOT.md`) with chain-integrity verdict
|
|
||||||
- <span class="badge planned">Planned</span>: Tamper-Evident Ledger Checkpoints (D-083)
|
|
||||||
|
|
||||||
> **Benefit:** you now know the trust is provable — not a marketing claim, a queryable record. The Decision Ledger is the moat; features can be copied, an immutable decision history cannot.
|
|
||||||
|
|
||||||
> **Speaker notes:** The trust metrics are the "provably trustworthy" proof. Decision Ledger Coverage = 100% means no AI decision is ever lost. Attestation Coverage = 100% means no prod/dr promotion lands without a human sign-off. The chain-integrity verdict (from the trust snapshot) proves the ledger hasn't been tampered with.
|
|
||||||
|
|
||||||
> **Transition:** "Trust is provable — here is the operational efficiency that makes the ROI real."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 12 — Zero-Touch Efficiency
|
|
||||||
|
|
||||||
This slide shows the zero-touch efficiency metrics — touchless resolution, human escalation, and MTTR.
|
|
||||||
|
|
||||||
- **Touchless Resolution Rate:** runs without operational HITL block ÷ total (attestation gates excluded)
|
|
||||||
- **Human Escalation Frequency:** operational HITL blocks only (confidence-driven; attestation sign-offs excluded)
|
|
||||||
- **MTTR (platform-run):** apply.failed → successful retry (D-131)
|
|
||||||
|
|
||||||
**Post-Pilot caveat:** these three metrics are computed on N internal runs today; the production-denominator activates when a pilot estate runs (see NORTH_STAR Post-Pilot Targets section).
|
|
||||||
|
|
||||||
> **Benefit:** you now know the zero-touch efficiency is measurable — the pipeline works today on internal runs, and the denominator expands to production estates when a pilot activates.
|
|
||||||
|
|
||||||
> **Speaker notes:** The Post-Pilot caveat is the honesty model. The pipeline is grounded (it works); the denominator is zero (0 consumers). This is not a fabricated "99% touchless" claim — it's "the measurement works, and the numbers fill when a pilot runs."
|
|
||||||
|
|
||||||
> **Transition:** "Efficiency is half the ROI story — here is the cost side."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 13 — Cost & ROI
|
|
||||||
|
|
||||||
This slide shows the cost estimates and the ROI formula — with honest caveats about the current denominator.
|
|
||||||
|
|
||||||
- **Cost Estimates via Infracost:** pre-apply, grounded (reads plan JSON, offline)
|
|
||||||
- **ROI formula (shown inline):** `Platform ROI = (FTE hours saved × blended rate + cloud savings + avoided downtime) ÷ platform op cost`
|
|
||||||
- **N=0 caveat:** "These derived metrics are computed on N internal runs today; the production-denominator activates post-pilot. The formula is grounded; the production numbers are not yet."
|
|
||||||
- **FTE Hours Saved** (derived), **Platform ROI** (derived formula)
|
|
||||||
- <span class="badge planned">Planned</span>: Live CUR Reconciliation (D-096), Drift Auto-Reversal (D-096)
|
|
||||||
|
|
||||||
> **Benefit:** you now know the ROI formula — and you know it's computed on internal runs today, not fabricated production numbers. The formula is ready; the production denominator activates with a pilot.
|
|
||||||
|
|
||||||
> **Speaker notes:** The ROI formula is shown inline — not hidden in a footnote. The N=0 caveat is stated explicitly. This is the "no fabrication" constraint in action: we show the formula, we show the caveat, we don't pretend the production numbers exist.
|
|
||||||
|
|
||||||
> **Transition:** "The proof is grounded — here is what is honestly deferred."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 14 — What's Deferred — and Why
|
|
||||||
|
|
||||||
This slide pairs each deferred metric with its blocking decision — honesty about what isn't measured yet.
|
|
||||||
|
|
||||||
**To be clear:** these deferrals are *measurement infrastructure*, not whether the platform runs without humans. The platform IS autonomous in operations. What's deferred is the *evidence pipeline* for certain metrics — not the autonomy itself.
|
|
||||||
|
|
||||||
| # | Deferred Metric | Blocking Decision |
|
|
||||||
|---|----------------|-------------------|
|
|
||||||
| 1 | Live Infrastructure Health | D-096 |
|
|
||||||
| 2 | Live Outbox Write Rate | D-096 |
|
|
||||||
| 3 | Tamper-Evident Ledger Checkpoints | D-083 |
|
|
||||||
| 4 | Onboarding Funnel (granted) | D-113/D-114/D-119 |
|
|
||||||
| 5 | Drift Auto-Reversal | D-096 + no scheduler |
|
|
||||||
| 6 | Live CUR Reconciliation | D-096 |
|
|
||||||
| 7 | SLA / Unplanned Downtime | D-096 |
|
|
||||||
| 8 | Predictive vs Reactive | future emitter |
|
|
||||||
|
|
||||||
From `docs/METRICS_DEFERRED_ROADMAP.md`.
|
|
||||||
|
|
||||||
> **Benefit:** you now know the boundaries — what Nova measures today, and exactly what blocks the rest. The autonomy is real; the measurement gaps are documented.
|
|
||||||
|
|
||||||
> **Speaker notes:** The preempt is critical: these deferrals are measurement infrastructure, not autonomy. The platform runs without humans in operations. What's deferred is the evidence pipeline for live-infra health, drift detection, predictive remediation — not the autonomy itself. Showing this slide to leadership demonstrates honesty, not weakness.
|
|
||||||
|
|
||||||
> **Transition:** "The proof is honest — here is the roadmap from here to the 12–18 month targets."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 15 — Roadmap to the North Star
|
|
||||||
|
|
||||||
This slide shows the path from v1.17's grounded metrics to the 12–18 month targets — the unblock path for each deferred metric.
|
|
||||||
|
|
||||||
- Each deferred metric → blocking decision → unblock requirement → candidate milestone
|
|
||||||
- The hot-path activation section (post-D-096, Nova-native only, D-120)
|
|
||||||
- Re-evaluation triggers: D-096 lift, D-083 lift, onboarding-grant lift
|
|
||||||
|
|
||||||
From `docs/METRICS_DEFERRED_ROADMAP.md`.
|
|
||||||
|
|
||||||
> **Benefit:** you now know the path — every deferred metric has an unblock requirement and a candidate milestone. Nothing is hand-waved; everything has a plan.
|
|
||||||
|
|
||||||
> **Speaker notes:** The roadmap is the bridge from "honestly deferred" to "here's how we get there." Each deferred metric has a specific unblock requirement and a candidate future milestone. The re-evaluation triggers ensure the metrics layer evolves when the blocking decisions lift.
|
|
||||||
|
|
||||||
> **Transition:** "The roadmap is clear — here is the recap and the ask."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slide 16 — Recap + Ask (the "what I told you" deck-level closing)
|
|
||||||
|
|
||||||
This slide recaps the 5 acts and states the ask.
|
|
||||||
|
|
||||||
**Recap:**
|
|
||||||
- **Problem:** the operator is the bottleneck; autonomy in operations, human at stage gates
|
|
||||||
- **Vision:** invisible operations with provable trust (NORTH_STAR)
|
|
||||||
- **How:** pipeline + Decision Ledger + 8-concern attestation matrix
|
|
||||||
- **Proof:** 18V+4S, 100% ledger coverage, 100% attestation, grounded ROI formula
|
|
||||||
- **Roadmap:** deferred metrics have unblock paths
|
|
||||||
|
|
||||||
**The ask:** "The ask is a business decision: approve a pilot estate to activate the production-denominator metrics (Touchless Resolution, Human Escalation, AI Decision Accuracy), and approve the tamper-evident ledger build-out (D-083 lift) to move from local hash-chain to S3 Object Lock + JWS. These two decisions move Nova from 'pipeline-ready' to 'production-proven.'"
|
|
||||||
|
|
||||||
> **Benefit:** you leave with a clear business decision to make — approve a pilot + the ledger build-out — and 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 something a C-suite can decide. "Approve the ledger build-out" is a budget decision. The recap reinforces the 5-act arc — the audience leaves with the structure, not a pile of facts.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix Slide A1 — Metrics Glossary
|
|
||||||
|
|
||||||
This appendix defines every KPI in one line with its grounding badge.
|
|
||||||
|
|
||||||
| KPI | Definition | Status |
|
|
||||||
|-----|-----------|--------|
|
|
||||||
| Touchless Resolution Rate | runs without operational HITL block ÷ total | partial (Post-Pilot) |
|
|
||||||
| Human Escalation Frequency | operational HITL blocks ÷ total | partial (Post-Pilot) |
|
|
||||||
| AI 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 (Infracost) | sum(delta_usd where delta < 0) | partial (CUR 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:** you now have a reference for every metric mentioned in the deck.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appendix Slide A2 — Operating Model & Cost
|
|
||||||
|
|
||||||
This appendix shows the real cost figures + the zero-cost steady state.
|
|
||||||
|
|
||||||
- **Cost figures** from `COST.md`: $0.001883 over 8 days, ~$0.007/month, S3-dominated, zero BAU compute
|
|
||||||
- **Zero-cost steady state:** all resources torn down post-v1.11 (D-096); the platform runs offline
|
|
||||||
- References the pre-mortem (`PRE_MORTEM.md`: v1.10 decay root cause + four forward failure modes + structural mitigations)
|
|
||||||
|
|
||||||
> **Benefit:** you now know the operating cost is negligible — and the structural mitigation that prevents decay.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> **End of deck.** 16 main slides + 2 appendix slides = 18 total.
|
|
||||||
> Both old decks (`how-the-platform-works` + `the-developer-experience`) are retired (D-130).
|
|
||||||
Binary file not shown.
+45
-33
@@ -1,13 +1,12 @@
|
|||||||
# RACI — Who Owns What
|
# RACI — Who Owns What
|
||||||
|
|
||||||
> **Source of truth:** `.ciagent/PROJECT.md` § RACI Matrix (v1.18, REQ-215,
|
> This page is the citizen-developer-facing copy.
|
||||||
> D-139). This page is the citizen-developer-facing copy.
|
|
||||||
|
|
||||||
Nova's delivery lifecycle has three roles. This page clarifies who owns
|
Nova's delivery lifecycle has four roles. This page clarifies who owns
|
||||||
what — so the citizen developer knows what they bring, what the platform
|
what — so the citizen developer knows what they bring, what the platform
|
||||||
provides, and what is co-owned.
|
provides, what quality engineering guards, and what is co-owned with SRE.
|
||||||
|
|
||||||
## The Three Roles
|
## The Four Roles
|
||||||
|
|
||||||
### Citizen Developer (CD)
|
### Citizen Developer (CD)
|
||||||
|
|
||||||
@@ -15,40 +14,49 @@ That's you — the consumer (technical developer L3A or non-technical L3B).
|
|||||||
You are **Responsible** for all **Functional Requirements (FRs)** and
|
You are **Responsible** for all **Functional Requirements (FRs)** and
|
||||||
**User Acceptance Testing (UAT)**. You produce the FRs + UAT via your AI
|
**User Acceptance Testing (UAT)**. You produce the FRs + UAT via your AI
|
||||||
coding agent, an upstream agentic SDLC platform, or any upstream
|
coding agent, an upstream agentic SDLC platform, or any upstream
|
||||||
development platform. **The source does not matter** — all are subject
|
development platform. **The source does not matter** — all are subject to
|
||||||
to the same compliance standards (the submission-readiness gate, the
|
the same compliance standards (the submission-readiness gate, the
|
||||||
contract schema, the policy envelope, the immutable audit stream). Nova
|
contract schema, the policy envelope, the immutable audit stream). Nova
|
||||||
validates the submission, not the author.
|
validates the submission, not the author.
|
||||||
|
|
||||||
### Platform (Nova)
|
### Platform (Nova)
|
||||||
|
|
||||||
Nova is **Responsible** for all **Non-Functional Requirements (NFRs)**,
|
Nova is **Responsible** for all **Non-Functional Requirements (NFRs)**,
|
||||||
**Infrastructure** (cloud resource lifecycle, state, IAM), **QA** (the
|
**Infrastructure** (cloud resource lifecycle, state, IAM), and
|
||||||
platform-side quality checks: policy enforcement, confidence scoring,
|
**Production deployments to cloud** (the apply path, the pipeline, the
|
||||||
schema validation), and **Production deployments to cloud** (the apply
|
release mechanics).
|
||||||
path, the pipeline, the release mechanics).
|
|
||||||
|
|
||||||
### Release Management (RM) — co-owned
|
### Quality Engineering (QE)
|
||||||
|
|
||||||
The release is **co-owned**. The platform performs the QA + SRE
|
Quality Engineering is **Responsible** for the platform-side quality
|
||||||
attestations agentically (it runs the confidence signal, the policy
|
checks: policy enforcement, confidence scoring, schema validation, and
|
||||||
checks, the separation-of-duties). The citizen developer **oversees and
|
the functional/contract/non-functional evidence that feeds attestation.
|
||||||
triggers** the actual release — the human attestation at the stage gate
|
QE owns the **quality** of what the platform produces — the gate
|
||||||
is your authorization. The platform runs the checks; you authorize the
|
evidence, not the gate decision.
|
||||||
promotion. This is the "autonomy in operations, human at stage gates"
|
|
||||||
model.
|
### 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
|
## The Matrix
|
||||||
|
|
||||||
| Work Category | Citizen Developer | Platform | Release Management |
|
| Work Category | Citizen Developer | Platform | Quality Engineering | SRE |
|
||||||
|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| **Functional Requirements (FRs)** | **R/A** | C | I |
|
| **Functional Requirements (FRs)** | **R/A** | C | I | I |
|
||||||
| **User Acceptance Testing (UAT)** | **R/A** | C | I |
|
| **User Acceptance Testing (UAT)** | **R/A** | C | I | I |
|
||||||
| **Non-Functional Requirements (NFRs)** | I | **R/A** | C |
|
| **Non-Functional Requirements (NFRs)** | I | **R/A** | C | C |
|
||||||
| **Infrastructure (cloud, state, IAM)** | I | **R/A** | C |
|
| **Infrastructure (cloud, state, IAM)** | I | **R/A** | I | C |
|
||||||
| **QA (policy, confidence, schema checks)** | C | **R/A** | I |
|
| **QA (policy, confidence, schema checks)** | C | R | **R/A** | I |
|
||||||
| **Production deployment to cloud** | I | **R/A** | C |
|
| **Production deployment to cloud** | I | **R/A** | C | C |
|
||||||
| **Release attestation (QA + SRE sign-off)** | **A** | R | **R** |
|
| **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
|
**Key:** **R** = Responsible (does the work) · **A** = Accountable (owns
|
||||||
the outcome, sign-off) · **C** = Consulted · **I** = Informed.
|
the outcome, sign-off) · **C** = Consulted · **I** = Informed.
|
||||||
@@ -64,11 +72,15 @@ the outcome, sign-off) · **C** = Consulted · **I** = Informed.
|
|||||||
- The NFRs (security, observability, compliance — baked into the
|
- The NFRs (security, observability, compliance — baked into the
|
||||||
pipeline, not your concern).
|
pipeline, not your concern).
|
||||||
- The infrastructure (cloud resources, state management, IAM scoping).
|
- The infrastructure (cloud resources, state management, IAM scoping).
|
||||||
- The QA (policy enforcement, confidence scoring, schema validation).
|
|
||||||
- The production deployment (the apply path, the pipeline, the release).
|
- The production deployment (the apply path, the pipeline, the release).
|
||||||
|
|
||||||
**You co-own the release:**
|
**Quality Engineering guards:**
|
||||||
- Nova runs the attestations (QA confidence, SRE operational readiness).
|
- 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
|
- You authorize the promotion at the stage gate. No promotion happens
|
||||||
without your recorded attestation.
|
without your recorded attestation.
|
||||||
|
|
||||||
@@ -79,7 +91,7 @@ agentic SDLC platform, or a traditional IDE. Nova does not
|
|||||||
differentiate. All submissions pass through the same gate
|
differentiate. All submissions pass through the same gate
|
||||||
(`schemas/submission-readiness.schema.json`): tags, environment
|
(`schemas/submission-readiness.schema.json`): tags, environment
|
||||||
metadata, policy preconditions, profile markers. The compliance
|
metadata, policy preconditions, profile markers. The compliance
|
||||||
standards are the same regardless of how the code was authored. This
|
standards are the same regardless of how the code was authored. This is
|
||||||
is by design: the audit trail is the same, the policy envelope is the
|
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
|
same, the evidence stream is the same. The source does not matter; the
|
||||||
submission does.
|
submission does.
|
||||||
+6
-2
@@ -1,6 +1,5 @@
|
|||||||
# Scope — Nova is Downstream of PDLC
|
# Scope — Nova is Downstream of PDLC
|
||||||
|
|
||||||
> **Source of truth:** `.ciagent/PROJECT.md` § Scope (v1.18, REQ-216).
|
|
||||||
> This page is the citizen-developer-facing copy.
|
> This page is the citizen-developer-facing copy.
|
||||||
|
|
||||||
## The Boundary
|
## The Boundary
|
||||||
@@ -15,7 +14,12 @@ PDLC includes:
|
|||||||
- IDE workflows / developer experience
|
- IDE workflows / developer experience
|
||||||
|
|
||||||
Nova never penetrates the PDLC. Nova's domain is **infrastructure +
|
Nova never penetrates the PDLC. Nova's domain is **infrastructure +
|
||||||
delivery only**.
|
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
|
## What Nova Does
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -34,14 +34,14 @@
|
|||||||
|
|
||||||
## Atelier Provenance
|
## Atelier Provenance
|
||||||
|
|
||||||
The skills are derived from [Atelier](https://git.cloudinit.dev/coreci/atelier)
|
The skills are derived from [Atelier](https://example.com/atelier)
|
||||||
— a first-principles docs-as-code engineering framework with 8 core
|
— a first-principles docs-as-code engineering framework with 8 core
|
||||||
principles (C1–C8) and 19 domains, each with 10 derived P-rules. The
|
principles (C1–C8) and 19 domains, each with 10 derived P-rules. The
|
||||||
skills distill the citizen-developer-relevant subset of each domain's
|
skills distill the citizen-developer-relevant subset of each domain's
|
||||||
first-principles, link to the agent-checklist triggers, and map to the
|
first-principles, link to the agent-checklist triggers, and map to the
|
||||||
existing BA.A catalog.
|
existing BA.A catalog.
|
||||||
|
|
||||||
Atelier is vendored under `mcp/atelier/vendor/` (pinned tag, D-136) for
|
Atelier is vendored under `mcp/atelier/vendor/` (pinned tag) for
|
||||||
audit reproducibility — an agentic validation result is replayable
|
audit reproducibility — an agentic validation result is replayable
|
||||||
against the exact principles that produced it.
|
against the exact principles that produced it.
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# Nova Atelier MCP Server
|
# Nova Atelier MCP Server
|
||||||
|
|
||||||
> **v1.18, REQ-223, REQ-224.** An MCP (Model Context Protocol) server that
|
|
||||||
> exposes Atelier engineering principles to the citizen developer's AI
|
> exposes Atelier engineering principles to the citizen developer's AI
|
||||||
> agent. Plugin-registry architecture (D-140); stdio transport (D-135);
|
> agent. Plugin-registry architecture; stdio transport;
|
||||||
> vendored Atelier (D-136) for audit reproducibility.
|
> vendored Atelier for audit reproducibility.
|
||||||
|
|
||||||
## What This Is
|
## What This Is
|
||||||
|
|
||||||
@@ -22,7 +21,7 @@ observability gaps.
|
|||||||
| `atelier.matrix_lookup(domain)` | Look up the domain→core principle mapping for a given domain. |
|
| `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. |
|
| `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 (D-140)
|
## Architecture — Plugin Registry
|
||||||
|
|
||||||
```
|
```
|
||||||
mcp/atelier/
|
mcp/atelier/
|
||||||
@@ -31,7 +30,7 @@ mcp/atelier/
|
|||||||
│ ├── __init__.py
|
│ ├── __init__.py
|
||||||
│ ├── principles.py # lookup_principle, list_domains, matrix_lookup
|
│ ├── principles.py # lookup_principle, list_domains, matrix_lookup
|
||||||
│ └── validation.py # validate_against_principles
|
│ └── validation.py # validate_against_principles
|
||||||
├── vendor/ # pinned Atelier snapshot (D-136)
|
├── vendor/ # pinned Atelier snapshot
|
||||||
│ ├── VERSION.md # pinned tag + upgrade instructions
|
│ ├── VERSION.md # pinned tag + upgrade instructions
|
||||||
│ ├── core/first-principles.md
|
│ ├── core/first-principles.md
|
||||||
│ ├── domains/security/first-principles.md
|
│ ├── domains/security/first-principles.md
|
||||||
@@ -68,7 +67,7 @@ s.load_plugins()
|
|||||||
result = s.call_tool("atelier_lookup_principle", {"domain": "security", "principle_id": "P4"})
|
result = s.call_tool("atelier_lookup_principle", {"domain": "security", "principle_id": "P4"})
|
||||||
```
|
```
|
||||||
|
|
||||||
## Vendoring (D-136)
|
## Vendoring
|
||||||
|
|
||||||
Atelier is vendored under `vendor/` at a pinned tag (`v0.3.6`, see
|
Atelier is vendored under `vendor/` at a pinned tag (`v0.3.6`, see
|
||||||
`vendor/VERSION.md`). An agentic validation result is only reproducible if
|
`vendor/VERSION.md`). An agentic validation result is only reproducible if
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
# Nova PowerBI Dashboard — Import Guide
|
# Nova PowerBI Dashboard — Import Guide
|
||||||
|
|
||||||
> v1.17 — Strategic Direction, Leadership Metrics & Unified Story (REQ-208)
|
|
||||||
> Generated: 2026-08-04
|
|
||||||
|
|
||||||
This guide documents how to import Nova's metrics views into PowerBI
|
This guide documents how to import Nova's metrics views into PowerBI
|
||||||
via the folder connector, and suggests a starter visual model.
|
via the folder connector, and suggests a starter visual model.
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
resource "aws_cloudfront_origin_access_control" "this" {
|
resource "aws_cloudfront_origin_access_control" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
name = local.oac_name
|
name = local.oac_name
|
||||||
origin_access_control_origin_type = local.oac_origin_type
|
origin_access_control_origin_type = local.oac_origin_type
|
||||||
signing_behavior = local.oac_signing_behavior
|
signing_behavior = local.oac_signing_behavior
|
||||||
@@ -6,10 +7,11 @@ resource "aws_cloudfront_origin_access_control" "this" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_cloudfront_distribution" "this" {
|
resource "aws_cloudfront_distribution" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
origin {
|
origin {
|
||||||
origin_id = "s3-origin"
|
origin_id = "s3-origin"
|
||||||
domain_name = var.bucket_regional_domain_name
|
domain_name = var.bucket_regional_domain_name
|
||||||
origin_access_control_id = aws_cloudfront_origin_access_control.this.id
|
origin_access_control_id = aws_cloudfront_origin_access_control.this[0].id
|
||||||
s3_origin_config {
|
s3_origin_config {
|
||||||
origin_access_identity = ""
|
origin_access_identity = ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
output "distribution_arn" {
|
output "distribution_arn" {
|
||||||
value = aws_cloudfront_distribution.this.arn
|
value = aws_cloudfront_distribution.this[0].arn
|
||||||
description = "The CloudFront distribution ARN."
|
description = "The CloudFront distribution ARN."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "distribution_domain_name" {
|
output "distribution_domain_name" {
|
||||||
value = aws_cloudfront_distribution.this.domain_name
|
value = aws_cloudfront_distribution.this[0].domain_name
|
||||||
description = "The CloudFront distribution domain name."
|
description = "The CloudFront distribution domain name."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "oac_id" {
|
output "oac_id" {
|
||||||
value = aws_cloudfront_origin_access_control.this.id
|
value = aws_cloudfront_origin_access_control.this[0].id
|
||||||
description = "The Origin Access Control ID."
|
description = "The Origin Access Control ID."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,3 +38,9 @@ variable "region" {
|
|||||||
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)."
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "ARN of the CMK for repository encryption; if absent, uses AWS-managed key.",
|
"description": "ARN of the CMK for repository encryption; if absent, uses AWS-managed key.",
|
||||||
"required": false
|
"required": false
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": {
|
"outputs": {
|
||||||
@@ -48,4 +53,4 @@
|
|||||||
"default": true
|
"default": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ locals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_ecr_repository" "this" {
|
resource "aws_ecr_repository" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
name = var.name
|
name = var.name
|
||||||
image_tag_mutability = "MUTABLE"
|
image_tag_mutability = "MUTABLE"
|
||||||
image_scanning_configuration {
|
image_scanning_configuration {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
output "repository_url" {
|
output "repository_url" {
|
||||||
value = aws_ecr_repository.this.repository_url
|
value = aws_ecr_repository.this[0].repository_url
|
||||||
description = "The ECR repository URL."
|
description = "The ECR repository URL."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "repository_arn" {
|
output "repository_arn" {
|
||||||
value = aws_ecr_repository.this.arn
|
value = aws_ecr_repository.this[0].arn
|
||||||
description = "The ECR repository ARN."
|
description = "The ECR repository ARN."
|
||||||
}
|
}
|
||||||
@@ -13,4 +13,10 @@ variable "kms_key_arn" {
|
|||||||
type = string
|
type = string
|
||||||
description = "ARN of the CMK for ECR encryption; if absent, uses managed key."
|
description = "ARN of the CMK for ECR encryption; if absent, uses managed key."
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "ARN of the CMK for CloudWatch log group encryption; if absent, uses managed key.",
|
"description": "ARN of the CMK for CloudWatch log group encryption; if absent, uses managed key.",
|
||||||
"required": false
|
"required": false
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": {
|
"outputs": {
|
||||||
@@ -43,4 +48,4 @@
|
|||||||
"default": true
|
"default": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
resource "aws_ecs_cluster" "this" {
|
resource "aws_ecs_cluster" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
name = var.name
|
name = var.name
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
output "cluster_arn" {
|
output "cluster_arn" {
|
||||||
value = aws_ecs_cluster.this.arn
|
value = aws_ecs_cluster.this[0].arn
|
||||||
description = "The ECS cluster ARN."
|
description = "The ECS cluster ARN."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "cluster_id" {
|
output "cluster_id" {
|
||||||
value = aws_ecs_cluster.this.id
|
value = aws_ecs_cluster.this[0].id
|
||||||
description = "The ECS cluster ID."
|
description = "The ECS cluster ID."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,3 +15,9 @@ variable "kms_key_arn" {
|
|||||||
description = "ARN of the CMK for CloudWatch log group encryption; if absent, uses managed key."
|
description = "ARN of the CMK for CloudWatch log group encryption; if absent, uses managed key."
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -79,6 +79,11 @@
|
|||||||
"description": "ECS task definition family name.",
|
"description": "ECS task definition family name.",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "app"
|
"default": "app"
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": {
|
"outputs": {
|
||||||
@@ -107,14 +112,32 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:ecs:task_definition",
|
"type": "aws:ecs:task_definition",
|
||||||
"description": "Fargate task definition; the adapter jsonencodes image/port/env into container_definitions.",
|
"description": "Fargate task definition; the adapter jsonencodes image/port/env into container_definitions.",
|
||||||
"inputs": ["image", "port", "cpu", "memory", "env", "family"],
|
"inputs": [
|
||||||
"outputs": ["task_def_arn"]
|
"image",
|
||||||
|
"port",
|
||||||
|
"cpu",
|
||||||
|
"memory",
|
||||||
|
"env",
|
||||||
|
"family"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"task_def_arn"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "aws:ecs:service",
|
"type": "aws:ecs:service",
|
||||||
"description": "Fargate service running the task definition in the cluster + subnets.",
|
"description": "Fargate service running the task definition in the cluster + subnets.",
|
||||||
"inputs": ["cluster_arn", "subnets", "security_group", "lb_target_group_arn", "desired_count", "launch_type"],
|
"inputs": [
|
||||||
"outputs": ["service_arn"]
|
"cluster_arn",
|
||||||
|
"subnets",
|
||||||
|
"security_group",
|
||||||
|
"lb_target_group_arn",
|
||||||
|
"desired_count",
|
||||||
|
"launch_type"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"service_arn"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
resource "aws_ecs_task_definition" "this" {
|
resource "aws_ecs_task_definition" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
family = var.family
|
family = var.family
|
||||||
cpu = tostring(var.cpu)
|
cpu = tostring(var.cpu)
|
||||||
memory = tostring(var.memory)
|
memory = tostring(var.memory)
|
||||||
@@ -8,9 +9,10 @@ resource "aws_ecs_task_definition" "this" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_ecs_service" "this" {
|
resource "aws_ecs_service" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
name = "nova-microservice"
|
name = "nova-microservice"
|
||||||
cluster = var.cluster_arn
|
cluster = var.cluster_arn
|
||||||
task_definition = aws_ecs_task_definition.this.arn
|
task_definition = aws_ecs_task_definition.this[0].arn
|
||||||
desired_count = var.desired_count
|
desired_count = var.desired_count
|
||||||
launch_type = var.launch_type
|
launch_type = var.launch_type
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
output "service_arn" {
|
output "service_arn" {
|
||||||
value = aws_ecs_service.this.id
|
value = aws_ecs_service.this[0].id
|
||||||
description = "The ECS service ARN."
|
description = "The ECS service ARN."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "task_def_arn" {
|
output "task_def_arn" {
|
||||||
value = aws_ecs_task_definition.this.arn
|
value = aws_ecs_task_definition.this[0].arn
|
||||||
description = "The ECS task definition ARN."
|
description = "The ECS task definition ARN."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,3 +78,9 @@ variable "family" {
|
|||||||
description = "ECS task definition family name."
|
description = "ECS task definition family name."
|
||||||
default = "app"
|
default = "app"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "AWS region the role is created in.",
|
"description": "AWS region the role is created in.",
|
||||||
"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": {
|
||||||
@@ -48,4 +53,4 @@
|
|||||||
"default": true
|
"default": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
resource "aws_iam_role" "this" {
|
resource "aws_iam_role" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
name = var.role_name
|
name = var.role_name
|
||||||
assume_role_policy = local.assume_role_policy
|
assume_role_policy = local.assume_role_policy
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_iam_role_policy" "ecr_logs" {
|
resource "aws_iam_role_policy" "ecr_logs" {
|
||||||
count = local.inline_policy != null ? 1 : 0
|
count = (local.inline_policy != null && var.enabled) ? 1 : 0
|
||||||
name = local.inline_policy.name
|
name = local.inline_policy.name
|
||||||
role = aws_iam_role.this.id
|
role = aws_iam_role.this[0].id
|
||||||
policy = local.inline_policy.policy
|
policy = local.inline_policy.policy
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
output "role_arn" {
|
output "role_arn" {
|
||||||
value = aws_iam_role.this.arn
|
value = aws_iam_role.this[0].arn
|
||||||
description = "The IAM role ARN."
|
description = "The IAM role ARN."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "role_id" {
|
output "role_id" {
|
||||||
value = aws_iam_role.this.id
|
value = aws_iam_role.this[0].id
|
||||||
description = "The IAM role ID."
|
description = "The IAM role ID."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,3 +21,9 @@ variable "region" {
|
|||||||
description = "AWS region (provider-level; not a resource arg)."
|
description = "AWS region (provider-level; not a resource arg)."
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,11 @@
|
|||||||
"description": "Number of days before the key is deleted after deletion is requested (default 30).",
|
"description": "Number of days before the key is deleted after deletion is requested (default 30).",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": 30
|
"default": 30
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": {
|
"outputs": {
|
||||||
@@ -49,4 +54,4 @@
|
|||||||
"default": true
|
"default": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
resource "aws_kms_key" "this" {
|
resource "aws_kms_key" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
description = var.description
|
description = var.description
|
||||||
enable_key_rotation = true
|
enable_key_rotation = true
|
||||||
deletion_window_in_days = var.deletion_window_days
|
deletion_window_in_days = var.deletion_window_days
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_kms_alias" "this" {
|
resource "aws_kms_alias" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
name = local.alias_name
|
name = local.alias_name
|
||||||
target_key_id = aws_kms_key.this.key_id
|
target_key_id = aws_kms_key.this[0].key_id
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
output "kms_key_arn" {
|
output "kms_key_arn" {
|
||||||
value = aws_kms_key.this.arn
|
value = aws_kms_key.this[0].arn
|
||||||
description = "The KMS key ARN."
|
description = "The KMS key ARN."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "kms_key_id" {
|
output "kms_key_id" {
|
||||||
value = aws_kms_key.this.key_id
|
value = aws_kms_key.this[0].key_id
|
||||||
description = "The KMS key ID."
|
description = "The KMS key ID."
|
||||||
}
|
}
|
||||||
@@ -14,4 +14,10 @@ variable "deletion_window_days" {
|
|||||||
type = number
|
type = number
|
||||||
description = "Deletion window in days (7-30)."
|
description = "Deletion window in days (7-30)."
|
||||||
default = 30
|
default = 30
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -79,6 +79,11 @@
|
|||||||
"description": "Database admin password",
|
"description": "Database admin password",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "ACdlcI2026!"
|
"default": "ACdlcI2026!"
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": {
|
"outputs": {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ resource "aws_db_subnet_group" "this" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_db_instance" "this" {
|
resource "aws_db_instance" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
engine = var.engine
|
engine = var.engine
|
||||||
engine_version = var.engine_version
|
engine_version = var.engine_version
|
||||||
instance_class = var.instance_class
|
instance_class = var.instance_class
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
output "db_endpoint" {
|
output "db_endpoint" {
|
||||||
value = aws_db_instance.this.endpoint
|
value = aws_db_instance.this[0].endpoint
|
||||||
description = "The RDS instance endpoint."
|
description = "The RDS instance endpoint."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "db_arn" {
|
output "db_arn" {
|
||||||
value = aws_db_instance.this.arn
|
value = aws_db_instance.this[0].arn
|
||||||
description = "The RDS instance ARN."
|
description = "The RDS instance ARN."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,3 +64,9 @@ variable "subnet_ids" {
|
|||||||
description = "Comma-separated subnet IDs for the DB subnet group (VPC-dependent)."
|
description = "Comma-separated subnet IDs for the DB subnet group (VPC-dependent)."
|
||||||
default = ""
|
default = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "ARN of the CMK for SSE-KMS; if absent, uses managed key.",
|
"description": "ARN of the CMK for SSE-KMS; if absent, uses managed key.",
|
||||||
"required": false
|
"required": false
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": {
|
"outputs": {
|
||||||
@@ -57,4 +62,4 @@
|
|||||||
"default": true
|
"default": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
resource "aws_s3_bucket" "this" {
|
resource "aws_s3_bucket" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
bucket = var.bucket_name
|
bucket = var.bucket_name
|
||||||
tags = local.tags
|
tags = local.tags
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_s3_bucket_versioning" "this" {
|
resource "aws_s3_bucket_versioning" "this" {
|
||||||
bucket = aws_s3_bucket.this.id
|
count = var.enabled ? 1 : 0
|
||||||
|
bucket = aws_s3_bucket.this[0].id
|
||||||
|
|
||||||
versioning_configuration {
|
versioning_configuration {
|
||||||
status = "Enabled"
|
status = "Enabled"
|
||||||
@@ -12,7 +14,8 @@ resource "aws_s3_bucket_versioning" "this" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_s3_bucket_server_side_encryption_configuration" "this" {
|
resource "aws_s3_bucket_server_side_encryption_configuration" "this" {
|
||||||
bucket = aws_s3_bucket.this.id
|
count = var.enabled ? 1 : 0
|
||||||
|
bucket = aws_s3_bucket.this[0].id
|
||||||
|
|
||||||
rule {
|
rule {
|
||||||
apply_server_side_encryption_by_default {
|
apply_server_side_encryption_by_default {
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
output "bucket_arn" {
|
output "bucket_arn" {
|
||||||
value = aws_s3_bucket.this.arn
|
value = aws_s3_bucket.this[0].arn
|
||||||
description = "The S3 bucket ARN."
|
description = "The S3 bucket ARN."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "bucket_name" {
|
output "bucket_name" {
|
||||||
value = aws_s3_bucket.this.id
|
value = aws_s3_bucket.this[0].id
|
||||||
description = "The bucket name (echoes the input)."
|
description = "The bucket name (echoes the input)."
|
||||||
}
|
}
|
||||||
|
|
||||||
output "bucket_regional_domain_name" {
|
output "bucket_regional_domain_name" {
|
||||||
value = aws_s3_bucket.this.bucket_regional_domain_name
|
value = aws_s3_bucket.this[0].bucket_regional_domain_name
|
||||||
description = "The bucket regional domain name (e.g. nova-spike-bucket.s3.us-east-1.amazonaws.com)."
|
description = "The bucket regional domain name (e.g. nova-spike-bucket.s3.us-east-1.amazonaws.com)."
|
||||||
}
|
}
|
||||||
@@ -19,4 +19,10 @@ variable "tags" {
|
|||||||
type = map(string)
|
type = map(string)
|
||||||
description = "Additional tags to merge with the module defaults."
|
description = "Additional tags to merge with the module defaults."
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -71,6 +71,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "ECS cluster ARN to deploy the service into",
|
"description": "ECS cluster ARN to deploy the service into",
|
||||||
"required": false
|
"required": false
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outputs": {
|
"outputs": {
|
||||||
@@ -99,4 +104,4 @@
|
|||||||
"default": true
|
"default": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ resource "aws_ecs_service" "uptime" {
|
|||||||
name = "nova-uptime"
|
name = "nova-uptime"
|
||||||
cluster = local.cluster_ref
|
cluster = local.cluster_ref
|
||||||
task_definition = aws_ecs_task_definition.uptime.arn
|
task_definition = aws_ecs_task_definition.uptime.arn
|
||||||
desired_count = var.feature_flag_enabled ? 1 : 0
|
desired_count = var.enabled ? (var.feature_flag_enabled ? 1 : 0) : 0
|
||||||
launch_type = "FARGATE"
|
launch_type = "FARGATE"
|
||||||
|
|
||||||
dynamic "network_configuration" {
|
dynamic "network_configuration" {
|
||||||
|
|||||||
@@ -69,3 +69,9 @@ variable "cluster_arn" {
|
|||||||
description = "ECS cluster ARN to deploy the service into."
|
description = "ECS cluster ARN to deploy the service into."
|
||||||
default = ""
|
default = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "AWS region the VPC is created in.",
|
"description": "AWS region the VPC is created in.",
|
||||||
"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": {
|
||||||
@@ -57,24 +62,44 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:ec2:vpc",
|
"type": "aws:ec2:vpc",
|
||||||
"description": "The VPC itself.",
|
"description": "The VPC itself.",
|
||||||
"inputs": ["cidr", "name"],
|
"inputs": [
|
||||||
"outputs": ["vpc_id"]
|
"cidr",
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"vpc_id"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "aws:ec2:subnet",
|
"type": "aws:ec2:subnet",
|
||||||
"description": "One subnet per availability zone (azs split on comma).",
|
"description": "One subnet per availability zone (azs split on comma).",
|
||||||
"inputs": ["cidr", "az", "vpc_id", "name"],
|
"inputs": [
|
||||||
"outputs": ["subnet_ids"]
|
"cidr",
|
||||||
|
"az",
|
||||||
|
"vpc_id",
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"subnet_ids"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "aws:ec2:routetable",
|
"type": "aws:ec2:routetable",
|
||||||
"description": "Route table bound to the VPC with an internet gateway + default route.",
|
"description": "Route table bound to the VPC with an internet gateway + default route.",
|
||||||
"inputs": ["vpc_id"],
|
"inputs": [
|
||||||
|
"vpc_id"
|
||||||
|
],
|
||||||
"outputs": []
|
"outputs": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"intra_refs": [
|
"intra_refs": [
|
||||||
{"from": "aws:ec2:subnet.vpc_id", "to": "aws:ec2:vpc.vpc_id"},
|
{
|
||||||
{"from": "aws:ec2:routetable.vpc_id", "to": "aws:ec2:vpc.vpc_id"}
|
"from": "aws:ec2:subnet.vpc_id",
|
||||||
|
"to": "aws:ec2:vpc.vpc_id"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "aws:ec2:routetable.vpc_id",
|
||||||
|
"to": "aws:ec2:vpc.vpc_id"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
resource "aws_vpc" "this" {
|
resource "aws_vpc" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
cidr_block = local.cidr_block
|
cidr_block = local.cidr_block
|
||||||
tags = {
|
tags = {
|
||||||
Name = local.name_tag
|
Name = local.name_tag
|
||||||
@@ -11,7 +12,7 @@ resource "aws_vpc" "this" {
|
|||||||
|
|
||||||
resource "aws_subnet" "this" {
|
resource "aws_subnet" "this" {
|
||||||
count = length(local.az_list)
|
count = length(local.az_list)
|
||||||
vpc_id = aws_vpc.this.id
|
vpc_id = aws_vpc.this[0].id
|
||||||
cidr_block = local.subnet_cidrs[count.index]
|
cidr_block = local.subnet_cidrs[count.index]
|
||||||
availability_zone = local.az_list[count.index]
|
availability_zone = local.az_list[count.index]
|
||||||
tags = {
|
tags = {
|
||||||
@@ -20,17 +21,19 @@ resource "aws_subnet" "this" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_internet_gateway" "this" {
|
resource "aws_internet_gateway" "this" {
|
||||||
vpc_id = aws_vpc.this.id
|
count = var.enabled ? 1 : 0
|
||||||
|
vpc_id = aws_vpc.this[0].id
|
||||||
tags = {
|
tags = {
|
||||||
Name = "${local.name_tag}-igw"
|
Name = "${local.name_tag}-igw"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_route_table" "this" {
|
resource "aws_route_table" "this" {
|
||||||
vpc_id = aws_vpc.this.id
|
count = var.enabled ? 1 : 0
|
||||||
|
vpc_id = aws_vpc.this[0].id
|
||||||
route {
|
route {
|
||||||
cidr_block = "0.0.0.0/0"
|
cidr_block = "0.0.0.0/0"
|
||||||
gateway_id = aws_internet_gateway.this.id
|
gateway_id = aws_internet_gateway.this[0].id
|
||||||
}
|
}
|
||||||
tags = {
|
tags = {
|
||||||
Name = "${local.name_tag}-rt"
|
Name = "${local.name_tag}-rt"
|
||||||
@@ -40,5 +43,5 @@ resource "aws_route_table" "this" {
|
|||||||
resource "aws_route_table_association" "this" {
|
resource "aws_route_table_association" "this" {
|
||||||
count = length(local.az_list)
|
count = length(local.az_list)
|
||||||
subnet_id = aws_subnet.this[count.index].id
|
subnet_id = aws_subnet.this[count.index].id
|
||||||
route_table_id = aws_route_table.this.id
|
route_table_id = aws_route_table.this[0].id
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
output "vpc_id" {
|
output "vpc_id" {
|
||||||
value = aws_vpc.this.id
|
value = aws_vpc.this[0].id
|
||||||
description = "The VPC id."
|
description = "The VPC id."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,3 +21,9 @@ variable "region" {
|
|||||||
description = "AWS region (provider-level; not a resource arg)."
|
description = "AWS region (provider-level; not a resource arg)."
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,6 +31,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "AWS region (CloudFront-scoped WAF is always us-east-1; the adapter ignores this for cloudfront scope).",
|
"description": "AWS region (CloudFront-scoped WAF is always us-east-1; the adapter ignores this for cloudfront scope).",
|
||||||
"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": {
|
||||||
@@ -60,8 +65,15 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:wafv2:webacl",
|
"type": "aws:wafv2:webacl",
|
||||||
"description": "WAFv2 Web ACL with managed rules.",
|
"description": "WAFv2 Web ACL with managed rules.",
|
||||||
"inputs": ["name", "scope", "default_action", "rules"],
|
"inputs": [
|
||||||
"outputs": ["web_acl_arn"]
|
"name",
|
||||||
|
"scope",
|
||||||
|
"default_action",
|
||||||
|
"rules"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"web_acl_arn"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
resource "aws_wafv2_web_acl" "this" {
|
resource "aws_wafv2_web_acl" "this" {
|
||||||
|
count = var.enabled ? 1 : 0
|
||||||
name = var.name
|
name = var.name
|
||||||
scope = local.scope
|
scope = local.scope
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
output "web_acl_arn" {
|
output "web_acl_arn" {
|
||||||
value = aws_wafv2_web_acl.this.arn
|
value = aws_wafv2_web_acl.this[0].arn
|
||||||
description = "The WAF Web ACL ARN."
|
description = "The WAF Web ACL ARN."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,3 +27,9 @@ variable "region" {
|
|||||||
description = "AWS region (provider-level; not a resource arg)."
|
description = "AWS region (provider-level; not a resource arg)."
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enabled" {
|
||||||
|
type = bool
|
||||||
|
description = "Feature flag: enable/disable this module. Set to false to skip resource creation."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|||||||
+5
-5
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Nova uses declarative pipeline contracts (YAML) as the single source of truth. Both Gitea and GitHub workflows implement the same contract (byte-identical). The shell runner (`scripts/run_ci.sh`) mirrors the CI pipeline locally so that every stage that runs in CI can be reproduced on a developer machine without a forge.
|
Nova uses declarative pipeline contracts (YAML) as the single source of truth. GitHub workflows implement the same contract (byte-identical across forges). The shell runner (`scripts/run_ci.sh`) mirrors the CI pipeline locally so that every stage that runs in CI can be reproduced on a developer machine without a forge.
|
||||||
|
|
||||||
## Existing Pipelines
|
## Existing Pipelines
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ Nova uses declarative pipeline contracts (YAML) as the single source of truth. B
|
|||||||
|
|
||||||
## How to Wire a Pipeline
|
## How to Wire a Pipeline
|
||||||
|
|
||||||
1. Create byte-identical workflow YAMLs in `.gitea/workflows/<name>.yml` and `.github/workflows/<name>.yml`.
|
1. Create the workflow YAML in `.github/workflows/<name>.yml`.
|
||||||
2. Both workflows must implement the same stages, commands, triggers, and runner declared in the contract.
|
2. Both workflows must implement the same stages, commands, triggers, and runner declared in the contract.
|
||||||
3. `scripts/run_ci.sh` mirrors `ci.yml` locally so the same stages run without a forge.
|
3. `scripts/run_ci.sh` mirrors `ci.yml` locally so the same stages run without a forge.
|
||||||
4. Consumer repos reference the deploy pipeline via `uses: acdl/.github/workflows/deploy.yml@vX.Y`.
|
4. Consumer repos reference the deploy pipeline via `uses: acdl/.github/workflows/deploy.yml@vX.Y`.
|
||||||
@@ -29,17 +29,17 @@ Nova uses declarative pipeline contracts (YAML) as the single source of truth. B
|
|||||||
|
|
||||||
- `scripts/run_ci.sh` — local CI mirror that runs the `ci.yml` stages.
|
- `scripts/run_ci.sh` — local CI mirror that runs the `ci.yml` stages.
|
||||||
- `scripts/run_platform.sh` — platform pipeline runner that implements the `contract.yml` stages.
|
- `scripts/run_platform.sh` — platform pipeline runner that implements the `contract.yml` stages.
|
||||||
- Workflow YAMLs in `.gitea/workflows/` and `.github/workflows/`.
|
- Workflow YAMLs in `.github/workflows/`.
|
||||||
- Schemas in `schemas/` (`pipeline.schema.json`, `deploy-pipeline.schema.json`).
|
- Schemas in `schemas/` (`pipeline.schema.json`, `deploy-pipeline.schema.json`).
|
||||||
|
|
||||||
## How to Test Pipelines
|
## How to Test Pipelines
|
||||||
|
|
||||||
- `tests/test_pipeline_contract.py` — validates each pipeline YAML against its schema, asserts workflow conformance (byte-identical Gitea/GitHub workflows with the same stages/commands/triggers), and tests `scripts/run_ci.sh` execution against the contract.
|
- `tests/test_pipeline_contract.py` — validates each pipeline YAML against its schema, asserts workflow conformance (byte-identical workflows with the same stages/commands/triggers), and tests `scripts/run_ci.sh` execution against the contract.
|
||||||
|
|
||||||
## Adding a New Pipeline
|
## Adding a New Pipeline
|
||||||
|
|
||||||
1. Create `pipelines/<name>.yml` using the structure above.
|
1. Create `pipelines/<name>.yml` using the structure above.
|
||||||
2. Create or extend the schema in `schemas/` for the new pipeline shape.
|
2. Create or extend the schema in `schemas/` for the new pipeline shape.
|
||||||
3. Create byte-identical workflow YAMLs in `.gitea/workflows/<name>.yml` and `.github/workflows/<name>.yml`.
|
3. Create the workflow YAML in `.github/workflows/<name>.yml`.
|
||||||
4. Extend `scripts/run_ci.sh` if a local mirror of the new pipeline is needed.
|
4. Extend `scripts/run_ci.sh` if a local mirror of the new pipeline is needed.
|
||||||
5. Write or extend tests in `tests/test_pipeline_contract.py` to assert schema validity and workflow conformance.
|
5. Write or extend tests in `tests/test_pipeline_contract.py` to assert schema validity and workflow conformance.
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
# Nova Central CI Pipeline Contract (v1.5)
|
# Nova Central CI Pipeline Contract (v1.5)
|
||||||
#
|
#
|
||||||
# This is the single source of truth for the CI/CD pipeline. Both
|
# This is the single source of truth for the CI/CD pipeline. Both
|
||||||
# .gitea/workflows/ci.yml (Gitea Actions, dev) and
|
# .github/workflows/ci.yml (dev) and
|
||||||
# .github/workflows/ci.yml (GitHub Actions, production) implement the
|
# .github/workflows/ci.yml (GitHub Actions, production) implement the
|
||||||
# stages, commands, triggers, and runner declared here.
|
# stages, commands, triggers, and runner declared here.
|
||||||
# scripts/run_ci.sh mirrors the same stages for shell reproducibility.
|
# scripts/run_ci.sh mirrors the same stages for shell reproducibility.
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
# The contract does NOT replace workflow YAML syntax — it declares the
|
# The contract does NOT replace workflow YAML syntax — it declares the
|
||||||
# *intent* that the forge-specific workflows implement. The workflow files
|
# *intent* that the forge-specific workflows implement. The workflow files
|
||||||
# use Gitea/GitHub Actions syntax (checkout, setup-python, run blocks);
|
# use GitHub Actions syntax (checkout, setup-python, run blocks);
|
||||||
# this contract declares what those blocks must contain.
|
# this contract declares what those blocks must contain.
|
||||||
#
|
#
|
||||||
# Validated against schemas/pipeline.schema.json.
|
# Validated against schemas/pipeline.schema.json.
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user