test(visibility): full suite green under RLS — sync paths, device-auth bridge, seed pool

Phase 5 (plan §7): the entire integration suite passes with the RLS
policies live. The suite was the triage enumerator the plan predicted:

- device_auth middleware: the THIRD identity bridge — KOReader/Kobo
  device-authenticated requests read media as the DEVICE OWNER
  (plan A9 called this path out; the flip was 404s on sync metadata).
- conflicts/analytics/progress handlers: detached
  context.Background() reads threaded to the request context (the
  requesting user's identity) — 12+ sites; resolve helpers take ctx.
- scanner: ScanFolders self-declares its configured admin identity
  (server maintenance, product-correct for any caller); generic job
  creation stamps the requesting admin.
- harness: setup.DBPool and the sync-test pool declare
  rls.SeedIdentity at SESSION scope via BeforeAcquire — the pool never
  serves a second identity, so no A3 bleed; setup.DB falls back to the
  seed identity (NewSeedDB) for ungoverned-context calls; filter tests
  use seedExec for raw governed-table statements.
- contract pin WIDENED (docs/contract_pins.md 2026-10-29): under RLS,
  item-scoped gates may answer 404 (row invisible — no existence leak)
  as well as 403 (Go-level checks on listings keep strict 403).
- TestWorker_JobStatusTracking — the pre-existing red from the Phase 0
  baseline — passes with the harness seed work; no product change.
This commit is contained in:
John O'Keefe committed 2026-10-29 10:14:08 -04:00
1 parent bb2cc26e9d
commit 4d697f5fcf
7 files changed
+84 -38

No files matched your search

+8
View File
@@ -2,6 +2,7 @@ package middleware
import (
"bookhoard/internal/database"
"bookhoard/internal/rls"
"context"
"net/http"
"strconv"
@@ -183,6 +184,13 @@ func (m *DeviceAuthMiddleware) Authenticate(next echo.HandlerFunc) echo.HandlerF
c.Set("device_ctx", ctx)
c.Set("device_id", device.ID.Bytes)
// RLS bridge (plan §5.1/A9): device-authenticated requests
// (KOReader/Kobo sync) read media as the DEVICE OWNER — echo's
// c.Set is echo-local, so the stdlib request context needs the
// identity explicitly or every governed read raises.
c.SetRequest(c.Request().WithContext(context.WithValue(
c.Request().Context(), rls.CtxKeyUserID, device.UserID)))
return next(c)
}
}