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.
- package/README.md +22 -2
- package/bin/create-quorum-router.js +25 -4
- package/package.json +1 -1
- package/templates/basic/README.md +72 -6
- package/templates/basic/deno.json +2 -0
- package/templates/basic/router.config.example.json +11 -0
- package/templates/basic/src/auth_session.ts +1 -0
- package/templates/basic/src/best_route.ts +10 -1
- package/templates/basic/src/calibration.ts +249 -0
- package/templates/basic/src/calibration_demo.ts +25 -0
- package/templates/basic/src/cli.ts +14 -2
- package/templates/basic/src/cost_aware.ts +150 -0
- package/templates/basic/src/provider_registry.ts +14 -7
- package/templates/basic/src/schema.ts +87 -0
- package/templates/basic/src/supabase.ts +462 -0
- package/templates/basic/src/trace.ts +3 -0
- package/templates/basic/src/wrapper_client.ts +46 -13
- package/templates/basic/supabase/migrations/20260701130000_workflow_access_audit.sql +125 -0
- package/templates/basic/supabase/migrations/20260712211500_workflow_access_audit_limits.sql +94 -0
|
@@ -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;
|