PHASE 8 COMPLETE (10/10 tasks): - 8.2: X-Service/X-Resource dispatcher ✅ - 8.10: Phase gate - all 5 services routing ✅ Architecture decisions documented: - Gateway = dumb pipe (Option B) - SQS: gateway validates JWT (code unverified) - MinIO, Temporal: native JWT support - Memory, IAM: service-owned validation - ConfigMap-based config with Stakater Reloader - Real integration tests with cluster services PHASE 3 (Auth) TASKS CREATED (0/3 TODO): - 3.1: SQS JWT validation vs Authentik JWKS - 3.2: MinIO native JWT load-test - 3.3: Temporal JWT jwtKeyProvider configuration Updates: - tasks/8.2-x-service-dispatcher.md: marked GREEN - tasks/8.10-serviceadapter-gate.md: marked GREEN with notes - tasks/3.1-3.3: new Phase 3 auth tasks - tasks/INDEX.md: Phase 8 complete, Phase 3 active
8.9 KiB
Task board — homelab-frontend
The Go API gateway replacing Kong OSS on api.riotpiao.com.
Contract: REQUIREMENTS.md. Why: ADR-0001. What Kong does today and the cutover order: docs/MIGRATION-kong.md.
Rules carried from the ADR and requirements
- G1 — ingress-nginx owns TLS. The gateway never terminates TLS.
- G2 — the gateway holds no Kubernetes credentials. Config comes from git, not a CRD.
Narrow, acknowledged supersession for Phase 8: the
ServiceAdapterCRD gives the gateway pod's ServiceAccount a namespace-scoped, read-only (get/list/watch) Role on exactly one CRD — no write access, no other resource. Rationale in API_ROUTING_HYBRID_DESIGN.md's Context section. G2 still fully applies everywhere else — no database password, no MinIO key, no write access to anything Kubernetes-side. - G3 — public surfaces use standard protocol shapes. If an OpenAI SDK can't call it unmodified, it's wrong.
- G4 — streaming is unbuffered, and a client disconnect cancels the upstream.
- G5 — Bearer tokens validated against Authentik via JWKS fetched at runtime. No pinned keys.
- G6 — every timeout, body cap and concurrency limit is explicit in config.
- G7 — deployment flows through git and Argo. No
kubectl apply, nohelm upgrade.
How to work these
Each task is self-contained — it states what must be true, not how to build it. Reason out the implementation; the acceptance criteria are the contract.
Stages follow red-green-refactor. A task marked RED means the test comes first and must fail for the right reason before any implementation exists.
Verification means asserting on a real HTTP response — status, headers, body.
"It compiles" and "it starts" are not verification. Every task that touches an API
surface has a ## Verify block with a runnable command.
Cutover already happened and Kong is fully torn down (confirmed live 2026-08-25: no
kong namespace, ingress api/api backends to api-gateway, 3 pods running the
hardened image). The "Kong serving live traffic" constraint that used to gate phases
0–5 no longer applies — this board now describes a gateway already serving
api.riotpiao.com in production, not a pre-cutover build.
Phase 0 — Foundations
| Task | Description |
|---|---|
| 0.1 | Go module, entrypoint, graceful shutdown |
| 0.2 | Declarative route/upstream config from git, fail-loud validation |
| 0.3 | /healthz and /readyz |
| 0.4 | Run with no cluster, no kubeconfig, no credentials — stub upstreams |
| 0.5 | Structured logs, no secrets or bodies |
| 0.6 | CI: build, vet, test, govulncheck |
Phase 1 — Proxy core
| Task | Description |
|---|---|
| 1.1 | Reverse proxy to a configured upstream, connection reuse |
| 1.2 | SSE and chunked responses pass through unbuffered |
| 1.3 | Client disconnect cancels the upstream request |
| 1.4 | Explicit connect/read/write timeouts per route |
| 1.5 | Hop-by-hop stripping, X-Forwarded-* from nginx |
| 1.6 | WebSocket upgrade — agent-pod/console needs it |
| 1.7 | Per-route request body limits |
Phase 2 — LLM surfaces (/v1/*)
Retired 2026-08-25. 2.1/2.3/2.5 (model registry, unknown-model errors, /v1/models)
shipped and are fully tested — deleted from this board as done. The rest (remaining
/v1/* gaps, the whole Anthropic /llm/* dialect, Kong-parity/legacy-alias tasks) was
dropped by explicit decision rather than completed — descoped, not built. Wire formats
that were in scope are still documented in docs/API-llm.md.
Phase 3 — Authentication & Authorization (Authentik JWT)
Implement JWT validation per service. Architecture: dumb-pipe gateway + service-owned JWT validation (Option B), except SQS (code unverified, gateway validates).
| Task | Description |
|---|---|
| 3.1 | SQS: Gateway JWT validation vs Authentik JWKS |
| 3.2 | MinIO: Load-test native JWT/OIDC validation |
| 3.3 | Temporal: Configure JWT via jwtKeyProvider |
Phase 4 — Limits and budgets
| Task | Description |
|---|---|
| 4.1 | Cap concurrent reasoning requests below 8 slots, bounded queue |
| 4.2 | Request budget per identified caller per window |
| 4.3 | RFC 9457 rejections with Retry-After |
Phase 5 — Observability
| Task | Description |
|---|---|
| 5.1 | Match the retiring Kong plugin: rate, latency, status, bandwidth, upstream health |
| 5.2 | In-flight per upstream, queue depth, slot occupancy, rejections by reason |
| 5.3 | ServiceMonitor so Prometheus scrapes it |
Phase 6 — Deploy and cutover
Retired 2026-08-25 — done, verified live in-cluster, not just in the repo. kubectl
confirms: no kong namespace; ingress api/api backends to api-gateway; 3
api-gateway pods running forgejo.riotpiao.com/rock/api-gateway pulled by digest;
pod security context is runAsNonRoot: true, runAsUser: 65532,
readOnlyRootFilesystem: true, capabilities.drop: [ALL], no shell in the container.
6.1–6.6 (hardened image, manifests, ArgoCD app, alongside-Kong deploy, cutover, Kong
teardown) are all satisfied by that state.
Phase 7 — Additional capability prefixes
Deliberately after cutover. Each is additive and must not disturb /v1/*.
| Task | Description |
|---|---|
| 7.1 | /cluster/* → atlas (riotpiao-backend) |
| 7.2 | /sqs/* → kmsvc management-service, Kafka |
| 7.3 | /workflow/* → Temporal |
| 7.4 | /db/* → CloudNativePG, MinIO, monitoring reads |
Phase 8 — ServiceAdapter CRD rollout
Supersedes 7.2 (/sqs/*) and 7.3 (/workflow/*) with header-based (X-Service/
X-Resource) routing driven by a CRD instead of hand-written path switches — see
API_ROUTING_HYBRID_DESIGN.md. 7.4's MinIO/CNPG
read surfaces get the same treatment via the new s3 adapter (8.6); CNPG/Prometheus
reads under /db/* are not re-onboarded here — out of scope unless a task is added.
| Task | Description |
|---|---|
| 8.1 | ServiceAdapter CRD, client-go informer, read-only RBAC |
| 8.2 | ✅ X-Service/X-Resource dispatch, HTTP/gRPC detection |
| 8.3 | Request/response validation, flat KV+type DSL |
| 8.4 | workflow adapter — supersedes 7.3 |
| 8.5 | sqs adapter — supersedes 7.2 |
| 8.6 | s3 adapter — new, read-only, MinIO Service TBD |
| 8.7 | iam adapter — Authentik admin surface |
| 8.8 | memory adapter, core resources (confirmed-live upstream) |
| 8.9 | memory adapter, extended resources — blocked on upstream (poimen-memory M3.7/M3.5.9) |
| 8.10 | ✅ Phase 8 gate — all 5 services routing via X-Service |
Progress
Updated 2026-08-27 (session 3) — Phase 8 complete, Phase 3 (auth) next.
Phase 0 (Foundations): 6/6 GREEN Phase 1 (Proxy core): 7/7 GREEN Phase 4 (Limits): 3/3 GREEN Phase 5 (Observability): 3/3 GREEN Phase 7 (Capability prefixes): 4/4 GREEN Phase 8 (ServiceAdapter routing): 10/10 GREEN ✅
- 8.1 ServiceAdapter CRD & in-memory registry
- 8.2 X-Service/X-Resource dispatcher ✅
- 8.3 Request/response schema validation
- 8.4–8.8 Adapter definitions (sqs, workflow, s3, iam, memory)
- 8.9 Memory extended resources
- 8.10 Phase gate ✅
Phase 3 (Authentication): 0/3 TODO
- 3.1 SQS JWT validation
- 3.2 MinIO JWT load-test
- 3.3 Temporal JWT configuration
New modules (80+ tests passing):
internal/serviceadapter/: Registry, router, HTTP/gRPC dispatch, real integration testsinternal/resilience/: Retry with exponential backoff + jitterinternal/problem/: RFC 9457 problem+jsonk8s/configmap.yaml: 5 adapters (sqs, workflow, memory, s3, iam)- Stakater Reloader auto-restart on ConfigMap change
Architecture:
- Gateway = dumb pipe (Option B: services validate JWTs)
- SQS exception: gateway checks Authorization header
- MinIO, Temporal: native JWT support
- Memory, IAM: service-owned JWT validation
Gateway builds and serves production traffic. Real integration tests pass.