@flowselections/ai-authenticatie 1.0.15 → 1.1.1

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.
Files changed (44) hide show
  1. package/dist-lib/components/AiAuthenticatiePage.d.ts.map +1 -1
  2. package/dist-lib/components/AiAuthenticatiePage.js +6 -3
  3. package/dist-lib/hooks/useAiForGoal.d.ts +2 -2
  4. package/dist-lib/hooks/useAiForGoal.d.ts.map +1 -1
  5. package/dist-lib/hooks/useAiForGoal.js +1 -1
  6. package/dist-lib/hooks/useIsAiAdmin.d.ts +1 -0
  7. package/dist-lib/hooks/useIsAiAdmin.d.ts.map +1 -1
  8. package/dist-lib/hooks/useIsAiAdmin.js +22 -3
  9. package/dist-lib/index.d.ts +6 -1
  10. package/dist-lib/index.d.ts.map +1 -1
  11. package/dist-lib/index.js +4 -0
  12. package/dist-lib/integrations/supabase/types.d.ts +102 -15
  13. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  14. package/dist-lib/lib/aiAttachments.d.ts +22 -0
  15. package/dist-lib/lib/aiAttachments.d.ts.map +1 -0
  16. package/dist-lib/lib/aiAttachments.js +105 -0
  17. package/dist-lib/lib/aiChat.functions.d.ts +3 -2
  18. package/dist-lib/lib/aiChat.functions.d.ts.map +1 -1
  19. package/dist-lib/lib/aiChat.functions.js +6 -1
  20. package/dist-lib/lib/aiChat.server.d.ts +8 -1
  21. package/dist-lib/lib/aiChat.server.d.ts.map +1 -1
  22. package/dist-lib/lib/aiChat.server.js +37 -17
  23. package/dist-lib/lib/aiChat.stream.server.d.ts.map +1 -1
  24. package/dist-lib/lib/aiChat.stream.server.js +3 -1
  25. package/dist-lib/lib/aiChat.types.d.ts +8 -1
  26. package/dist-lib/lib/aiChat.types.d.ts.map +1 -1
  27. package/dist-lib/lib/aiModules.server.d.ts +4 -0
  28. package/dist-lib/lib/aiModules.server.d.ts.map +1 -1
  29. package/dist-lib/lib/aiModules.server.js +6 -3
  30. package/dist-lib/lib/aiRegistry.d.ts +31 -0
  31. package/dist-lib/lib/aiRegistry.d.ts.map +1 -0
  32. package/dist-lib/lib/aiRegistry.functions.d.ts +25 -0
  33. package/dist-lib/lib/aiRegistry.functions.d.ts.map +1 -0
  34. package/dist-lib/lib/aiRegistry.functions.js +25 -0
  35. package/dist-lib/lib/aiRegistry.js +46 -0
  36. package/dist-lib/lib/aiRegistry.server.d.ts +13 -0
  37. package/dist-lib/lib/aiRegistry.server.d.ts.map +1 -0
  38. package/dist-lib/lib/aiRegistry.server.js +21 -0
  39. package/dist-lib/lib/aiUsageByModule.functions.d.ts.map +1 -1
  40. package/dist-lib/lib/aiUsageByModule.functions.js +1 -4
  41. package/dist-lib/lib/modules.server.d.ts.map +1 -1
  42. package/dist-lib/lib/modules.server.js +7 -7
  43. package/package.json +14 -4
  44. package/schema/ai-authenticatie.sql +124 -0
@@ -31,13 +31,13 @@ export async function registerModuleRow(supabase, input) {
31
31
  const key = (input.module_key ?? '').trim() || slugifyModuleKey(name);
32
32
  if (!key)
33
33
  return { ok: false, message: 'Gebruik minimaal één letter of cijfer in de naam.' };
34
- const { error } = await supabase.from('modules').upsert({
35
- module_key: key,
36
- module_name: name,
37
- description: input.description ?? null,
38
- is_active: true,
39
- last_seen_at: new Date().toISOString(),
40
- }, { onConflict: 'module_key' });
34
+ // Nooit rechtstreeks naar de Shell-tabel `modules` schrijven: alleen toevoegen als die
35
+ // nog niet bestaat, via de beveiligde databasefunctie (alleen beheerders).
36
+ const { error } = await supabase.rpc('ai_register_consumers', {
37
+ _modules: [{ moduleKey: key, name, description: input.description ?? null }],
38
+ _full_list: false,
39
+ _source: 'handmatig',
40
+ });
41
41
  if (error)
42
42
  return { ok: false, message: `Registreren mislukt: ${error.message}` };
43
43
  return { ok: true, message: 'Module geregistreerd.', module_key: key };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/ai-authenticatie",
3
- "version": "1.0.15",
3
+ "version": "1.1.1",
4
4
  "flowselections": {
5
5
  "moduleId": "ai-authenticatie",
6
6
  "pages": [
@@ -14,7 +14,12 @@
14
14
  "route": "ai-authenticatie/$moduleKey",
15
15
  "title": "Module details"
16
16
  }
17
- ]
17
+ ],
18
+ "schema": {
19
+ "file": "schema/ai-authenticatie.sql",
20
+ "order": 50
21
+ },
22
+ "ai": []
18
23
  },
19
24
  "private": false,
20
25
  "sideEffects": false,
@@ -26,11 +31,16 @@
26
31
  "types": "./dist-lib/index.d.ts",
27
32
  "default": "./dist-lib/index.js"
28
33
  },
29
- "./styles": "./dist-lib/styles.css"
34
+ "./styles": "./dist-lib/styles.css",
35
+ "./server": {
36
+ "types": "./dist-lib/lib/aiRegistry.server.d.ts",
37
+ "default": "./dist-lib/lib/aiRegistry.server.js"
38
+ }
30
39
  },
31
40
  "files": [
32
41
  "dist-lib",
33
- "public"
42
+ "public",
43
+ "schema"
34
44
  ],
35
45
  "publishConfig": {
36
46
  "access": "public"
@@ -0,0 +1,124 @@
1
+ -- AI-Authenticatie: automatische registratie van AI-gebruikende modules.
2
+ -- Idempotent: dit bestand mag meerdere keren achter elkaar draaien.
3
+ -- De Shell-tabel public.modules wordt NIET gewijzigd (geen kolommen/rechten/beleid);
4
+ -- er wordt alleen een rij toegevoegd als die nog niet bestaat.
5
+
6
+ -- 1. Extra kolommen op de eigen tabel ai_modules
7
+ ALTER TABLE public.ai_modules ADD COLUMN IF NOT EXISTS declared_ai boolean NOT NULL DEFAULT false;
8
+ ALTER TABLE public.ai_modules ADD COLUMN IF NOT EXISTS ai_source text NOT NULL DEFAULT 'handmatig';
9
+ ALTER TABLE public.ai_modules ADD COLUMN IF NOT EXISTS last_declared_at timestamptz;
10
+ ALTER TABLE public.ai_modules ADD COLUMN IF NOT EXISTS is_in_use boolean NOT NULL DEFAULT true;
11
+
12
+ -- 2. Beheerderscontrole
13
+ CREATE OR REPLACE FUNCTION public.ai_is_admin(_uid uuid)
14
+ RETURNS boolean
15
+ LANGUAGE sql STABLE SECURITY DEFINER SET search_path = public
16
+ AS $$
17
+ SELECT _uid IS NOT NULL AND (
18
+ public.has_role(_uid, 'ai_admin') OR public.has_role(_uid, 'admin')
19
+ OR public.has_role(_uid, 'superadmin') OR public.has_role(_uid, 'developer')
20
+ )
21
+ $$;
22
+ REVOKE ALL ON FUNCTION public.ai_is_admin(uuid) FROM PUBLIC, anon;
23
+ GRANT EXECUTE ON FUNCTION public.ai_is_admin(uuid) TO authenticated, service_role;
24
+
25
+ -- 3. Rechten op eigen tabellen: iedereen ingelogd leest, alleen beheerders schrijven
26
+ GRANT SELECT, INSERT, UPDATE, DELETE ON public.ai_modules TO authenticated;
27
+ GRANT ALL ON public.ai_modules TO service_role;
28
+ GRANT SELECT, INSERT, UPDATE, DELETE ON public.ai_module_bindings TO authenticated;
29
+ GRANT ALL ON public.ai_module_bindings TO service_role;
30
+ ALTER TABLE public.ai_modules ENABLE ROW LEVEL SECURITY;
31
+ ALTER TABLE public.ai_module_bindings ENABLE ROW LEVEL SECURITY;
32
+
33
+ DROP POLICY IF EXISTS "Authenticated can manage ai modules" ON public.ai_modules;
34
+ DROP POLICY IF EXISTS "ai_modules_read" ON public.ai_modules;
35
+ DROP POLICY IF EXISTS "ai_modules_admin_write" ON public.ai_modules;
36
+ CREATE POLICY "ai_modules_read" ON public.ai_modules FOR SELECT TO authenticated USING (true);
37
+ CREATE POLICY "ai_modules_admin_write" ON public.ai_modules FOR ALL TO authenticated
38
+ USING (public.ai_is_admin(auth.uid())) WITH CHECK (public.ai_is_admin(auth.uid()));
39
+
40
+ DROP POLICY IF EXISTS "authenticated full access" ON public.ai_module_bindings;
41
+ DROP POLICY IF EXISTS "ai_module_bindings manage ai_admin" ON public.ai_module_bindings;
42
+ DROP POLICY IF EXISTS "ai_module_bindings_read" ON public.ai_module_bindings;
43
+ DROP POLICY IF EXISTS "ai_module_bindings_admin_write" ON public.ai_module_bindings;
44
+ CREATE POLICY "ai_module_bindings_read" ON public.ai_module_bindings FOR SELECT TO authenticated USING (true);
45
+ CREATE POLICY "ai_module_bindings_admin_write" ON public.ai_module_bindings FOR ALL TO authenticated
46
+ USING (public.ai_is_admin(auth.uid())) WITH CHECK (public.ai_is_admin(auth.uid()));
47
+
48
+ -- 4. Registratie vanuit manifest (shell-setup / update dashboard / beheerscherm)
49
+ -- _source: 'manifest' (flowselections.ai) of 'handmatig' (beheerscherm).
50
+ -- Nooit verwijderen. "Niet meer in gebruik" alleen bij _full_list = true en een niet-lege lijst.
51
+ CREATE OR REPLACE FUNCTION public.ai_register_consumers(
52
+ _modules jsonb, _full_list boolean DEFAULT false, _source text DEFAULT 'manifest'
53
+ ) RETURNS jsonb
54
+ LANGUAGE plpgsql SECURITY DEFINER SET search_path = public
55
+ AS $$
56
+ DECLARE
57
+ item jsonb; k text; n text; d text;
58
+ keys text[] := ARRAY[]::text[];
59
+ retired int := 0;
60
+ src text := CASE WHEN _source = 'handmatig' THEN 'handmatig' ELSE 'manifest' END;
61
+ BEGIN
62
+ IF coalesce(auth.role(), '') <> 'service_role' AND NOT public.ai_is_admin(auth.uid()) THEN
63
+ RAISE EXCEPTION 'Geen rechten om AI-modules te registreren' USING ERRCODE = '42501';
64
+ END IF;
65
+ IF _modules IS NULL OR jsonb_typeof(_modules) <> 'array' THEN
66
+ RAISE EXCEPTION 'Ongeldige modulelijst: verwacht een lijst';
67
+ END IF;
68
+
69
+ FOR item IN SELECT value FROM jsonb_array_elements(_modules) LOOP
70
+ IF jsonb_typeof(item) <> 'object' THEN CONTINUE; END IF;
71
+ k := lower(trim(coalesce(item->>'moduleKey', item->>'module_key', '')));
72
+ IF k !~ '^[a-z0-9][a-z0-9-]{0,63}$' THEN CONTINUE; END IF;
73
+ n := coalesce(nullif(trim(item->>'name'), ''), nullif(trim(item->>'module_name'), ''), k);
74
+ d := nullif(trim(coalesce(item->>'description', '')), '');
75
+ keys := array_append(keys, k);
76
+
77
+ INSERT INTO public.modules (module_key, module_name, description)
78
+ VALUES (k, n, d) ON CONFLICT (module_key) DO NOTHING;
79
+
80
+ IF src = 'manifest' THEN
81
+ INSERT INTO public.ai_modules (module_key, module_name, ai_enabled, declared_ai, ai_source, last_declared_at, is_in_use)
82
+ VALUES (k, n, true, true, 'manifest', now(), true)
83
+ ON CONFLICT (module_key) DO UPDATE
84
+ SET declared_ai = true, last_declared_at = now(), is_in_use = true,
85
+ ai_source = CASE WHEN public.ai_modules.ai_source = 'runtime' THEN 'manifest' ELSE public.ai_modules.ai_source END;
86
+ ELSE
87
+ INSERT INTO public.ai_modules (module_key, module_name, ai_enabled, ai_source)
88
+ VALUES (k, n, false, 'handmatig')
89
+ ON CONFLICT (module_key) DO NOTHING;
90
+ END IF;
91
+ END LOOP;
92
+
93
+ IF src = 'manifest' AND _full_list AND array_length(keys, 1) > 0 THEN
94
+ UPDATE public.ai_modules
95
+ SET is_in_use = false, declared_ai = false
96
+ WHERE declared_ai = true AND NOT (module_key = ANY (keys));
97
+ GET DIAGNOSTICS retired = ROW_COUNT;
98
+ END IF;
99
+
100
+ RETURN jsonb_build_object('registered', coalesce(array_length(keys, 1), 0), 'retired', retired);
101
+ END;
102
+ $$;
103
+ REVOKE ALL ON FUNCTION public.ai_register_consumers(jsonb, boolean, text) FROM PUBLIC, anon;
104
+ GRANT EXECUTE ON FUNCTION public.ai_register_consumers(jsonb, boolean, text) TO authenticated, service_role;
105
+
106
+ -- 5. Vangnet: onbekende module registreren bij de eerste AI-aanroep (alleen server)
107
+ CREATE OR REPLACE FUNCTION public.ai_register_runtime_consumer(_module_key text)
108
+ RETURNS boolean
109
+ LANGUAGE plpgsql SECURITY DEFINER SET search_path = public
110
+ AS $$
111
+ DECLARE k text := lower(trim(coalesce(_module_key, '')));
112
+ BEGIN
113
+ IF coalesce(auth.role(), '') <> 'service_role' THEN
114
+ RAISE EXCEPTION 'Alleen de server mag dit aanroepen' USING ERRCODE = '42501';
115
+ END IF;
116
+ IF k !~ '^[a-z0-9][a-z0-9-]{0,63}$' THEN RETURN false; END IF;
117
+ INSERT INTO public.modules (module_key, module_name) VALUES (k, k) ON CONFLICT (module_key) DO NOTHING;
118
+ INSERT INTO public.ai_modules (module_key, module_name, ai_enabled, ai_source, is_in_use)
119
+ VALUES (k, k, true, 'runtime', true) ON CONFLICT (module_key) DO NOTHING;
120
+ RETURN FOUND;
121
+ END;
122
+ $$;
123
+ REVOKE ALL ON FUNCTION public.ai_register_runtime_consumer(text) FROM PUBLIC, anon, authenticated;
124
+ GRANT EXECUTE ON FUNCTION public.ai_register_runtime_consumer(text) TO service_role;