Review: Provision infrastructure in pal-e-services (v3)

review-593-2026-03-28-v3 Doc

review ready

Verdict: READY

Round 3 re-review of board item #593. Previous reviews: review-593-2026-03-28 (v1, NEEDS_REFINEMENT, 5 findings), review-593-2026-03-28-v2 (v2, NEEDS_REFINEMENT, 2 findings). Both v2 findings have been addressed in the current issue body.

V2 Findings Resolution

  • [x] Finding 1 (image_repo naming): AC1 now says image_repo: "westside-ai-assistant/api" (was /app). Constraints section explicitly documents the convention: "image_repo uses /api suffix (FastAPI convention), NOT /app (SvelteKit convention)."
  • [x] Finding 2 (valid_redirect_uris): AC2 now specifies valid_redirect_uris: []. Context section explains why: "The valid_redirect_uris field is required by the variable type but a service-account-only client needs an empty list []."

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — Standalone, with merge-order dependency on #2 documented
  • [x] Repo — forgejo_admin/pal-e-services
  • [x] User Story — Marcus as admin, infra provisioning
  • [x] Context — includes keycloak variable type + resource extension rationale, valid_redirect_uris empty-list requirement
  • [x] File Targets — 3 should-modify, 3 should-not-touch, all verified
  • [x] Acceptance Criteria — 6 criteria, all testable
  • [x] Test Expectations — tofu validate + plan command with -lock=false
  • [x] Constraints — backward-compatibility, no-apply guard, image_repo naming convention
  • [x] Checklist — present
  • [x] Related — present

Traceability

  • [x] story:read-ops — Admin Read Operations via GroupMe
  • [x] story:write-ops — Admin Write Operations via GroupMe
  • [x] arch:A4 — Deployment architecture component
  • [x] Forgejo issue — forgejo_admin/westside-ai-assistant#1, open

File Targets

  • [x] terraform/k3s.tfvars — verified: file exists (178 lines). services map at line 104, keycloak_clients map at line 40. basketball-api reference pattern at line 113-120 matches proposed entry structure. All FastAPI services (port 8000) use /api suffix: basketball-api/api, pal-e-docs/api, mcd-tracker/api, pal-e-mail/api.
  • [x] terraform/variables.tf — verified: file exists (139 lines). keycloak_clients type at lines 102-125. No service_accounts_enabled or service_account_realm_roles fields present. valid_redirect_uris = list(string) at line 112 is required (no default). Extension scope is accurate.
  • [x] terraform/keycloak.tf — verified: file exists (138 lines). keycloak_openid_client resource at lines 91-118 does not set service_accounts_enabled. No keycloak_openid_client_service_account_realm_role resource exists. Provider is mrparkers/keycloak ~5.0, which supports both.
  • [x] terraform/services.tf (should NOT touch) — verified: exists
  • [x] terraform/main.tf (should NOT touch) — verified: exists
  • [x] terraform/cnpg.tf (should NOT touch) — verified: exists

Repo Placement

Correct. Issue filed on westside-ai-assistant repo, work targets forgejo_admin/pal-e-services. Single-repo change. PR goes to pal-e-services, documented in Constraints.

Dependencies

  • [x] Issue #2 (kustomize overlay) — board item #594, todo column. Merge-order dependency documented in Lineage: "#2 must also merge before ArgoCD can sync, but the two PRs are to different repos and can be developed in parallel." Correct — no build-time dependency, only deploy-time.
  • [x] Issue #3 (NetworkPolicy) — board item #595, todo column. Post-deploy dependency, not blocking this ticket.

Acceptance Criteria

  • [x] AC1: services entry — complete. Specifies forgejo_repo, image_repo (correctly /api), port 8000, funnel: true, source_repo, source_path. Matches existing basketball-api pattern.
  • [x] AC2: keycloak_clients entry — complete. Specifies confidential, service_accounts_enabled: true, service_account_realm_roles: ["admin"], direct access grants enabled, valid_redirect_uris: []. The empty-list for redirect URIs is explicitly called out in Context.
  • [x] AC3: variables.tf type extension — clear. Optional fields with backward-compatible defaults.
  • [x] AC4: keycloak.tf resource update — clear. Single attribute addition.
  • [x] AC5: new service_account_realm_role resource — clear. Conditionally applied when roles list is non-empty.
  • [x] AC6: tofu plan verification — testable. Run command provided in Test Expectations.
All 6 criteria are agent-verifiable. Test command is real and includes -lock=false per convention.

Blast Radius

Low. The services entry uses existing for_each — no structural change. The keycloak_clients variable type extension adds two optional fields with safe defaults (false, []). Verified: no existing client sets service_accounts_enabled or service_account_realm_roles. Existing clients are unaffected. The new keycloak_openid_client_service_account_realm_role resource is conditionally created only when roles are non-empty, so it triggers for westside-ai-bot only.

Decomposition Assessment

3 files in 1 repo, 6 AC. The 6 AC technically touches the >5 threshold, but these are tightly coupled changes to a single variable type + resource + tfvars entry. Splitting would create artificial dependencies. Estimated agent time: <5 minutes. No decomposition needed.

Recommendation

No action needed. All previous findings have been addressed. Scope is solid, file targets verified, traceability complete, acceptance criteria testable, blast radius low. This ticket is ready for dispatch.