--- project: acdl milestone: v1.28 generated_at: 2026-08-19 generator: lead-developer verification_toolchain: typecheck: "python3 -m py_compile core/mode_resolver.py nova/cli.py 2>&1 | head -5 || true" test: "pytest tests/test_mode_resolver.py tests/test_cli_subcommands.py -q 2>&1 | tail -15 || true" lint: "ruff check nova/ core/lambda/nova_idp_*.py 2>/dev/null || true" note: | v1.28 is a feature milestone (CLI Canonicalization + Identity Layer). Four active personas: backend-engineer (Lambda/DynamoDB/KMS/CodeArtifact), security-engineer (Argon2id/KMS/ABAC/threat model), cli-engineer (subcommand surface/mode_resolver/argparse/CAP-034), lead-developer (plan/review/ship/capability gate). frontend-engineer + data-engineer deactivated (no UI, no data pipelines). The kj-binary-in-Lambda-layer risk (D-227, RESEARCH §7) is the highest-risk item; P2 spike confirms. --- # Personas — v1.28 CLI Canonicalization + Identity Layer ## Roster ### backend-engineer ```yaml active: true domain: "Lambda functions, DynamoDB, KMS integration, dual-use packaging, CodeArtifact publish, CloudFormation generation" frameworks: ["Python 3.12", "boto3", "argparse", "pytest", "moto[dynamodb]", "CloudFormation"] constraints: ["INV-15", "INV-16", "INV-17", "D-228", "D-229", "D-230", "NFR-5", "NFR-6", "NFR-7", "NFR-8"] territory: - "core/lambda/**" - "core/metrics/**" - "core/env.py" - "core/outbox_writer.py" - "terraform/bootstrap/**" - ".gitea/workflows/publish.yml" - ".github/workflows/publish.yml" - ".github/actions/nova-cli/**" ``` ### security-engineer ```yaml active: true domain: "Argon2id hashing, KMS asymmetric signing (ECDSA P-256 / ES256), ABAC policy, JWKS exposure, PAT lifecycle, threat model, DER→raw ECDSA conversion" frameworks: ["argon2-cffi", "cryptography", "pyjwt", "kyverno-json", "JMESPath", "KMS Sign/Verify/GetPublicKey"] constraints: ["INV-15", "INV-16", "INV-17", "NFR-5", "NFR-8", "NFR-9", "D-227", "D-231"] territory: - "platform/abac/**" - "core/policy_engine.py" - "adapters/kyverno-json/**" - "core/lambda/nova_idp_auth.py" - "core/lambda/nova_idp_token_vend.py" - "core/lambda/nova_idp_jwks.py" - "docs/threat-model.md" ``` ### cli-engineer ```yaml active: true domain: "CLI subcommand surface, mode_resolver, argparse, [project.scripts] entry-point, CAP-034 AST scan, nova auth/idp subgroups, property tests" frameworks: ["Python 3.12", "argparse", "setuptools [project.scripts]", "hypothesis", "pkgutil"] constraints: ["INV-12", "INV-13", "INV-14", "D-226", "NFR-1", "NFR-2", "NFR-3"] territory: - "nova/**" - "core/mode_resolver.py" - "pyproject.toml" - "tests/test_mode_resolver.py" - "tests/test_cli_subcommands.py" ``` ### lead-developer ```yaml active: true domain: "Phase plan, persona roster, review gates, milestone ship, capability gate (CAP-033..038), ROADMAP/STATE/PROJECT wiring" frameworks: ["git", "Gitea Actions", "semver tagging", ".ciagent/ discipline"] constraints: ["INV-1..17 (cross-cutting)", "v1.28 hard constraints", "NFR-6", "NFR-11"] territory: - ".ciagent/**" - "PLAN.md" - "CHECKPOINT.json" - "STATE.md" - "REQUIREMENTS.md" - "ROADMAP.md" ``` ### frontend-engineer ```yaml active: false phase_specific: false reason: "No UI in v1.28 (CLI + JSON endpoints only). JWKS serves application/json; no HTML/CSS/JS surface." ``` ### data-engineer ```yaml active: false phase_specific: false reason: "No data pipelines / metrics / PowerBI work in v1.28. The metrics layer is v1.17-complete; v1.28 adds audit events but no new fact/dim tables." ``` ## Territory overlap notes - `core/lambda/contract_ingestor.py` (dual-use refactor, REQ-329) = backend-engineer territory. `core/lambda/nova_idp_auth.py` + `nova_idp_token_vend.py` are **co-owned** by backend-engineer (Lambda plumbing, DynamoDB, function URLs) + security-engineer (crypto, ABAC, Argon2id logic inside). - `core/mode_resolver.py` = cli-engineer. `core/policy_engine.py` = security-engineer (the ABAC evaluation path). - `nova/idp/setup.py` = cli-engineer (the subcommand + arg parsing) + backend-engineer (the CloudFormation generation + deploy). - `nova/auth/*` = cli-engineer (subcommands) + security-engineer (the token exchange + credential storage logic). ## Phase-specific personas None. All four active personas span the full milestone. The security-engineer is heaviest in P2 (identity layer) + P3 (threat model); the cli-engineer is heaviest in P1 (CLI substrate); the backend-engineer spans P1 (CodeArtifact/layer) + P2 (Lambdas/DynamoDB). --- # Personas — v1.29 Reposplit + Identity Layer Bring-Live ```yaml project: acdl milestone: v1.29 generated_at: 2026-08-20 generator: lead-developer verification_toolchain: typecheck: "python3 -m py_compile nova/idp/setup.py core/lambda/nova_idp_setup.py 2>&1 | head -5 || true" test: "pytest tests/test_idp_auth.py tests/test_kms_roundtrip.py -q 2>&1 | tail -15 || true" lint: "ruff check nova/idp/ core/lambda/nova_idp_setup.py 2>/dev/null || true" note: | v1.29 is a feature milestone (Reposplit + Identity Layer Bring-Live). Pure ops/devops focus — Terraform modules are authored out-of-band in nova-platform-ops; CIAgent in acdel delivers publish.yml, Gitea scrub, CFN archive + CLI terraform-delegation, operator guide, consumer bump. Five active personas: backend-engineer (publish.yml ECR image, Lambda zip, GitHub Releases), security-engineer (kj static build verification, KMS round-trip tests, ABAC E2E, M1.5 gate), cli-engineer (nova idp setup --apply terraform delegation, CFN archive), data-engineer (DynamoDB import references, outbox bootstrap docs), lead-developer (plan/review/ship, Gitea scrub, decisions, operator guide, milestone wiring). frontend-engineer deactivated (no UI). ``` ## Roster ### lead-developer ```yaml active: true domain: "Milestone plan, persona roster, Gitea scrub (REQ-367), decisions D-232..240 (REQ-368), operator guide (P4), milestone ship, STATE/ROADMAP/PROJECT wiring, covered-reference REQ tracking" frameworks: ["git", "Gitea Actions", "GitHub Actions", "semver tagging", ".ciagent/ discipline", "Terraform (reference only)"] constraints: ["D-232 (forge parity abandoned)", "D-235 (tag-pin handoff)", "D-236 (cutover shape)", "D-238 (KJ-LOCKSTEP)", "OPER-PRIV", "TFM-HITL", "v1.29 hard constraints"] territory: - ".ciagent/**" - "PLAN.md" - "CHECKPOINT.json" - "STATE.md" - "REQUIREMENTS.md" - "ROADMAP.md" - "PROJECT.md" - "CLARIFY.md" - "RESEARCH.md" - "docs/operator-guide-platform-ops.md" - ".github/workflows/ci.yml" - "scripts/sync_workflows.py" - "pyproject.toml" - "README.md" ``` ### backend-engineer ```yaml active: true domain: "publish.yml ECR container image build (CGO_ENABLED=0 static kj), Lambda zip + layer wheel + Python wheel attach to GitHub Releases, ECR push with tag v1.29.x-kj-, kj-version.txt read, Dockerfile for lambda:3.12-al2023 base" frameworks: ["Python 3.12", "GitHub Actions", "Docker", "ECR", "Go (CGO_ENABLED=0 build)", "file(1)", "sha256sum"] constraints: ["KJ-STATIC", "D-239 (ECR tag format)", "D-235 (tag-pin handoff)", "REQ-354 criteria 1-4"] territory: - ".github/workflows/publish.yml" - "platform/abac/kj-version.txt" - "core/lambda/nova_idp_token_vend.py" - "core/lambda/nova_idp_auth.py" - "core/lambda/nova_idp_jwks.py" - "tests/test_idp_auth.py" - "tests/test_kms_roundtrip.py" ``` ### security-engineer ```yaml active: true domain: "kj static-link audit (file(1) asserts statically linked + no shared library), KMS round-trip test against alias/nova-oidc-signing, ABAC E2E (sign-up→sign-in→token-vend→verify, INV-17 fail-closed), M1.5 verification gate tests (8-item spike), KJ-LOCKSTEP digest-equality verification" frameworks: ["KMS Sign/Verify/GetPublicKey", "kyverno-json", "jose", "file(1)", "readelf", "pytest", "moto[dynamodb]"] constraints: ["KJ-STATIC", "KJ-LOCKSTEP", "INV-17 (ABAC fail-closed)", "INV-18 (JWKS-EDGE-ONLY)", "ABAC-FAIL-CLOSED", "ARGON", "KF (KMS asymmetric)"] territory: - "platform/abac/**" - "platform/abac/kj-version.txt" - "adapters/kyverno-json/policies/token-vend.policy" - "tests/test_kms_roundtrip.py" - "tests/test_idp_auth.py" - "tests/test_abac_e2e.py" - "docs/threat-model.md" ``` ### cli-engineer ```yaml active: true domain: "nova idp setup --apply terraform delegation (REQ-369 AC 2), CFN archive to docs/archive/nova-idp-cfn-v1.28.md (REQ-369 AC 3), which terraform detection + CFN fallback deprecation warning" frameworks: ["Python 3.12", "argparse", "subprocess", "importlib", "shutil.which"] constraints: ["REQ-369", "D-235 (tag-pin handoff)"] territory: - "nova/idp/setup.py" - "core/lambda/nova_idp_setup.py" - "docs/archive/nova-idp-cfn-v1.28.md" - "nova/idp/__init__.py" ``` ### data-engineer ```yaml active: true phase_specific: false domain: "DynamoDB table import references (nova-contracts, nova-change-requests, nova-outbox, nova-users, nova-sessions, nova-pats) documented in operator guide, PITR restore procedure, audit outbox bootstrap" frameworks: ["DynamoDB", "AWS CLI (reference)"] constraints: ["REQ-361 (import idempotency, covered-reference)", "JWKS-ROTATION"] territory: - "docs/operator-guide-platform-ops.md" - ".ciagent/ARCHITECTURE.md" reason: | Re-activated for v1.29: the operator guide (P4) documents DynamoDB PITR restore, table imports, and the audit outbox bootstrap — data-engineer owns the data-layer sections of the guide. The Terraform import itself is out-of-band (nova-platform-ops), but the operator-facing docs are in-acdl. ``` ### frontend-engineer ```yaml active: false phase_specific: false reason: "No UI in v1.29 (pure ops/devops focus). JWKS serves application/json via CloudFront; no HTML/CSS/JS surface." ``` ## Territory overlap notes - `.github/workflows/publish.yml` (REQ-354) = backend-engineer (ECR image build, Dockerfile, Lambda zip) + lead-developer (Gitea scrub removes the `.gitea/workflows/publish.yml` mirror in P2, D-232). - `nova/idp/setup.py` (REQ-369) = cli-engineer (the `--apply` delegation + `which terraform` detection) + backend-engineer (the CFN archive content — the CFN template is backend-engineer territory from v1.28). - `platform/abac/kj-version.txt` = security-engineer (KJ-STATIC audit reads + verifies the SHA) + backend-engineer (publish.yml reads the SHA to embed in the ECR tag). - `docs/operator-guide-platform-ops.md` (P4) = lead-developer (cutover gates, cost section, artifact-mirror fallback) + data-engineer (PITR restore, DynamoDB imports) + security-engineer (KMS rotation, JWKS reachability, PAT revocation). ## Phase-specific personas None. All five active personas span the full milestone. The backend-engineer is heaviest in P1 (publish pipeline); the lead-developer is heaviest in P2 (Gitea scrub + decisions) + P4 (operator guide) + P6 (final ship); the cli-engineer is heaviest in P3 (CFN archive + TF delegation); the security-engineer is heaviest in P1 (M1.5 gate tests) + P4 (operator guide security sections); the data-engineer is heaviest in P4 (operator guide data sections).