--- phase: P0 name: pre-execution milestone: v1.15 requirements: [REQ-155, REQ-156, REQ-157, REQ-158, REQ-159, REQ-160, REQ-161, REQ-162, REQ-163, REQ-164] wave: 0 depends_on: [] --- # v1.15 — Nova Rebrand Plan (4 execution phases + 1 final) **Milestone:** v1.15 (Nova Rebrand — Major/breaking) **Type:** Major (breaking — consumer path, env vars, SSM path, tag keys, AWS resource names all change). Per the branch-strategy precedent (v1.10.2 → v1.11.0, v1.9.x → v1.10.0 — breaking/feature milestones tag on their OWN minor line, not the previous minor's patch line), v1.15 tags run on the **v1.15.x minor line**: `v1.15.0` (P0) → `v1.15.1..v1.15.4` (P1–P4) → `v1.15.4` (P5 = milestone release). (G-104 binding: the v1.14.x patch line is the NFR convention; a Major milestone ships on its own minor.) **Branch:** `milestone/v1.15-nova` → `phase/NN-` ## Wave ordering (D-098 v1.15 analogue) - **Wave 1 (P1):** docs/decks/prose — no runtime impact; establishes the Nova vocabulary + ships the consumer migration guide. REQ-155, REQ-156, REQ-157. Independent (first phase). - **Wave 2 (P2):** code + env vars (dual-read) + consumer path — deployments don't break during the transition window. REQ-158, REQ-159, REQ-160. Depends on P1 (docs establish the guide P2 changes are announced in). - **Wave 3 (P3):** SSM path + tag keys — SSM copy/read/delete; tag keys parallel-tag → policy swap → remove old. REQ-161, REQ-162. Depends on P2 (env var dual-read + nova_tagging.py warn mode must land first). - **Wave 4 (P4):** AWS resource names — staged terraform migration. REQ-163. Depends on P3 (tag keys nova:* enforced hard before resource recreation; nova_tagging.py hard mode). - **Wave 5 (P5):** final-review-ship — remove dual-read fallback, review, audit, milestone ship. REQ-164. Depends on P1–P4. ## Execution approach Each phase: EXECUTE (persona-assigned task groups) → VERIFY (4 layers + regression gate stays 16/16) → SHIP (patch tag on v1.14.x line). Phase boundary checkpoint resets context. The execute workflow reads this PLAN.md + ROADMAP.md §v1.15 + PERSONAS.md §v1.15 for task decomposition. **Binding constraint (capability gate):** the regression gate (CAP-001..CAP-016, `scripts/run_regression.sh`) MUST stay 16/16 Verified throughout the rebrand. Each phase updates test fixtures that reference `ACDL`/`acdl` so the gate stays green. No capability is added, removed, or reclassified — the rebrand is nomenclature + identifiers, not behavior. --- ## Wave 1 — Docs / Decks / Prose (P1) ### P1 — docs-decks-prose (REQ-155, REQ-156, REQ-157) **Persona:** lead-developer **Territory:** `README.md`, `docs/**`, `.ciagent/*.md`, deck `.md`/`-marp.md`/`-talking-points.md`/`.html`, `docs/presentations/assets/mmd/*.mmd` (+ PNG re-export), `pyproject.toml`, `schemas/*.schema.json` `$id` (D-110), `docs/NOVA_MIGRATION.md` (NEW), `.github/workflows/release.yml` title, `.gitea/workflows/release.yml` (if present), `modules/STANDARDS.md`, `contracts/**` prose **Tasks:** 1. **Prose rebrand (REQ-155).** Find/replace across all docs + .ciagent markdown: `ACDL` → `Nova`, `Agentic Cloud Delivery Platform` → `Nova` (full phrase). Preserve historical narrative (e.g. "formerly ACDL" in any changelog-style section is acceptable; otherwise full swap). Update `pyproject.toml` `name` → `nova`, `description` → Nova. Update `release.yml` release-title prefix `ACDL ` → `Nova `. Update illustrative URLs in docs: `github.com/acdl/...` → `github.com/nova/...`, `git.cloudinit.dev/continuous-intelligence/acdl*` → `.../nova*` (prose only; config.json `release.gitea.repo` stays `acdl` per D-105). 2. **Schema $id rebrand (D-110, REQ-155).** Update `$id` in all `schemas/*.schema.json` + `schemas/tagging-standard.json`: `https://acdl.cloudinit.dev/schemas/...` → `https://nova.cloudinit.dev/schemas/...`. Update test fixtures that assert the `$id` value. 3. **Deck + mermaid rebrand (REQ-156).** Edit both deck markdown sources (`docs/presentations/how-the-platform-works.md`, `the-developer-experience.md` + their `-marp.md` + `-talking-points.md` variants): `ACDL` → `Nova` in slide content + mermaid cluster labels (`["ACDL — infrastructure only"]` → `["Nova — infrastructure only"]`). Edit the 5 `.mmd` sources (`docs/presentations/assets/mmd/*.mmd`): `ACDL` → `Nova`. Re-export the PNG diagrams from the edited `.mmd` sources so the committed PNGs match the new labels (use the deck README's documented process: mmdc CLI or the render script). 4. **Nova tagline insertion (REQ-157).** Add the tagline "The New Dawn of DevSecOps — security as a seamless enabler of fast deployments" to: the README header (below the title), both deck title slides (as the subtitle, replacing "Agentic Cloud Delivery Platform"), and `docs/vision.md` (top of the Vision section). Retain the existing "North Star" / "consumers declare intent" framing — do NOT remove it (D-106). 5. **Consumer migration guide (REQ-155/160).** Create `docs/NOVA_MIGRATION.md` announcing the 5 breaking changes coming in P2–P4: (a) `.acdl/contract.yml` → `.nova/contract.yml` (P2); (b) `ACDL_*` env vars → `NOVA_*` (P2, dual-read fallback); (c) SSM path `/acdl/` → `/nova/` (P3); (d) AWS tag keys `acdl:*` → `nova:*` (P3); (e) AWS resource names `acdl-*` → `nova-*` (P4, maintenance window). Include the dual-read fallback window (P2–P4) + the cutoff (P5 removes fallback). 6. **HTML re-render (REQ-156).** Re-render both deck HTML files from the updated `-marp.md` sources (self-contained, base64 images, S&P theme unchanged per D-107). Commit the re-rendered HTML. 7. **Regress gate.** `bash scripts/run_regression.sh` — expect 16/16 Verified (fixtures referencing `ACDL`/`acdl` in paths are updated in P2; P1 only touches prose/decks/schema-$id, so the gate should stay green. If a test asserts an `ACDL` string in a doc it reads, update the assertion to `Nova`). --- ## Wave 2 — Code / Env Vars / Consumer Path (P2) ### P2 — code-envvars-consumer-path (REQ-158, REQ-159, REQ-160) **Persona:** backend-engineer (lead) + lead-developer (docs/runbook) **Territory:** `core/env.py` (NEW), `core/*.py`, `scripts/*.py` + `*.sh`, `adapters/**`, `tests/**`, `.gitea/workflows/**` + `.github/workflows/**`, `.env` + `.env.secrets` (key rename), `schemas/tagging-standard.json`, `adapters/terraform/policy/custom_rules/acdl_tagging.py` → `nova_tagging.py` **Tasks:** 1. **Dual-read env helper (D-108, REQ-159).** Create `core/env.py` with `get_env(name, default=None)` that reads `NOVA_` then falls back to `ACDL_`, returning `default` if neither. Add unit tests in `tests/test_env_helper.py` covering: both set (NOVA wins), only NOVA set, only ACDL set (fallback), neither set (default). 2. **Env var rename (REQ-159).** Migrate all 21 `ACDL_*` env var references → `NOVA_*` across `core/*.py`, `scripts/*.py` + `*.sh`, `adapters/**`, `tests/**`, `.gitea/workflows/**`, `.github/workflows/**`. Use the `core/env.py` helper at Python call sites (replace `os.environ.get("ACDL_X")` → `env.get_env("X")`); for shell scripts, use `${NOVA_X:-$ACDL_X}` dual-read inline. Rename keys in `.env` + `.env.secrets` (KEY names only — VALUES/secret material stay). Leave a comment in `.env.secrets` noting the legacy `ACDL_*` keys are the dual-read fallback source until P5. **G-106 binding:** the `.env.secrets` direct-read paths (`scripts/run_platform.sh:288-289` `export AWS_ACCESS_KEY_ID="$ACDL_AWS_ACCESS_KEY_ID"` + `core/regression_verify.py:309-312` `if k == "ACDL_AWS_ACCESS_KEY_ID"`) bypass the helper and MUST be updated to dual-read `NOVA_*` first, `ACDL_*` fallback (shell: `${NOVA_AWS_ACCESS_KEY_ID:-$ACDL_AWS_ACCESS_KEY_ID}`; Python: match `k == "NOVA_AWS_ACCESS_KEY_ID" or k == "ACDL_AWS_ACCESS_KEY_ID"`) — otherwise AWS creds vanish mid-rename and CAP-013/014/015 fail. 3. **Gitea secrets rotation + workflow refs (G-108 binding, REQ-159).** Use the Gitea API (`scripts/rotate_spike_key.sh` pattern or a new `scripts/rename_gitea_secrets.py`) to create `NOVA_*` secrets mirroring the `ACDL_*` values (idempotent + retry-on-failure), then (after P5) delete the old `ACDL_*` secrets. For P2, just create the `NOVA_*` aliases; deletion is P5. **G-108 binding:** when `NOVA_*` secrets are created, the CI workflow `secrets:` references (`.gitea/workflows/deploy.yml:105,107,108,148`, `.gitea/workflows/modules-lifecycle.yml:63,64,103,104,111,112,117,118,123,124,161,162,169,170`, `.github/workflows/*` mirrored) MUST be updated from `secrets.ACDL_*` → `secrets.NOVA_*` in the SAME phase, with graceful degrade + the `acdl-deploy-` role name in deploy.yml:105 → `nova-deploy-` (P4 renames the IAM role). Until both secrets + refs are updated, CI breaks — this is a hard gate, not a silent skip. 4. **Checkov rule rename (D-109 warn mode, REQ-158).** Rename `adapters/terraform/policy/custom_rules/acdl_tagging.py` → `nova_tagging.py`. Update the Checkov registration in `schemas/tagging-standard.json` (line 5 + the `description`) and the adapter config (`adapters/terraform/policy/checkov_adapter.py`). The rule enforces `nova:*` tag keys BUT in **warn mode** for P2 (existing resources still carry `acdl:*` until P3) — log a warning, don't fail the check. Update `ACDL_TAG_NAMING` → `NOVA_TAG_NAMING`. 5. **Consumer path rename (REQ-160).** Rename the consumer on-disk contract path `.acdl/contract.yml` → `.nova/contract.yml` across: `core/contract_resolver.py` (any default path), the deploy workflow `default:` field (`.gitea/workflows/deploy.yml` + `.github/workflows/deploy.yml` line 54), `schemas/contract.schema.json` description, `tests/test_pipeline_contract.py:313` assertion, and consumer docs (`docs/consumer-guide.md`, `docs/modules/index.md`). Also `.acdl/static-assets.*.yml` → `.nova/...` + `.acdl/contract.yaml` → `.nova/contract.yaml`. 6. **Test fixture update (binding).** Update all test fixtures in `tests/**` that reference `ACDL`/`acdl` (env var names, paths, table names, tag keys) to the new `NOVA`/`nova` values — EXCEPT fixtures that assert the dual-read fallback behavior (those keep `ACDL_*` as the fallback source). `pytest` must pass. 7. **Regress gate.** `bash scripts/run_regression.sh` — 16/16 Verified. --- ## Wave 3 — SSM Path + Tag Keys (P3) ### P3 — ssm-tagkeys (REQ-161, REQ-162) **Persona:** data-engineer (lead) + backend-engineer (readers) **Territory:** `core/output_publisher.py`, `core/contract_resolver.py`, `scripts/migrate_ssm_paths.py` (NEW), `terraform/**` (tag keys), `adapters/terraform/policy/custom_rules/nova_tagging.py` (hard mode), ABAC session-policy terraform **Tasks:** 1. **SSM path migration (REQ-161).** Update `core/output_publisher.py`: the SSM parameter path prefix `/acdl/{env}/{contractId}/{output}` → `/nova/{env}/{contractId}/{output}`. Update `core/contract_resolver.py` SSM reads. Update consumer docs. Create `scripts/migrate_ssm_paths.py` that: (a) lists `/acdl/...` parameters, (b) copies each to `/nova/...` (same value/type), (c) verifies the copy, (d) deletes the old `/acdl/...` parameters. The script is idempotent + dry-run by default (`--apply` to execute). 2. **Tag keys: parallel-tag (REQ-162).** Update terraform tagging (`terraform/platform/main.tf`, `terraform/microservice/main.tf`, `terraform/ci-vpc/main.tf`, `modules/l1/*/terraform/main.tf`, `modules/l2/*/composition.json` tag defaults) to emit **both** `nova:*` and `acdl:*` tag keys during P3 (parallel-tag period). The `acdl:cost-center` default `acdl-default` → `nova-default` for the `nova:cost-center` key (keep `acdl-default` on the `acdl:cost-center` key during the parallel period). 3. **Tag keys: ABAC policy swap (REQ-162).** Update the ABAC session policies (the deploy role's inline policy in `terraform/platform/main.tf` + `terraform/bootstrap/**`) to match `nova:*` tags (the `StringEquals`/`Resource` tag conditions reference `nova:owner`/`nova:environment`/etc.). Keep the `acdl:*` match as a secondary condition during the parallel period so neither old nor new consumers break. 4. **Checkov rule: hard mode (D-109, REQ-162).** Update `nova_tagging.py` from warn → hard mode: enforce `nova:*` tag keys (hard fail on missing `nova:*` or presence of `acdl:*`-only tags). Update `schemas/tagging-standard.json` tag keys → `nova:*`. 5. **Tag keys: remove old (REQ-162).** Once the parallel-tag period is verified (terraform validate passes; the ABAC policy matches `nova:*`), remove the `acdl:*` tag emissions from terraform. (Live removal of `acdl:*` tags from existing AWS resources is a documentation/runbook step — the terraform `null_resource` or a script `scripts/untag_acdl_keys.py` can do it with live AWS access; without live access, this is documented in the P4 runbook as a runtime step.) 6. **Test fixture + regress gate.** Update test fixtures asserting `acdl:*` tag keys → `nova:*`. `pytest` passes; `bash scripts/run_regression.sh` — 16/16 Verified. --- ## Wave 4 — AWS Resource Name Migration (P4) ### P4 — aws-resource-migration (REQ-163) **Persona:** data-engineer (lead) + lead-developer (runbook) **Territory:** `terraform/platform/main.tf`, `terraform/microservice/main.tf`, `terraform/ci-vpc/main.tf`, `terraform/bootstrap/**`, `modules/l1/alb/instance.json`, `scripts/migrate_dynamodb_data.py` (NEW), `docs/NOVA_AWS_MIGRATION.md` (NEW runbook), `core/lambda/contract_ingestor.py` (default table names, D-111) **Tasks:** 1. **Runbook (REQ-163).** Create `docs/NOVA_AWS_MIGRATION.md` — the maintenance-window + rollback runbook. Documents each resource rename, the migration command, the verification step, and the rollback procedure. Orders the migration: KMS alias (cheap) → SNS/SG (recreate) → Lambda (recreate) → DynamoDB (scan+copy) → ECR (re-push) → IAM (re-bootstrap) → state bucket (`-migrate-state`) → ALB (recreate, brief downtime, last). 2. **Terraform resource names (REQ-163).** Rename all `acdl-*` resource names/labels → `nova-*` in `terraform/platform/main.tf`, `terraform/microservice/main.tf`, `terraform/ci-vpc/main.tf`, `terraform/bootstrap/**`, `modules/l1/alb/instance.json`: - DynamoDB: `acdl-contracts` → `nova-contracts`, `acdl-change-requests` → `nova-change-requests` - Secrets Manager: `acdl/github-token` → `nova/github-token` - Lambda: `acdl-contract-ingestor` (role/policy/function) → `nova-contract-ingestor` - SNS: `acdl-sod-halt` → `nova-sod-halt` - SG: `acdl-ecs-sg` → `nova-ecs-sg` - KMS: `alias/acdl-platform` → `alias/nova-platform` - ECS: `acdl-microservice` (cluster/service/task/role) → `nova-microservice` - ECR: `acdl-microservice` → `nova-microservice` - IAM: `acdl-spike-runner` (+policy) → `nova-spike-runner` - S3 state bucket: `acdl-tfstate-581513795199-us-east-1` → `nova-tfstate-581513795199-us-east-1` - ALB: `acdl-alb` → `nova-alb` 3. **Lambda default table names (D-111, REQ-163).** Update `core/lambda/contract_ingestor.py` default env-var values: `CONTRACTS_TABLE` default `acdl-contracts` → `nova-contracts`, `CHANGE_REQUESTS_TABLE` `acdl-change-requests` → `nova-change-requests`, `GITHUB_TOKEN_SECRET_ID` `acdl/github-token` → `nova/github-token`, `PLATFORM_REPO` `acdl/acdl` → `nova/acdl` (prose consistency; real repo unchanged). 4. **State bucket migration (REQ-63).** Update the terraform backend config (`terraform/{platform,microservice,ci-vpc}/terraform.tf` + `bootstrap/create_state_backend.py` + `bootstrap/.bootstrap_state.json`) to the new `nova-tfstate-...` bucket. Document the `terraform init -migrate-state` command in the runbook (back up the state JSON first). 5. **DynamoDB data-migration script (REQ-163).** Create `scripts/migrate_dynamodb_data.py` — scan+copy all items from `acdl-contracts` → `nova-contracts` + `acdl-change-requests` → `nova-change-requests`. Verify row counts match. Keep old tables until verified (deletion is a manual post-verification step, documented in the runbook). 6. **terraform validate + regress gate.** `terraform validate` passes for platform/microservice/ci-vpc. `grep -rn "acdl-" terraform/` returns 0 hits. `pytest` passes; `bash scripts/run_regression.sh` — 16/16 Verified. --- ## Wave 5 — Final Review + Ship (P5) ### P5 — final-review-ship (REQ-164) **Persona:** lead-developer (lead) + all active (review) **Territory:** `.ciagent/**`, `core/env.py` (remove fallback), `nova_tagging.py` (hard-fail `acdl:*`), review + audit **Tasks:** 1. **Remove dual-read fallback (REQ-164).** Update `core/env.py` `get_env()` to read `NOVA_*` only (remove the `ACDL_*` fallback). Update shell scripts to `${NOVA_X}` only (remove `:-$ACDL_X`). Update `nova_tagging.py` to hard-fail on any `acdl:*` tag key (no warn). Delete the `ACDL_*` secrets from Gitea (the `NOVA_*` aliases created in P2 are now the only source). Remove the legacy comment from `.env.secrets`. 2. **Multi-persona review.** Run `ciagent-review` across all v1.15 phases (P1–P4 changes). Auto-apply P0 fixes; flag P1+ for post-hoc. If P1+ found, fix in this phase. 3. **Audit.** Run `ciagent-audit` — reconstruction test (git log matches `.ciagent/` files), file discipline, branch hygiene, commit discipline. If critical issues, fix in this phase. 4. **Finalize consumer migration guide (REQ-164).** Update `docs/NOVA_MIGRATION.md` to mark the migration complete (cutoff passed; `ACDL_*` fallback removed). 5. **Complete milestone.** Update `REQUIREMENTS.md` (REQ-155..164 → complete), `ROADMAP.md` (v1.15 complete), `PROJECT.md`. Tag `v1.14.5` (IS the milestone release). Merge `milestone/v1.15-nova` → `main`. Create Gitea release with full milestone summary. --- ## Success Criteria (milestone gate) 1. All 10 REQ-155..REQ-164 marked complete in REQUIREMENTS.md. 2. Review: 0 new P0; all P1+ flagged or auto-fixed. 3. Audit: clean; reconstruction test passes. 4. Regression gate (D-091) 16/16 Verified throughout + at milestone complete. 5. `grep -rni "ACDL\|Agentic Cloud Delivery" README.md docs/ .ciagent/*.md` returns 0 hits (except explicit "formerly ACDL" historical notes). 6. `grep -rn "ACDL_" core/ scripts/ adapters/ tests/ .gitea/ .github/` returns 0 hits (except the removed-fallback test in P5 that asserts the fallback is gone). 7. `grep -rn "acdl-" terraform/` returns 0 hits. 8. `pytest` passes; `run_ci.sh` exits 0; `terraform validate` passes for platform/microservice/ci-vpc. 9. Tag `v1.15.4` created (IS the milestone release, G-104); milestone merged to main.