SCRUM-223 — Patch service foundation¶
Plan ref: PAT-B1 (docs/11-admin-plane-plan.md). Replaces the fmt.Println stub in
services/patch (module path fixed to github.com/tanukifurhire/otomo/services/patch).
What exists¶
Ported from services/config's skeleton (same code, PATCH_* names):
| Piece | Notes |
|---|---|
patch serve (default) |
no migrate: Patch owns no schema; it reads Config's DB as patch_ro |
| Config | listen/metrics addrs, PATCH_DATABASE_URL, PATCH_BLOB_ROOT (read-only mount), staff JWKS URL/issuer/audience/refresh + clock skew (for dev/staging manifests), PATCH_POLL_INTERVAL (60s, for SCRUM-225), timeouts, log level |
internal/auth |
Config's staff verifier, copied verbatim; constructed and counted in readiness, no route uses it yet |
internal/blob |
read-only root check only (a directory stat); Patch never writes blobs |
| Public listener | only a COM-5 404 catch-all |
| Internal listener | /healthz, /readyz, /metrics (patch_*), pprof |
/readyz |
Postgres and staff JWKS has keys and blob root is a directory and manifests loaded. The manifest check is a placeholder returning manifests not loaded until SCRUM-224, so 503 is expected for now |
dockerfile, .env.example, README.md |
distroless nonroot, serve |
How to verify¶
cd services/patch
go vet ./... && go test -race -count=1 ./...
PATCH_TEST_DATABASE_URL='postgres://USER:PASS@127.0.0.1:5433/config_test?sslmode=disable' go test -count=1 ./internal/store/
go build -o /tmp/patch . && PATCH_DATABASE_URL=… PATCH_BLOB_ROOT=/some/dir \
PATCH_STAFF_JWKS_URL=http://127.0.0.1:18180/.well-known/jwks.json /tmp/patch &
curl -i localhost:9090/readyz # 503 until SCRUM-224 (first failing check is named)
curl -i localhost:8080/healthz # 404 COM-5 (internal only)
Results at time of writing¶
go vet,go test -race(4 packages, incl. DB readiness) pass.- Binary:
/readyz503 naming the first failing check (with no JWKS reachable:staff jwks not fetched yet …);/healthz404 on the public port; 16patch_*series. Themanifests not loadedbranch is covered byinternal/server/server_test.gowith injected checks.
How it was built¶
DeepSeek run scoped (Landlock) to services/patch (167 s, ~33k output tokens),
adapting services/config. Claude review: diffed against Config, binary run.