---ci--- project: acdl phase: 0 milestone: v1.29 status: complete ---/ci---
24 KiB
CLARIFY — v1.28 CLI Canonicalization + Identity Layer
Autonomy: full. Auto-resolution with assumption logging per
config.autonomy.level: "full". No human escalation unless confidence < 0.60. The user-approved re-mapping plan (v1.18 spec → v1.28) resolved the headline discrepancy. This file records the remaining ambiguities and the grounding gaps surfaced in pre-flight.
Method
The clarify stage identifies ambiguities in the v1.28 specification and resolves them at full autonomy. The v1.28 spec is the user-provided "Universal Feature Specification — v1.18 CLI Canonicalization + Identity Layer," re-mapped to v1.28 (milestone number, tag line, and all ID namespaces) per the user-approved plan. Each ambiguity gets a decision ID (D-226+, continuing from v1.27's D-214..D-225), a resolution, a confidence score, and a rationale.
Prior-conversation resolutions (already locked, restated for the record)
These were resolved by the user-approved re-mapping plan in the conversation that spawned v1.28. They are load-bearing for v1.28 execution.
Q-P1 — The source spec is titled "v1.18" but v1.18 already shipped. What milestone is this?
Resolution: Re-map the spec's content (CLI Canonicalization +
Identity Layer) to v1.28, the next milestone after v1.27 (complete).
Tags run on the v1.27.x line (P0 = v1.27.0). Milestone branch:
milestone/v1.28-cli-identity.
Confidence: 1.0 (user-confirmed — "Re-map to v1.28"). Decision: n/a (milestone identity, not a D-ID).
Q-P2 — The spec's "locked inputs" (D-NEW-26, kj engine, Nova-idp, INV-63/64/65, CAP-025..030, REQ-001..031) don't exist in the repo. How to handle?
Resolution: Author them fresh in this milestone's CLARIFY/RESEARCH as
D-226..D-231, INV-12..17, CAP-033..038, REQ-323..353. The kj engine
is mapped to the existing kyverno-json engine (INV-4 swappable) — no
new engine is built. CAP/INV/REQ IDs are re-allocated to avoid collisions
with shipped history (CAP-025..032 and INV-1..11 are blockchain/pilot).
Confidence: 1.0 (user-confirmed — "Re-map to v1.28"). Decision: D-227 (kj→kyverno-json), plus the ID-allocation block in REQUIREMENTS.md.
Q-P3 — The spec claims a "Cognito drop." No Cognito exists in the repo. What does NFR-5 mean?
Resolution: NFR-5 (no AWS-managed identity in the path) is a greenfield constraint, not a migration. Nova-idp is built fresh; no Cognito/IAM Identity Center is introduced. The "drop" framing is aspirational language from the source spec, not a literal removal. Confidence: 1.0. Decision: D-226 (recorded below; NFR-5 restated as a greenfield constraint in INV-15).
Open questions from the spec's §7 (auto-resolved at full autonomy)
Q1 — Argon2 native dependency in Lambda runtime
argon2-cffi has a C extension that may not build cleanly in the Lambda
Python 3.12 runtime.
Resolution (D-228): Use argon2-cffi with bundled wheels; if the
extension fails to load, fall back to the pure-Python implementation. If
both fail, document the Fargate migration path for the auth Lambda.
CAP-036 covers end-to-end verification.
Confidence: 0.85. Rationale: Bundled wheels are the standard
workaround for Lambda native deps; the pure-Python fallback is a safe
degradation. Fargate is the escape hatch if Lambda's runtime is
fundamentally incompatible. RESEARCH will validate wheel availability for
Python 3.12 + the Lambda execution environment.
Impact if wrong: Auth Lambda migrates to Fargate, adding ~1 week to P2.
Q2 — PAT revocation propagation latency
The 60-second SLO (NFR-4) depends on whether the token-vend Lambda reads PAT revocation state from DynamoDB on every request (eventually consistent reads) or via a cached/denylist mechanism.
Resolution (D-229): Read-on-every-request with strongly consistent reads on the PAT hash table. Cost is acceptable given expected request volume (token vending is not a hot path — it precedes a deploy, not every request). REV-351 verifies the SLO in CI. Confidence: 0.90. Rationale: Strongly consistent DynamoDB reads have single-digit-ms latency at expected volume; the 60s SLO has >10x headroom. A cache layer adds invalidation complexity that the SLO does not require. Impact if wrong: If read latency exceeds 60s under load, introduce a DynamoDB TTL + cache layer; SLO must be re-verified.
Q3 — JWKS endpoint: Lambda function URL vs. API Gateway
A function URL is simpler and cheaper but lacks throttling, WAF, and custom domains out of the box.
Resolution (D-230): Start with a Lambda function URL behind a custom domain; rate limiting configured at the DNS/CDN layer. API Gateway migration deferred to v1.19+ if throttling requirements grow. Confidence: 0.80. Rationale: The JWKS endpoint is public-key only (no secrets); the threat surface is low. Function URL + CDN rate- limiting covers the v1.28 volume. API Gateway is over-engineering until traffic patterns are known. Impact if wrong: If throttling becomes a requirement, API Gateway migration adds ~3-5 days.
Q4 — Mode resolver precedence with invalid NOVA_CLIENT_MODE value
What happens if the env var is set to something other than agent or
interactive (e.g., NOVA_CLIENT_MODE=auto)?
Resolution (D-226): Invalid env var values are ignored, falling
through to credential type. A warning is logged. Behavior is documented
in the nova-cli README. This is a sub-clause of the mode-resolution
priority decision.
Confidence: 0.90. Rationale: Ignoring + warning is the least
surprising behavior for an operator debugging mode issues. Failing hard
would block legitimate workflows that set a stale/typo'd env var.
Impact if wrong: Operators debugging mode issues may be confused;
non-blocking.
Q5 — Service-account PAT vs. developer PAT in the same session
What if both credential types are available (e.g., a developer explicitly exports a service-account PAT)?
Resolution (D-226): The most recently acquired credential wins.
Documented in nova auth login output. The credential type is what
drives mode resolution (INV-14), so the operator sees which mode was
selected and why.
Confidence: 0.85. Rationale: "Most recent wins" is the simplest
deterministic rule that matches operator mental models of "I just logged
in as X." The audit event records the winning credential type, so the
selection is traceable.
Impact if wrong: Mode selection may surprise the operator; non-
blocking, but nova auth status must make the active credential explicit.
Q6 — ABAC policy ownership and versioning
platform/abac/token-vend.policy is referenced, but who owns changes?
How are policy versions tracked in audit?
Resolution (D-231): Policy changes require PR review; the policy
version (git SHA) is recorded in every token-vend audit event. Owner:
Platform Security. The policy file lives in the platform repo at
platform/abac/token-vend.policy and is reviewed like any other
production config.
Confidence: 0.90. Rationale: Git SHA is the natural version
identifier for a repo-resident policy; recording it in the audit event
makes every allow/deny decision reconstructable to the exact policy text.
Impact if wrong: Untracked policy changes could lead to unexpected
allow/deny decisions in production, undermining audit defensibility.
Grounding gaps surfaced in pre-flight (auto-resolved)
G1 — The kj engine does not exist; the spec treats it as locked.
Resolution (D-227): The token-vend Lambda uses the existing
kyverno-json engine (INV-4 swappable) as the ABAC evaluator. The
policy at platform/abac/token-vend.policy is a kyverno-json policy.
No new kj engine is built in v1.28. If a distinct kj engine is
desired later, it is a separate research spike (not this milestone).
Confidence: 0.95. Rationale: The repo already has a swappable
policy engine (INV-4) implemented as kyverno-json. Building a second
engine to do the same job violates the swappable-engine invariant's
spirit. kyverno-json's evaluate semantics cover the spec's ABAC needs
(subject, claims, resource, environment → allow/deny).
Impact if wrong: If the user actually wants a new kj engine, v1.28
scope expands significantly (engine design + implementation + migration).
This was flagged as caveat #3 in the approved plan; the recommended path
(kyverno-json) is locked here.
G2 — The spec's INV-18..21, INV-34, INV-63/64/65 don't exist.
Resolution: Re-allocated as INV-12..INV-17 (see REQUIREMENTS.md §v1.28 Invariants). The 1:1 mapping:
- INV-63 (mode observability) → INV-12
- INV-64 (mode determinism) → INV-13
- INV-65 (credential type encodes role) → INV-14
- INV-18..21 (attestation invariants) → INV-15 (no AWS-managed identity), INV-16 (password storage), INV-17 (ABAC discipline). The spec's attestation invariants INV-18..21 are partially covered by existing invariants (INV-6 immutable audit) + INV-17; the JWS-from-PAT behavior (REQ-332) is a requirement, not a separate invariant, in this mapping.
- INV-34 (MFA enforcement) → deferred to v1.21+ (out of scope per §2.2); no INV allocated in v1.28. Confidence: 0.85. Rationale: The mapping preserves the spec's intent without colliding with the repo's INV-1..11. INV-34 (MFA) is explicitly deferred per the spec's own §2.2 out-of-scope table. Impact if wrong: If the user wants the exact INV-18..21 semantics as separate invariants, INV-12..17 can be re-numbered; non-blocking.
G3 — The spec's CAP-025..030 collide with blockchain/pilot CAPs.
Resolution: Re-allocated as CAP-033..CAP-038 (see REQUIREMENTS.md §v1.28 + REQ-352). The 1:1 mapping:
- CAP-025 (CLI subcommand surface) → CAP-033
- CAP-026 (subcommand delegates to core/) → CAP-034
- CAP-027 (layer matches wheel) → CAP-035
- CAP-028 (Nova-idp auth flow) → CAP-036
- CAP-029 (token-vend signs via KMS) → CAP-037
- CAP-030 (PAT issuance + revocation) → CAP-038 Confidence: 1.0. Rationale: Existing CAP-025..032 are blockchain/pilot capabilities (STATE.md); re-use would corrupt the capability registry. The re-allocated IDs are the next available. Impact if wrong: None — this is a numbering decision, not a semantic one.
G4 — The spec's REQ-001..031 collide / don't exist.
Resolution: Re-allocated as REQ-323..REQ-353 (1:1 with the spec's REQ-001..031). Full text in REQUIREMENTS.md §v1.28. Max existing REQ = REQ-322. Confidence: 1.0. Rationale: Same as G3 — avoid collision, use next available range.
G5 — platform/abac/, nova/ subcommand dir, nova-idp-* Lambdas don't exist.
Resolution: These are greenfield deliverables of v1.28 execution phases, not pre-existing "locked architectures." RESEARCH will design them; PLAN will sequence them; EXECUTE will build them. The spec's "Operating Principle 1" (incremental delivery) is honored — v1.28 is net-new work. Confidence: 1.0. Rationale: The spec itself describes these as new ("introducing Nova-idp"). The mis-framing was in calling them "locked" — they are locked in scope, not in prior existence. Impact if wrong: None — this is a framing correction.
Decision ledger (v1.28 — D-226..D-231)
| ID | Title | Confidence | Load-bearing for |
|---|---|---|---|
| D-226 | Mode resolution priority + invalid-env + dual-credential | 0.90 | REQ-327, INV-12, INV-13, INV-14 |
| D-227 | ABAC engine = kyverno-json (no kj engine built) |
0.95 | REQ-336, REQ-339, INV-17, NFR-9 |
| D-228 | Argon2id in Lambda: bundled wheels + pure-Python fallback + Fargate path | 0.85 | REQ-333, REQ-334, INV-16, NFR-8 |
| D-229 | PAT revocation: strongly-consistent DDB read-on-every-request, 60s SLO | 0.90 | REQ-342, REQ-343, REQ-351, NFR-4 |
| D-230 | JWKS endpoint: Lambda function URL + custom domain + CDN rate-limit | 0.80 | REQ-338, NFR-5 |
| D-231 | ABAC policy ownership: Platform Security, git SHA in audit | 0.90 | REQ-339, NFR-9 |
Assumptions logged (full autonomy, no human escalation)
- CodeArtifact is provisionable in AWS account
581513795199(the pilot account). RESEARCH will confirm IAM permissions + repository creation. If not, v1.28 falls back to a private PyPI server or a Gitea-hosted wheel index; the CLI subcommand surface (REQ-324) and identity layer (REQ-333+) are unaffected. - Python 3.12 is the target runtime for both the CLI wheel and the Lambda functions (spec §4 REQ-004.3). The repo's current Python version will be confirmed in RESEARCH; if it differs, the CLI pins 3.12 and Lambda uses the 3.12 runtime regardless.
- KMS asymmetric signing (RSA-2048 or ECDSA P-256) is available in the target account. RESEARCH will confirm. If only symmetric KMS is available, the token-vend Lambda uses symmetric signing + a public-key publication step (less ideal, but functional); INV-15 is unaffected.
- The Forge action (REQ-326) is the existing
nova cli-actionpattern, extended to both GitHub and Gitea marketplaces. The repo's current Forge/Gitea workflow conventions (.gitea/workflows/,deploy.yml@v1.25) are the baseline. - MFA/TOTP code path ships in v1.28 (per spec §2.2) but enforcement for prod/dr is deferred to v1.21+. This is a doc/test-only path in v1.28 — no enforcement gate.
CLARIFY complete
All material ambiguities resolved at full autonomy (6 open questions + 5 grounding gaps → D-226..D-231, confidence ≥ 0.80). No human escalation triggered (all confidences ≥ 0.60 threshold). REQUIREMENTS.md updated with the decision ledger + invariants. Next: RESEARCH.
CLARIFY — v1.29 Reposplit + Identity Layer Bring-Live
Autonomy: full. Auto-resolution with assumption logging per
config.autonomy.level: "full". No human escalation unless confidence < 0.60. The v1.29 spec is v1.1 (highly detailed — §7 resolves Q1-6, Q7 carried forward as a verification-gate dependency). This file records the v1.29 ambiguities and the scope-split grounding.
Method
The v1.29 spec ("Universal Feature Specification — Reposplit + Identity
Layer Bring-Live", v1.1) is the most detailed spec the project has
received: it includes BDD acceptance criteria, an 8-item M1.5 spike
checklist, 7 decisions pre-drafted (D-232..238), 14 NFRs, and an
explicit §7 resolving Q1-6. Clarify work focuses on (a) the scope split
between acdl (CIAgent) and nova-platform-ops (out-of-band), (b) the
kj identity (Go binary vs. the v1.28 kyverno-json re-mapping), and (c)
the carried-forward Q7. Each ambiguity gets a decision ID (D-232+,
continuing from v1.28's D-226..D-231), a resolution, a confidence score,
and a rationale.
Prior-conversation resolutions (already locked, restated for the record)
These were resolved by the user-approved execution plan in the conversation that spawned v1.29.
Q-P1 — The spec creates a separate repo nova-platform-ops. CIAgent runs inside acdl. Where does the Terraform code land?
Resolution: Terraform modules
(networking/kms/identity/contract-ingest/bootstrap/edge) are
authored out-of-band in nova-platform-ops (operator-owned). CIAgent
in acdl delivers only the acdl-side work (publish.yml, Gitea scrub,
CFN archive, operator guide, consumer bump) and tracks the ops-side
REQs as covered-reference (verification surface = the M1/M1.5/M2
cutover gates documented in the operator guide).
Confidence: 1.0 (user-confirmed — "Author out-of-band in
nova-platform-ops"). Decision: scope split documented in
PROJECT.md §v1.29 + REQUIREMENTS.md §v1.29.
Q-P2 — The run scope. How far does this /ci-run go?
Resolution: Full milestone through the final phase (P0 → P1..P5 →
P6 final review + audit + milestone ship, tag v1.28.6).
Confidence: 1.0 (user-confirmed — "Full milestone through final
phase"). Decision: n/a (execution scope, not a D-ID).
Q-P3 — Edge 8 / REQ-354 footnote: pilot consumer deploy bump. Handle how?
Resolution: Include a cross-project phase (P5) in this CIAgent run
(multi-project mode is active). Bump nova-blockchain-exchange
deploy.yml @v1.25 → @v1.29 + smoke test.
Confidence: 1.0 (user-confirmed — "Cross-project phase in this
run"). Decision: n/a (execution scope).
Spec-grounded resolutions (from §7 + §5)
Q1 — State bucket bootstrap on day-0 (resolved per spec §7.1)
Resolution: Manual one-time at the operator's secure scratch; Terraform
then adopts it via terraform import. Avoids bootstrapping the
bootstrapper. Confidence: 1.0 (spec §7.1 explicit). Decision:
D-235 (tag-pin handoff) — the state bucket is one of the imported
resources.
Q2 — pyproject.toml version bump (resolved per spec §7.2)
Resolution: Bump to 1.29.0 in M1 (P2 — Gitea scrub phase) of v1.29
alongside the Gitea scrub. Confidence: 1.0 (spec §7.2 explicit).
Decision: n/a (implementation detail, tracked in PLAN.md P2).
Q3 — WAF cost (resolved per spec §7.3)
Resolution: Acceptable for the JWKS public surface; documented in operator-guide cost section (~$5–10/month per WebACL + per-request). Confidence: 1.0 (spec §7.3 explicit). Decision: documented in REQ-OPS-GUIDE AC.
Q4 — Coverage 73.8% — does this milestone drive it down further? (resolved per spec §7.4)
Resolution: Accept any further debt as carry-forward to the separate NFR milestone. New modules have ≥80% coverage; older code paths are unchanged. YELLOW carried without scope expansion. Confidence: 1.0 (spec §7.4 explicit). Decision: n/a (NFR carry-forward, not a v1.29 D-ID).
Q5 — CFN code deletion timing (resolved per spec §7.5)
Resolution: Archive to docs/archive/nova-idp-cfn-v1.28.md; deletion
is a follow-up after the next pilot run verifies Terraform parity.
Confidence: 1.0 (spec §7.5 explicit). Decision: REQ-369 AC (3).
Q6 — acdl-act-runner-role reuse (resolved per spec §7.6)
Resolution: Reuse the existing role for v1.29 to minimize IAM surface changes; scope narrow per REQ-360. Confidence: 1.0 (spec §7.6 explicit). Decision: covered by REQ-360 (IAM-NARROW).
Q7 — kj image verification dependency (CARRY-FORWARD per spec §7.7)
Resolution (carry-forward): M1 cutover is conditional on the M1.5
verification gate. Recommendation: Block M1 cutover until M1.5
passes. If M1.5 fails three consecutive rebuilds, defer to M2a and ship
Nova-idp in read-only partial mode (no token issuance) until kj is
verified. Impact if wrong: A live token-vend that signs with a
broken ABAC path would let through a denied claim — fails closed only if
ImageUri is verified pre-apply. Confidence: 0.92 (spec §7.7
explicit + D-236 cutover shape). Decision: D-236 (cutover shape +
rollback procedure). This is the only outstanding carry-forward;
CIAgent in acdl builds + publishes the image + the gate tests (P1), but
the live 3-rebuild verification happens in nova-platform-ops CI
(out-of-band). CIAgent does not block on it.
Grounding-gap resolutions (surfaced in pre-flight)
G1 — The spec's kj vs. v1.28's kj re-mapping
Ambiguity: v1.28 (D-227) re-mapped the spec's kj engine →
kyverno-json (INV-4 swappable), explicitly stating "no new kj engine
is built." v1.29 reintroduces kj as a compiled Go binary
(platform/abac/kj-version.txt, pinned v0.0.3) embedded in an ECR
container image. Is this a contradiction?
Resolution: No contradiction. v1.28's kj was a policy engine
reference; v1.29's kj is a compiled Go binary (a distinct artifact).
The kyverno-json engine remains the policy engine (INV-4). The v1.29
kj binary is invoked via subprocess.run(['/opt/kj/kj', 'apply', ...])
by the Lambda handler — it is a substrate binary, not a policy
engine. The two coexist: kyverno-json evaluates ABAC policy; kj is the
container image's static binary that the Lambda runtime executes. No
collision.
Confidence: 0.95 (spec §3.3 Edge 5 item 4 explicit + v1.28 D-227
scope). Decision: documented in PROJECT.md §v1.29 ID allocations +
KJ-STATIC NFR.
G2 — REQ-363b sub-requirement numbering
Ambiguity: The spec uses REQ-363b for the Fargate defensive
fallback. The repo's REQ namespace is REQ-NNN (numeric). How to
record 363b?
Resolution: Keep REQ-363b as-is (sub-requirement of REQ-363). It
is a distinct requirement (Fargate fallback, KJ-LOCKSTEP) but logically
paired with REQ-363 (production substrate). The b suffix is
unambiguous and matches the spec. No collision with any existing REQ.
Confidence: 0.98 (spec explicit + no collision). Decision: n/a
(naming convention).
G3 — REQ-370 gap
Ambiguity: The spec jumps from REQ-369 to REQ-371. Is REQ-370 missing or intentionally unused?
Resolution: Intentionally unused per the source spec. REQ-370 is a gap in the spec's numbering (likely a deleted/renumbered item during spec v1.0 → v1.1). v1.29 does not allocate REQ-370; it remains a reserved gap. Confidence: 0.90 (spec explicit gap, no content). Decision: n/a (spec fidelity).
G4 — Covered-reference REQs and CIAgent verification
Ambiguity: REQ-355, 356, 357, 358, 359, 360, 361, 362, 363, 363b,
364, 365, 366, 371 are authored in nova-platform-ops (out-of-band).
How does CIAgent verify them? Are they human_needed?
Resolution: They are covered-reference, NOT human_needed. The
verification surface is the M1/M1.5/M2 cutover gates documented in the
operator guide (docs/operator-guide-platform-ops.md). The operator
guide lists each covered-reference REQ with its cutover gate entry
(M1/M1.5/M2). CIAgent verify marks them covered-reference and the
final-phase audit confirms the operator guide documents all gates.
Confidence: 0.94 (scope-split decision + spec §2.3 milestone
gates). Decision: documented in REQUIREMENTS.md §v1.29 + REQ-OPS-
GUIDE AC.
Assumptions (logged, not escalated — confidence ≥ 0.80)
kjv0.0.3 is available at the pinned SHA inplatform/abac/kj-version.txtand compiles withCGO_ENABLED=0 GOOS=linux GOARCH=amd64. RESEARCH will confirm the source repository- build commands. If the binary is not available, P1 (publish pipeline) cannot produce the ECR image; M1.5 gate fails by construction → M2a (Fargate toggle, same image) also fails → escalate (but this is a spec dependency, not a CIAgent ambiguity).
- ECR repository exists or is creatable in account
581513795199for thekjimage. RESEARCH will confirm. The repo name is not specified in the spec; the operator guide will document it. - GitHub Releases is the artifact distribution channel (per
REQ-354). The
acdl/acdlrepo is already on GitHub (the Gitea scrub in REQ-367 standardizes on GitHub). NOVA_FORGE_TOKEN (Gitea) is retained fornova-platform-opsreleases only. - The
nova idp setup --applyterraform-delegation (REQ-369 AC 2) requiresterraformto be on the operator's PATH. The CLI detects terraform viawhich terraform; if absent, it falls back to the CFN path with a deprecation warning (the CFN archive remains read-only reference, but the delegation is the preferred path). - The M1.5 8-item spike (spec §3.3 Edge 5) is the verification
gate. CIAgent in acdl authors the tests (test_idp_auth,
test_kms_roundtrip, ABAC E2E) in P1; the live 3-rebuild run
happens in
nova-platform-opsCI. This is the Q7 carry-forward surface.
CLARIFY complete
All material ambiguities resolved at full autonomy (3 prior-conversation
- 7 spec-grounded + 4 grounding-gap → D-232..D-238, confidence ≥ 0.80). Q7 is the only carry-forward (verification-gate dependency, not a blocking ambiguity). No human escalation triggered (all confidences ≥ 0.60 threshold). REQUIREMENTS.md updated with the decision ledger + invariants + NFR constraints. Next: RESEARCH.