Skip to content

Commit 76c5447

Browse files
authored
fix(db): complete artifact intent insert acl (#148)
## Summary - add the missing column-level `INSERT` grant for `v2_artifact_upload_intents.quiesced_at` to the single clean baseline - assert that exact grant in production schema validation - assert that the agent role still has no table-wide update access ## Why Drizzle emits the nullable `quiesced_at` column as `DEFAULT` when reserving an artifact upload. PostgreSQL therefore requires column-level insert permission even though application code omits the field. Production logs showed this exact permission failure after the preceding ownership-query corrections. ## Production application The grant and the one-row Drizzle baseline checksum were updated atomically under the database maintenance advisory lock. The production ledger still contains exactly one migration row. ## Verification - production contract dry-run passes - production `app_agent` can insert `quiesced_at` - production `app_agent` still cannot update the table broadly - `pnpm typecheck:scripts` - `pnpm turbo lint` - `pnpm --filter @cheatcode/db db:generate` reports no schema changes
1 parent 6efb6a9 commit 76c5447

2 files changed

Lines changed: 16 additions & 1 deletion

File tree

packages/db/drizzle/0000_current_schema.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3403,7 +3403,7 @@ GRANT SELECT(cleanup_not_before) ON TABLE public.v2_artifact_upload_intents TO a
34033403
-- Name: COLUMN v2_artifact_upload_intents.quiesced_at; Type: ACL; Schema: public; Owner: -
34043404
--
34053405

3406-
GRANT SELECT(quiesced_at),UPDATE(quiesced_at) ON TABLE public.v2_artifact_upload_intents TO app_agent;
3406+
GRANT SELECT(quiesced_at),INSERT(quiesced_at),UPDATE(quiesced_at) ON TABLE public.v2_artifact_upload_intents TO app_agent;
34073407
GRANT SELECT(quiesced_at) ON TABLE public.v2_artifact_upload_intents TO app_webhooks;
34083408

34093409

scripts/supabase-target/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export async function assertSupabaseTarget(client: PgClient): Promise<void> {
3333
await validateRuntimeRoles(client),
3434
await validateRuntimeAcl(client),
3535
await validateImmutableGeneratedOutputAcl(client),
36+
await validateArtifactUploadIntentAcl(client),
3637
await validateDataApiIsolation(client),
3738
await validateIntegrityConstraints(client),
3839
await validateIntegrityIndexes(client),
@@ -290,6 +291,20 @@ async function validateImmutableGeneratedOutputAcl(client: PgClient): Promise<st
290291
: ["app_agent must not update immutable generated outputs."];
291292
}
292293

294+
async function validateArtifactUploadIntentAcl(client: PgClient): Promise<string[]> {
295+
const result = await client.query(
296+
`select has_column_privilege(pg_catalog.to_regrole('app_agent'), 'public.v2_artifact_upload_intents', 'quiesced_at', 'INSERT') as can_insert_quiesced_at,
297+
has_table_privilege(pg_catalog.to_regrole('app_agent'), 'public.v2_artifact_upload_intents', 'UPDATE') as can_update_table`,
298+
);
299+
const row = result.rows[0];
300+
if (row?.["can_insert_quiesced_at"] !== true) {
301+
return ["app_agent must insert the bounded quiesced-at default on artifact upload intents."];
302+
}
303+
return row["can_update_table"] === false
304+
? []
305+
: ["app_agent must not have table-wide update access to artifact upload intents."];
306+
}
307+
293308
function validateFunctionAcl(
294309
object: string,
295310
privilege: string,

0 commit comments

Comments
 (0)