Hostname swap step 1 — add additive api.pal-e-docs funnel via pal-e-deployments kustomize #278

Closed
opened 2026-04-11 20:42:38 +00:00 by forgejo_admin · 2 comments
Contributor

Type

Feature

Lineage

Discovered during 2026-04-11 architecture-routing review with Lucas. The product name (pal-e-docs.tail5b443a.ts.net) currently points at the FastAPI backend; the SvelteKit frontend lives at pal-e-production.tail5b443a.ts.net. This is the first step of a 7-step migration to swap the routing.

Scope review round 1: NEEDS_REFINEMENT (review-972-2026-04-11). Round 1 reviewer correctly identified that the original ticket scope (5 repos, 9 ACs, multi-step coordinated migration) violated the 5-minute rule. Round 2 addresses this by shrinking #278 to scope ONLY Step 1 (additive funnel — purely additive, zero blast radius) and filing the remaining 6 steps as a separate follow-up roadmap ticket.

Round 1 also raised these findings, addressed below:

  • [FALSE POSITIVE] arch-domain-pal-e-docs does not exist — REFUTED. Verified via mcp__pal-e-docs__list_notes(note_type="architecture", project="pal-e-docs"): the note exists with id=1410, created 2026-04-10. The round 1 reviewer's search missed it.
  • [REAL] file targets wrong — addressed: Option B (pal-e-deployments kustomize overlay) chosen to match the pattern already used by pal-e-production-funnel. The unmanaged pal-e-docs-funnel is NOT touched in this ticket — only an additive new funnel is created.
  • [REAL] arch:k8s-deploy has no backing arch note — accepted as known traceability debt. Used by sibling tickets (#234, #613, #973). A proper backing note for k8s-deploy components belongs in a future arch-deployment-pal-e-docs (the third leg of the triplet) and is out of scope here.
  • [REAL] decomposition needed — addressed: this ticket is now Step 1 of 7. Steps 2-7 are scoped in the follow-up roadmap ticket.

Repo

forgejo_admin/pal-e-deployments — kustomize overlays for ArgoCD. The pal-e-production-funnel precedent lives at overlays/pal-e-production/prod/ingress.yaml; this ticket adds a parallel overlay for the new API funnel.

User Story

As the Superuser (Lucas)
I want a new api.pal-e-docs.tail5b443a.ts.net Tailscale funnel that serves the existing FastAPI backend
So that the API has a stable forward-facing hostname that announces it is an API, with zero impact on the existing pal-e-docs.tail5b443a.ts.net ingress (no risk to current consumers)

Traces to: story:reader-browse on project-pal-e-docs.

Architecture

  • arch:notes — the notes component in arch-domain-pal-e-docs (id 1410). This funnel exposes the API surface that serves note-shaped resources.
  • arch:k8s-deploy — known traceability debt; no backing arch note exists yet (see Lineage)

Context

Current state (verified live 2026-04-11):

Funnel Namespace Backend service Management Status
pal-e-docs-funnel pal-e-docs pal-e-docs (FastAPI) unmanaged (hand-applied 2026-02-24, no IaC label) active, 46d old
pal-e-production-funnel pal-e-production frontend (nginx + SvelteKit) ArgoCD via ~/pal-e-deployments/overlays/pal-e-production/prod/ingress.yaml active, 7d old

This ticket adds a third funnel:

Funnel Namespace Backend service Management
pal-e-docs-api-funnel (new) pal-e-docs pal-e-docs (FastAPI, same namespace as the funnel — same-namespace ingress constraint satisfied trivially) ArgoCD via new overlay

After this ticket lands, both pal-e-docs.tail5b443a.ts.net AND api.pal-e-docs.tail5b443a.ts.net will serve the API. They are functionally redundant — the new hostname is additive only. No swap, no removal, no risk to existing consumers. The swap happens in a later ticket (Step 6).

Why Option B (kustomize) and not Option A (terraform import):

  • pal-e-production-funnel already uses kustomize. Matching the precedent is lower friction than introducing a parallel terraform-import code path.
  • The unmanaged pal-e-docs-funnel is left untouched — no risky terraform import step.
  • ArgoCD picks up new overlays automatically. No manual cluster apply.
  • Per pal-e-platform/CLAUDE.md: "Cluster: k3s with Tailscale funnels for ingress and TLS" — funnels CAN live in either layer; matching the existing per-app pattern is the lower-risk call.

Rationale (from round 1 — preserved verbatim because it remains the canonical decision record)

Considered three options for the overall migration: subdomain split, path-based split, content negotiation. Chose subdomain because:

  1. Migration cost is dramatically lower than path-based. Path-based would require renaming every API route from /notes/{slug} to /api/notes/{slug}, rippling through pal-e-sdk, pal-e-mcp, every CLAUDE.md curl example, every agent prompt, and every in-flight ticket. Subdomain requires changing two constants (SDK base URL and MCP base URL) plus a kustomize overlay.
  2. convention-spa-no-subpath-proxy is a hard constraint. Vite assets are absolute from /. Even if the SPA stays at root and only the API moves to /api/*, this paints us into a corner the moment a second SPA wants a subpath.
  3. The auth/cookie advantage of path-based is weaker than it sounds. SvelteKit adapter-node SSR hits the API backend-to-backend; cookies don't traverse host boundaries. With CORS middleware (#256), browser-side fetches work from a separate subdomain just fine.
  4. Pal-e-docs already follows a subdomain-per-service pattern (three funnels: pal-e-docs, pal-e-production, pal-e-streamlit). The fix is renaming/swapping within an existing pattern, not introducing a new architecture.
  5. Tailscale funnel "complexity" is overstated. A funnel is ~10 lines of YAML (kustomize) — the same module pattern used three times already.

Rejected content negotiation because it hides routing in code (varies-by-Accept caching pain), and would either reintroduce in-process Jinja2 (which Phase F35 explicitly sunset) or add a SvelteKit upstream proxy (complexity without benefit).

File Targets

Single repo, single PR:

  • overlays/pal-e-docs-api/prod/kustomization.yaml (new) — kustomization referencing ingress.yaml
  • overlays/pal-e-docs-api/prod/ingress.yaml (new) — Kubernetes Ingress + Tailscale funnel annotations for api.pal-e-docs.tail5b443a.ts.net, backend service pal-e-docs in pal-e-docs namespace, port matching the existing pal-e-docs-funnel service port

Use ~/pal-e-deployments/overlays/pal-e-production/prod/ingress.yaml as the template — copy structure, change hostname, change backend service ref, change name labels.

Files NOT to touch:

  • The unmanaged pal-e-docs-funnel ingress (the existing one) — explicitly not touched in this step
  • overlays/pal-e-production/ — frontend stays where it is
  • Any non-pal-e-deployments repo — this is a single-overlay change

Acceptance Criteria

  • New kustomize overlay at overlays/pal-e-docs-api/prod/ exists with kustomization.yaml and ingress.yaml
  • ingress.yaml defines a Kubernetes Ingress named pal-e-docs-api-funnel (or similar) in the pal-e-docs namespace, with host api.pal-e-docs.tail5b443a.ts.net and Tailscale funnel annotations matching the pal-e-production-funnel precedent
  • Backend service ref points at the existing pal-e-docs service in the pal-e-docs namespace, port matching the existing funnel
  • ArgoCD picks up the new overlay (visible in ArgoCD UI as a new application or sync target)
  • After ArgoCD sync: kubectl -n pal-e-docs get ingress shows BOTH pal-e-docs-funnel (existing, untouched) AND the new pal-e-docs-api-funnel
  • After Tailscale provisions the cert: curl -I https://api.pal-e-docs.tail5b443a.ts.net/notes/arch-westside-emails returns 200 with content-type: application/json
  • Existing pal-e-docs.tail5b443a.ts.net is unchanged — all current consumers continue working as before
  • No SDK, MCP, frontend, or downstream consumer changes in this PR

Test Expectations

  • Pre-deploy: kubectl get ingress -n pal-e-docs baseline captured
  • Post-deploy: same query shows both funnels, no errors in either ingress controller log
  • Smoke test 1: curl -I https://pal-e-docs.tail5b443a.ts.net/notes/arch-westside-emails returns 200 (regression check on existing hostname)
  • Smoke test 2: curl -I https://api.pal-e-docs.tail5b443a.ts.net/notes/arch-westside-emails returns 200 (new hostname works)
  • Smoke test 3: curl -s https://api.pal-e-docs.tail5b443a.ts.net/notes/arch-westside-emails | jq .id returns the same id as the existing hostname (same backing service, content parity)
  • MCP smoke test: hand-edit ~/.mcp.json (or equivalent) to point pal-e-docs MCP at the new hostname, run list_notes(limit=1), verify a result is returned. Then revert the MCP config — this is a smoke test only, NOT a permanent migration (that's Step 3).

Constraints

  • Purely additive — do NOT touch the existing pal-e-docs-funnel ingress
  • Match the kustomize overlay pattern from overlays/pal-e-production/prod/ exactly — same labels, same annotation style, same file structure
  • Do NOT introduce terraform — the funnel lives in kustomize, matching the precedent
  • Do NOT update SDK / MCP / frontend / CORS env var — those are subsequent steps in the follow-up roadmap ticket
  • This ticket must be reversible by kubectl delete ingress pal-e-docs-api-funnel -n pal-e-docs if anything goes wrong

Checklist

  • PR opened against pal-e-deployments main
  • Overlay structure mirrors overlays/pal-e-production/prod/
  • PR body includes the curl smoke tests showing new hostname returns 200
  • No unrelated changes
  • Follow-up roadmap ticket linked in PR body
  • forgejo_admin/pal-e-api#256dependency: CORS middleware. Even though Step 1 doesn't change browser fetches, the new API hostname must still serve correct CORS headers when consumed by the frontend in later steps.
  • forgejo_admin/pal-e-platform#280follow-up: hostname swap roadmap (Steps 2-7) — to be filed once this ticket is in flight or just before
  • arch-domain-pal-e-docs (id 1410) — the architecture diagram
  • convention-spa-no-subpath-proxy — the constraint that ruled out path-based routing
  • ~/pal-e-deployments/overlays/pal-e-production/prod/ingress.yaml — the template to copy from
  • review-972-2026-04-11 — the round 1 review that drove this decomposition
### Type Feature ### Lineage Discovered during 2026-04-11 architecture-routing review with Lucas. The product name (`pal-e-docs.tail5b443a.ts.net`) currently points at the FastAPI backend; the SvelteKit frontend lives at `pal-e-production.tail5b443a.ts.net`. This is the **first step** of a 7-step migration to swap the routing. **Scope review round 1:** NEEDS_REFINEMENT (review-972-2026-04-11). Round 1 reviewer correctly identified that the original ticket scope (5 repos, 9 ACs, multi-step coordinated migration) violated the 5-minute rule. Round 2 addresses this by **shrinking #278 to scope ONLY Step 1** (additive funnel — purely additive, zero blast radius) and filing the remaining 6 steps as a separate follow-up roadmap ticket. Round 1 also raised these findings, addressed below: - **[FALSE POSITIVE] `arch-domain-pal-e-docs` does not exist** — REFUTED. Verified via `mcp__pal-e-docs__list_notes(note_type="architecture", project="pal-e-docs")`: the note exists with id=1410, created 2026-04-10. The round 1 reviewer's search missed it. - **[REAL] file targets wrong** — addressed: Option B (pal-e-deployments kustomize overlay) chosen to match the pattern already used by `pal-e-production-funnel`. The unmanaged `pal-e-docs-funnel` is NOT touched in this ticket — only an additive new funnel is created. - **[REAL] arch:k8s-deploy has no backing arch note** — accepted as known traceability debt. Used by sibling tickets (#234, #613, #973). A proper backing note for k8s-deploy components belongs in a future `arch-deployment-pal-e-docs` (the third leg of the triplet) and is out of scope here. - **[REAL] decomposition needed** — addressed: this ticket is now Step 1 of 7. Steps 2-7 are scoped in the follow-up roadmap ticket. ### Repo `forgejo_admin/pal-e-deployments` — kustomize overlays for ArgoCD. The `pal-e-production-funnel` precedent lives at `overlays/pal-e-production/prod/ingress.yaml`; this ticket adds a parallel overlay for the new API funnel. ### User Story As the Superuser (Lucas) I want a new `api.pal-e-docs.tail5b443a.ts.net` Tailscale funnel that serves the existing FastAPI backend So that the API has a stable forward-facing hostname that announces it is an API, with zero impact on the existing `pal-e-docs.tail5b443a.ts.net` ingress (no risk to current consumers) Traces to: `story:reader-browse` on `project-pal-e-docs`. ### Architecture - `arch:notes` — the `notes` component in `arch-domain-pal-e-docs` (id 1410). This funnel exposes the API surface that serves note-shaped resources. - `arch:k8s-deploy` — known traceability debt; no backing arch note exists yet (see Lineage) ### Context **Current state (verified live 2026-04-11):** | Funnel | Namespace | Backend service | Management | Status | |---|---|---|---|---| | `pal-e-docs-funnel` | `pal-e-docs` | `pal-e-docs` (FastAPI) | **unmanaged** (hand-applied 2026-02-24, no IaC label) | active, 46d old | | `pal-e-production-funnel` | `pal-e-production` | frontend (nginx + SvelteKit) | ArgoCD via `~/pal-e-deployments/overlays/pal-e-production/prod/ingress.yaml` | active, 7d old | **This ticket adds a third funnel:** | Funnel | Namespace | Backend service | Management | |---|---|---|---| | `pal-e-docs-api-funnel` (new) | `pal-e-docs` | `pal-e-docs` (FastAPI, **same namespace as the funnel — same-namespace ingress constraint satisfied trivially**) | ArgoCD via new overlay | After this ticket lands, both `pal-e-docs.tail5b443a.ts.net` AND `api.pal-e-docs.tail5b443a.ts.net` will serve the API. They are functionally redundant — the new hostname is **additive only**. No swap, no removal, no risk to existing consumers. The swap happens in a later ticket (Step 6). **Why Option B (kustomize) and not Option A (terraform import):** - `pal-e-production-funnel` already uses kustomize. Matching the precedent is lower friction than introducing a parallel terraform-import code path. - The unmanaged `pal-e-docs-funnel` is left untouched — no risky `terraform import` step. - ArgoCD picks up new overlays automatically. No manual cluster apply. - Per `pal-e-platform/CLAUDE.md`: "Cluster: k3s with Tailscale funnels for ingress and TLS" — funnels CAN live in either layer; matching the existing per-app pattern is the lower-risk call. ### Rationale (from round 1 — preserved verbatim because it remains the canonical decision record) Considered three options for the overall migration: subdomain split, path-based split, content negotiation. Chose **subdomain** because: 1. **Migration cost is dramatically lower than path-based.** Path-based would require renaming every API route from `/notes/{slug}` to `/api/notes/{slug}`, rippling through `pal-e-sdk`, `pal-e-mcp`, every CLAUDE.md curl example, every agent prompt, and every in-flight ticket. Subdomain requires changing **two constants** (SDK base URL and MCP base URL) plus a kustomize overlay. 2. **`convention-spa-no-subpath-proxy` is a hard constraint.** Vite assets are absolute from `/`. Even if the SPA stays at root and only the API moves to `/api/*`, this paints us into a corner the moment a second SPA wants a subpath. 3. **The auth/cookie advantage of path-based is weaker than it sounds.** SvelteKit `adapter-node` SSR hits the API backend-to-backend; cookies don't traverse host boundaries. With CORS middleware (#256), browser-side fetches work from a separate subdomain just fine. 4. **Pal-e-docs already follows a subdomain-per-service pattern** (three funnels: `pal-e-docs`, `pal-e-production`, `pal-e-streamlit`). The fix is renaming/swapping within an existing pattern, not introducing a new architecture. 5. **Tailscale funnel "complexity" is overstated.** A funnel is ~10 lines of YAML (kustomize) — the same module pattern used three times already. Rejected content negotiation because it hides routing in code (varies-by-Accept caching pain), and would either reintroduce in-process Jinja2 (which Phase F35 explicitly sunset) or add a SvelteKit upstream proxy (complexity without benefit). ### File Targets **Single repo, single PR:** - `overlays/pal-e-docs-api/prod/kustomization.yaml` (new) — kustomization referencing `ingress.yaml` - `overlays/pal-e-docs-api/prod/ingress.yaml` (new) — Kubernetes Ingress + Tailscale funnel annotations for `api.pal-e-docs.tail5b443a.ts.net`, backend service `pal-e-docs` in `pal-e-docs` namespace, port matching the existing `pal-e-docs-funnel` service port Use `~/pal-e-deployments/overlays/pal-e-production/prod/ingress.yaml` as the template — copy structure, change hostname, change backend service ref, change name labels. **Files NOT to touch:** - The unmanaged `pal-e-docs-funnel` ingress (the existing one) — explicitly not touched in this step - `overlays/pal-e-production/` — frontend stays where it is - Any non-pal-e-deployments repo — this is a single-overlay change ### Acceptance Criteria - [ ] New kustomize overlay at `overlays/pal-e-docs-api/prod/` exists with `kustomization.yaml` and `ingress.yaml` - [ ] `ingress.yaml` defines a Kubernetes Ingress named `pal-e-docs-api-funnel` (or similar) in the `pal-e-docs` namespace, with host `api.pal-e-docs.tail5b443a.ts.net` and Tailscale funnel annotations matching the `pal-e-production-funnel` precedent - [ ] Backend service ref points at the existing `pal-e-docs` service in the `pal-e-docs` namespace, port matching the existing funnel - [ ] ArgoCD picks up the new overlay (visible in ArgoCD UI as a new application or sync target) - [ ] After ArgoCD sync: `kubectl -n pal-e-docs get ingress` shows BOTH `pal-e-docs-funnel` (existing, untouched) AND the new `pal-e-docs-api-funnel` - [ ] After Tailscale provisions the cert: `curl -I https://api.pal-e-docs.tail5b443a.ts.net/notes/arch-westside-emails` returns `200` with `content-type: application/json` - [ ] Existing `pal-e-docs.tail5b443a.ts.net` is **unchanged** — all current consumers continue working as before - [ ] No SDK, MCP, frontend, or downstream consumer changes in this PR ### Test Expectations - [ ] Pre-deploy: `kubectl get ingress -n pal-e-docs` baseline captured - [ ] Post-deploy: same query shows both funnels, no errors in either ingress controller log - [ ] Smoke test 1: `curl -I https://pal-e-docs.tail5b443a.ts.net/notes/arch-westside-emails` returns 200 (regression check on existing hostname) - [ ] Smoke test 2: `curl -I https://api.pal-e-docs.tail5b443a.ts.net/notes/arch-westside-emails` returns 200 (new hostname works) - [ ] Smoke test 3: `curl -s https://api.pal-e-docs.tail5b443a.ts.net/notes/arch-westside-emails | jq .id` returns the same id as the existing hostname (same backing service, content parity) - [ ] MCP smoke test: hand-edit `~/.mcp.json` (or equivalent) to point pal-e-docs MCP at the new hostname, run `list_notes(limit=1)`, verify a result is returned. Then revert the MCP config — this is a smoke test only, NOT a permanent migration (that's Step 3). ### Constraints - Purely additive — do NOT touch the existing `pal-e-docs-funnel` ingress - Match the kustomize overlay pattern from `overlays/pal-e-production/prod/` exactly — same labels, same annotation style, same file structure - Do NOT introduce terraform — the funnel lives in kustomize, matching the precedent - Do NOT update SDK / MCP / frontend / CORS env var — those are subsequent steps in the follow-up roadmap ticket - This ticket must be reversible by `kubectl delete ingress pal-e-docs-api-funnel -n pal-e-docs` if anything goes wrong ### Checklist - [ ] PR opened against `pal-e-deployments` main - [ ] Overlay structure mirrors `overlays/pal-e-production/prod/` - [ ] PR body includes the curl smoke tests showing new hostname returns 200 - [ ] No unrelated changes - [ ] Follow-up roadmap ticket linked in PR body ### Related - `forgejo_admin/pal-e-api#256` — **dependency**: CORS middleware. Even though Step 1 doesn't change browser fetches, the new API hostname must still serve correct CORS headers when consumed by the frontend in later steps. - `forgejo_admin/pal-e-platform#280` — **follow-up**: hostname swap roadmap (Steps 2-7) — to be filed once this ticket is in flight or just before - `arch-domain-pal-e-docs` (id 1410) — the architecture diagram - `convention-spa-no-subpath-proxy` — the constraint that ruled out path-based routing - `~/pal-e-deployments/overlays/pal-e-production/prod/ingress.yaml` — the template to copy from - `review-972-2026-04-11` — the round 1 review that drove this decomposition
Author
Contributor

Scope Review: NEEDS_REFINEMENT

Review note: review-972-2026-04-11

Rationale is strong (subdomain-vs-path-vs-content-neg decision is the best part of this ticket and should survive decomposition verbatim). Blockers are scoping gaps in file targets, traceability, and size.

Blockers:

  • [BODY/SCOPE] File targets do not match reality. Claimed terraform/k3s-funnels.tf does not exist. Live cluster inspection shows pal-e-docs-funnel is unmanaged (hand-applied 2026-02-24, no argocd label, no terraform, no kustomize) and pal-e-production-funnel is managed by pal-e-deployments (ArgoCD), NOT pal-e-platform. Must decide Option A (import into pal-e-platform terraform networking module — triggers cross-namespace ingress refactor) vs Option B (manage via pal-e-deployments kustomize overlays — this ticket then belongs in pal-e-deployments, not pal-e-platform). Repo placement is likely wrong.
  • [SCOPE] arch:k8s-deploy has no backing note. arch-k8s-deploy doesn't exist in pal-e-docs, and the tag itself isn't registered (only arch:jersey-intake is a real arch tag). Same gap blocks sibling #279. Create the arch note with the project-pal-e-docs#architecture mermaid as seed content.
  • [SCOPE] arch:notes has no backing note, and arch-domain-pal-e-docs (cited in body and Related) does not exist as a slug. Hallucinated reference — either create the note or point Related at project-pal-e-docs#architecture.
  • [DECOMPOSE] 5-minute rule fails. 5 repos, 9 AC, platform-PR alone is ~15–25 min given the unmanaged-ingress discovery. Route to skill-decompose-ticket with seeds 972a–972g (additive-funnel → sdk → mcp → api-cors-env → app → swap → decom) from the review note. Each sub-ticket is a clean single-repo, single-PR, <5-min pass. Keep #278 as umbrella; preserve the Rationale section.

Non-blockers (also fix during refine):

  • [BODY] "redirect OR decommission old pal-e-production hostname (decide during execution)" — resolve up front, not at apply time.
  • [BODY] Call out k8s Ingress same-namespace backend constraint.
  • [BODY] Add pre-cutover MCP smoke test matrix to blast-radius checklist.

Verified good:

  • story:reader-browse exists in project-pal-e-docs user-stories ✓
  • Dependency pal-e-api#256 (CORS middleware) open and correctly scoped ✓
  • Rationale faithfully captures the three-option decision ✓
  • Acceptance criteria are machine-verifiable ✓

Not ready for todo. Return to Ava for SCOPE decisions (arch notes + Option A/B), refine, re-review.

## Scope Review: NEEDS_REFINEMENT Review note: `review-972-2026-04-11` Rationale is strong (subdomain-vs-path-vs-content-neg decision is the best part of this ticket and should survive decomposition verbatim). Blockers are scoping gaps in file targets, traceability, and size. **Blockers:** - **[BODY/SCOPE] File targets do not match reality.** Claimed `terraform/k3s-funnels.tf` does not exist. Live cluster inspection shows `pal-e-docs-funnel` is **unmanaged** (hand-applied 2026-02-24, no argocd label, no terraform, no kustomize) and `pal-e-production-funnel` is managed by **pal-e-deployments** (ArgoCD), NOT pal-e-platform. Must decide Option A (import into pal-e-platform terraform networking module — triggers cross-namespace ingress refactor) vs Option B (manage via pal-e-deployments kustomize overlays — this ticket then belongs in pal-e-deployments, not pal-e-platform). Repo placement is likely wrong. - **[SCOPE] `arch:k8s-deploy` has no backing note.** `arch-k8s-deploy` doesn't exist in pal-e-docs, and the tag itself isn't registered (only `arch:jersey-intake` is a real arch tag). Same gap blocks sibling #279. Create the arch note with the project-pal-e-docs#architecture mermaid as seed content. - **[SCOPE] `arch:notes` has no backing note, and `arch-domain-pal-e-docs` (cited in body and Related) does not exist as a slug.** Hallucinated reference — either create the note or point Related at `project-pal-e-docs#architecture`. - **[DECOMPOSE] 5-minute rule fails.** 5 repos, 9 AC, platform-PR alone is ~15–25 min given the unmanaged-ingress discovery. Route to `skill-decompose-ticket` with seeds 972a–972g (additive-funnel → sdk → mcp → api-cors-env → app → swap → decom) from the review note. Each sub-ticket is a clean single-repo, single-PR, <5-min pass. Keep #278 as umbrella; preserve the Rationale section. **Non-blockers (also fix during refine):** - [BODY] "redirect OR decommission old pal-e-production hostname (decide during execution)" — resolve up front, not at apply time. - [BODY] Call out k8s Ingress same-namespace backend constraint. - [BODY] Add pre-cutover MCP smoke test matrix to blast-radius checklist. **Verified good:** - story:reader-browse exists in project-pal-e-docs user-stories ✓ - Dependency pal-e-api#256 (CORS middleware) open and correctly scoped ✓ - Rationale faithfully captures the three-option decision ✓ - Acceptance criteria are machine-verifiable ✓ Not ready for todo. Return to Ava for SCOPE decisions (arch notes + Option A/B), refine, re-review.
forgejo_admin changed title from Swap hostname routing — pal-e-docs.ts.net serves frontend, api.pal-e-docs.ts.net serves API to Hostname swap step 1 — add additive api.pal-e-docs funnel via pal-e-deployments kustomize 2026-04-11 21:02:24 +00:00
Author
Contributor

Scope Review: APPROVED (round 2)

Review note: review-972-2026-04-11-r2

Round 2 resolves every round 1 finding. Scope is now single-repo, two-new-files, additive-only, fits the 5-minute rule.

Round 1 findings — status:

  • [FALSE POSITIVE] arch-domain-pal-e-docs missing — refuted, note id=1410 exists (round 1 search missed it)
  • [REAL] wrong file targets — resolved, pivoted to Option B, precedent overlays/pal-e-production/prod/ingress.yaml verified
  • [REAL] decomposition needed — resolved, Steps 2-7 filed as #280 (verified open)
  • [REAL] arch:k8s-deploy no backing note — accepted as known debt, consistent with sibling tickets #234/#613/#973
  • [REAL] deferred decisions — resolved, all moved to #280
  • [REAL] same-namespace constraint — trivially satisfied, both live in pal-e-docs namespace

Verification performed:

  • arch-domain-pal-e-docs id=1410 confirmed live
  • story:reader-browse confirmed in project-pal-e-docs#user-stories table
  • Precedent ingress (16 lines) inspected — copy-edit is <5 min
  • ~/pal-e-deployments/overlays/pal-e-docs/prod/ confirmed to NOT contain an ingress.yaml (existing funnel is unmanaged — safe to add a new overlay next to it)
  • Service rename to pal-e-docs confirmed in existing kustomization
  • Follow-up issue #280 verified open

Decomposition: No further split. 2 files, 1 repo, 8 ACs that are all verification facets of one atomic change.

Minor non-blocking nit:

  • [LABEL] Board item #972 display title still reflects round 1 framing ("Swap hostname routing…"). Optional: update to match current issue title. Not a blocker.

Ready to advance backlog → todo when Ava dispatches.

## Scope Review: APPROVED (round 2) Review note: `review-972-2026-04-11-r2` Round 2 resolves every round 1 finding. Scope is now single-repo, two-new-files, additive-only, fits the 5-minute rule. **Round 1 findings — status:** - [FALSE POSITIVE] `arch-domain-pal-e-docs` missing — **refuted**, note id=1410 exists (round 1 search missed it) - [REAL] wrong file targets — **resolved**, pivoted to Option B, precedent `overlays/pal-e-production/prod/ingress.yaml` verified - [REAL] decomposition needed — **resolved**, Steps 2-7 filed as #280 (verified open) - [REAL] `arch:k8s-deploy` no backing note — **accepted as known debt**, consistent with sibling tickets #234/#613/#973 - [REAL] deferred decisions — **resolved**, all moved to #280 - [REAL] same-namespace constraint — **trivially satisfied**, both live in `pal-e-docs` namespace **Verification performed:** - `arch-domain-pal-e-docs` id=1410 confirmed live - `story:reader-browse` confirmed in `project-pal-e-docs#user-stories` table - Precedent ingress (16 lines) inspected — copy-edit is <5 min - `~/pal-e-deployments/overlays/pal-e-docs/prod/` confirmed to NOT contain an `ingress.yaml` (existing funnel is unmanaged — safe to add a new overlay next to it) - Service rename to `pal-e-docs` confirmed in existing kustomization - Follow-up issue #280 verified open **Decomposition:** No further split. 2 files, 1 repo, 8 ACs that are all verification facets of one atomic change. **Minor non-blocking nit:** - `[LABEL]` Board item #972 display title still reflects round 1 framing ("Swap hostname routing…"). Optional: update to match current issue title. Not a blocker. **Ready to advance backlog → todo** when Ava dispatches.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/pal-e-platform#278
No description provided.