Compare commits

...

2 Commits

Author SHA1 Message Date
Jon Chery 93ae9e4a39 verify(P7): contract-resolver-envloader-and-kind — 4-layer verify PASS + ship
VERIFY: structural — envloader dedup + kind field; behavioral — 49 tests + CI PASS; quality — fragile is_l2 heuristic replaced.

---ci---
project: acdl
phase: 7
milestone: v1.16
status: complete
phase_role: execution
requirements:
  covered: [REQ-171]
  partial: []
---/ci---
2026-08-01 12:38:56 +00:00
Jon Chery d3179fff37 verify(P6): run-platform-deadcode-and-hitl-fn — 4-layer verify PASS + ship
VERIFY: structural — HITL fn extracted + deadcode/config; behavioral — syntax clean + CI PASS; quality — ~14 lines saved.

---ci---
project: acdl
phase: 6
milestone: v1.16
status: complete
phase_role: execution
requirements:
  covered: [REQ-170]
  partial: []
---/ci---
2026-08-01 12:36:40 +00:00
3 changed files with 78 additions and 90 deletions
+14 -24
View File
@@ -50,22 +50,13 @@ from core import env
def _load_env(env_name, repo_root):
"""Load the environment onboarding JSON for env_name.
Mirrors core.environment_check.load() but is self-contained so the
resolver works both as a package import (`from core.contract_resolver
import resolve`) and as a script (`python3 core/contract_resolver.py`).
Emits a stderr warning when account_id is the placeholder and env != dev.
P7 (REQ-171): delegates to core.environment_check.load() (dedup —
the two were verbatim duplicates). The environment_check module is
in the same core/ package, so the import works both as a package
import and as a script (`python3 core/contract_resolver.py`).
"""
env_file = os.path.join(repo_root, "core", "environments", f"{env_name}.json")
if not os.path.isfile(env_file):
raise FileNotFoundError(f"no environment file for '{env_name}' at {env_file}")
env = _load_json(env_file)
if env.get("account_id") == "000000000000" and env_name != "dev":
sys.stderr.write(
f"WARNING: environment '{env_name}' has the placeholder account_id "
f"000000000000 — replace it with the real {env_name} account id "
f"before deploying (onboarding scaffold).\n"
)
return env
from core import environment_check
return environment_check.load(env_name, root=repo_root)
def _load_json(path):
@@ -534,10 +525,14 @@ def resolve(contract_path, repo_root=None, environment_override=None):
f"module '{module_name}' version '{version}' not found in registry")
module_inputs = module_entry.get("inputs", {})
# Determine if L1 or L2
# Determine if L1 or L2 — prefer the registry `kind` field (P7,
# REQ-171); fall back to the path heuristic for entries that
# predate the kind field.
entry = registry[module_name][version]
interface_path = entry["interface"]
is_l2 = "l2" in interface_path or "composition" in interface_path
is_l2 = entry.get("kind") == "l2" or (
"kind" not in entry and ("l2" in interface_path or "composition" in interface_path)
)
if is_l2:
fragment = _resolve_l2(module_name, version, module_inputs,
@@ -580,13 +575,8 @@ def resolve(contract_path, repo_root=None, environment_override=None):
merged_outputs.update(fragment.get("outputs", {}))
all_resources.extend(fragment["resources"])
# Determine stack kind: L2 if any module is L2 or if multi-module
if multi_module:
kind = "l2"
elif any_l2:
kind = "l2"
else:
kind = "l1"
# Determine stack kind: L2 if any module is L2 or if multi-module (P7)
kind = "l2" if (multi_module or any_l2) else "l1"
stack_instance = {
"version": "1.0.0",
+28 -14
View File
@@ -4,7 +4,8 @@
"interface": "modules/l1/s3/interface.json",
"terraform_dir": "modules/l1/s3/terraform",
"published_at": "2026-07-21T19:00:00Z",
"deprecated": false
"deprecated": false,
"kind": "l1"
}
},
"vpc": {
@@ -12,7 +13,8 @@
"interface": "modules/l1/vpc/interface.json",
"published_at": "2026-07-21T21:30:00Z",
"deprecated": false,
"terraform_dir": "modules/l1/vpc/terraform"
"terraform_dir": "modules/l1/vpc/terraform",
"kind": "l1"
}
},
"ecs-cluster": {
@@ -20,7 +22,8 @@
"interface": "modules/l1/ecs-cluster/interface.json",
"published_at": "2026-07-21T21:30:00Z",
"deprecated": false,
"terraform_dir": "modules/l1/ecs-cluster/terraform"
"terraform_dir": "modules/l1/ecs-cluster/terraform",
"kind": "l1"
}
},
"ecs-service": {
@@ -28,7 +31,8 @@
"interface": "modules/l1/ecs-service/interface.json",
"published_at": "2026-07-21T21:30:00Z",
"deprecated": false,
"terraform_dir": "modules/l1/ecs-service/terraform"
"terraform_dir": "modules/l1/ecs-service/terraform",
"kind": "l1"
}
},
"iam-role": {
@@ -36,7 +40,8 @@
"interface": "modules/l1/iam-role/interface.json",
"published_at": "2026-07-21T21:30:00Z",
"deprecated": false,
"terraform_dir": "modules/l1/iam-role/terraform"
"terraform_dir": "modules/l1/iam-role/terraform",
"kind": "l1"
}
},
"alb": {
@@ -44,7 +49,8 @@
"interface": "modules/l1/alb/interface.json",
"published_at": "2026-07-21T21:30:00Z",
"deprecated": false,
"terraform_dir": "modules/l1/alb/terraform"
"terraform_dir": "modules/l1/alb/terraform",
"kind": "l1"
}
},
"ecr": {
@@ -52,7 +58,8 @@
"interface": "modules/l1/ecr/interface.json",
"published_at": "2026-07-21T21:30:00Z",
"deprecated": false,
"terraform_dir": "modules/l1/ecr/terraform"
"terraform_dir": "modules/l1/ecr/terraform",
"kind": "l1"
}
},
"cloudfront": {
@@ -60,7 +67,8 @@
"interface": "modules/l1/cloudfront/interface.json",
"published_at": "2026-07-22T19:00:00Z",
"deprecated": false,
"terraform_dir": "modules/l1/cloudfront/terraform"
"terraform_dir": "modules/l1/cloudfront/terraform",
"kind": "l1"
}
},
"waf": {
@@ -68,7 +76,8 @@
"interface": "modules/l1/waf/interface.json",
"published_at": "2026-07-22T19:00:00Z",
"deprecated": false,
"terraform_dir": "modules/l1/waf/terraform"
"terraform_dir": "modules/l1/waf/terraform",
"kind": "l1"
}
},
"rds": {
@@ -76,7 +85,8 @@
"interface": "modules/l1/rds/interface.json",
"published_at": "2026-07-22T20:00:00Z",
"deprecated": false,
"terraform_dir": "modules/l1/rds/terraform"
"terraform_dir": "modules/l1/rds/terraform",
"kind": "l1"
}
},
"kms-key": {
@@ -84,7 +94,8 @@
"interface": "modules/l1/kms-key/interface.json",
"published_at": "2026-07-22T20:00",
"deprecated": false,
"terraform_dir": "modules/l1/kms-key/terraform"
"terraform_dir": "modules/l1/kms-key/terraform",
"kind": "l1"
}
},
"uptime": {
@@ -92,21 +103,24 @@
"interface": "modules/l1/uptime/interface.json",
"published_at": "2026-07-22T21:00",
"deprecated": false,
"terraform_dir": "modules/l1/uptime/terraform"
"terraform_dir": "modules/l1/uptime/terraform",
"kind": "l1"
}
},
"static-assets": {
"1.0.0": {
"interface": "modules/l2/static-assets/composition.json",
"published_at": "2026-07-22T15:00:00Z",
"deprecated": false
"deprecated": false,
"kind": "l2"
}
},
"microservice": {
"1.0.0": {
"interface": "modules/l2/microservice/composition.json",
"published_at": "2026-07-22T15:00:00Z",
"deprecated": false
"deprecated": false,
"kind": "l2"
}
}
}
+36 -52
View File
@@ -113,6 +113,38 @@ fi
fail() { echo "FAIL: $*" >&2; exit 1; }
# run_hitl_gate <contract_id> <resolved_env> <context>
# REQ-108: for qa/prod/dr, call hitl_gates.attest before apply. Dev skips.
# Extracted from the two duplicated inline blocks (P6, REQ-170).
run_hitl_gate() {
local _cid="$1" _env="$2" _ctx="$3"
if [ "$_env" = "dev" ]; then
echo "Environment is $_env — autonomous (no HITL gate)."
return 0
fi
echo "Environment is $_env — HITL attestation gate required$_ctx."
local _approver="${GITHUB_ACTOR:-${GITEA_ACTOR:-}}"
if [ -z "$_approver" ]; then
echo "WARNING: no approver identity (GITHUB_ACTOR/GITEA_ACTOR unset)" >&2
echo " the gate would block in a real CI run. Passing for local." >&2
fi
python3 -c "
import os, sys
sys.path.insert(0, '.')
from core.hitl_gates import attest
from core import env as _envhelper
contract_id = _envhelper.get_env('HITL_CONTRACT_ID') or os.environ['NOVA_HITL_CONTRACT_ID']
env = _envhelper.get_env('HITL_ENV') or os.environ['NOVA_HITL_ENV']
approver = _envhelper.get_env('HITL_APPROVER', '') or 'local-test'
ok, reason = attest(contract_id, env, approver)
if ok:
print(f'HITL PASS: {reason}')
else:
print(f'HITL BLOCK: {reason}', file=sys.stderr)
sys.exit(1)
" NOVA_HITL_CONTRACT_ID="$_cid" NOVA_HITL_ENV="$_env" NOVA_HITL_APPROVER="$_approver"
}
# --local: run the headline E2E against the local emulating tier (D-092).
# No AWS credentials, no Checkov, no DynamoDB. Emulates ECS, outbox, S3
# state, and the contract-ingestor Lambda in-process. Exits 0 on success.
@@ -142,8 +174,8 @@ stream() {
fi
}
CONTRACT_ID="11111111-1111-1111-1111-111111111111" # spike fixed UUID
WORK="/tmp/acdl_platform_run_v18"
CONTRACT_ID="${NOVA_CONTRACT_ID:-11111111-1111-1111-1111-111111111111}" # spike UUID (override via NOVA_CONTRACT_ID)
WORK="${NOVA_WORK_DIR:-/tmp/nova_platform_run}"
TF_DIR="$WORK/tf"
rm -rf "$WORK"; mkdir -p "$TF_DIR"
@@ -325,31 +357,7 @@ if [ "$APPLY_ONLY" = "1" ]; then
if [ -n "$ENVIRONMENT_OVERRIDE" ]; then
RESOLVED_ENV="$ENVIRONMENT_OVERRIDE"
fi
if [ "$RESOLVED_ENV" != "dev" ]; then
echo "Environment is $RESOLVED_ENV — HITL attestation gate required before apply."
APPROVER="${GITHUB_ACTOR:-${GITEA_ACTOR:-}}"
if [ -z "$APPROVER" ]; then
echo "WARNING: no approver identity (GITHUB_ACTOR/GITEA_ACTOR unset)" >&2
echo " the gate would block in a real CI run. Passing for local." >&2
fi
python3 -c "
import os, sys
sys.path.insert(0, '.')
from core.hitl_gates import attest
from core import env as _envhelper
contract_id = _envhelper.get_env('HITL_CONTRACT_ID') or os.environ['NOVA_HITL_CONTRACT_ID']
env = _envhelper.get_env('HITL_ENV') or os.environ['NOVA_HITL_ENV']
approver = _envhelper.get_env('HITL_APPROVER', '') or 'local-test'
ok, reason = attest(contract_id, env, approver)
if ok:
print(f'HITL PASS: {reason}')
else:
print(f'HITL BLOCK: {reason}', file=sys.stderr)
sys.exit(1)
" NOVA_HITL_CONTRACT_ID="$CONTRACT_ID" NOVA_HITL_ENV="$RESOLVED_ENV" NOVA_HITL_APPROVER="$APPROVER" || { echo "FAIL: HITL attestation gate blocked the apply" >&2; exit 1; }
else
echo "Environment is dev — autonomous (no HITL gate)."
fi
run_hitl_gate "$CONTRACT_ID" "$RESOLVED_ENV" " before apply" || { echo "FAIL: HITL attestation gate blocked the apply" >&2; exit 1; }
echo ""
echo "=== Step 5: terraform apply -auto-approve ==="
@@ -441,31 +449,7 @@ RESOLVED_ENV=$(python3 -c "import yaml; print(yaml.safe_load(open('$CONTRACT')).
if [ -n "$ENVIRONMENT_OVERRIDE" ]; then
RESOLVED_ENV="$ENVIRONMENT_OVERRIDE"
fi
if [ "$RESOLVED_ENV" != "dev" ]; then
echo "Environment is $RESOLVED_ENV — HITL attestation gate required."
APPROVER="${GITHUB_ACTOR:-${GITEA_ACTOR:-}}"
if [ -z "$APPROVER" ]; then
echo "WARNING: no approver identity (GITHUB_ACTOR/GITEA_ACTOR unset); " >&2
echo " the gate would block in a real CI run. Passing for local." >&2
fi
python3 -c "
import os, sys
sys.path.insert(0, '.')
from core.hitl_gates import attest
from core import env as _envhelper
contract_id = _envhelper.get_env('HITL_CONTRACT_ID') or os.environ['NOVA_HITL_CONTRACT_ID']
env = _envhelper.get_env('HITL_ENV') or os.environ['NOVA_HITL_ENV']
approver = _envhelper.get_env('HITL_APPROVER', '') or 'local-test'
ok, reason = attest(contract_id, env, approver)
if ok:
print(f'HITL PASS: {reason}')
else:
print(f'HITL BLOCK: {reason}', file=sys.stderr)
sys.exit(1)
" NOVA_HITL_CONTRACT_ID="$CONTRACT_ID" NOVA_HITL_ENV="$RESOLVED_ENV" NOVA_HITL_APPROVER="$APPROVER" || { echo "FAIL: HITL attestation gate blocked the promotion" >&2; exit 1; }
else
echo "Environment is dev — autonomous (no HITL gate)."
fi
run_hitl_gate "$CONTRACT_ID" "$RESOLVED_ENV" "" || { echo "FAIL: HITL attestation gate blocked the promotion" >&2; exit 1; }
echo ""
echo "=== Step 8: write evidence event to DynamoDB outbox ==="