Review: Add Ingress/TLS + wire Keycloak env vars for production deploy

review-1812-2026-07-05 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

  • [x] Type — Feature
  • [ ] Lineage — MISSING
  • [x] Repo — prediction-assistant
  • [x] User Story — present
  • [x] Context — present
  • [x] File Targets — 7 targets (3 new, 4 existing)
  • [x] Feature Flag — None (acceptable for infra work)
  • [ ] Acceptance Criteria — MISSING (only Test Expectations present)
  • [x] Test Expectations — present (3 items)
  • [x] Constraints — present
  • [x] Checklist — present
  • [x] Related — present (Blocks #93, Sprint 12)

Traceability

  • [x] story:platform-setup label — Platform Setup
  • [x] story note verified — found in project-prediction-assistant user-stories section
  • [x] arch:k8s-deploy label — k8s deployment component
  • [ ] arch note MISSING — [SCOPE] Create architecture note arch-k8s-deploy for component k8s-deploy
  • [x] arch:keycloak label — Keycloak auth component
  • [ ] arch note MISSING — [SCOPE] Create architecture note arch-keycloak for component keycloak
  • [x] Forgejo issue — ldraney/prediction-assistant#105, open

File Targets

  • [x] k8s/overlays/prod/ingress.yaml (new) — verified: does not exist, correctly marked as new
  • [x] k8s/overlays/prod/cluster-issuer.yaml (new) — verified: does not exist, correctly marked as new
  • [ ] k8s/overlays/prod/redirect-middleware.yaml (new) — ISSUE: resource type unclear. "Middleware" is a Traefik CRD concept. Issue does not specify which ingress controller is in use or what k8s resource kind this file should contain
  • [x] k8s/overlays/prod/kustomization.yaml — verified: exists, currently has image pin, patches, and labels. New resources must be added to the resources list
  • [x] k8s/base/configmap.yaml — verified: exists with RAILS_ENV, RAILS_LOG_TO_STDOUT, RAILS_SERVE_STATIC_FILES, RAILS_MAX_THREADS, PORT. No Keycloak vars present (confirms the gap)
  • [x] k8s/base/deployment.yaml — verified: exists with envFrom configMapRef and secret env vars (DATABASE_URL, SECRET_KEY_BASE, KALSHI_*). No Keycloak env vars present
  • [x] k8s/base/worker-deployment.yaml — verified: exists with same env pattern as deployment.yaml. No Keycloak env vars present

Repo Placement

OK — issue filed on ldraney/prediction-assistant. All 7 file targets are within the prediction-assistant repo k8s/ directory.

Dependencies

  • Documented: Blocks #93 "Verify prediction-assistant.com is live" (todo column, sprint:12)
  • Undocumented: Depends on pal-e-services#173 "tofu apply — provision prediction-assistant infra" (board item 1772, todo column, sprint:12). The Keycloak env vars reference secrets (KEYCLOAK_CLIENT_SECRET at minimum) that must be provisioned by Terraform before pods can start with correct auth. This dependency is not documented in the issue.
  • Related: pal-e-services#171 "Add Keycloak realm + OIDC client" (validation column, sprint:11) — the Keycloak realm and OIDC client must exist before these env vars are meaningful.

Acceptance Criteria

No ### Acceptance Criteria section exists. The Test Expectations section provides partial coverage but is insufficient:
  • "kustomize build k8s/overlays/prod/ succeeds" — verifiable by agent
  • "Ingress routes prediction-assistant.com to service" — only verifiable post-deploy, not by agent
  • "Keycloak env vars present in pod specs" — verifiable via kustomize build output, but does not specify WHICH vars
Missing criteria:
  • Which specific Keycloak env vars must appear: KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET, KEYCLOAK_URL, KEYCLOAK_REALM (per config/initializers/omniauth.rb)
  • KEYCLOAK_CLIENT_SECRET must come from a Secret (not ConfigMap) — security constraint not stated
  • TLS certificate provisioning verified (ClusterIssuer references valid issuer)
  • HTTP-to-HTTPS redirect behavior

Blast Radius

  • ConfigMap changes via envFrom propagate to both web and worker deployments — both are listed as file targets, so this is covered
  • Adding Keycloak env vars to base/ affects both prod and dev overlays. If dev should use different Keycloak settings (different realm URL, different client), the issue should specify overlay-level overrides
  • No sibling services in this repo to check for similar patterns

Decomposition Assessment

7 file targets in 1 repo, 3 test expectations, estimated agent work ~3-5 minutes. No decomposition needed.

Recommendation

  • [BODY] Add ### Acceptance Criteria section with verifiable conditions: "kustomize build output contains KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET, KEYCLOAK_URL, KEYCLOAK_REALM in pod specs", "KEYCLOAK_CLIENT_SECRET sourced from Secret not ConfigMap", "Ingress host is prediction-assistant.com", "TLS secretName references cert-manager Certificate"
  • [BODY] Add ### Lineage section (e.g., "Standalone — discovered during deployment audit")
  • [BODY] Specify which Keycloak env vars (KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET, KEYCLOAK_URL, KEYCLOAK_REALM per config/initializers/omniauth.rb) and whether each goes in ConfigMap or Secret (KEYCLOAK_CLIENT_SECRET MUST be a Secret)
  • [BODY] Clarify what k8s resource type redirect-middleware.yaml represents (Traefik Middleware CRD? Ingress annotation? Something else?) and which ingress controller is in use
  • [BODY] Document dependency on tofu apply (pal-e-services#173) for k8s secrets provisioning
  • [SCOPE] Create architecture note arch-k8s-deploy for component k8s-deploy
  • [SCOPE] Create architecture note arch-keycloak for component keycloak