@fayz-ai/db 0.8.4 → 0.9.0-next.0
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,74 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- 021_tenant_roles.sql — custom access profiles, per tenant.
|
|
3
|
+
--
|
|
4
|
+
-- The SDK has always been able to BUILD a custom role (duplicate a system role
|
|
5
|
+
-- in Settings → Permissions, or ask the assistant for one), but the table it
|
|
6
|
+
-- writes to never existed outside one legacy pool: `saas_core.tenant_roles`,
|
|
7
|
+
-- swept into `public` by 0000b and created nowhere else. Everywhere else the
|
|
8
|
+
-- insert threw and the screen swallowed it — a "Criar perfil" button that did
|
|
9
|
+
-- nothing.
|
|
10
|
+
--
|
|
11
|
+
-- Two changes, both required for a custom profile to survive a reload:
|
|
12
|
+
--
|
|
13
|
+
-- 1. public.tenant_roles — the role's IDENTITY (key + name). Its grants live
|
|
14
|
+
-- in tenant_role_overrides, keyed by that same `key`.
|
|
15
|
+
--
|
|
16
|
+
-- 2. tenant_role_overrides.permission_id loses its FK to public.permissions.
|
|
17
|
+
-- That catalog is a legacy of DB-driven RBAC; the feature catalog is now
|
|
18
|
+
-- DECLARED IN CODE by plugins (`declaredFeatures`) and merged at runtime,
|
|
19
|
+
-- so an app can grant `crm.leads.read` on a pool whose permissions table
|
|
20
|
+
-- never heard of plugin-crm. The FK made every such grant fail. The column
|
|
21
|
+
-- stays text in `feature.action` form — the shape agent_guard reads.
|
|
22
|
+
--
|
|
23
|
+
-- Idempotent: safe to re-run, no-ops when already applied.
|
|
24
|
+
-- ============================================================================
|
|
25
|
+
|
|
26
|
+
CREATE TABLE IF NOT EXISTS public.tenant_roles (
|
|
27
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
28
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
29
|
+
-- Stable slug the grants and tenant_members.role point at. Renaming the
|
|
30
|
+
-- profile must never orphan its permissions, so the key is not the name.
|
|
31
|
+
key text NOT NULL,
|
|
32
|
+
name text NOT NULL,
|
|
33
|
+
description text,
|
|
34
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
35
|
+
UNIQUE(tenant_id, key)
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
ALTER TABLE public.tenant_roles ENABLE ROW LEVEL SECURITY;
|
|
39
|
+
|
|
40
|
+
-- Members see their own tenant's roles (the permission screen lists them);
|
|
41
|
+
-- only tenant admins create, rename or delete one.
|
|
42
|
+
DROP POLICY IF EXISTS "tenant_roles_select" ON public.tenant_roles;
|
|
43
|
+
CREATE POLICY "tenant_roles_select" ON public.tenant_roles FOR SELECT
|
|
44
|
+
USING (tenant_id IN (SELECT tenant_id FROM public.tenant_members WHERE user_id = auth.uid()));
|
|
45
|
+
|
|
46
|
+
DROP POLICY IF EXISTS "tenant_roles_manage" ON public.tenant_roles;
|
|
47
|
+
CREATE POLICY "tenant_roles_manage" ON public.tenant_roles FOR ALL
|
|
48
|
+
USING (public.is_tenant_admin(tenant_id));
|
|
49
|
+
|
|
50
|
+
GRANT ALL ON public.tenant_roles TO authenticated, service_role;
|
|
51
|
+
|
|
52
|
+
-- The FK, dropped by lookup rather than by name: pools created before the
|
|
53
|
+
-- rename carry the constraint under whatever name Postgres minted.
|
|
54
|
+
DO $$
|
|
55
|
+
DECLARE
|
|
56
|
+
c record;
|
|
57
|
+
BEGIN
|
|
58
|
+
IF to_regclass('public.tenant_role_overrides') IS NULL THEN
|
|
59
|
+
RETURN;
|
|
60
|
+
END IF;
|
|
61
|
+
FOR c IN
|
|
62
|
+
SELECT con.conname
|
|
63
|
+
FROM pg_constraint con
|
|
64
|
+
JOIN pg_class rel ON rel.oid = con.conrelid
|
|
65
|
+
JOIN pg_namespace nsp ON nsp.oid = rel.relnamespace
|
|
66
|
+
JOIN pg_class frel ON frel.oid = con.confrelid
|
|
67
|
+
WHERE nsp.nspname = 'public'
|
|
68
|
+
AND rel.relname = 'tenant_role_overrides'
|
|
69
|
+
AND con.contype = 'f'
|
|
70
|
+
AND frel.relname = 'permissions'
|
|
71
|
+
LOOP
|
|
72
|
+
EXECUTE format('ALTER TABLE public.tenant_role_overrides DROP CONSTRAINT %I', c.conname);
|
|
73
|
+
END LOOP;
|
|
74
|
+
END $$;
|
package/package.json
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
"fayz": {
|
|
4
4
|
"status": "beta"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.9.0-next.0",
|
|
7
7
|
"description": "Fayz SDK database layer — Drizzle schema primitives, spine references, and migration helpers shared across plugins.",
|
|
8
8
|
"type": "module",
|
|
9
|
+
"sideEffects": false,
|
|
9
10
|
"main": "./dist/index.cjs",
|
|
10
11
|
"module": "./dist/index.js",
|
|
11
12
|
"types": "./dist/index.d.ts",
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
"database",
|
|
38
39
|
"schema"
|
|
39
40
|
],
|
|
41
|
+
"peerDependencies": {},
|
|
40
42
|
"scripts": {
|
|
41
43
|
"build": "tsup && tsc --emitDeclarationOnly --declaration --declarationMap --noEmit false",
|
|
42
44
|
"dev": "tsup --watch",
|