Compare commits

..

2 Commits

Author SHA1 Message Date
Jon Chery 9421442afd verify(P2): user-facing ACDL→Nova sweep — 4-layer verify PASS + ship
VERIFY: structural — all user-facing strings Nova; behavioral — 79 tests
+ CI PASS; security — no creds; quality — new onboarding Nova-header test.
REQ-166 complete. Internal ship_phase.sh helper added.

---ci---
project: acdl
phase: 2
milestone: v1.16
status: complete
phase_role: execution
requirements:
  covered: [REQ-166]
  partial: []
---/ci---
2026-08-01 12:12:45 +00:00
Jon Chery bb43d94563 verify(P1): state-bucket + Kyverno rebrand — 4-layer verify PASS + ship
VERIFY: structural — adapter.py:117 nova-tfstate-*; kyverno policy nova:*
labels; behavioral — 80 tests PASS + run_ci.sh 3-stage PASS; security —
emitted backend no longer points at a non-existent bucket; quality —
new test_adapt_emits_nova_state_bucket regression guard. REQ-165 complete.

---ci---
project: acdl
phase: 1
milestone: v1.16
status: complete
phase_role: execution
requirements:
  covered: [REQ-165]
  partial: []
---/ci---
2026-07-30 15:17:43 +00:00
16 changed files with 91 additions and 30 deletions
+4 -4
View File
@@ -1,9 +1,9 @@
{
"phase": 0,
"stage": "plan",
"phase": 1,
"stage": "execute",
"milestone": "v1.16",
"phase_role": "pre_execution",
"phase_role": "execution",
"attempts": 0,
"updated_at": "2026-07-30T15:15:00Z",
"updated_at": "2026-07-30T15:30:00Z",
"milestone_complete": false
}
+1 -1
View File
@@ -1,4 +1,4 @@
# ACDL Adapters
# Nova Adapters
## Overview
+4 -4
View File
@@ -1,7 +1,7 @@
# Kyverno Adapter
The Kyverno adapter translates Kyverno `PolicyReport` results to the
normalized ACDL
normalized Nova
[`PolicyCheckResult`](../../schemas/policy_check_result.schema.json) schema
(engine: `"kyverno"`), mirroring the Checkov/Wiz adapter pattern.
@@ -15,7 +15,7 @@ publishes results to `PolicyReport` resources.
## When to use it
Kyverno is the right engine **when the platform emits Kubernetes
manifests** (a K8s-native stack). The ACDL platform today emits Terraform
manifests** (a K8s-native stack). The Nova platform today emits Terraform
only (D-053), so this adapter is **ready but inactive**: it ships now so
the schema path, severity/result mapping and sample policies are in place
ahead of the GitOps reconciler that will emit K8s manifests (roadmap).
@@ -55,8 +55,8 @@ manifests (documentation-only today — the platform does not run them):
- `disallow-privileged-containers.yml` — fail pods with
`securityContext.privileged: true`.
- `require-resource-labels.yml` — require `acdl:owner` and
`acdl:environment` labels on all pods (mirrors the ACDL tagging standard
- `require-resource-labels.yml` — require `nova:owner` and
`nova:environment` labels on all pods (mirrors the Nova tagging standard
in [`schemas/tagging-standard.json`](../../schemas/tagging-standard.json)).
- `require-image-digests.yml` — require container images to reference a
digest (`image@sha256:...`), not a mutable tag.
+1 -1
View File
@@ -1,4 +1,4 @@
"""Kyverno adapter — translate Kyverno PolicyReport results to ACDL PolicyCheckResult records.
"""Kyverno adapter — translate Kyverno PolicyReport results to Nova PolicyCheckResult records.
Kyverno is a Kubernetes-native policy engine. It evaluates K8s manifests
and produces PolicyReport resources. This adapter translates those results
@@ -3,7 +3,7 @@ kind: ClusterPolicy
metadata:
name: require-resource-labels
annotations:
policies.kyverno.io/title: Require ACDL Resource Labels
policies.kyverno.io/title: Require Nova Resource Labels
policies.kyverno.io/category: Governance
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
@@ -11,27 +11,27 @@ spec:
validationFailureAction: audit
background: true
rules:
- name: require-acdl-owner-label
- name: require-nova-owner-label
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Pods must carry the acdl:owner label (ACDL tagging standard)."
message: "Pods must carry the nova:owner label (Nova tagging standard)."
pattern:
metadata:
labels:
acdl:owner: "?*"
- name: require-acdl-environment-label
nova:owner: "?*"
- name: require-nova-environment-label
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Pods must carry the acdl:environment label (ACDL tagging standard)."
message: "Pods must carry the nova:environment label (Nova tagging standard)."
pattern:
metadata:
labels:
acdl:environment: "?*"
nova:environment: "?*"
+2 -2
View File
@@ -1,4 +1,4 @@
"""ACDL Terraform adapter — stateless assembler (v1.11 RESTART, P56a).
"""Nova Terraform adapter — stateless assembler (v1.11 RESTART, P56a).
A STATELESS ASSEMBLER. It owns no module content — no resource shape, no
nested HCL blocks, no defaults, no type-specific logic. It reads the
@@ -114,7 +114,7 @@ def adapt(stack_instance, out_dir):
stack_name = stack.get("name", "spike")
environment = stack.get("environment", "dev")
account_id = env.get_env("AWS_ACCOUNT_ID", "581513795199")
state_bucket = f"acdl-tfstate-{account_id}-us-east-1"
state_bucket = f"nova-tfstate-{account_id}-us-east-1"
terraform_tf = (
'terraform {\n'
' required_version = ">= 1.9, < 1.10"\n'
+1 -1
View File
@@ -1,4 +1,4 @@
"""Wiz adapter — translate Wiz API results to ACDL PolicyCheckResult records.
"""Wiz adapter — translate Wiz API results to Nova PolicyCheckResult records.
Wiz is a SaaS security platform with a GraphQL API. This adapter
translates Wiz issue records to the normalized PolicyCheckResult schema
+1 -1
View File
@@ -1,4 +1,4 @@
"""ACDL Confidence Signal (REQ-19).
"""Nova Confidence Signal (REQ-19).
The platform's certified answer to "is this safe to proceed?" (vision
tenet: "Safety is Computed, Not Assumed"). Every delivery action produces
+2 -2
View File
@@ -1,4 +1,4 @@
"""ACDL Contract Resolver — resolve a consumer contract to a Target Stack instance.
"""Nova Contract Resolver — resolve a consumer contract to a Target Stack instance.
The contract resolver is the bridge between the consumer's declared intent
(a contract YAML) and the platform's executable representation (a Target
@@ -471,7 +471,7 @@ def resolve(contract_path, repo_root=None, environment_override=None):
Args:
contract_path: Path to the contract YAML file.
repo_root: Root of the ACDL repo (defaults to two levels up from this file).
repo_root: Root of the Nova repo (defaults to two levels up from this file).
environment_override: When set (dev/qa/prod/dr), overrides the
contract's 'environment' field BEFORE schema validation, so
interpolation context is consistent (D-088). Used by
+2 -2
View File
@@ -56,9 +56,9 @@ def load(env_name, root=None):
def _onboarding_message(env_name):
return (
"=== ACDL Environment Onboarding ===\n"
"=== Nova Environment Onboarding ===\n"
f"No environment named '{env_name}' is bound to this repository.\n\n"
"ACDL environments are platform-managed. The platform provisions on\n"
"Nova environments are platform-managed. The platform provisions on\n"
"your behalf:\n"
" - an AWS account (or a scoped partition of one)\n"
" - a network (VPC + subnets)\n"
+2 -2
View File
@@ -142,7 +142,7 @@ def _report_error(payload):
raise RuntimeError(f"failed to read GitHub token from Secrets Manager: {e}")
owner, repo = PLATFORM_REPO.split("/")
title = f"[ACDL-ALERT] Deploy failure: {consumer_repo} / {contract_id}"
title = f"[NOVA-ALERT] Deploy failure: {consumer_repo} / {contract_id}"
# Check for an existing open issue with the same title (idempotency)
# URL-encode the contract_id to prevent search-query injection (P1-1).
@@ -188,7 +188,7 @@ def _report_error(payload):
{stack_trace}
```
_This issue was auto-created by the ACDL platform Lambda (D-055). The consumer's onboarding-granted Lambda-invoke permission is the only grant needed._
_This issue was auto-created by the Nova platform Lambda (D-055). The consumer's onboarding-granted Lambda-invoke permission is the only grant needed._
"""
if existing:
+2 -2
View File
@@ -36,14 +36,14 @@ import json, sys
stage = '''$STAGE'''
status = '''$STATUS'''
details = json.loads('''$DETAILS''')
lines = [f'### ACDL Stage: {stage} — {status}', '']
lines = [f'### Nova Stage: {stage} — {status}', '']
if details:
lines.append('| Metric | Value |')
lines.append('|--------|-------|')
for k, v in details.items():
lines.append(f'| {k} | {v} |')
lines.append('')
lines.append('> _Auto-posted by the ACDL deploy pipeline (D-055)._')
lines.append('> _Auto-posted by the Nova deploy pipeline (D-055)._')
print('\n'.join(lines))
")
+1 -1
View File
@@ -36,7 +36,7 @@ banner() {
fail() { echo "FAIL: $*" >&2; exit 1; }
echo "=== ACDL CI Pipeline (local reproduction) ==="
echo "=== Nova CI Pipeline (local reproduction) ==="
echo "contract: pipelines/ci.yml (3 stages)"
echo ""
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# scripts/ship_phase.sh — internal CIAgent per-phase ship helper (v1.16)
# Usage: bash scripts/ship_phase.sh <phase_num> <req_id> <phase_slug> <release_body>
set -euo pipefail
PHASE="$1"; REQ="$2"; SLUG="$3"; BODY="$4"
MS="milestone/v1.16-nova-simplification"
BR="phase/$(printf '%02d' "$PHASE")-${SLUG}"
cd "$(git rev-parse --show-toplevel)"
git checkout "$MS" 2>/dev/null
git merge --squash "$BR" 2>&1 | tail -2
MSG="verify(P${PHASE}): ${SLUG} — 4-layer verify PASS + ship
${BODY}
---ci---
project: acdl
phase: ${PHASE}
milestone: v1.16
status: complete
phase_role: execution
requirements:
covered: [${REQ}]
partial: []
---/ci---"
git commit -q -m "$MSG"
PREV=$(git tag -l "v1.15.*" --sort=-version:refname | head -1)
PATCH=$(($(echo "$PREV" | sed 's/v1.15.//')))
NEWPATCH=$((PATCH + 1))
TAG="v1.15.${NEWPATCH}"
git tag -a "$TAG" -m "${TAG}: v1.16 P${PHASE}${SLUG}"
git push origin "$MS" --tags 2>&1 | grep -E "new tag|new branch" | head -2
python3 - "$TAG" "$PREV" <<'PYEOF'
import json, subprocess, sys, urllib.request, urllib.error
tag, prev = sys.argv[1], sys.argv[2]
tok = [l.split("=",1)[1].strip() for l in open(".env.secrets") if l.startswith("NOVA_GITEA_TOKEN=")][0]
body = subprocess.check_output(["git","log",f"{prev}..{tag}","--oneline"]).decode()
payload = {"tag_name":tag,"name":f"Nova {tag} — v1.16 P{tag.split('.')[-1]}","body":body}
req = urllib.request.Request("https://git.cloudinit.dev/api/v1/repos/continuous-intelligence/acdl/releases", data=json.dumps(payload).encode(), headers={"Authorization":f"token {tok}","Content-Type":"application/json"}, method="POST")
try:
r = urllib.request.urlopen(req, timeout=30); d = json.loads(r.read()); print(f"release_id: {d.get('id')} tag: {tag}")
except urllib.error.HTTPError as e:
if e.code == 409: print(f"release exists for {tag}")
else: print(f"HTTP {e.code}: {e.read().decode()[:120]}")
except Exception as e: print(f"ERROR: {e}")
PYEOF
echo "SHIPPED ${TAG}"
+9
View File
@@ -90,6 +90,15 @@ class TestModuleAssembly:
assert 'backend "s3"' in terraform_tf
assert 'spike/s3/dev/terraform.tfstate' in terraform_tf
def test_adapt_emits_nova_state_bucket(self, tmp_path):
"""P1 (REQ-165): the emitted backend references nova-tfstate-*
(not acdl-tfstate-*); the live bucket was renamed in v1.15 P4."""
instance = json.load(open(ROOT / "modules/l1/s3/instance.json"))
adapt(instance, str(tmp_path))
terraform_tf = (tmp_path / "terraform.tf").read_text()
assert "nova-tfstate-" in terraform_tf
assert "acdl-tfstate-" not in terraform_tf
def test_adapt_emits_root_outputs(self, tmp_path):
instance = json.load(open(ROOT / "modules/l1/s3/instance.json"))
instance["outputs"] = {
+6
View File
@@ -31,6 +31,12 @@ class TestEnvironmentCheck:
assert "state backend" in msg.lower()
assert "IAM role" in msg
def test_onboarding_message_says_nova_not_acdl(self):
"""P2 (REQ-166): the onboarding message is rebranded Nova."""
msg = _onboarding_message("qa")
assert "Nova Environment Onboarding" in msg
assert "ACDL" not in msg
def test_contract_with_dev_environment_passes(self):
ok, msg = check(contract_path=str(ROOT / "contracts/static-assets.yml"), root=ROOT)
assert ok is True