// Package web is the multi-user HTTP read/write surface (ADR-012, docs/ui-spec.md). // It serves the summary reader over the existing store; the engine and ports are // untouched (ADR-003). ADR-011 shipped this as a single-user Stage-0 reader; ADR-012 // opened Stage 1 — multiple Dex-authenticated users with DB-enforced (RLS) isolation. // // This file defines the auth SEAM so the Dex session layer (internal/web/oidc) // and the page/handler layer can be built independently: handlers depend only on // the Auth interface, never on a concrete provider. StubAuth is the allow-all // dev/test impl; oidc.DexAuth is the production impl wired in cmd/tapir. package web import "net/http" // User is the authenticated principal. Subject is the Dex subject — the key for the // user_identities lookup (ADR-012) that resolves to a tapir user_id (UUID); store // operations scope every row by that id, not by this subject. A subject with no // users row is routed through the registration gate (see registration.go). type User struct { Subject string Email string } // Auth gates routes and exposes the current user. Implementations: StubAuth // (dev/test, allow-all) and oidc.DexAuth (Dex OIDC session, lane B). type Auth interface { // Middleware wraps h, redirecting/refusing unauthenticated requests. Middleware(h http.Handler) http.Handler // CurrentUser returns the authenticated user for a request. CurrentUser(r *http.Request) (User, bool) // Routes returns the auth endpoints to mount under /auth/ (login, callback, // logout). StubAuth returns an empty mux. Routes() http.Handler } // StubAuth allows every request as a fixed user. Default for local dev/tests; // replaced by oidc.DexAuth when Dex config is present (decided in cmd/tapir). type StubAuth struct{ U User } func (s StubAuth) Middleware(h http.Handler) http.Handler { return h } func (s StubAuth) CurrentUser(*http.Request) (User, bool) { return s.U, true } func (s StubAuth) Routes() http.Handler { return http.NewServeMux() }