diff --git a/packages/db/drizzle/0000_current_schema.sql b/packages/db/drizzle/0000_current_schema.sql index 7608c85..8232312 100644 --- a/packages/db/drizzle/0000_current_schema.sql +++ b/packages/db/drizzle/0000_current_schema.sql @@ -3403,7 +3403,7 @@ GRANT SELECT(cleanup_not_before) ON TABLE public.v2_artifact_upload_intents TO a -- Name: COLUMN v2_artifact_upload_intents.quiesced_at; Type: ACL; Schema: public; Owner: - -- -GRANT SELECT(quiesced_at),UPDATE(quiesced_at) ON TABLE public.v2_artifact_upload_intents TO app_agent; +GRANT SELECT(quiesced_at),INSERT(quiesced_at),UPDATE(quiesced_at) ON TABLE public.v2_artifact_upload_intents TO app_agent; GRANT SELECT(quiesced_at) ON TABLE public.v2_artifact_upload_intents TO app_webhooks; diff --git a/scripts/supabase-target/index.ts b/scripts/supabase-target/index.ts index 8a9b3bd..d41e016 100644 --- a/scripts/supabase-target/index.ts +++ b/scripts/supabase-target/index.ts @@ -33,6 +33,7 @@ export async function assertSupabaseTarget(client: PgClient): Promise { await validateRuntimeRoles(client), await validateRuntimeAcl(client), await validateImmutableGeneratedOutputAcl(client), + await validateArtifactUploadIntentAcl(client), await validateDataApiIsolation(client), await validateIntegrityConstraints(client), await validateIntegrityIndexes(client), @@ -290,6 +291,20 @@ async function validateImmutableGeneratedOutputAcl(client: PgClient): Promise { + const result = await client.query( + `select has_column_privilege(pg_catalog.to_regrole('app_agent'), 'public.v2_artifact_upload_intents', 'quiesced_at', 'INSERT') as can_insert_quiesced_at, + has_table_privilege(pg_catalog.to_regrole('app_agent'), 'public.v2_artifact_upload_intents', 'UPDATE') as can_update_table`, + ); + const row = result.rows[0]; + if (row?.["can_insert_quiesced_at"] !== true) { + return ["app_agent must insert the bounded quiesced-at default on artifact upload intents."]; + } + return row["can_update_table"] === false + ? [] + : ["app_agent must not have table-wide update access to artifact upload intents."]; +} + function validateFunctionAcl( object: string, privilege: string,