Review: Add paldocs Keycloak OIDC client via Terraform (re-review)

review-1387-2026-07-03-r2 Review

review approved

Verdict: APPROVED

Re-review of board item #1387. Previous review (review-1387-2026-07-03) returned NEEDS_REFINEMENT with four recommendations. All four have been addressed. Scope is solid, file targets verified, traceability complete, fits in a single agent pass.

Previous Findings -- Resolution Status

  • [x] [SCOPE] "Create architecture note arch-keycloak" -- FIXED. arch-keycloak-paldocs created (architecture type, active, paldocs project). Comprehensive content: mermaid sequence diagram, component table, key decisions (confidential client rationale, PKCE S256, refresh tokens, CSS-only theme, Terraform-managed). References landscaping-assistant as reference implementation. Platform-level arch-keycloak also exists in pal-enterprises.
  • [x] [BODY] "Update Constraints: change precedent from pal-enterprises to landscaping-assistant" -- FIXED. Context section now says "The landscaping-assistant client is the closest precedent -- same CONFIDENTIAL type, PKCE S256, realm roles mapper enabled, and critically it includes both Tailscale hostnames AND the public domain." Constraints section says "Follow the existing landscaping-assistant client pattern (dual-origin: Tailscale + public domain)."
  • [x] [BODY] "Add pal-e-platform #491 to Related" -- FIXED. Related section now includes both pal-e-platform#490 (DNS A record + Caddy) and pal-e-platform#491 (NetworkPolicy) with dependency descriptions.
  • [x] [BODY] "Repo placement advisory" -- Acknowledged (non-blocking). Issue remains on paldocs with ### Repo field set to ldraney/pal-e-services. The Repo field disambiguates for agents.

Template Completeness

  • [x] Type -- Feature
  • [x] Lineage -- Child of paldocs#23 (spike: Keycloak auth + visibility-based access control)
  • [x] Repo -- ldraney/pal-e-services
  • [x] User Story -- As a platform operator, I want a Keycloak OIDC client provisioned for paldocs
  • [x] Context -- References landscaping-assistant dual-origin pattern, pal-e-docs realm, existing roles
  • [x] File Targets -- 1 modify target + 2 no-touch targets
  • [x] Feature Flag -- none
  • [x] Acceptance Criteria -- 7 items (expanded from 4 in previous review)
  • [x] Test Expectations -- tofu validate + tofu plan -var-file=k3s.tfvars
  • [x] Constraints -- 6 constraints including dual-origin pattern
  • [x] Checklist -- 3 items
  • [x] Related -- 5 items including both platform dependencies

Traceability

  • [x] story:auth label -- present on board item #1387
  • [x] story note verified -- story-paldocs-auth exists in project paldocs, listed on project-paldocs user-stories section ("role-based access control via Keycloak")
  • [x] arch:keycloak label -- present on board item #1387
  • [x] arch note verified -- arch-keycloak-paldocs exists (architecture type, active status, paldocs project). Covers OIDC client, themes, secrets wiring, NetworkPolicy. Also arch-keycloak exists in pal-enterprises as platform-level reference.
  • [x] Forgejo issue -- ldraney/paldocs#26, open

File Targets

  • [x] terraform/k3s.tfvars -- verified: exists (symlink to ~/secrets/pal-e-services/k3s.tfvars). keycloak_clients map present. No paldocs entry yet. landscaping-assistant precedent confirmed: public_client=false, standard_flow_enabled=true, direct_access_grants_enabled=false, pkce_code_challenge_method="S256", include_realm_roles_mapper=true, use_refresh_tokens=true, dual-origin URIs (Tailscale + landscaping-assistant.app).
  • [x] terraform/keycloak.tf -- verified: exists. keycloak_openid_client.this at line 148 uses for_each on var.keycloak_clients. Realm roles mapper at line 186. No changes needed -- correct.
  • [x] terraform/variables.tf -- verified: exists. Type definition at line 167-196 supports all fields needed: public_client (line 173), standard_flow_enabled (line 174), direct_access_grants_enabled (line 175), pkce_code_challenge_method (line 176), include_realm_roles_mapper (line 185), use_refresh_tokens (line 194). No changes needed -- correct.

Repo Placement

Advisory (non-blocking): issue filed on ldraney/paldocs, work is in ldraney/pal-e-services. The ### Repo field says ldraney/pal-e-services, which disambiguates for agents. Other cross-repo items on the paldocs board (pal-e-platform #490, #491, pal-e-deployments #224) are filed where the work happens, but this convention break is not blocking.

Dependencies

  • Upstream: pal-e-platform #491 / board #1708 (NetworkPolicy: paldocs to Keycloak) -- on board, sprint:3, backlog. Now documented in Related section.
  • Upstream: pal-e-platform #490 / board #1703 (DNS A record + Caddy block for paldocs.app) -- on board, sprint:3, backlog. Now documented in Related. Public domain must resolve before public redirect URIs work, but client creation itself doesn't depend on this.
  • Downstream: #1704 (KEYCLOAK_* env vars), #1389 (Rails OIDC integration), #1390 (visibility filtering). All depend on this client existing.
  • Realm: pal-e-docs realm already exists with admin and user roles. No realm-level changes needed.

Acceptance Criteria

7 criteria, all agent-verifiable. Expanded from 4 in previous review to cover both domains:
  • [x] paldocs client exists in pal-e-docs realm -- verifiable via tofu plan output
  • [x] Realm roles mapper attached -- verifiable via tofu plan (mapper resource)
  • [x] Redirect URIs include both paldocs.tail5b443a.ts.net and paldocs.app -- verifiable via tfvars inspection
  • [x] Web origins include both domains -- verifiable via tfvars inspection
  • [x] Post-logout redirect URIs include both domains -- verifiable via tfvars inspection
  • [x] tofu plan shows only new client + mapper -- verifiable via plan output
  • [x] Client secret retrievable -- verifiable post-apply via Keycloak admin console

Blast Radius

Low. The for_each pattern in keycloak.tf isolates each client as a separate Terraform resource. Adding paldocs to keycloak_clients cannot affect existing clients. The pal-e-docs realm is shared with pal-e-app but no realm-level changes are needed (admin/user roles already defined).

Decomposition Assessment

1 file target, 7 AC, estimated agent work under 5 minutes. No decomposition needed.

Recommendations

No action needed.