Review: Add kustomize overlay in pal-e-deployments (westside-streamlit #4) — Round 2

review-935-2026-04-11-r2 Review

review approved

Verdict: APPROVED

Round-2 review of board item #935 / forgejo_admin/westside-streamlit#4. Body rewritten 2026-04-11 after round-1 NEEDS_REFINEMENT. All 5 round-1 findings addressed. Conventions verified against live ~/pal-e-deployments repo. Ready to advance backlog → todo → next_up.

Round-1 Findings Resolution

  • [x] Finding 1 — Base pattern (invented per-service base): FIXED. Body now consumes shared bases/standard + bases/servicemonitor via resources: [../../../bases/standard, ../../../bases/servicemonitor], with JSON6902 rename patches turning base appwestside-streamlit for Deployment/Service/ServiceMonitor name + labels + container name. Matches overlays/basketball-api/prod/kustomization.yaml exactly.
  • [x] Finding 2 — Overlay directory structure (flat, not /prod/): FIXED. All file targets live under overlays/westside-streamlit/prod/. Matches overlays/basketball-api/prod/ and overlays/westsidekingsandqueens/prod/ convention.
  • [x] Finding 3 — Hostname discrepancy: Ticket uses westside-streamlit.tail5b443a.ts.net consistently. Story/arch notes still say westside-ops.tail5b443a.ts.net — flagged by reviewer as KNOWN DOC DRIFT to be fixed in a separate update pass, NOT a defect of this ticket body. Not blocking approval. Recommend doc update ticket on board-westside-streamlit to update story-westside-streamlit-reachable + arch-deployment-westside-streamlit to the new hostname.
  • [x] Finding 4 — ArgoCD Application location undefined: FIXED. Body now explicitly marks the ArgoCD Application declaration as Out of Scope: "pal-e-deployments has no Application YAML convention; Applications are managed externally in pal-e-platform terraform. A follow-up ticket will add the ArgoCD Application entry. Without it, kubectl apply -k overlays/westside-streamlit/prod/ is the manual sync path until the follow-up lands." Dev agent has an unambiguous path.
  • [x] Finding 5 — NetworkPolicy ambiguity (additive vs replacement): FIXED by omission. Body no longer lists a per-overlay networkpolicy.yaml as a file target, and notes the base NetworkPolicy is "temporarily disabled per kube-router ipset bug." Matches how basketball-api + westsidekingsandqueens handle this today (commented-out patches). No ambiguity left for the agent.

Convention Verification (live repo grep 2026-04-11)

  • [x] bases/standard/ and bases/servicemonitor/ exist (only two shared bases)
  • [x] overlays/basketball-api/prod/ contains deployment-patch.yaml, harbor-creds.enc.yaml, kustomization.yaml — matches body's proposed file set (minus app-specific extras)
  • [x] overlays/westsidekingsandqueens/prod/ contains ingress.yaml alongside the standard files — confirms per-overlay ingress.yaml is a valid pattern (ingress not in base)
  • [x] overlays/westside-email/prod/namespace.yaml exists — confirms separate namespace.yaml is a valid pattern (2 of ~15 services use it, rest inline or manage externally)
  • [x] .sops.yaml creation_rules regex: \.enc\.yaml$ — confirms body's requirement that SOPS files use .enc.yaml suffix
  • [x] JSON6902 rename pattern in basketball-api/prod/kustomization.yaml matches body spec exactly (kind: Deployment, name: app, replace ops on /metadata/name, /spec/selector/matchLabels/app, /spec/template/metadata/labels/app, /spec/template/spec/containers/0/name)
  • [x] overlays/pal-e-streamlit/ orphan confirmed present for deletion (tracked dev/ingress.yaml from incident PR #109)

Template Completeness

  • [x] Type (Feature), Lineage, Repo, User Story, Context, File Targets (create + delete), Acceptance Criteria (11 testable), Test Expectations, Constraints, Checklist, Related — all present
  • [x] Revision history noted in body ("Revised again 2026-04-11 post-scope-review-round-1")
  • [x] Cluster-side manual cleanup documented for PR body (not agent-run)
  • [x] Out-of-scope items explicitly enumerated (ArgoCD Application, Keycloak wiring)

Traceability

  • [x] story:reachable — label present; story-westside-streamlit-reachable note exists and lists this work
  • [x] arch:k8s-deploy — label present; arch-k8s-deploy backing note still missing (platform-wide gap, waived per round-1 precedent)
  • [x] Forgejo issue #4 — open, scoped to forgejo_admin/pal-e-deployments
  • [x] Incident incident-2026-04-10-pal-e-streamlit-public-funnel linked
  • [x] Parent/child relationships to #2 (merged), #3 (blocks-on-this), #5 (merged), #6 (hostname dep), #10/#11/#12 (Keycloak children) all enumerated

File Targets

  • [x] overlays/westside-streamlit/prod/kustomization.yaml — matches convention, shared bases, JSON6902 rename, image pinning by Woodpecker
  • [x] overlays/westside-streamlit/prod/deployment-patch.yaml — additive env/probes/resources/securityContext/strategy, targets base app
  • [x] overlays/westside-streamlit/prod/service-patch.yaml (or inline) — port/targetPort override acceptable either way
  • [x] overlays/westside-streamlit/prod/ingress.yaml — tailnet-private, NO funnel annotation, hostname westside-streamlit.tail5b443a.ts.net
  • [x] overlays/westside-streamlit/prod/harbor-creds.enc.yaml — SOPS-encrypted, convention match
  • [x] overlays/westside-streamlit/prod/secret.enc.yaml — SOPS-encrypted westside-streamlit-secrets with PGURL from westside_streamlit_ro (matches #5 migration)
  • [x] overlays/westside-streamlit/prod/namespace.yaml — restricted PSA label, valid pattern (precedent: westside-email)
  • [x] DELETE overlays/pal-e-streamlit/ — in same PR, supersedes incident PR #109 partial

Repo Placement

OK. All file changes in forgejo_admin/pal-e-deployments. Cluster-side namespace cleanup documented as post-merge manual commands for Lucas.

Dependencies

  • Upstream satisfied: #2 Dockerfile MERGED, #5 Postgres role MERGED
  • Downstream: #3 Woodpecker CI blocks on this (needs overlays/westside-streamlit/prod/kustomization.yaml as image-tag target); #12 Keycloak env wiring additive post-this; #6 funnel depends on #7 Keycloak chain landing first
  • Follow-up identified: ArgoCD Application in pal-e-platform terraform (separate ticket)
  • Follow-up identified: Story/arch hostname doc drift (separate ticket, NOT blocking this one)

Acceptance Criteria

11 programmatically verifiable criteria: kustomize build exit 0, kubectl apply --dry-run=server passes, rendered names match, namespace PSA label, ingress class + no funnel, orphan deleted, SOPS decrypt, correct PG credentials, PR body includes build/dry-run output + manual cleanup commands. All testable in a local dev agent pass.

Blast Radius

  • Migration risk: LOW — no live ArgoCD app watches the orphan overlay, deletion is pure filetree cleanup. Cluster untouched until Lucas runs manual kubectl delete namespace post-merge.
  • Harbor project: body specifies harbor.tail5b443a.ts.net/westside/westside-streamlit. Per feedback_harbor_project_naming, agent should verify westside Harbor project exists before image pull works (acceptance-time check, not scoping-time).
  • Hostname doc drift (westside-ops in story/arch vs westside-streamlit in ticket): known, flagged separately, not blocking.
  • No similar-pattern bugs detected elsewhere — conventions now match the 15 existing service overlays.

Decomposition Assessment

  • Discrete file changes: 7 creates + 1 directory delete = 8 discrete changes, all in one directory tree
  • Acceptance criteria: 11 — above the 5-AC rule of thumb, but all tightly coupled to a single overlay landing; splitting would create artificial seams
  • Estimated agent time: 8-12 minutes (clone, copy basketball-api/prod as template, adapt, SOPS encrypt, kustomize build, dry-run, PR)
  • Borderline on 5-min rule but no decomposition — all changes are one cohesive overlay bundle; splitting would force a dev agent to land half a service

Recommendation

APPROVED. No action needed on the ticket body.
  • All 5 round-1 findings resolved in the 2026-04-11 rewrite.
  • Conventions verified against live ~/pal-e-deployments repo (bases, overlay structure, SOPS regex, JSON6902 patches, namespace pattern).
  • Out-of-scope items (ArgoCD Application, Keycloak) explicitly deferred with unambiguous paths.
  • Known residual: story/arch hostname doc drift — tracked separately, not blocking this ticket.
  • Ready for todo → next_up advance and dev dispatch.