create-quorum-router 0.1.5 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,94 @@
1
+ -- Harden the BYO audit RPC for both existing and fresh projects.
2
+ -- Every user owns their own Supabase project; no central database or shared
3
+ -- tenant-routing claim is used. Runtime callers remain authenticated JWT users.
4
+
5
+ create or replace function public.insert_workflow_access_audit_batch(records jsonb)
6
+ returns void
7
+ language plpgsql
8
+ security definer
9
+ set search_path = public, pg_temp
10
+ as $$
11
+ declare
12
+ rec jsonb;
13
+ claim_actor_id uuid;
14
+ workflow_id text;
15
+ route text;
16
+ decision text;
17
+ metadata jsonb;
18
+ begin
19
+ claim_actor_id := auth.uid();
20
+ if claim_actor_id is null then
21
+ raise exception 'missing authenticated user' using errcode = '28000';
22
+ end if;
23
+
24
+ if records is null or jsonb_typeof(records) <> 'array' then
25
+ raise exception 'records must be a JSON array' using errcode = '22023';
26
+ end if;
27
+ if jsonb_array_length(records) < 1 or jsonb_array_length(records) > 100 then
28
+ raise exception 'records batch size must be between 1 and 100' using errcode = '22023';
29
+ end if;
30
+ if pg_column_size(records) > 262144 then
31
+ raise exception 'records payload exceeds 256 KiB' using errcode = '22023';
32
+ end if;
33
+
34
+ for rec in select value from jsonb_array_elements(records) as entry(value) loop
35
+ if jsonb_typeof(rec) <> 'object' then
36
+ raise exception 'each audit record must be an object' using errcode = '22023';
37
+ end if;
38
+ if exists (
39
+ select 1 from jsonb_object_keys(rec) as key
40
+ where key not in ('workflow_id', 'route', 'decision', 'metadata')
41
+ ) then
42
+ raise exception 'audit record contains unsupported fields' using errcode = '22023';
43
+ end if;
44
+
45
+ workflow_id := nullif(rec ->> 'workflow_id', '');
46
+ route := nullif(rec ->> 'route', '');
47
+ decision := nullif(rec ->> 'decision', '');
48
+ metadata := coalesce(rec -> 'metadata', '{}'::jsonb);
49
+
50
+ if workflow_id is null or length(workflow_id) > 256 then
51
+ raise exception 'audit workflow_id is required and limited to 256 characters' using errcode = '22023';
52
+ end if;
53
+ if route is not null and length(route) > 256 then
54
+ raise exception 'audit route exceeds 256 characters' using errcode = '22023';
55
+ end if;
56
+ if decision not in ('allow', 'error') then
57
+ raise exception 'invalid route outcome decision' using errcode = '22023';
58
+ end if;
59
+ if jsonb_typeof(metadata) <> 'object' or pg_column_size(metadata) > 16384 then
60
+ raise exception 'audit metadata must be an object no larger than 16 KiB' using errcode = '22023';
61
+ end if;
62
+ if exists (
63
+ select 1 from jsonb_object_keys(metadata) as key
64
+ where key not in (
65
+ 'command', 'mode', 'auth_mode', 'provider_selection_honored',
66
+ 'fallback_used', 'schema_valid'
67
+ )
68
+ ) then
69
+ raise exception 'audit metadata contains unsupported fields' using errcode = '22023';
70
+ end if;
71
+
72
+ insert into public.workflow_access_audit (
73
+ org_id, actor_id, actor_type, event_type, workflow_id, route,
74
+ decision, reason, metadata, created_at
75
+ ) values (
76
+ claim_actor_id::text,
77
+ claim_actor_id,
78
+ 'ai_assistant',
79
+ 'route.outcome',
80
+ workflow_id,
81
+ route,
82
+ decision,
83
+ case when decision = 'allow' then 'route completed' else 'route validation failed' end,
84
+ metadata,
85
+ now()
86
+ );
87
+ end loop;
88
+ end;
89
+ $$;
90
+
91
+ revoke all privileges on function public.insert_workflow_access_audit_batch(jsonb) from public;
92
+ revoke all privileges on function public.insert_workflow_access_audit_batch(jsonb) from anon;
93
+ revoke all privileges on function public.insert_workflow_access_audit_batch(jsonb) from authenticated;
94
+ grant execute on function public.insert_workflow_access_audit_batch(jsonb) to authenticated;