Review: feat: add overlays/notion-mcp-remote/prod kustomize overlay

review-1044-2026-04-21 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Board item #1044 on board-notion-mcp-remote -- Forgejo issue forgejo_admin/pal-e-deployments#132. Scope is substantially correct but three gaps will trip the dev agent. Fixable in the issue body.

Template Completeness

  • [x] Type (Feature)
  • [x] Lineage
  • [x] Repo
  • [x] User Story
  • [x] Context
  • [x] File Targets
  • [x] Acceptance Criteria
  • [x] Test Expectations
  • [x] Constraints
  • [x] Checklist
  • [x] Related

Traceability

  • [x] story:ops-deploy-gitops label -- GitOps Deploy via pal-e Platform
  • [x] story note verified -- story-notion-mcp-remote-ops-deploy-gitops listed in project-notion-mcp-remote user-stories section
  • [x] arch:kustomize-overlay label -- refers to cross-service deployment pattern
  • [ ] arch note MISSING -- search_notes(query="arch-kustomize-overlay") returns empty. convention-kustomize-overlay exists and is the canonical reference, but no arch- prefixed note. [SCOPE] Decide whether to (a) create arch-kustomize-overlay (likely a cross-service arch diagram showing bases/standard -> overlay -> ArgoCD Image Updater write-back chain), or (b) relabel this ticket to drop arch:kustomize-overlay and rely on convention-kustomize-overlay since kustomize-overlay is really a convention, not a diagrammable arch component of this service. Recommend (b) -- kustomize-overlay is a platform convention, and the service-specific arch is already captured in arch-deployment-notion-mcp-remote.
  • [x] type:feature label matches ### Type Feature header
  • [x] Forgejo issue open (forgejo_admin/pal-e-deployments#132)

File Targets

  • [x] overlays/notion-mcp-remote/prod/kustomization.yaml -- path matches existing sibling overlays (overlays/pal-e-docs/prod/, overlays/basketball-api/prod/, etc.) confirmed in pal-e-deployments repo
  • [x] overlays/notion-mcp-remote/prod/deployment-patch.yaml -- standard overlay pattern per convention-kustomize-overlay
  • [ ] overlays/notion-mcp-remote/prod/ingress.yaml -- ISSUE: listed as "possibly" with the check "only if Tailscale Funnel ingress is not created by pal-e-services terraform". Confirmed via arch-deployment-notion-mcp-remote ("Tailscale Funnel provisioned by pal-e-services terraform when funnel=true") and pal-e-docs overlay (no ingress.yaml present). Funnel Ingress is NOT the overlay's concern. [BODY] Remove the "Possibly" line entirely and add "ingress.yaml -- NOT created here; Tailscale Funnel ingress is provisioned by pal-e-services terraform (funnel=true)" to the "Files NOT to touch" list.
  • [x] base source -- notion-mcp-remote k8s/ directory verified to contain deployment.yaml, service.yaml, pvc.yaml, servicemonitor.yaml, kustomization.yaml on main

Base Factoring Ambiguity (CRITICAL)

Issue body says: "references the base (either inline manifests from the service repo or a new bases/notion-mcp-remote/ if the pattern favours that)". This offers THREE options without choosing one. The convention is clear:
  • convention-kustomize-overlay specifies overlays consume bases/standard/ (placeholder name: app) + bases/servicemonitor/ with JSON6902 rename patches from app -> service name.
  • Confirmed by inspecting overlays/pal-e-docs/prod/kustomization.yaml -- uses ../../../bases/standard and ../../../bases/servicemonitor plus rename JSON6902 patches.
  • The existing notion-mcp-remote/k8s/ base already uses name: notion-mcp-remote (not app), so it CANNOT be consumed by the standard overlay pattern without modification.
  • The service also has a PVC and custom liveness/readiness probes on /health (not /healthz), plus Recreate strategy and custom port, so it doesn't neatly fit bases/standard either.
[BODY] Pick ONE approach and state it explicitly. Two viable choices:
  • Reference the service repo's k8s/ as a remote base (e.g. resources: - https://forgejo.tail5b443a.ts.net/forgejo_admin/notion-mcp-remote.git//k8s?ref=main). Overlay patches tag via images: transformer and tweaks prod-specific bits. This matches the terraform source_repo/source_path rollback story in convention-kustomize-overlay. Simpler for a service with non-standard shape (PVC, Recreate, /health probe).
  • Factor a new bases/notion-mcp-remote/-shaped base with the service's resources and rename them in the overlay. More work, diverges from bases/standard, and puts two copies of the deployment spec in two repos (service repo k8s/ + deployment repo bases/).
Recommend option 1. Update the File Targets section to spell it out.

Secret Name + Shape Mismatch (CRITICAL)

Issue body says:
Real secrets (NOTION_OAUTH_CLIENT_ID, NOTION_OAUTH_CLIENT_SECRET, SESSION_SECRET, ONBOARD_SECRET, BASE_URL) are provisioned via kubectl create secret generic ... Overlay references the secret by name via envFrom. ... envFrom: secretRef: name: notion-mcp-remote
But the existing base notion-mcp-remote/k8s/deployment.yaml on main already defines each env var via valueFrom: secretKeyRef: name: notion-mcp-secrets, key: {kebab-case}:
  • Secret name: notion-mcp-secrets (NOT notion-mcp-remote)
  • Shape: per-key secretKeyRef with kebab-case keys (oauth-client-id, oauth-client-secret, session-secret, onboard-secret, base-url) -- NOT envFrom
  • Env var names uppercase SCREAMING_SNAKE (NOTION_OAUTH_CLIENT_ID etc.) are injected via the per-key binding, not via envFrom (which would require matching uppercase keys in the secret)
So the overlay CANNOT just add envFrom: secretRef: name: notion-mcp-remote. Either:
  • Align the overlay with the existing base (keep secretKeyRef shape, keep name notion-mcp-secrets), in which case the deployment-patch doesn't need to touch env/secrets at all and the overlay is just image tag + prod tweaks; or
  • Change the base deployment in notion-mcp-remote/k8s/ to use envFrom and uppercase keys, AND change the sibling secret-creation ticket (notion-mcp-remote #7, arch:k8s-secret) to match. This is a bigger scope change that affects two repos.
[BODY] Resolve the mismatch. Recommended: pick option 1 -- state that the overlay does NOT need to patch secrets because the base already wires them correctly; the overlay only needs to pin image tag, set replicas/resources, and carry Image Updater annotations. Update Acceptance Criteria bullets about envFrom and secret name notion-mcp-remote to match: the secret name to be provisioned (per sibling ticket) must be notion-mcp-secrets with kebab-case keys.

Repo Placement

OK. Issue is filed on forgejo_admin/pal-e-deployments and File Targets are all overlays/notion-mcp-remote/prod/*. Correct repo. Service repo k8s manifests already exist (commits 455b62c, 837e2f2).

Dependencies

  • Hard prerequisite: Secret notion-mcp-secrets must exist in the target namespace BEFORE first ArgoCD sync (service-onboarding-sop step 3 warning). Tracked by notion-mcp-remote issue #7 (board item #1047, story:ops-deploy-gitops, arch:k8s-secret) -- NOT named in the issue body. [BODY] Name the sibling issue explicitly.
  • Downstream consumer: pal-e-services var.services entry (board item #1043, Forgejo pal-e-services#57) will set source_path = "overlays/notion-mcp-remote/prod". Overlay path name is contractual with that ticket -- must not change after this merges.
  • Downstream consumer: pal-e-platform issue #296 (board item #1045, arch:argocd) -- ArgoCD Application creation. Order: overlay lands -> secret provisioned -> tofu apply creates Application -> ArgoCD syncs.
  • Image tag: First-deploy bootstrap -- Image Updater writes newTag to overlay after Woodpecker pushes. Per convention, must set a placeholder newTag (issue says latest, but convention says full SHA format ^[0-9a-f]{7,40}$). [BODY] Change newTag: latest to "set newTag to the SHA from a successful Woodpecker build on main (Image Updater then rewrites). Do NOT use latest -- violates the tag regex ^[0-9a-f]{7,40}$ that Image Updater expects."

Acceptance Criteria

Mostly testable, but three gaps:
  • No AC covers the images: transformer entries (per convention there should be two: app-image -> harbor.../notion-mcp-remote/notion-mcp-remote with SHA, plus the Image Updater write-back target). [BODY] Add: "images: transformer in kustomization.yaml has both entries (app-image mapping and Harbor URL mapping) with matching newTag in full-SHA format."
  • "Container port 8000 matches Dockerfile EXPOSE" -- port 8000 is already set in the base deployment; unless overlay is overriding it, this AC is testing the base, not the overlay. [BODY] Either remove or rephrase as "Rendered Deployment keeps containerPort 8000 (no port override in overlay)."
  • AC about envFrom and secret name notion-mcp-remote will be obsolete after the secret-shape refinement above. [BODY] Rewrite to match whichever approach is chosen.

Blast Radius

Low. Single overlay in pal-e-deployments; no change to bases/standard, no change to other services' overlays. Overlay is inert until the pal-e-services ArgoCD Application points at it (#1043) AND the secret exists (#1047). Cannot break prod by merging this alone.
Follow-on risk: if base factoring option 2 (new bases/notion-mcp-remote/) is chosen, future changes to the service's deployment shape must be kept in sync across two repos -- avoid.

Decomposition Assessment

3 points, 2-3 files, 1 repo, ~6 AC. Fits single agent pass (<5 min). No decomposition needed.

Recommendation

NEEDS_REFINEMENT. Apply these fixes to the Forgejo issue body:
  • [BODY] Resolve base factoring ambiguity: pick option 1 (reference service repo's k8s/ as a remote base via git URL) and state it explicitly. Remove the "inline manifests from the service repo or a new bases/notion-mcp-remote/" alternatives.
  • [BODY] Fix secret name + shape mismatch. The existing base already uses secretKeyRef with secret name notion-mcp-secrets and kebab-case keys. The overlay should not patch env/secrets; the secret-provisioning sibling ticket (notion-mcp-remote#7) must create notion-mcp-secrets with keys oauth-client-id, oauth-client-secret, session-secret, onboard-secret, base-url.
  • [BODY] Name the sibling secret-provisioning ticket by URL in the Context/Dependencies section (notion-mcp-remote#7) so the dev agent can cross-check.
  • [BODY] Remove the "Possibly ingress.yaml" line from File Targets. Add an explicit "NOT to touch" entry: ingress.yaml is provisioned by pal-e-services terraform (funnel=true).
  • [BODY] Replace newTag: latest with SHA-format bootstrap per convention-kustomize-overlay Image Management section.
  • [BODY] Update Acceptance Criteria to (a) drop the envFrom/secret-name AC, (b) add an AC that the images: transformer has both entries with full-SHA newTag.
  • [SCOPE] Decide: drop the arch:kustomize-overlay label on the board item (kustomize-overlay is a platform convention, not a service-specific arch diagram; the service's arch is covered by arch-deployment-notion-mcp-remote). If kept, create arch-kustomize-overlay as a cross-service platform-level arch note.
Non-blocking: the ticket is well-structured and the sequence is correct; refinements above bring it into alignment with the existing pal-e-deployments pattern and the already-merged service base so the dev agent doesn't have to make these calls itself.