@nodii/db-rls 0.2.2 → 0.4.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.
Files changed (48) hide show
  1. package/dist/configure.d.ts +42 -8
  2. package/dist/configure.d.ts.map +1 -1
  3. package/dist/configure.js +87 -16
  4. package/dist/configure.js.map +1 -1
  5. package/dist/context.d.ts +36 -7
  6. package/dist/context.d.ts.map +1 -1
  7. package/dist/context.js +67 -6
  8. package/dist/context.js.map +1 -1
  9. package/dist/drizzle-client.d.ts +9 -2
  10. package/dist/drizzle-client.d.ts.map +1 -1
  11. package/dist/drizzle-client.js +28 -2
  12. package/dist/drizzle-client.js.map +1 -1
  13. package/dist/drizzle-grants.d.ts +203 -0
  14. package/dist/drizzle-grants.d.ts.map +1 -0
  15. package/dist/drizzle-grants.js +68 -0
  16. package/dist/drizzle-grants.js.map +1 -0
  17. package/dist/drizzle-policies.d.ts +90 -0
  18. package/dist/drizzle-policies.d.ts.map +1 -0
  19. package/dist/drizzle-policies.js +223 -0
  20. package/dist/drizzle-policies.js.map +1 -0
  21. package/dist/index.d.ts +9 -6
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +22 -10
  24. package/dist/index.js.map +1 -1
  25. package/dist/init.d.ts +23 -5
  26. package/dist/init.d.ts.map +1 -1
  27. package/dist/init.js +38 -4
  28. package/dist/init.js.map +1 -1
  29. package/dist/metrics.d.ts +28 -0
  30. package/dist/metrics.d.ts.map +1 -0
  31. package/dist/metrics.js +263 -0
  32. package/dist/metrics.js.map +1 -0
  33. package/dist/migrate-guard.d.ts +14 -0
  34. package/dist/migrate-guard.d.ts.map +1 -0
  35. package/dist/migrate-guard.js +33 -0
  36. package/dist/migrate-guard.js.map +1 -0
  37. package/dist/pg-pool-adapter.d.ts.map +1 -1
  38. package/dist/pg-pool-adapter.js +78 -25
  39. package/dist/pg-pool-adapter.js.map +1 -1
  40. package/dist/postgres-js-client.d.ts +60 -0
  41. package/dist/postgres-js-client.d.ts.map +1 -0
  42. package/dist/postgres-js-client.js +223 -0
  43. package/dist/postgres-js-client.js.map +1 -0
  44. package/dist/types.d.ts +68 -2
  45. package/dist/types.d.ts.map +1 -1
  46. package/dist/types.js +31 -1
  47. package/dist/types.js.map +1 -1
  48. package/package.json +24 -5
@@ -0,0 +1,203 @@
1
+ export type PlatformOpsScopeKind = "tenant" | "platform_global" | "all_tenants";
2
+ /**
3
+ * Returns a Drizzle pgTable definition for the
4
+ * `platform_ops_grants_replica` table per D185 § 2.
5
+ *
6
+ * Schema:
7
+ * - id UUID PRIMARY KEY DEFAULT gen_random_uuid()
8
+ * - user_id UUID NOT NULL -- principal with platform-admin membership
9
+ * - service_id TEXT NOT NULL -- consumer service id
10
+ * - scope_kind TEXT NOT NULL CHECK (IN ('tenant','platform_global','all_tenants'))
11
+ * - scope_target UUID -- tenant_id when scope_kind='tenant'; NULL otherwise
12
+ * - permission TEXT NOT NULL -- catalog entry name
13
+ * - granted_by_user_id UUID NOT NULL -- audit trail
14
+ * - granted_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
15
+ * - expires_at TIMESTAMPTZ -- optional time-bound
16
+ * - revoked_at TIMESTAMPTZ -- soft revoke
17
+ *
18
+ * Constraints:
19
+ * - UNIQUE (user_id, service_id, scope_kind, scope_target, permission)
20
+ * - CHECK ((scope_kind = 'tenant' AND scope_target IS NOT NULL)
21
+ * OR (scope_kind IN ('platform_global','all_tenants') AND scope_target IS NULL))
22
+ *
23
+ * Indexes:
24
+ * - (user_id, service_id) WHERE revoked_at IS NULL
25
+ */
26
+ export declare function platformOpsGrantsReplica(name?: string): import("drizzle-orm/pg-core").PgTableWithColumns<{
27
+ name: string;
28
+ schema: undefined;
29
+ columns: {
30
+ id: import("drizzle-orm/pg-core").PgColumn<{
31
+ name: "id";
32
+ tableName: string;
33
+ dataType: "string";
34
+ columnType: "PgUUID";
35
+ data: string;
36
+ driverParam: string;
37
+ notNull: true;
38
+ hasDefault: true;
39
+ isPrimaryKey: true;
40
+ isAutoincrement: false;
41
+ hasRuntimeDefault: false;
42
+ enumValues: undefined;
43
+ baseColumn: never;
44
+ identity: undefined;
45
+ generated: undefined;
46
+ }, {}, {}>;
47
+ userId: import("drizzle-orm/pg-core").PgColumn<{
48
+ name: "user_id";
49
+ tableName: string;
50
+ dataType: "string";
51
+ columnType: "PgUUID";
52
+ data: string;
53
+ driverParam: string;
54
+ notNull: true;
55
+ hasDefault: false;
56
+ isPrimaryKey: false;
57
+ isAutoincrement: false;
58
+ hasRuntimeDefault: false;
59
+ enumValues: undefined;
60
+ baseColumn: never;
61
+ identity: undefined;
62
+ generated: undefined;
63
+ }, {}, {}>;
64
+ serviceId: import("drizzle-orm/pg-core").PgColumn<{
65
+ name: "service_id";
66
+ tableName: string;
67
+ dataType: "string";
68
+ columnType: "PgText";
69
+ data: string;
70
+ driverParam: string;
71
+ notNull: true;
72
+ hasDefault: false;
73
+ isPrimaryKey: false;
74
+ isAutoincrement: false;
75
+ hasRuntimeDefault: false;
76
+ enumValues: [string, ...string[]];
77
+ baseColumn: never;
78
+ identity: undefined;
79
+ generated: undefined;
80
+ }, {}, {}>;
81
+ scopeKind: import("drizzle-orm/pg-core").PgColumn<{
82
+ name: "scope_kind";
83
+ tableName: string;
84
+ dataType: "string";
85
+ columnType: "PgText";
86
+ data: string;
87
+ driverParam: string;
88
+ notNull: true;
89
+ hasDefault: false;
90
+ isPrimaryKey: false;
91
+ isAutoincrement: false;
92
+ hasRuntimeDefault: false;
93
+ enumValues: [string, ...string[]];
94
+ baseColumn: never;
95
+ identity: undefined;
96
+ generated: undefined;
97
+ }, {}, {}>;
98
+ scopeTarget: import("drizzle-orm/pg-core").PgColumn<{
99
+ name: "scope_target";
100
+ tableName: string;
101
+ dataType: "string";
102
+ columnType: "PgUUID";
103
+ data: string;
104
+ driverParam: string;
105
+ notNull: false;
106
+ hasDefault: false;
107
+ isPrimaryKey: false;
108
+ isAutoincrement: false;
109
+ hasRuntimeDefault: false;
110
+ enumValues: undefined;
111
+ baseColumn: never;
112
+ identity: undefined;
113
+ generated: undefined;
114
+ }, {}, {}>;
115
+ permission: import("drizzle-orm/pg-core").PgColumn<{
116
+ name: "permission";
117
+ tableName: string;
118
+ dataType: "string";
119
+ columnType: "PgText";
120
+ data: string;
121
+ driverParam: string;
122
+ notNull: true;
123
+ hasDefault: false;
124
+ isPrimaryKey: false;
125
+ isAutoincrement: false;
126
+ hasRuntimeDefault: false;
127
+ enumValues: [string, ...string[]];
128
+ baseColumn: never;
129
+ identity: undefined;
130
+ generated: undefined;
131
+ }, {}, {}>;
132
+ grantedByUserId: import("drizzle-orm/pg-core").PgColumn<{
133
+ name: "granted_by_user_id";
134
+ tableName: string;
135
+ dataType: "string";
136
+ columnType: "PgUUID";
137
+ data: string;
138
+ driverParam: string;
139
+ notNull: true;
140
+ hasDefault: false;
141
+ isPrimaryKey: false;
142
+ isAutoincrement: false;
143
+ hasRuntimeDefault: false;
144
+ enumValues: undefined;
145
+ baseColumn: never;
146
+ identity: undefined;
147
+ generated: undefined;
148
+ }, {}, {}>;
149
+ grantedAt: import("drizzle-orm/pg-core").PgColumn<{
150
+ name: "granted_at";
151
+ tableName: string;
152
+ dataType: "date";
153
+ columnType: "PgTimestamp";
154
+ data: Date;
155
+ driverParam: string;
156
+ notNull: true;
157
+ hasDefault: true;
158
+ isPrimaryKey: false;
159
+ isAutoincrement: false;
160
+ hasRuntimeDefault: false;
161
+ enumValues: undefined;
162
+ baseColumn: never;
163
+ identity: undefined;
164
+ generated: undefined;
165
+ }, {}, {}>;
166
+ expiresAt: import("drizzle-orm/pg-core").PgColumn<{
167
+ name: "expires_at";
168
+ tableName: string;
169
+ dataType: "date";
170
+ columnType: "PgTimestamp";
171
+ data: Date;
172
+ driverParam: string;
173
+ notNull: false;
174
+ hasDefault: false;
175
+ isPrimaryKey: false;
176
+ isAutoincrement: false;
177
+ hasRuntimeDefault: false;
178
+ enumValues: undefined;
179
+ baseColumn: never;
180
+ identity: undefined;
181
+ generated: undefined;
182
+ }, {}, {}>;
183
+ revokedAt: import("drizzle-orm/pg-core").PgColumn<{
184
+ name: "revoked_at";
185
+ tableName: string;
186
+ dataType: "date";
187
+ columnType: "PgTimestamp";
188
+ data: Date;
189
+ driverParam: string;
190
+ notNull: false;
191
+ hasDefault: false;
192
+ isPrimaryKey: false;
193
+ isAutoincrement: false;
194
+ hasRuntimeDefault: false;
195
+ enumValues: undefined;
196
+ baseColumn: never;
197
+ identity: undefined;
198
+ generated: undefined;
199
+ }, {}, {}>;
200
+ };
201
+ dialect: "pg";
202
+ }>;
203
+ //# sourceMappingURL=drizzle-grants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle-grants.d.ts","sourceRoot":"","sources":["../src/drizzle-grants.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,iBAAiB,GAAG,aAAa,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,SAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsC5E"}
@@ -0,0 +1,68 @@
1
+ // D185 — Drizzle table builder for `platform_ops_grants_replica`.
2
+ //
3
+ // Per hub decision D185 § 2 + § 6.2. The canonical schema lives in
4
+ // `nodii-tenant-service` (source of truth); each consumer service that
5
+ // wires a 4-pool db-rls replicates the table locally via the
6
+ // `@nodii/replica-consumer` outbox-consumer pattern (`09-replication
7
+ // § 6.2`). This helper emits the Drizzle schema for the replica so
8
+ // consumer services don't drift on column shape.
9
+ //
10
+ // Subpath export: `@nodii/db-rls/drizzle/platform-ops-grants`.
11
+ //
12
+ // Usage:
13
+ //
14
+ // import { platformOpsGrantsReplica } from "@nodii/db-rls/drizzle/platform-ops-grants";
15
+ //
16
+ // export const grantsReplica = platformOpsGrantsReplica();
17
+ // // OR with custom name:
18
+ // export const grantsReplica = platformOpsGrantsReplica("tenant_platform_ops_grants_replica");
19
+ import { sql } from "drizzle-orm";
20
+ import { check, index, pgTable, text, timestamp, unique, uuid, } from "drizzle-orm/pg-core";
21
+ /**
22
+ * Returns a Drizzle pgTable definition for the
23
+ * `platform_ops_grants_replica` table per D185 § 2.
24
+ *
25
+ * Schema:
26
+ * - id UUID PRIMARY KEY DEFAULT gen_random_uuid()
27
+ * - user_id UUID NOT NULL -- principal with platform-admin membership
28
+ * - service_id TEXT NOT NULL -- consumer service id
29
+ * - scope_kind TEXT NOT NULL CHECK (IN ('tenant','platform_global','all_tenants'))
30
+ * - scope_target UUID -- tenant_id when scope_kind='tenant'; NULL otherwise
31
+ * - permission TEXT NOT NULL -- catalog entry name
32
+ * - granted_by_user_id UUID NOT NULL -- audit trail
33
+ * - granted_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
34
+ * - expires_at TIMESTAMPTZ -- optional time-bound
35
+ * - revoked_at TIMESTAMPTZ -- soft revoke
36
+ *
37
+ * Constraints:
38
+ * - UNIQUE (user_id, service_id, scope_kind, scope_target, permission)
39
+ * - CHECK ((scope_kind = 'tenant' AND scope_target IS NOT NULL)
40
+ * OR (scope_kind IN ('platform_global','all_tenants') AND scope_target IS NULL))
41
+ *
42
+ * Indexes:
43
+ * - (user_id, service_id) WHERE revoked_at IS NULL
44
+ */
45
+ export function platformOpsGrantsReplica(name = "platform_ops_grants_replica") {
46
+ return pgTable(name, {
47
+ id: uuid("id").primaryKey().default(sql `gen_random_uuid()`),
48
+ userId: uuid("user_id").notNull(),
49
+ serviceId: text("service_id").notNull(),
50
+ scopeKind: text("scope_kind").notNull(),
51
+ scopeTarget: uuid("scope_target"),
52
+ permission: text("permission").notNull(),
53
+ grantedByUserId: uuid("granted_by_user_id").notNull(),
54
+ grantedAt: timestamp("granted_at", { withTimezone: true })
55
+ .notNull()
56
+ .default(sql `NOW()`),
57
+ expiresAt: timestamp("expires_at", { withTimezone: true }),
58
+ revokedAt: timestamp("revoked_at", { withTimezone: true }),
59
+ }, (t) => [
60
+ unique(`${name}_grant_uniq`).on(t.userId, t.serviceId, t.scopeKind, t.scopeTarget, t.permission),
61
+ check(`${name}_scope_target_shape`, sql `(${t.scopeKind} = 'tenant' AND ${t.scopeTarget} IS NOT NULL) OR (${t.scopeKind} IN ('platform_global','all_tenants') AND ${t.scopeTarget} IS NULL)`),
62
+ check(`${name}_scope_kind_enum`, sql `${t.scopeKind} IN ('tenant','platform_global','all_tenants')`),
63
+ index(`${name}_user_service_active`)
64
+ .on(t.userId, t.serviceId)
65
+ .where(sql `${t.revokedAt} IS NULL`),
66
+ ]);
67
+ }
68
+ //# sourceMappingURL=drizzle-grants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle-grants.js","sourceRoot":"","sources":["../src/drizzle-grants.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,mEAAmE;AACnE,uEAAuE;AACvE,6DAA6D;AAC7D,qEAAqE;AACrE,mEAAmE;AACnE,iDAAiD;AACjD,EAAE;AACF,+DAA+D;AAC/D,EAAE;AACF,SAAS;AACT,EAAE;AACF,0FAA0F;AAC1F,EAAE;AACF,6DAA6D;AAC7D,4BAA4B;AAC5B,iGAAiG;AAEjG,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EACL,KAAK,EACL,KAAK,EACL,OAAO,EACP,IAAI,EACJ,SAAS,EACT,MAAM,EACN,IAAI,GACL,MAAM,qBAAqB,CAAC;AAI7B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAI,GAAG,6BAA6B;IAC3E,OAAO,OAAO,CACZ,IAAI,EACJ;QACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA,mBAAmB,CAAC;QAC3D,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;QACjC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;QACvC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;QACvC,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC;QACjC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;QACxC,eAAe,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC,OAAO,EAAE;QACrD,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;aACvD,OAAO,EAAE;aACT,OAAO,CAAC,GAAG,CAAA,OAAO,CAAC;QACtB,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;QAC1D,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;KAC3D,EACD,CAAC,CAAC,EAAE,EAAE,CAAC;QACL,MAAM,CAAC,GAAG,IAAI,aAAa,CAAC,CAAC,EAAE,CAC7B,CAAC,CAAC,MAAM,EACR,CAAC,CAAC,SAAS,EACX,CAAC,CAAC,SAAS,EACX,CAAC,CAAC,WAAW,EACb,CAAC,CAAC,UAAU,CACb;QACD,KAAK,CACH,GAAG,IAAI,qBAAqB,EAC5B,GAAG,CAAA,IAAI,CAAC,CAAC,SAAS,mBAAmB,CAAC,CAAC,WAAW,qBAAqB,CAAC,CAAC,SAAS,6CAA6C,CAAC,CAAC,WAAW,WAAW,CACxJ;QACD,KAAK,CACH,GAAG,IAAI,kBAAkB,EACzB,GAAG,CAAA,GAAG,CAAC,CAAC,SAAS,gDAAgD,CAClE;QACD,KAAK,CAAC,GAAG,IAAI,sBAAsB,CAAC;aACjC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC;aACzB,KAAK,CAAC,GAAG,CAAA,GAAG,CAAC,CAAC,SAAS,UAAU,CAAC;KACtC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,90 @@
1
+ import type { PgColumn, PgPolicy } from "drizzle-orm/pg-core";
2
+ import type { WithRlsOpts } from "./rls-policy-gen";
3
+ /**
4
+ * Returns the canonical 5-policy Drizzle constructs (per doctrine § 4)
5
+ * for a tenant-scoped table.
6
+ *
7
+ * Default (`allow=["SELECT","INSERT"]`) emits:
8
+ *
9
+ * 1. `<table>_owner` FOR ALL TO nodii_owner USING (true) WITH CHECK (true)
10
+ * 2. `<table>_auth_select` FOR SELECT TO authenticated USING (<col> IN (SELECT auth.user_tenant_ids(auth.get_user_id())))
11
+ * 3. `<table>_auth_insert` FOR INSERT TO authenticated WITH CHECK (...)
12
+ * 4. `<table>_svc_select` FOR SELECT TO nodii_services USING (<col> = auth.get_tenant_id())
13
+ * 5. `<table>_svc_insert` FOR INSERT TO nodii_services WITH CHECK (...)
14
+ *
15
+ * Extending `allow` to include `"UPDATE"` / `"DELETE"` adds the
16
+ * corresponding verb policies for both auth + svc.
17
+ *
18
+ * `t.tenantId` must be a Drizzle column reference (used to thread the
19
+ * column name + table binding into the policy `link(table)` step that
20
+ * drizzle-kit performs).
21
+ */
22
+ export declare function withRls(tenantCol: PgColumn, opts?: WithRlsOpts): PgPolicy[];
23
+ /** Per-verb permission name binding for the platform-ops policies. Each
24
+ * string is a catalog entry name (e.g. `"modules.write"`) — when a
25
+ * request runs with `app.platform_ops_permission` matching this name,
26
+ * the corresponding policy applies. A missing entry means there's no
27
+ * policy emitted for that verb (deny-by-default RLS behavior). */
28
+ export interface PlatformOpsPerVerbPermissions {
29
+ read?: string;
30
+ insert?: string;
31
+ update?: string;
32
+ delete?: string;
33
+ }
34
+ export interface WithPlatformOpsOpts {
35
+ /** Override the default `platform_ops_grants_replica` table name.
36
+ * Use when the consuming service replicates the grants table under
37
+ * a different name (e.g. prefixed with the service slug). */
38
+ grantsTable?: string;
39
+ /** Override the tenant column name in the generated predicate. Falls
40
+ * back to the Drizzle column's name. */
41
+ tenantColumn?: string;
42
+ }
43
+ /**
44
+ * Returns the platform-ops policy bundle (per D185 § 3) for a
45
+ * **tenant-scoped** table exposed via a platform-ops cross-tenant
46
+ * surface. Emits one policy per verb in `perms`:
47
+ *
48
+ * - `<table>_platform_ops_read` FOR SELECT TO nodii_platform_ops USING (<grants-predicate with perms.read>)
49
+ * - `<table>_platform_ops_insert` FOR INSERT TO nodii_platform_ops WITH CHECK (<grants-predicate with perms.insert>)
50
+ * - `<table>_platform_ops_update` FOR UPDATE TO nodii_platform_ops USING + WITH CHECK (<grants-predicate with perms.update>)
51
+ * - `<table>_platform_ops_delete` FOR DELETE TO nodii_platform_ops USING (<grants-predicate with perms.delete>)
52
+ *
53
+ * Predicate shape (per D185 § 3):
54
+ *
55
+ * EXISTS (
56
+ * SELECT 1 FROM platform_ops_grants_replica g
57
+ * WHERE g.user_id = current_setting('app.user_id')::uuid
58
+ * AND g.service_id = current_setting('app.platform_ops_service_id')
59
+ * AND g.permission = <permission name literal>
60
+ * AND g.revoked_at IS NULL
61
+ * AND (g.expires_at IS NULL OR g.expires_at > NOW())
62
+ * AND (
63
+ * g.scope_kind = 'all_tenants'
64
+ * OR (g.scope_kind = 'tenant' AND g.scope_target = <tenantCol>)
65
+ * )
66
+ * )
67
+ *
68
+ * Note: the permission literal is embedded in the policy body at
69
+ * migration-emit time (not read from `app.platform_ops_permission` at
70
+ * runtime). This means each verb can be bound to a distinct catalog
71
+ * entry — `app.platform_ops_permission` GUC is set by `withPlatformOps`
72
+ * to enable auditing/forensics but is NOT what the policy checks.
73
+ *
74
+ * Compose alongside `withRls(t.tenantId)` on the same table when both
75
+ * platform-ops AND in-tenant surfaces are exposed.
76
+ */
77
+ export declare function withPlatformOpsTenant(tenantCol: PgColumn, perms: PlatformOpsPerVerbPermissions, opts?: WithPlatformOpsOpts): PgPolicy[];
78
+ /**
79
+ * Returns the platform-ops policy bundle (per D185 § 3) for a
80
+ * **platform-global** table that has no tenant_id column (modules,
81
+ * role catalogs, etc.). Emits one policy per verb in `perms` using the
82
+ * `scope_kind='platform_global'` predicate variant.
83
+ */
84
+ export declare function withPlatformOpsGlobal(table: {
85
+ _: {
86
+ name: string;
87
+ };
88
+ [key: string]: unknown;
89
+ }, perms: PlatformOpsPerVerbPermissions, opts?: WithPlatformOpsOpts): PgPolicy[];
90
+ //# sourceMappingURL=drizzle-policies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle-policies.d.ts","sourceRoot":"","sources":["../src/drizzle-policies.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,KAAK,EAAW,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAI7D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,OAAO,CACrB,SAAS,EAAE,QAAQ,EACnB,IAAI,GAAE,WAAgB,GACrB,QAAQ,EAAE,CAsCZ;AA6ED;;;;mEAImE;AACnE,MAAM,WAAW,6BAA6B;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,MAAM,WAAW,mBAAmB;IAClC;;kEAE8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;6CACyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,QAAQ,EACnB,KAAK,EAAE,6BAA6B,EACpC,IAAI,GAAE,mBAAwB,GAC7B,QAAQ,EAAE,CA0BZ;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE;IAAE,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EACtD,KAAK,EAAE,6BAA6B,EACpC,IAAI,GAAE,mBAAwB,GAC7B,QAAQ,EAAE,CA0BZ"}
@@ -0,0 +1,223 @@
1
+ // Drizzle table-builder helper — `withRls(t.tenantId)` per doctrine § 4.2.
2
+ //
3
+ // Exposed via subpath `@nodii/db-rls/drizzle`. Returns an array of
4
+ // `PgPolicy` constructs that consumers spread into Drizzle's third-arg
5
+ // extras callback:
6
+ //
7
+ // import { withRls } from "@nodii/db-rls/drizzle";
8
+ //
9
+ // export const billingInvoices = pgTable("billing_invoices", {
10
+ // id: uuid("id").primaryKey().defaultRandom(),
11
+ // tenantId: uuid("tenant_id").notNull(),
12
+ // amount: integer("amount").notNull(),
13
+ // }, (t) => [
14
+ // ...withRls(t.tenantId), // default 5 policies
15
+ // // OR with extra verbs:
16
+ // // ...withRls(t.tenantId, { allow: ["SELECT","INSERT","UPDATE","DELETE"] }),
17
+ // ]);
18
+ //
19
+ // Drizzle-kit reads these PgPolicy constructs and emits the canonical
20
+ // 5-policy DDL (§ 4) into the generated migration SQL. Naming follows
21
+ // doctrine § 4 exactly: `<table>_owner`, `<table>_auth_select`,
22
+ // `<table>_auth_insert`, `<table>_svc_select`, `<table>_svc_insert`
23
+ // (no `_policy` suffix).
24
+ //
25
+ // The legacy string-DDL `withRls(table: string)` helper exported from
26
+ // `@nodii/db-rls` (main barrel) keeps its `*_policy` suffix for backwards
27
+ // parity with v0.1.x consumers — both surfaces ship.
28
+ import { getTableName, sql } from "drizzle-orm";
29
+ import { pgPolicy } from "drizzle-orm/pg-core";
30
+ const DEFAULT_ALLOW = ["SELECT", "INSERT"];
31
+ /**
32
+ * Returns the canonical 5-policy Drizzle constructs (per doctrine § 4)
33
+ * for a tenant-scoped table.
34
+ *
35
+ * Default (`allow=["SELECT","INSERT"]`) emits:
36
+ *
37
+ * 1. `<table>_owner` FOR ALL TO nodii_owner USING (true) WITH CHECK (true)
38
+ * 2. `<table>_auth_select` FOR SELECT TO authenticated USING (<col> IN (SELECT auth.user_tenant_ids(auth.get_user_id())))
39
+ * 3. `<table>_auth_insert` FOR INSERT TO authenticated WITH CHECK (...)
40
+ * 4. `<table>_svc_select` FOR SELECT TO nodii_services USING (<col> = auth.get_tenant_id())
41
+ * 5. `<table>_svc_insert` FOR INSERT TO nodii_services WITH CHECK (...)
42
+ *
43
+ * Extending `allow` to include `"UPDATE"` / `"DELETE"` adds the
44
+ * corresponding verb policies for both auth + svc.
45
+ *
46
+ * `t.tenantId` must be a Drizzle column reference (used to thread the
47
+ * column name + table binding into the policy `link(table)` step that
48
+ * drizzle-kit performs).
49
+ */
50
+ export function withRls(tenantCol, opts = {}) {
51
+ const verbs = opts.allow && opts.allow.length > 0 ? opts.allow : DEFAULT_ALLOW;
52
+ const tableName = getTableName(tenantCol.table);
53
+ const policyBase = unqualifiedName(tableName);
54
+ const tenantColumn = opts.tenantColumn ?? tenantCol.name;
55
+ // Authenticated predicate: tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id()))
56
+ const authPredicate = sql.raw(`${tenantColumn} IN (SELECT auth.user_tenant_ids(auth.get_user_id()))`);
57
+ // Services predicate: tenant_id = auth.get_tenant_id()
58
+ const svcPredicate = sql.raw(`${tenantColumn} = auth.get_tenant_id()`);
59
+ const policies = [];
60
+ // 1. Owner FOR ALL.
61
+ policies.push(pgPolicy(`${policyBase}_owner`, {
62
+ as: "permissive",
63
+ for: "all",
64
+ to: "nodii_owner",
65
+ using: sql `true`,
66
+ withCheck: sql `true`,
67
+ }));
68
+ // 2. authenticated per verb.
69
+ for (const verb of verbs) {
70
+ policies.push(authPolicyFor(policyBase, verb, authPredicate));
71
+ }
72
+ // 3. nodii_services per verb.
73
+ for (const verb of verbs) {
74
+ policies.push(svcPolicyFor(policyBase, verb, svcPredicate));
75
+ }
76
+ return policies;
77
+ }
78
+ function authPolicyFor(policyBase, verb, predicate) {
79
+ const name = `${policyBase}_auth_${verb.toLowerCase()}`;
80
+ return pgPolicy(name, {
81
+ as: "permissive",
82
+ for: drizzleFor(verb),
83
+ to: "authenticated",
84
+ ...predicates(verb, predicate),
85
+ });
86
+ }
87
+ function svcPolicyFor(policyBase, verb, predicate) {
88
+ const name = `${policyBase}_svc_${verb.toLowerCase()}`;
89
+ return pgPolicy(name, {
90
+ as: "permissive",
91
+ for: drizzleFor(verb),
92
+ to: "nodii_services",
93
+ ...predicates(verb, predicate),
94
+ });
95
+ }
96
+ function drizzleFor(verb) {
97
+ return verb.toLowerCase();
98
+ }
99
+ function predicates(verb, predicate) {
100
+ switch (verb) {
101
+ case "INSERT":
102
+ return { withCheck: predicate };
103
+ case "UPDATE":
104
+ return { using: predicate, withCheck: predicate };
105
+ default:
106
+ // SELECT, DELETE
107
+ return { using: predicate };
108
+ }
109
+ }
110
+ function unqualifiedName(table) {
111
+ const tail = table.includes(".") ? (table.split(".").pop() ?? table) : table;
112
+ return tail.replace(/^"|"$/g, "");
113
+ }
114
+ const PLATFORM_OPS_GRANTS_REPLICA_DEFAULT = "platform_ops_grants_replica";
115
+ /**
116
+ * Returns the platform-ops policy bundle (per D185 § 3) for a
117
+ * **tenant-scoped** table exposed via a platform-ops cross-tenant
118
+ * surface. Emits one policy per verb in `perms`:
119
+ *
120
+ * - `<table>_platform_ops_read` FOR SELECT TO nodii_platform_ops USING (<grants-predicate with perms.read>)
121
+ * - `<table>_platform_ops_insert` FOR INSERT TO nodii_platform_ops WITH CHECK (<grants-predicate with perms.insert>)
122
+ * - `<table>_platform_ops_update` FOR UPDATE TO nodii_platform_ops USING + WITH CHECK (<grants-predicate with perms.update>)
123
+ * - `<table>_platform_ops_delete` FOR DELETE TO nodii_platform_ops USING (<grants-predicate with perms.delete>)
124
+ *
125
+ * Predicate shape (per D185 § 3):
126
+ *
127
+ * EXISTS (
128
+ * SELECT 1 FROM platform_ops_grants_replica g
129
+ * WHERE g.user_id = current_setting('app.user_id')::uuid
130
+ * AND g.service_id = current_setting('app.platform_ops_service_id')
131
+ * AND g.permission = <permission name literal>
132
+ * AND g.revoked_at IS NULL
133
+ * AND (g.expires_at IS NULL OR g.expires_at > NOW())
134
+ * AND (
135
+ * g.scope_kind = 'all_tenants'
136
+ * OR (g.scope_kind = 'tenant' AND g.scope_target = <tenantCol>)
137
+ * )
138
+ * )
139
+ *
140
+ * Note: the permission literal is embedded in the policy body at
141
+ * migration-emit time (not read from `app.platform_ops_permission` at
142
+ * runtime). This means each verb can be bound to a distinct catalog
143
+ * entry — `app.platform_ops_permission` GUC is set by `withPlatformOps`
144
+ * to enable auditing/forensics but is NOT what the policy checks.
145
+ *
146
+ * Compose alongside `withRls(t.tenantId)` on the same table when both
147
+ * platform-ops AND in-tenant surfaces are exposed.
148
+ */
149
+ export function withPlatformOpsTenant(tenantCol, perms, opts = {}) {
150
+ const tableName = getTableName(tenantCol.table);
151
+ const policyBase = unqualifiedName(tableName);
152
+ const tenantColumn = opts.tenantColumn ?? tenantCol.name;
153
+ const grantsTable = opts.grantsTable ?? PLATFORM_OPS_GRANTS_REPLICA_DEFAULT;
154
+ const policies = [];
155
+ for (const verb of ["read", "insert", "update", "delete"]) {
156
+ const permission = perms[verb];
157
+ if (!permission)
158
+ continue;
159
+ const predicate = platformOpsTenantPredicate(grantsTable, tenantColumn, permission);
160
+ policies.push(pgPolicy(`${policyBase}_platform_ops_${verb}`, {
161
+ as: "permissive",
162
+ for: drizzleForPlatformOps(verb),
163
+ to: "nodii_platform_ops",
164
+ ...platformOpsPredicates(verb, predicate),
165
+ }));
166
+ }
167
+ return policies;
168
+ }
169
+ /**
170
+ * Returns the platform-ops policy bundle (per D185 § 3) for a
171
+ * **platform-global** table that has no tenant_id column (modules,
172
+ * role catalogs, etc.). Emits one policy per verb in `perms` using the
173
+ * `scope_kind='platform_global'` predicate variant.
174
+ */
175
+ export function withPlatformOpsGlobal(table, perms, opts = {}) {
176
+ // For platform-global tables, callers pass the Drizzle pgTable itself
177
+ // (no tenant column to thread). We derive the policy name from the
178
+ // table's symbol identifier via getTableName(table).
179
+ const tableName = getTableName(table);
180
+ const policyBase = unqualifiedName(tableName);
181
+ const grantsTable = opts.grantsTable ?? PLATFORM_OPS_GRANTS_REPLICA_DEFAULT;
182
+ const policies = [];
183
+ for (const verb of ["read", "insert", "update", "delete"]) {
184
+ const permission = perms[verb];
185
+ if (!permission)
186
+ continue;
187
+ const predicate = platformOpsGlobalPredicate(grantsTable, permission);
188
+ policies.push(pgPolicy(`${policyBase}_platform_ops_${verb}`, {
189
+ as: "permissive",
190
+ for: drizzleForPlatformOps(verb),
191
+ to: "nodii_platform_ops",
192
+ ...platformOpsPredicates(verb, predicate),
193
+ }));
194
+ }
195
+ return policies;
196
+ }
197
+ function platformOpsTenantPredicate(grantsTable, tenantColumn, permission) {
198
+ const lit = sqlLiteral(permission);
199
+ return sql.raw(`EXISTS (SELECT 1 FROM ${grantsTable} g WHERE g.user_id = current_setting('app.user_id')::uuid AND g.service_id = current_setting('app.platform_ops_service_id') AND g.permission = ${lit} AND g.revoked_at IS NULL AND (g.expires_at IS NULL OR g.expires_at > NOW()) AND (g.scope_kind = 'all_tenants' OR (g.scope_kind = 'tenant' AND g.scope_target = ${tenantColumn})))`);
200
+ }
201
+ function platformOpsGlobalPredicate(grantsTable, permission) {
202
+ const lit = sqlLiteral(permission);
203
+ return sql.raw(`EXISTS (SELECT 1 FROM ${grantsTable} g WHERE g.user_id = current_setting('app.user_id')::uuid AND g.service_id = current_setting('app.platform_ops_service_id') AND g.scope_kind = 'platform_global' AND g.permission = ${lit} AND g.revoked_at IS NULL AND (g.expires_at IS NULL OR g.expires_at > NOW()))`);
204
+ }
205
+ function drizzleForPlatformOps(verb) {
206
+ return verb === "read" ? "select" : verb;
207
+ }
208
+ function platformOpsPredicates(verb, predicate) {
209
+ switch (verb) {
210
+ case "insert":
211
+ return { withCheck: predicate };
212
+ case "update":
213
+ return { using: predicate, withCheck: predicate };
214
+ default:
215
+ return { using: predicate };
216
+ }
217
+ }
218
+ /** SQL literal escape — doubles single quotes, wraps in quotes. */
219
+ function sqlLiteral(s) {
220
+ const escaped = s.replace(/'/g, "''");
221
+ return `'${escaped}'`;
222
+ }
223
+ //# sourceMappingURL=drizzle-policies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle-policies.js","sourceRoot":"","sources":["../src/drizzle-policies.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,14 +1,16 @@
1
1
  export declare const LIB_NAME = "db-rls";
2
- export declare const VERSION = "0.1.1";
2
+ export declare const VERSION = "0.4.0";
3
3
  export { initDbRls, requireDbRls, getDbRlsOrNull, requirePool, _resetForTests, } from "./init";
4
4
  export type { InitDbRlsConfig, ResolvedDbRls } from "./init";
5
- export { configureDbRls, PoolCredentialMismatch, _resetConfigureForTests, } from "./configure";
6
- export type { ConfigureDbRlsOpts } from "./configure";
5
+ export { configureDbRls, configureDbRls2Pool, configureDbRls4Pool, PoolCredentialMismatch, _resetConfigureForTests, } from "./configure";
6
+ export type { ConfigureDbRlsOpts, ConfigureDbRlsPools, } from "./configure";
7
7
  export { PgClientPool } from "./pg-pool-adapter";
8
8
  export type { PgPoolAdapterOpts } from "./pg-pool-adapter";
9
- export { withUserContext, withSystemContext, withOwnerContext, autoDispatch, } from "./context";
9
+ export { withUserContext, withSystemContext, withOwnerContext, withPlatformOps, autoDispatch, } from "./context";
10
10
  export { withUserContextDb, withSystemContextDb, withOwnerContextDb, } from "./drizzle-client";
11
11
  export type { DrizzleClient, NodePgDatabase } from "./drizzle-client";
12
+ export type { OwnerContextOpts } from "./migrate-guard";
13
+ export { assertMigrateAllowed } from "./migrate-guard";
12
14
  export { AUTH_SCHEMA_SQL, AUTH_SCHEMA_GRANTS_SQL, applyAuthSchemaMigrations, authSchemaFullSql, } from "./auth-schema";
13
15
  export type { SqlExecutor } from "./auth-schema";
14
16
  export { withRls, generateTableGrants } from "./rls-policy-gen";
@@ -18,6 +20,7 @@ export type { MigrateGenInput, MigrateGenResult } from "./migrate-gen";
18
20
  export { generateRlsPolicy, authSchemaHelpers } from "./rls-policy";
19
21
  export { InMemoryPgPool } from "./in-memory-pool";
20
22
  export type { TranscriptEntry } from "./in-memory-pool";
21
- export { DbRlsError, DbRlsNotInitialized, PoolUnavailable, MissingTenantContext, TransactionRolledBack, } from "./types";
22
- export type { AuthContext, AutoDispatchOpts, GenerateRlsPolicyOpts, PgPool, PgTx, PoolKind, SystemContextOpts, UserContextOpts, } from "./types";
23
+ export { DB_RLS_METRIC_VOCABULARY, _resetMetricsWarnLedgerForTests, } from "./metrics";
24
+ export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, MissingTenantContext, OwnerContextOutsideMigrate, PoolUnavailable, TransactionRolledBack, } from "./types";
25
+ export type { AuthContext, AutoDispatchOpts, DbRlsMode, GenerateRlsPolicyOpts, PgPool, PgTx, PlatformOpsContextOpts, PoolKind, SystemContextOpts, UserContextOpts, } from "./types";
23
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,QAAQ,WAAW,CAAC;AACjC,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B,OAAO,EACL,SAAS,EACT,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,QAAQ,CAAC;AAChB,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE7D,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEtE,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAChE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAIvE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,iBAAiB,EACjB,eAAe,GAChB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiCA,eAAO,MAAM,QAAQ,WAAW,CAAC;AACjC,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B,OAAO,EACL,SAAS,EACT,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,QAAQ,CAAC;AAChB,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE7D,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEtE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAChE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAIvE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EACL,wBAAwB,EACxB,+BAA+B,GAChC,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,EAC1B,eAAe,EACf,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,SAAS,EACT,qBAAqB,EACrB,MAAM,EACN,IAAI,EACJ,sBAAsB,EACtB,QAAQ,EACR,iBAAiB,EACjB,eAAe,GAChB,MAAM,SAAS,CAAC"}