Files
homelab-frontend/tasks/7.4-db-prefix.md
T
Story Crater BotandClaude Opus 5 058f11cf2b
CI / Test (push) Canceled after 0s
CI / Vet (push) Canceled after 0s
CI / Build (push) Canceled after 0s
CI / Security (govulncheck) (push) Canceled after 0s
chore: initial commit of Go API gateway
Baseline for the Kong replacement on api.riotpiao.com. Brings the working
tree under version control for the first time: gateway source, the task
board that drives the agent runs, test fixtures, and K8s manifests.

Anchor the gateway ignore rule to the repo root. Unanchored, "gateway"
also matched the cmd/gateway/ source directory, so the program entrypoint
was excluded from every commit.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-19 20:54:34 -07:00

2.4 KiB

7.4 — /db/* read surfaces (GREEN)

Phase: 7 — Additional capability prefixes Stage: GREEN Depends on: 6.5

The most dangerous prefix in this phase. G2 says the gateway holds no cluster credentials — so it cannot be the thing that authenticates to CloudNativePG, MinIO or Prometheus on a caller's behalf. If designing this route makes you want to give the gateway a secret, the design is wrong: put the credential-holding logic in a service behind the gateway and proxy to that.

  • /db/* on api.riotpiao.com exposes read surfaces backed by CloudNativePG, MinIO and monitoring
  • The gateway holds no database password, no MinIO access key and no cluster credential of any kind (G2). Credentials, if any are needed, live in the service being proxied to
  • Exposed operations are read-only. There is no write, no delete and no schema-changing path on this prefix
  • Which sub-paths reach which upstream is enumerated explicitly in configuration. No catch-all, no pass-through of arbitrary query text
  • Timeouts and body caps are explicit per sub-route, with no silent defaults (G6)
  • The route requires authentication and the token is checked for a distinct read capability
  • Result sets are paginated with a bounded page size; an unbounded read cannot be requested
  • The NetworkPolicy is extended only to the specific upstreams reached. Note prometheus-operated.monitoring is headless with ClusterIP None, so it needs a pod selector, not a ClusterIP
  • /v1/* behaviour is unchanged before and after
  • Metrics and rejection counters cover this route with its own route label

Verify

curl -s -o /dev/null -w '%{http_code}\n' https://api.riotpiao.com/db/healthz
# expected: 401 without a token

curl -s -o /dev/null -w '%{http_code}\n' -X DELETE -H "authorization: Bearer $DB_READ_TOKEN" \
  https://api.riotpiao.com/db/anything
# expected: 405 or 404 — no mutating method is routable on this prefix

kubectl -n api get pod -l app=homelab-frontend -o jsonpath='{range .items[0].spec.containers[0].env[*]}{.name}{"\n"}{end}' \
  | grep -Ei 'password|secret|access_key'
# expected: no output — the gateway carries no database or object-store credentials

curl -s -H "authorization: Bearer $DB_READ_TOKEN" 'https://api.riotpiao.com/db/...?limit=100000' \
  | python3 -c "import json,sys;d=json.load(sys.stdin);print(len(d['items']))"
# expected: capped at the configured maximum page size, not 100000