Review: Terraform Keycloak OIDC client westside-admin

review-1096-2026-04-25 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Board item #1096 — forgejo_admin/pal-e-platform#301 — Terraform: Keycloak OIDC client westside-admin. Reviewed 2026-04-25.

Critical Finding

The ticket's core premise is incorrect. It instructs the dev agent to "find the westside-app client definition and clone its structure." No such terraform-managed client exists. The Keycloak terraform module at terraform/modules/keycloak/main.tf deploys only the Keycloak server (namespace, secret, PVC, deployment, service, theme configmap). The keycloak terraform provider is not configured in terraform/providers.tf, no keycloak_realm resource exists, and no keycloak_openid_client resource exists. The westside-basketball realm and existing westside-app client are managed manually via the Keycloak admin console, not by terraform.
This means the ticket as written cannot be executed. The dev agent will either (a) get blocked, or (b) bootstrap the keycloak provider + realm import + client resource themselves, which is materially larger scope than "add a client resource."

Template Completeness

  • [x] Type — Task
  • [x] Lineage
  • [x] Repo
  • [x] User Story
  • [x] Context
  • [x] Scope
  • [x] Acceptance Criteria
  • [x] Test Expectations
  • [x] Constraints
  • [x] Checklist
  • [x] Related

Traceability

  • [x] story:admin-row-crud label — Admin Row CRUD
  • [x] story note verified — story-westside-admin-admin-row-crud exists; user-stories section on project-westside-admin exists
  • [x] arch:keycloak label
  • [ ] arch note MISSING — search for arch-keycloak returned no results. Existing arch notes for the project are arch-domain-westside-admin, arch-dataflow-westside-admin, arch-deployment-westside-admin. No keycloak-component arch note exists in pal-e-docs. [SCOPE] Create architecture note arch-keycloak documenting the Keycloak component (realm, clients, terraform vs manual management boundary).
  • [x] Forgejo issue — #301, open

File Targets

Ticket references ~/pal-e-platform/keycloak.tf "or equivalent." Verified state of repo:
  • [ ] ~/pal-e-platform/keycloak.tf — DOES NOT EXIST. Keycloak terraform lives at terraform/modules/keycloak/main.tf.
  • [ ] "westside-app client definition" — DOES NOT EXIST in terraform. Grepped terraform/ for keycloak_openid_client, keycloak_realm, provider "keycloak", mrparkers, keycloak/keycloak — zero matches. The realm and any existing clients are unmanaged by IaC.
  • [x] terraform/modules/keycloak/main.tf — exists, deploys Keycloak server only.
  • [x] terraform/providers.tf — exists; declares kubernetes, helm, tailscale, minio. No keycloak provider.

Repo Placement

Repo (forgejo_admin/pal-e-platform) is correct for terraform-managed Keycloak resources. No mismatch.

Dependencies

Implicit prerequisite NOT declared in ticket:
  • Configuring the keycloak terraform provider in providers.tf (with admin credentials sourced from existing keycloak-admin secret or a new tfvar).
  • Importing or declaring the westside-basketball realm as a terraform resource (or marking it as data-only via a data "keycloak_realm" lookup so the new client can reference it without taking over realm management).
  • Decision needed: does this ticket also adopt the existing westside-app client into terraform (import), or leave it manual and only add the new westside-admin client? The ticket assumes the latter is trivially possible by "cloning"; in reality there is no terraform pattern to clone.
Downstream board items relying on this:
  • #1087 (westside-admin SvelteKit scaffold) — needs this client to wire OIDC env vars, but does not block scaffolding.
  • #1088 (deployment) and #1095 (pal-e-deployments overlay) — consume the client_id and (if confidential) client_secret from k8s secret. Currently no defined export path.

Acceptance Criteria

ACs are testable as written, but several depend on the unstated bootstrap work (provider config, realm reference). The "If confidential: secret available in pal-e-platform secret store" criterion has no defined target — there is no existing secret-export pattern in this module to follow. Needs an explicit decision.

Blast Radius

If the dev agent attempts to manage the westside-basketball realm via a fresh keycloak_realm resource without import, terraform will try to create a realm that already exists, returning a 409 from Keycloak — or worse, if force-imported wrong, it will overwrite realm settings (login theme, password policies, registered users not stored in terraform) and could break westside-app SSO for Lucas and Marcus. This is a real outage risk. Realm must be imported via tofu import or referenced as a data source — not declared fresh.

Decomposition Assessment

If the bootstrap work (provider config + realm import + client resource + secret export) is included, this exceeds the 5-minute single-agent window: 3+ file targets in 1 repo, 7 ACs, plus a real outage risk requiring careful import sequencing. NEEDS DECOMPOSITION after the SCOPE questions are answered. Suggested split:
  • Add keycloak terraform provider + import (or data lookup) the westside-basketball realm. PR shows tofu plan with zero diff after import.
  • Add keycloak_openid_client resource for westside-admin with the spec'd settings.
  • If confidential: add secret export to k8s for the deployment overlay to consume.

Recommendation

  • [SCOPE] Lucas/Ava: confirm strategy — bootstrap keycloak terraform provider in this ticket, or first land a separate "adopt Keycloak under IaC" ticket and rebase this on top? Premise of "clone existing client pattern" is false; pick the replacement plan.
  • [SCOPE] Decide: public+PKCE or confidential client? Ticket leaves it open, but the answer drives whether secret-export work is in scope.
  • [SCOPE] Create architecture note arch-keycloak documenting the component and the IaC boundary (what's terraform-managed vs admin-console-managed).
  • [BODY] Fix file path reference: ~/pal-e-platform/keycloak.tfterraform/modules/keycloak/main.tf.
  • [BODY] Replace "find the westside-app client definition and clone" with the actual bootstrap path chosen in the SCOPE decision above.
  • [BODY] Add explicit AC for realm management: "westside-basketball realm referenced via data "keycloak_realm" lookup OR imported via tofu import, with no realm-level drift in tofu plan."
  • [DECOMPOSE] After SCOPE answered: split into 2-3 sub-tickets per Decomposition Assessment. Route to skill-decompose-ticket.