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---
This commit is contained in:
Jon Chery
2026-08-01 12:12:45 +00:00
parent bb43d94563
commit 9421442afd
13 changed files with 68 additions and 16 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
# ACDL Adapters # Nova Adapters
## Overview ## Overview
+2 -2
View File
@@ -1,7 +1,7 @@
# Kyverno Adapter # Kyverno Adapter
The Kyverno adapter translates Kyverno `PolicyReport` results to the The Kyverno adapter translates Kyverno `PolicyReport` results to the
normalized ACDL normalized Nova
[`PolicyCheckResult`](../../schemas/policy_check_result.schema.json) schema [`PolicyCheckResult`](../../schemas/policy_check_result.schema.json) schema
(engine: `"kyverno"`), mirroring the Checkov/Wiz adapter pattern. (engine: `"kyverno"`), mirroring the Checkov/Wiz adapter pattern.
@@ -15,7 +15,7 @@ publishes results to `PolicyReport` resources.
## When to use it ## When to use it
Kyverno is the right engine **when the platform emits Kubernetes 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 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 the schema path, severity/result mapping and sample policies are in place
ahead of the GitOps reconciler that will emit K8s manifests (roadmap). ahead of the GitOps reconciler that will emit K8s manifests (roadmap).
+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 Kyverno is a Kubernetes-native policy engine. It evaluates K8s manifests
and produces PolicyReport resources. This adapter translates those results and produces PolicyReport resources. This adapter translates those results
+1 -1
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 A STATELESS ASSEMBLER. It owns no module content — no resource shape, no
nested HCL blocks, no defaults, no type-specific logic. It reads the nested HCL blocks, no defaults, no type-specific logic. It reads the
+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 Wiz is a SaaS security platform with a GraphQL API. This adapter
translates Wiz issue records to the normalized PolicyCheckResult schema 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 The platform's certified answer to "is this safe to proceed?" (vision
tenet: "Safety is Computed, Not Assumed"). Every delivery action produces 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 The contract resolver is the bridge between the consumer's declared intent
(a contract YAML) and the platform's executable representation (a Target (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: Args:
contract_path: Path to the contract YAML file. 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 environment_override: When set (dev/qa/prod/dr), overrides the
contract's 'environment' field BEFORE schema validation, so contract's 'environment' field BEFORE schema validation, so
interpolation context is consistent (D-088). Used by 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): def _onboarding_message(env_name):
return ( return (
"=== ACDL Environment Onboarding ===\n" "=== Nova Environment Onboarding ===\n"
f"No environment named '{env_name}' is bound to this repository.\n\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" "your behalf:\n"
" - an AWS account (or a scoped partition of one)\n" " - an AWS account (or a scoped partition of one)\n"
" - a network (VPC + subnets)\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}") raise RuntimeError(f"failed to read GitHub token from Secrets Manager: {e}")
owner, repo = PLATFORM_REPO.split("/") 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) # Check for an existing open issue with the same title (idempotency)
# URL-encode the contract_id to prevent search-query injection (P1-1). # URL-encode the contract_id to prevent search-query injection (P1-1).
@@ -188,7 +188,7 @@ def _report_error(payload):
{stack_trace} {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: if existing:
+2 -2
View File
@@ -36,14 +36,14 @@ import json, sys
stage = '''$STAGE''' stage = '''$STAGE'''
status = '''$STATUS''' status = '''$STATUS'''
details = json.loads('''$DETAILS''') details = json.loads('''$DETAILS''')
lines = [f'### ACDL Stage: {stage} — {status}', ''] lines = [f'### Nova Stage: {stage} — {status}', '']
if details: if details:
lines.append('| Metric | Value |') lines.append('| Metric | Value |')
lines.append('|--------|-------|') lines.append('|--------|-------|')
for k, v in details.items(): for k, v in details.items():
lines.append(f'| {k} | {v} |') lines.append(f'| {k} | {v} |')
lines.append('') 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)) print('\n'.join(lines))
") ")
+1 -1
View File
@@ -36,7 +36,7 @@ banner() {
fail() { echo "FAIL: $*" >&2; exit 1; } 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 "contract: pipelines/ci.yml (3 stages)"
echo "" 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}"
+6
View File
@@ -31,6 +31,12 @@ class TestEnvironmentCheck:
assert "state backend" in msg.lower() assert "state backend" in msg.lower()
assert "IAM role" in msg 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): def test_contract_with_dev_environment_passes(self):
ok, msg = check(contract_path=str(ROOT / "contracts/static-assets.yml"), root=ROOT) ok, msg = check(contract_path=str(ROOT / "contracts/static-assets.yml"), root=ROOT)
assert ok is True assert ok is True