wip(rls): engine-side fail-loud + harness seed identity [pin: work interrupted]
Design correction discovered by the auth chicken-and-egg: the decorator-level refusal was re-created a convention gate (plan B thinking). ScopedDB now NEVER refuses — it declares the GUC when the context carries an identity and declares nothing otherwise; the ENGINE is the fail-loud layer (policies raise on governed tables, ungoverned tables like auth lookups simply work). rls.WithInternal removed as a dead concept. - search service's raw DBTX path now receives the ScopedDB itself (main.go + harness) — a bare pool bypassed the GUC. - database/schema.go: migration tx declares a synthetic identity (schema.sql's dedup DO block SELECTs media_items; with policies live, boot 2 raised 'unrecognized configuration parameter' — A11). - harness: TestServerSetup.DB is a raw-pool SEED handle (write policies permissive, other seeded tables ungoverned); the server under test keeps the scoped wiring. 33 CreateMediaItem sites use seedCtx() — a seed identity with no visibility rows — because RETURNING requires SELECT visibility of the new row. - invariant test: regex UUID-scraping replaced with a structured JSON decode of the sections payload. INTERRUPTION NOTE: an edit to this same effect (seedCtx) was applied, confirmed by the tool, and subsequently vanished from disk while an 'opencode serve' process (PID 84551) is alive on the machine. This commit pins the tree against further loss; implementation is PAUSED pending the user killing that process.
This commit is contained in:
1 parent
004d4197a4
commit
8c3d919aa0
19 files changed
+124
-111
No files matched your search
@@ -178,6 +178,16 @@ func verifyFunctions(ctx context.Context, db *pgxpool.Pool, expectedFunctions []
|
||||
return nil
|
||||
}
|
||||
|
||||
// schemaMigrationIdentity is the synthetic identity the schema
|
||||
// migration transaction declares for RLS (plan appendix A11). The
|
||||
// schema's dedup DO block SELECTs/DELETEs media_items, and with the
|
||||
// visibility policies live (FORCE applies to the owner) that SELECT
|
||||
// needs app.user_id set even in this maintenance tx. The identity has
|
||||
// NO library_visibility rows, so the policy grants it full visibility
|
||||
// — appropriate for the server's own schema pass, and unreachable by
|
||||
// requests (this tx only ever runs at startup, on the raw pool).
|
||||
const schemaMigrationIdentity = "00000000-0000-0000-0000-000000000001"
|
||||
|
||||
// executeSchema runs the entire schema.sql in a single transaction
|
||||
func executeSchema(ctx context.Context, db *pgxpool.Pool) error {
|
||||
tx, err := db.Begin(ctx)
|
||||
@@ -186,6 +196,12 @@ func executeSchema(ctx context.Context, db *pgxpool.Pool) error {
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
// Declare the migration identity BEFORE the file executes (A11):
|
||||
// policy'd tables are queried by schema.sql itself on re-runs.
|
||||
if _, err := tx.Exec(ctx, `SELECT set_config('app.user_id', $1, true)`, schemaMigrationIdentity); err != nil {
|
||||
return fmt.Errorf("schema execution failed (declare migration identity): %w", err)
|
||||
}
|
||||
|
||||
_, err = tx.Exec(ctx, SchemaFile)
|
||||
if err != nil {
|
||||
log.Printf("HINT: Run manually to debug: psql -h localhost -U postgres -d bookhoard -f database/schema/schema.sql")
|
||||
|
||||
Reference in new issue
Block a user