@nodii/db-rls 0.5.1 → 0.5.3
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/bin/migrate-gen.mjs +24 -7
- package/dist/drizzle-policies.d.ts +34 -2
- package/dist/drizzle-policies.d.ts.map +1 -1
- package/dist/drizzle-policies.js +84 -2
- package/dist/drizzle-policies.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/migrate-gen.d.ts +51 -1
- package/dist/migrate-gen.d.ts.map +1 -1
- package/dist/migrate-gen.js +69 -3
- package/dist/migrate-gen.js.map +1 -1
- package/dist/rls-policy-gen.d.ts +43 -0
- package/dist/rls-policy-gen.d.ts.map +1 -1
- package/dist/rls-policy-gen.js +93 -0
- package/dist/rls-policy-gen.js.map +1 -1
- package/dist/verify-rls-cli.d.ts +20 -0
- package/dist/verify-rls-cli.d.ts.map +1 -0
- package/dist/verify-rls-cli.js +99 -0
- package/dist/verify-rls-cli.js.map +1 -0
- package/dist/verify-rls.d.ts +76 -0
- package/dist/verify-rls.d.ts.map +1 -0
- package/dist/verify-rls.js +145 -0
- package/dist/verify-rls.js.map +1 -0
- package/package.json +1 -1
package/bin/migrate-gen.mjs
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// CLI shim for `npx @nodii/db-rls
|
|
2
|
+
// CLI shim for `npx @nodii/db-rls <subcommand>`.
|
|
3
3
|
//
|
|
4
|
-
// The real logic lives in src
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// The real logic lives in src/*.ts; this shim unwraps argv, dispatches by
|
|
5
|
+
// subcommand, and translates the return value to process.exit.
|
|
6
|
+
//
|
|
7
|
+
// Subcommands:
|
|
8
|
+
// migrate-gen <serviceName> [--out <dir>] [--stub]
|
|
9
|
+
// verify-rls --tables <a,b,c> [--ref <x,y>] [--schema <name>] [--db <url>]
|
|
10
|
+
//
|
|
11
|
+
// (Filename kept as migrate-gen.mjs for the package.json `bin` mapping;
|
|
12
|
+
// it is the single `nodii-db-rls` entrypoint, not migrate-gen only.)
|
|
7
13
|
|
|
8
14
|
import { runMigrateGenCli } from "../dist/migrate-gen.js";
|
|
15
|
+
import { runVerifyRlsCli } from "../dist/verify-rls-cli.js";
|
|
16
|
+
|
|
17
|
+
const argv = process.argv.slice(2);
|
|
18
|
+
const sub = argv[0];
|
|
9
19
|
|
|
10
|
-
|
|
11
|
-
const code =
|
|
12
|
-
|
|
20
|
+
if (sub === "verify-rls") {
|
|
21
|
+
const { code, message } = await runVerifyRlsCli(argv.slice(1));
|
|
22
|
+
// Coverage failures (1) + usage (2) go to stderr; success (0) to stdout.
|
|
23
|
+
(code === 0 ? console.log : console.error)(message);
|
|
24
|
+
process.exit(code);
|
|
25
|
+
} else {
|
|
26
|
+
// migrate-gen (default + back-compat: runMigrateGenCli accepts the
|
|
27
|
+
// leading "migrate-gen" token and prints usage on a missing serviceName).
|
|
28
|
+
process.exit(runMigrateGenCli(argv));
|
|
29
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { PgColumnBuilderBase, PgPolicy, PgTableWithColumns } from "drizzle-orm/pg-core";
|
|
2
|
+
import type { PgColumn } from "drizzle-orm/pg-core";
|
|
3
|
+
import type { PlatformOpsPerVerbPermissions, ReferenceTableSqlOpts, WithRlsOpts } from "./rls-policy-gen";
|
|
3
4
|
export type { PlatformOpsPerVerbPermissions } from "./rls-policy-gen";
|
|
5
|
+
export type { ReferenceTableReadRole, ReferenceTableSqlOpts, } from "./rls-policy-gen";
|
|
6
|
+
export { ReferenceTableTenantColumnError, referenceTableGrantsSql, } from "./rls-policy-gen";
|
|
4
7
|
/**
|
|
5
8
|
* Returns the canonical 5-policy Drizzle constructs (per doctrine § 4)
|
|
6
9
|
* for a tenant-scoped table.
|
|
@@ -78,4 +81,33 @@ export declare function withPlatformOpsGlobal(table: {
|
|
|
78
81
|
};
|
|
79
82
|
[key: string]: unknown;
|
|
80
83
|
}, perms: PlatformOpsPerVerbPermissions, opts?: WithPlatformOpsOpts): PgPolicy[];
|
|
84
|
+
/**
|
|
85
|
+
* Builds a pure platform-global reference table (08-rls § 7.6).
|
|
86
|
+
*
|
|
87
|
+
* Identical signature to Drizzle's `pgTable(name, columns)` — returns the
|
|
88
|
+
* `PgTableWithColumns`. No third-arg extras callback is accepted because a
|
|
89
|
+
* reference table gets NO RLS policies (GRANT-controlled per § 7.6).
|
|
90
|
+
*
|
|
91
|
+
* Throws {@link ReferenceTableTenantColumnError} at construction time if any
|
|
92
|
+
* column is named `tenant_id` (case-insensitive). A reference table is
|
|
93
|
+
* platform-global by definition; a `tenant_id` column means the table is
|
|
94
|
+
* tenant-scoped and should use `withRls` + the canonical 5-policy DDL instead.
|
|
95
|
+
*
|
|
96
|
+
* @param name Postgres table name.
|
|
97
|
+
* @param columns Drizzle column-builder map (same shape as `pgTable`'s).
|
|
98
|
+
*/
|
|
99
|
+
export declare function referenceTable<TColumns extends Record<string, PgColumnBuilderBase>>(name: string, columns: TColumns): PgTableWithColumns<any>;
|
|
100
|
+
/**
|
|
101
|
+
* Emits the GRANT/REVOKE DDL (08-rls § 7.6) for a reference table built via
|
|
102
|
+
* {@link referenceTable}. Convenience wrapper over `referenceTableGrantsSql`
|
|
103
|
+
* that derives the table name from the Drizzle table.
|
|
104
|
+
*
|
|
105
|
+
* Same single-source SQL as migrate-gen's `platform_global_reference` kind.
|
|
106
|
+
*/
|
|
107
|
+
export declare function referenceTableGrants(table: {
|
|
108
|
+
_: {
|
|
109
|
+
name: string;
|
|
110
|
+
};
|
|
111
|
+
[key: string]: unknown;
|
|
112
|
+
}, opts?: ReferenceTableSqlOpts): string;
|
|
81
113
|
//# sourceMappingURL=drizzle-policies.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drizzle-policies.d.ts","sourceRoot":"","sources":["../src/drizzle-policies.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"drizzle-policies.d.ts","sourceRoot":"","sources":["../src/drizzle-policies.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EACV,mBAAmB,EACnB,QAAQ,EACR,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAUpD,OAAO,KAAK,EACV,6BAA6B,EAC7B,qBAAqB,EAErB,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAI1B,YAAY,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACtE,YAAY,EACV,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,+BAA+B,EAC/B,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAI1B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,OAAO,CACrB,SAAS,EAAE,QAAQ,EACnB,IAAI,GAAE,WAAgB,GACrB,QAAQ,EAAE,CAsCZ;AA6ED,MAAM,WAAW,mBAAmB;IAClC;;kEAE8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;6CACyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,QAAQ,EACnB,KAAK,EAAE,6BAA6B,EACpC,IAAI,GAAE,mBAAwB,GAC7B,QAAQ,EAAE,CAwBZ;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,CA4BZ;AA6DD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAEpD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,QAAQ,GAEhB,kBAAkB,CAAC,GAAG,CAAC,CAoBzB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE;IAAE,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EACtD,IAAI,GAAE,qBAA0B,GAC/B,MAAM,CAKR"}
|
package/dist/drizzle-policies.js
CHANGED
|
@@ -25,9 +25,11 @@
|
|
|
25
25
|
// The legacy string-DDL `withRls(table: string)` helper exported from
|
|
26
26
|
// `@nodii/db-rls` (main barrel) keeps its `*_policy` suffix for backwards
|
|
27
27
|
// parity with v0.1.x consumers — both surfaces ship.
|
|
28
|
-
import { getTableName, sql } from "drizzle-orm";
|
|
28
|
+
import { getTableColumns, getTableName, sql } from "drizzle-orm";
|
|
29
|
+
import { pgTable } from "drizzle-orm/pg-core";
|
|
29
30
|
import { pgPolicy } from "drizzle-orm/pg-core";
|
|
30
|
-
import { PLATFORM_OPS_GRANTS_REPLICA_DEFAULT, platformOpsGlobalPredicateSql, platformOpsTenantPredicateSql, } from "./rls-policy-gen";
|
|
31
|
+
import { PLATFORM_OPS_GRANTS_REPLICA_DEFAULT, ReferenceTableTenantColumnError, findTenantColumn, platformOpsGlobalPredicateSql, platformOpsTenantPredicateSql, referenceTableGrantsSql, } from "./rls-policy-gen";
|
|
32
|
+
export { ReferenceTableTenantColumnError, referenceTableGrantsSql, } from "./rls-policy-gen";
|
|
31
33
|
const DEFAULT_ALLOW = ["SELECT", "INSERT"];
|
|
32
34
|
/**
|
|
33
35
|
* Returns the canonical 5-policy Drizzle constructs (per doctrine § 4)
|
|
@@ -208,4 +210,84 @@ function platformOpsPredicates(verb, predicate) {
|
|
|
208
210
|
return { using: predicate };
|
|
209
211
|
}
|
|
210
212
|
}
|
|
213
|
+
// ----------------------------------------------------------------------------
|
|
214
|
+
// 08-rls § 7.6 — pure platform-global reference table builder.
|
|
215
|
+
//
|
|
216
|
+
// A pure platform-global reference table (no tenant_id + non-confidential +
|
|
217
|
+
// platform-admin write path) is GRANT-controlled, NOT RLS-protected. This
|
|
218
|
+
// builder wraps Drizzle's `pgTable` and:
|
|
219
|
+
//
|
|
220
|
+
// 1. REFUSES (throws ReferenceTableTenantColumnError) if a `tenant_id`
|
|
221
|
+
// column is declared — a tenant_id is a category error for a
|
|
222
|
+
// platform-global reference table (§ 7.6 property 1). This is the
|
|
223
|
+
// doctrine's hard safety boundary.
|
|
224
|
+
// 2. Returns the plain pgTable — NO RLS policies are attached (§ 7.6
|
|
225
|
+
// INTENTIONALLY omits ENABLE ROW LEVEL SECURITY).
|
|
226
|
+
//
|
|
227
|
+
// The companion GRANT/REVOKE DDL (GRANT SELECT to the read role + GRANT
|
|
228
|
+
// write to nodii_owner + REVOKE write from the read role) is emitted by
|
|
229
|
+
// `referenceTableGrantsSql(getTableName(t))` — apply it in the consumer's
|
|
230
|
+
// migration. migrate-gen's `platform_global_reference` kind emits the same
|
|
231
|
+
// DDL via the same single-source `referenceTableGrantsSql` (no fork).
|
|
232
|
+
//
|
|
233
|
+
// Usage:
|
|
234
|
+
//
|
|
235
|
+
// import { referenceTable, referenceTableGrantsSql } from "@nodii/db-rls/drizzle";
|
|
236
|
+
// import { getTableName } from "drizzle-orm";
|
|
237
|
+
//
|
|
238
|
+
// export const taskActionButtonRegistry = referenceTable(
|
|
239
|
+
// "task_action_button_registry",
|
|
240
|
+
// {
|
|
241
|
+
// id: text("id").primaryKey(),
|
|
242
|
+
// label: text("label").notNull(),
|
|
243
|
+
// icon: text("icon"),
|
|
244
|
+
// },
|
|
245
|
+
// );
|
|
246
|
+
// // Apply alongside the Drizzle migration:
|
|
247
|
+
// const grantDdl = referenceTableGrantsSql(getTableName(taskActionButtonRegistry));
|
|
248
|
+
/**
|
|
249
|
+
* Builds a pure platform-global reference table (08-rls § 7.6).
|
|
250
|
+
*
|
|
251
|
+
* Identical signature to Drizzle's `pgTable(name, columns)` — returns the
|
|
252
|
+
* `PgTableWithColumns`. No third-arg extras callback is accepted because a
|
|
253
|
+
* reference table gets NO RLS policies (GRANT-controlled per § 7.6).
|
|
254
|
+
*
|
|
255
|
+
* Throws {@link ReferenceTableTenantColumnError} at construction time if any
|
|
256
|
+
* column is named `tenant_id` (case-insensitive). A reference table is
|
|
257
|
+
* platform-global by definition; a `tenant_id` column means the table is
|
|
258
|
+
* tenant-scoped and should use `withRls` + the canonical 5-policy DDL instead.
|
|
259
|
+
*
|
|
260
|
+
* @param name Postgres table name.
|
|
261
|
+
* @param columns Drizzle column-builder map (same shape as `pgTable`'s).
|
|
262
|
+
*/
|
|
263
|
+
export function referenceTable(name, columns) {
|
|
264
|
+
// Refuse a tenant_id column declared in the column map — the § 7.6
|
|
265
|
+
// safety boundary. Check the keys first (the column property name) so we
|
|
266
|
+
// reject `tenantId: uuid("tenant_id")` AND `tenant_id: ...`.
|
|
267
|
+
const declaredKey = findTenantColumn(Object.keys(columns));
|
|
268
|
+
if (declaredKey) {
|
|
269
|
+
throw new ReferenceTableTenantColumnError(name, declaredKey);
|
|
270
|
+
}
|
|
271
|
+
const table = pgTable(name, columns);
|
|
272
|
+
// Also refuse if the resolved DB column name is tenant_id even when the
|
|
273
|
+
// property key isn't (e.g. `foo: uuid("tenant_id")`). getTableColumns
|
|
274
|
+
// resolves the actual DB column names.
|
|
275
|
+
const resolvedCols = getTableColumns(table);
|
|
276
|
+
const tenantDbCol = findTenantColumn(Object.values(resolvedCols).map((c) => c.name));
|
|
277
|
+
if (tenantDbCol) {
|
|
278
|
+
throw new ReferenceTableTenantColumnError(name, tenantDbCol);
|
|
279
|
+
}
|
|
280
|
+
return table;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Emits the GRANT/REVOKE DDL (08-rls § 7.6) for a reference table built via
|
|
284
|
+
* {@link referenceTable}. Convenience wrapper over `referenceTableGrantsSql`
|
|
285
|
+
* that derives the table name from the Drizzle table.
|
|
286
|
+
*
|
|
287
|
+
* Same single-source SQL as migrate-gen's `platform_global_reference` kind.
|
|
288
|
+
*/
|
|
289
|
+
export function referenceTableGrants(table, opts = {}) {
|
|
290
|
+
const tableName = getTableName(table);
|
|
291
|
+
return referenceTableGrantsSql(tableName, opts);
|
|
292
|
+
}
|
|
211
293
|
//# sourceMappingURL=drizzle-policies.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drizzle-policies.js","sourceRoot":"","sources":["../src/drizzle-policies.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,mEAAmE;AACnE,uEAAuE;AACvE,mBAAmB;AACnB,EAAE;AACF,qDAAqD;AACrD,EAAE;AACF,iEAAiE;AACjE,mDAAmD;AACnD,6CAA6C;AAC7C,2CAA2C;AAC3C,gBAAgB;AAChB,sFAAsF;AACtF,8BAA8B;AAC9B,mFAAmF;AACnF,QAAQ;AACR,EAAE;AACF,sEAAsE;AACtE,sEAAsE;AACtE,gEAAgE;AAChE,oEAAoE;AACpE,yBAAyB;AACzB,EAAE;AACF,sEAAsE;AACtE,0EAA0E;AAC1E,qDAAqD;AAErD,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"drizzle-policies.js","sourceRoot":"","sources":["../src/drizzle-policies.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,mEAAmE;AACnE,uEAAuE;AACvE,mBAAmB;AACnB,EAAE;AACF,qDAAqD;AACrD,EAAE;AACF,iEAAiE;AACjE,mDAAmD;AACnD,6CAA6C;AAC7C,2CAA2C;AAC3C,gBAAgB;AAChB,sFAAsF;AACtF,8BAA8B;AAC9B,mFAAmF;AACnF,QAAQ;AACR,EAAE;AACF,sEAAsE;AACtE,sEAAsE;AACtE,gEAAgE;AAChE,oEAAoE;AACpE,yBAAyB;AACzB,EAAE;AACF,sEAAsE;AACtE,0EAA0E;AAC1E,qDAAqD;AAErD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAQ/C,OAAO,EACL,mCAAmC,EACnC,+BAA+B,EAC/B,gBAAgB,EAChB,6BAA6B,EAC7B,6BAA6B,EAC7B,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAe1B,OAAO,EACL,+BAA+B,EAC/B,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,aAAa,GAAuB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAE/D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,OAAO,CACrB,SAAmB,EACnB,OAAoB,EAAE;IAEtB,MAAM,KAAK,GACT,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC;IACnE,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,SAAS,CAAC,IAAI,CAAC;IAEzD,0FAA0F;IAC1F,MAAM,aAAa,GAAG,GAAG,CAAC,GAAG,CAC3B,GAAG,YAAY,uDAAuD,CACvE,CAAC;IACF,uDAAuD;IACvD,MAAM,YAAY,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY,yBAAyB,CAAC,CAAC;IAEvE,MAAM,QAAQ,GAAe,EAAE,CAAC;IAEhC,oBAAoB;IACpB,QAAQ,CAAC,IAAI,CACX,QAAQ,CAAC,GAAG,UAAU,QAAQ,EAAE;QAC9B,EAAE,EAAE,YAAY;QAChB,GAAG,EAAE,KAAK;QACV,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,GAAG,CAAA,MAAM;QAChB,SAAS,EAAE,GAAG,CAAA,MAAM;KACrB,CAAC,CACH,CAAC;IAEF,6BAA6B;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,8BAA8B;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CACpB,UAAkB,EAClB,IAAa,EACb,SAAqC;IAErC,MAAM,IAAI,GAAG,GAAG,UAAU,SAAS,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;IACxD,OAAO,QAAQ,CAAC,IAAI,EAAE;QACpB,EAAE,EAAE,YAAY;QAChB,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC;QACrB,EAAE,EAAE,eAAe;QACnB,GAAG,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;KAC/B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CACnB,UAAkB,EAClB,IAAa,EACb,SAAqC;IAErC,MAAM,IAAI,GAAG,GAAG,UAAU,QAAQ,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;IACvD,OAAO,QAAQ,CAAC,IAAI,EAAE;QACpB,EAAE,EAAE,YAAY;QAChB,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC;QACrB,EAAE,EAAE,gBAAgB;QACpB,GAAG,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;KAC/B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,IAAa;IAC/B,OAAO,IAAI,CAAC,WAAW,EAA+C,CAAC;AACzE,CAAC;AAED,SAAS,UAAU,CACjB,IAAa,EACb,SAAqC;IAKrC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QAClC,KAAK,QAAQ;YACX,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QACpD;YACE,iBAAiB;YACjB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAChC,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC;AAgCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,qBAAqB,CACnC,SAAmB,EACnB,KAAoC,EACpC,OAA4B,EAAE;IAE9B,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,SAAS,CAAC,IAAI,CAAC;IACzD,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,mCAAmC,CAAC;IAC5E,MAAM,QAAQ,GAAe,EAAE,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAU,EAAE,CAAC;QACnE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,MAAM,SAAS,GAAG,GAAG,CAAC,GAAG,CACvB,6BAA6B,CAAC,WAAW,EAAE,YAAY,EAAE,UAAU,CAAC,CACrE,CAAC;QACF,QAAQ,CAAC,IAAI,CACX,QAAQ,CAAC,GAAG,UAAU,iBAAiB,IAAI,EAAE,EAAE;YAC7C,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,qBAAqB,CAAC,IAAI,CAAC;YAChC,EAAE,EAAE,oBAAoB;YACxB,GAAG,qBAAqB,CAAC,IAAI,EAAE,SAAS,CAAC;SAC1C,CAAC,CACH,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAsD,EACtD,KAAoC,EACpC,OAA4B,EAAE;IAE9B,sEAAsE;IACtE,mEAAmE;IACnE,qDAAqD;IACrD,MAAM,SAAS,GAAG,YAAY,CAC5B,KAAsD,CACvD,CAAC;IACF,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,mCAAmC,CAAC;IAC5E,MAAM,QAAQ,GAAe,EAAE,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAU,EAAE,CAAC;QACnE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,MAAM,SAAS,GAAG,GAAG,CAAC,GAAG,CACvB,6BAA6B,CAAC,WAAW,EAAE,UAAU,CAAC,CACvD,CAAC;QACF,QAAQ,CAAC,IAAI,CACX,QAAQ,CAAC,GAAG,UAAU,iBAAiB,IAAI,EAAE,EAAE;YAC7C,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,qBAAqB,CAAC,IAAI,CAAC;YAChC,EAAE,EAAE,oBAAoB;YACxB,GAAG,qBAAqB,CAAC,IAAI,EAAE,SAAS,CAAC;SAC1C,CAAC,CACH,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,qBAAqB,CAC5B,IAA6C;IAE7C,OAAO,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3C,CAAC;AAED,SAAS,qBAAqB,CAC5B,IAA6C,EAC7C,SAAqC;IAKrC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QAClC,KAAK,QAAQ;YACX,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QACpD;YACE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAChC,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,+DAA+D;AAC/D,EAAE;AACF,4EAA4E;AAC5E,0EAA0E;AAC1E,yCAAyC;AACzC,EAAE;AACF,yEAAyE;AACzE,kEAAkE;AAClE,uEAAuE;AACvE,wCAAwC;AACxC,uEAAuE;AACvE,uDAAuD;AACvD,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,0EAA0E;AAC1E,2EAA2E;AAC3E,sEAAsE;AACtE,EAAE;AACF,SAAS;AACT,EAAE;AACF,qFAAqF;AACrF,gDAAgD;AAChD,EAAE;AACF,4DAA4D;AAC5D,qCAAqC;AACrC,QAAQ;AACR,qCAAqC;AACrC,wCAAwC;AACxC,4BAA4B;AAC5B,SAAS;AACT,OAAO;AACP,8CAA8C;AAC9C,sFAAsF;AAEtF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAG5B,IAAY,EACZ,OAAiB;IAGjB,mEAAmE;IACnE,yEAAyE;IACzE,6DAA6D;IAC7D,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3D,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,IAAI,+BAA+B,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,wEAAwE;IACxE,sEAAsE;IACtE,uCAAuC;IACvC,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,gBAAgB,CAClC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAC/C,CAAC;IACF,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,IAAI,+BAA+B,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAsD,EACtD,OAA8B,EAAE;IAEhC,MAAM,SAAS,GAAG,YAAY,CAC5B,KAAsD,CACvD,CAAC;IACF,OAAO,uBAAuB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAClD,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,12 +11,14 @@ export { withUserContextDb, withSystemContextDb, withOwnerContextDb, } from "./d
|
|
|
11
11
|
export type { DrizzleClient, NodePgDatabase } from "./drizzle-client";
|
|
12
12
|
export type { OwnerContextOpts } from "./migrate-guard";
|
|
13
13
|
export { assertMigrateAllowed } from "./migrate-guard";
|
|
14
|
+
export { RlsCoverageError, verifyRls } from "./verify-rls";
|
|
15
|
+
export type { ReferenceTablePredicate, RlsCoverageOffender, RlsQuerier, VerifyRlsOpts, } from "./verify-rls";
|
|
14
16
|
export { AUTH_SCHEMA_SQL, AUTH_SCHEMA_GRANTS_SQL, applyAuthSchemaMigrations, authSchemaFullSql, } from "./auth-schema";
|
|
15
17
|
export type { SqlExecutor } from "./auth-schema";
|
|
16
|
-
export { withRls, generateTableGrants, withPlatformOpsTenantSql, withPlatformOpsGlobalSql, platformOpsTenantPredicateSql, platformOpsGlobalPredicateSql, platformOpsVerbClauseSql, sqlLiteral, PLATFORM_OPS_GRANTS_REPLICA_DEFAULT, } from "./rls-policy-gen";
|
|
17
|
-
export type { RlsVerb, WithRlsOpts, PlatformOpsVerb, PlatformOpsPerVerbPermissions, WithPlatformOpsSqlOpts, } from "./rls-policy-gen";
|
|
18
|
-
export { migrateGen, runMigrateGenCli, userTenantIdsRealSql, userTenantIdsStubSql, platformOpsPoliciesSql, } from "./migrate-gen";
|
|
19
|
-
export type { MigrateGenInput, MigrateGenResult, PlatformOpsTableSpec, } from "./migrate-gen";
|
|
18
|
+
export { withRls, generateTableGrants, withPlatformOpsTenantSql, withPlatformOpsGlobalSql, platformOpsTenantPredicateSql, platformOpsGlobalPredicateSql, platformOpsVerbClauseSql, sqlLiteral, PLATFORM_OPS_GRANTS_REPLICA_DEFAULT, referenceTableGrantsSql, findTenantColumn, ReferenceTableTenantColumnError, REFERENCE_TABLE_SKIP_RLS_MARKER, } from "./rls-policy-gen";
|
|
19
|
+
export type { RlsVerb, WithRlsOpts, PlatformOpsVerb, PlatformOpsPerVerbPermissions, WithPlatformOpsSqlOpts, ReferenceTableReadRole, ReferenceTableSqlOpts, } from "./rls-policy-gen";
|
|
20
|
+
export { migrateGen, runMigrateGenCli, userTenantIdsRealSql, userTenantIdsStubSql, platformOpsPoliciesSql, referenceTablesSql, } from "./migrate-gen";
|
|
21
|
+
export type { MigrateGenInput, MigrateGenResult, PlatformOpsTableSpec, ReferenceTableSpec, } from "./migrate-gen";
|
|
20
22
|
export { generateRlsPolicy, authSchemaHelpers } from "./rls-policy";
|
|
21
23
|
export { InMemoryPgPool } from "./in-memory-pool";
|
|
22
24
|
export type { TranscriptEntry } from "./in-memory-pool";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,sBAAsB,EAItB,eAAe,EACf,8CAA8C,EAC9C,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;
|
|
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,sBAAsB,EAItB,eAAe,EACf,8CAA8C,EAC9C,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;AAMvD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC3D,YAAY,EACV,uBAAuB,EACvB,mBAAmB,EACnB,UAAU,EACV,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,6BAA6B,EAC7B,6BAA6B,EAC7B,wBAAwB,EACxB,UAAU,EACV,mCAAmC,EAEnC,uBAAuB,EACvB,gBAAgB,EAChB,+BAA+B,EAC/B,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,OAAO,EACP,WAAW,EACX,eAAe,EACf,6BAA6B,EAC7B,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAIvB,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"}
|
package/dist/index.js
CHANGED
|
@@ -42,9 +42,16 @@ export { withUserContext, withSystemContext, withOwnerContext, withPlatformOpsCo
|
|
|
42
42
|
withPlatformOps, _resetWithPlatformOpsDeprecationWarnedForTests, autoDispatch, } from "./context";
|
|
43
43
|
export { withUserContextDb, withSystemContextDb, withOwnerContextDb, } from "./drizzle-client";
|
|
44
44
|
export { assertMigrateAllowed } from "./migrate-guard";
|
|
45
|
+
// 08-rls § A1 + § 7.6 — RLS-coverage preflight guard. Service db:setup
|
|
46
|
+
// gates call verifyRls() after migrations to catch the drizzle-snapshot
|
|
47
|
+
// RLS hazard (a tenant table created without ENABLE ROW LEVEL SECURITY),
|
|
48
|
+
// exempting § 7.6 reference tables (GRANT-controlled, NO RLS by design).
|
|
49
|
+
export { RlsCoverageError, verifyRls } from "./verify-rls";
|
|
45
50
|
export { AUTH_SCHEMA_SQL, AUTH_SCHEMA_GRANTS_SQL, applyAuthSchemaMigrations, authSchemaFullSql, } from "./auth-schema";
|
|
46
|
-
export { withRls, generateTableGrants, withPlatformOpsTenantSql, withPlatformOpsGlobalSql, platformOpsTenantPredicateSql, platformOpsGlobalPredicateSql, platformOpsVerbClauseSql, sqlLiteral, PLATFORM_OPS_GRANTS_REPLICA_DEFAULT,
|
|
47
|
-
|
|
51
|
+
export { withRls, generateTableGrants, withPlatformOpsTenantSql, withPlatformOpsGlobalSql, platformOpsTenantPredicateSql, platformOpsGlobalPredicateSql, platformOpsVerbClauseSql, sqlLiteral, PLATFORM_OPS_GRANTS_REPLICA_DEFAULT,
|
|
52
|
+
// 08-rls § 7.6 — pure platform-global reference tables (GRANT-controlled).
|
|
53
|
+
referenceTableGrantsSql, findTenantColumn, ReferenceTableTenantColumnError, REFERENCE_TABLE_SKIP_RLS_MARKER, } from "./rls-policy-gen";
|
|
54
|
+
export { migrateGen, runMigrateGenCli, userTenantIdsRealSql, userTenantIdsStubSql, platformOpsPoliciesSql, referenceTablesSql, } from "./migrate-gen";
|
|
48
55
|
// Legacy v0.1.0 surface kept for callers that already imported these
|
|
49
56
|
// names. Both are byte-equal SQL helpers — no NotImplemented paths.
|
|
50
57
|
export { generateRlsPolicy, authSchemaHelpers } from "./rls-policy";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,EAAE;AACF,oEAAoE;AACpE,oEAAoE;AACpE,wDAAwD;AACxD,6CAA6C;AAC7C,EAAE;AACF,yCAAyC;AACzC,sEAAsE;AACtE,wCAAwC;AACxC,sDAAsD;AACtD,+DAA+D;AAC/D,4EAA4E;AAC5E,gDAAgD;AAChD,mEAAmE;AACnE,mDAAmD;AACnD,wEAAwE;AACxE,2EAA2E;AAC3E,+EAA+E;AAC/E,wEAAwE;AACxE,sEAAsE;AACtE,6EAA6E;AAC7E,6EAA6E;AAC7E,sCAAsC;AACtC,uEAAuE;AACvE,0EAA0E;AAC1E,8EAA8E;AAC9E,kFAAkF;AAClF,yEAAyE;AACzE,mEAAmE;AACnE,0EAA0E;AAC1E,qCAAqC;AAErC,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AACjC,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,OAAO,EACL,SAAS,EACT,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB;AACtB,uEAAuE;AACvE,wEAAwE;AACxE,sCAAsC;AACtC,eAAe,EACf,8CAA8C,EAC9C,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,6BAA6B,EAC7B,6BAA6B,EAC7B,wBAAwB,EACxB,UAAU,EACV,mCAAmC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,EAAE;AACF,oEAAoE;AACpE,oEAAoE;AACpE,wDAAwD;AACxD,6CAA6C;AAC7C,EAAE;AACF,yCAAyC;AACzC,sEAAsE;AACtE,wCAAwC;AACxC,sDAAsD;AACtD,+DAA+D;AAC/D,4EAA4E;AAC5E,gDAAgD;AAChD,mEAAmE;AACnE,mDAAmD;AACnD,wEAAwE;AACxE,2EAA2E;AAC3E,+EAA+E;AAC/E,wEAAwE;AACxE,sEAAsE;AACtE,6EAA6E;AAC7E,6EAA6E;AAC7E,sCAAsC;AACtC,uEAAuE;AACvE,0EAA0E;AAC1E,8EAA8E;AAC9E,kFAAkF;AAClF,yEAAyE;AACzE,mEAAmE;AACnE,0EAA0E;AAC1E,qCAAqC;AAErC,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AACjC,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,OAAO,EACL,SAAS,EACT,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB;AACtB,uEAAuE;AACvE,wEAAwE;AACxE,sCAAsC;AACtC,eAAe,EACf,8CAA8C,EAC9C,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,uEAAuE;AACvE,wEAAwE;AACxE,yEAAyE;AACzE,yEAAyE;AACzE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAQ3D,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,6BAA6B,EAC7B,6BAA6B,EAC7B,wBAAwB,EACxB,UAAU,EACV,mCAAmC;AACnC,2EAA2E;AAC3E,uBAAuB,EACvB,gBAAgB,EAChB,+BAA+B,EAC/B,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAW1B,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAQvB,qEAAqE;AACrE,oEAAoE;AACpE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,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"}
|
package/dist/migrate-gen.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type PlatformOpsPerVerbPermissions } from "./rls-policy-gen";
|
|
1
|
+
import { type PlatformOpsPerVerbPermissions, type ReferenceTableReadRole } from "./rls-policy-gen";
|
|
2
2
|
/**
|
|
3
3
|
* One table exposed via the platform-ops cross-tenant surface (D185).
|
|
4
4
|
* `scope='tenant'` tables emit the tenant predicate (joins on
|
|
@@ -21,6 +21,27 @@ export interface PlatformOpsTableSpec {
|
|
|
21
21
|
/** Override the `platform_ops_grants_replica` table name. */
|
|
22
22
|
grantsTable?: string;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* One pure platform-global reference table (08-rls § 7.6). Declaring a
|
|
26
|
+
* table here makes migrate-gen emit the GRANT-controlled (NO RLS) DDL —
|
|
27
|
+
* `GRANT SELECT` to the read role(s) + `GRANT INSERT, UPDATE, DELETE` to
|
|
28
|
+
* `nodii_owner` + `REVOKE` write from the read role(s) — and NOT the
|
|
29
|
+
* 5-policy RLS DDL.
|
|
30
|
+
*
|
|
31
|
+
* `kind` is fixed to the discriminant `'platform_global_reference'` so a
|
|
32
|
+
* schema's table-set can be a heterogeneous list and migrate-gen routes
|
|
33
|
+
* each entry by `kind`.
|
|
34
|
+
*/
|
|
35
|
+
export interface ReferenceTableSpec {
|
|
36
|
+
/** Discriminant — pure platform-global reference table per 08-rls § 7.6. */
|
|
37
|
+
kind: "platform_global_reference";
|
|
38
|
+
/** Table name. May be schema-qualified (`schema.tbl`). */
|
|
39
|
+
table: string;
|
|
40
|
+
/** Read role(s) that get `GRANT SELECT` + `REVOKE` write. Defaults to
|
|
41
|
+
* `["nodii_services"]` (3-pool). 2-pool services may pass
|
|
42
|
+
* `["authenticated"]`; 4-pool may add `"nodii_platform_ops"`. */
|
|
43
|
+
readRoles?: readonly ReferenceTableReadRole[];
|
|
44
|
+
}
|
|
24
45
|
export interface MigrateGenInput {
|
|
25
46
|
/** Pattern A service name, e.g. "nodii-billing-service". Used only for
|
|
26
47
|
* the file header comment; not in the SQL body. */
|
|
@@ -35,6 +56,10 @@ export interface MigrateGenInput {
|
|
|
35
56
|
* file `0002_platform_ops_policies.sql` is emitted with the per-verb
|
|
36
57
|
* platform-ops CREATE POLICY DDL. Applies only in the non-stub path. */
|
|
37
58
|
platformOps?: readonly PlatformOpsTableSpec[];
|
|
59
|
+
/** Pure platform-global reference tables (08-rls § 7.6). When non-empty,
|
|
60
|
+
* a file `0003_reference_table_grants.sql` is emitted with the
|
|
61
|
+
* GRANT-controlled (NO RLS) DDL. Applies only in the non-stub path. */
|
|
62
|
+
referenceTables?: readonly ReferenceTableSpec[];
|
|
38
63
|
}
|
|
39
64
|
export interface MigrateGenResult {
|
|
40
65
|
/** Absolute path of the file that was written. */
|
|
@@ -46,6 +71,11 @@ export interface MigrateGenResult {
|
|
|
46
71
|
/** Platform-ops policy DDL contents, when emitted (also returned for
|
|
47
72
|
* parity-fence + test assertions). */
|
|
48
73
|
platformOpsContents?: string;
|
|
74
|
+
/** Absolute path of the reference-table grants file, when emitted. */
|
|
75
|
+
referenceTablesPath?: string;
|
|
76
|
+
/** Reference-table grants DDL contents, when emitted (also returned for
|
|
77
|
+
* parity-fence + test assertions). */
|
|
78
|
+
referenceTablesContents?: string;
|
|
49
79
|
}
|
|
50
80
|
/**
|
|
51
81
|
* SQL text for the real (joins mirror tables) helper. Module-level
|
|
@@ -66,6 +96,22 @@ export declare function userTenantIdsStubSql(serviceName: string): string;
|
|
|
66
96
|
* Returns `""` when no tables are configured.
|
|
67
97
|
*/
|
|
68
98
|
export declare function platformOpsPoliciesSql(serviceName: string, tables: readonly PlatformOpsTableSpec[]): string;
|
|
99
|
+
/**
|
|
100
|
+
* SQL text for the pure platform-global reference-table grants file
|
|
101
|
+
* (08-rls § 7.6). One GRANT-block per configured table, in input order.
|
|
102
|
+
* Reuses `referenceTableGrantsSql` — the same single-source generator the
|
|
103
|
+
* Drizzle `referenceTable` table-builder consumes — so the emitted DDL is
|
|
104
|
+
* equivalent (no forked GRANT DDL).
|
|
105
|
+
*
|
|
106
|
+
* GATE: each block carries the skip-RLS marker comment and INTENTIONALLY
|
|
107
|
+
* never emits `ALTER TABLE ... ENABLE ROW LEVEL SECURITY`. This function
|
|
108
|
+
* asserts (throws) if any generated block somehow contains an ENABLE RLS
|
|
109
|
+
* statement — a structural guard against the § 7.6 boundary being violated
|
|
110
|
+
* by a future refactor.
|
|
111
|
+
*
|
|
112
|
+
* Returns `""` when no tables are configured.
|
|
113
|
+
*/
|
|
114
|
+
export declare function referenceTablesSql(serviceName: string, tables: readonly ReferenceTableSpec[]): string;
|
|
69
115
|
/**
|
|
70
116
|
* Generates the residual migration phase file and returns its contents.
|
|
71
117
|
* If `outDir` is set, writes the file to disk; otherwise just returns
|
|
@@ -74,6 +120,10 @@ export declare function platformOpsPoliciesSql(serviceName: string, tables: read
|
|
|
74
120
|
* When `platformOps` tables are configured (and not in `--stub` mode), a
|
|
75
121
|
* second file `0002_platform_ops_policies.sql` is also written with the
|
|
76
122
|
* per-verb platform-ops CREATE POLICY DDL (08-rls § 7.6).
|
|
123
|
+
*
|
|
124
|
+
* When `referenceTables` are configured (and not in `--stub` mode), a file
|
|
125
|
+
* `0003_reference_table_grants.sql` is also written with the
|
|
126
|
+
* GRANT-controlled (NO RLS) DDL (08-rls § 7.6).
|
|
77
127
|
*/
|
|
78
128
|
export declare function migrateGen(input: MigrateGenInput): MigrateGenResult;
|
|
79
129
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-gen.d.ts","sourceRoot":"","sources":["../src/migrate-gen.ts"],"names":[],"mappings":"AA8BA,OAAO,EACL,KAAK,6BAA6B,
|
|
1
|
+
{"version":3,"file":"migrate-gen.d.ts","sourceRoot":"","sources":["../src/migrate-gen.ts"],"names":[],"mappings":"AA8BA,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,sBAAsB,EAK5B,MAAM,kBAAkB,CAAC;AAE1B;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;qCACiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd;wDACoD;IACpD,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B;qCACiC;IACjC,WAAW,EAAE,6BAA6B,CAAC;IAC3C;yBACqB;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,IAAI,EAAE,2BAA2B,CAAC;IAClC,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd;;sEAEkE;IAClE,SAAS,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,eAAe;IAC9B;wDACoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;6CAEyC;IACzC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;6EAEyE;IACzE,WAAW,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC9C;;4EAEwE;IACxE,eAAe,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;2CACuC;IACvC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;2CACuC;IACvC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAehE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAWhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,SAAS,oBAAoB,EAAE,GACtC,MAAM,CAoBR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,SAAS,kBAAkB,EAAE,GACpC,MAAM,CAoCR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAuDnE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CA6BhE"}
|
package/dist/migrate-gen.js
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
// asserts directly.
|
|
27
27
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
28
28
|
import { dirname, join, resolve } from "node:path";
|
|
29
|
-
import { withPlatformOpsGlobalSql, withPlatformOpsTenantSql, } from "./rls-policy-gen";
|
|
29
|
+
import { REFERENCE_TABLE_SKIP_RLS_MARKER, referenceTableGrantsSql, withPlatformOpsGlobalSql, withPlatformOpsTenantSql, } from "./rls-policy-gen";
|
|
30
30
|
/**
|
|
31
31
|
* SQL text for the real (joins mirror tables) helper. Module-level
|
|
32
32
|
* constant so parity-fence can byte-compare.
|
|
@@ -93,6 +93,55 @@ export function platformOpsPoliciesSql(serviceName, tables) {
|
|
|
93
93
|
`;
|
|
94
94
|
return `${header}\n${blocks.join("")}`;
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* SQL text for the pure platform-global reference-table grants file
|
|
98
|
+
* (08-rls § 7.6). One GRANT-block per configured table, in input order.
|
|
99
|
+
* Reuses `referenceTableGrantsSql` — the same single-source generator the
|
|
100
|
+
* Drizzle `referenceTable` table-builder consumes — so the emitted DDL is
|
|
101
|
+
* equivalent (no forked GRANT DDL).
|
|
102
|
+
*
|
|
103
|
+
* GATE: each block carries the skip-RLS marker comment and INTENTIONALLY
|
|
104
|
+
* never emits `ALTER TABLE ... ENABLE ROW LEVEL SECURITY`. This function
|
|
105
|
+
* asserts (throws) if any generated block somehow contains an ENABLE RLS
|
|
106
|
+
* statement — a structural guard against the § 7.6 boundary being violated
|
|
107
|
+
* by a future refactor.
|
|
108
|
+
*
|
|
109
|
+
* Returns `""` when no tables are configured.
|
|
110
|
+
*/
|
|
111
|
+
export function referenceTablesSql(serviceName, tables) {
|
|
112
|
+
if (tables.length === 0)
|
|
113
|
+
return "";
|
|
114
|
+
const blocks = [];
|
|
115
|
+
for (const spec of tables) {
|
|
116
|
+
if (spec.kind !== "platform_global_reference") {
|
|
117
|
+
throw new Error(`migrate-gen: unknown reference-table kind "${spec.kind}" — expected "platform_global_reference" (08-rls § 7.6).`);
|
|
118
|
+
}
|
|
119
|
+
const block = referenceTableGrantsSql(spec.table, {
|
|
120
|
+
readRoles: spec.readRoles,
|
|
121
|
+
});
|
|
122
|
+
// GATE — a reference table MUST NOT enable RLS (08-rls § 7.6). If the
|
|
123
|
+
// single-source generator ever emits an ENABLE RLS *statement*, fail
|
|
124
|
+
// loudly here rather than apply a doctrine-violating migration. We
|
|
125
|
+
// strip comment lines first so the skip-RLS marker (which deliberately
|
|
126
|
+
// contains the literal "ENABLE ROW LEVEL SECURITY" inside a comment
|
|
127
|
+
// documenting its omission) does not trip the guard.
|
|
128
|
+
const executableSql = block
|
|
129
|
+
.split("\n")
|
|
130
|
+
.filter((line) => !line.trimStart().startsWith("--"))
|
|
131
|
+
.join("\n");
|
|
132
|
+
if (/ENABLE\s+ROW\s+LEVEL\s+SECURITY/i.test(executableSql)) {
|
|
133
|
+
throw new Error(`migrate-gen: reference table "${spec.table}" generated an ENABLE ROW LEVEL SECURITY statement — forbidden by 08-rls § 7.6 (reference tables are GRANT-controlled, NOT RLS).`);
|
|
134
|
+
}
|
|
135
|
+
blocks.push(block);
|
|
136
|
+
}
|
|
137
|
+
const header = `-- Service: ${serviceName}
|
|
138
|
+
-- Generated by @nodii/db-rls migrate-gen
|
|
139
|
+
-- Phase: 004-helpers-and-grants — pure platform-global reference-table grants
|
|
140
|
+
-- Spec: 08-rls § 7.6 (GRANT-controlled, NO RLS)
|
|
141
|
+
-- ${REFERENCE_TABLE_SKIP_RLS_MARKER.replace(/^-- /, "")}
|
|
142
|
+
`;
|
|
143
|
+
return `${header}\n${blocks.join("\n")}`;
|
|
144
|
+
}
|
|
96
145
|
/**
|
|
97
146
|
* Generates the residual migration phase file and returns its contents.
|
|
98
147
|
* If `outDir` is set, writes the file to disk; otherwise just returns
|
|
@@ -101,6 +150,10 @@ export function platformOpsPoliciesSql(serviceName, tables) {
|
|
|
101
150
|
* When `platformOps` tables are configured (and not in `--stub` mode), a
|
|
102
151
|
* second file `0002_platform_ops_policies.sql` is also written with the
|
|
103
152
|
* per-verb platform-ops CREATE POLICY DDL (08-rls § 7.6).
|
|
153
|
+
*
|
|
154
|
+
* When `referenceTables` are configured (and not in `--stub` mode), a file
|
|
155
|
+
* `0003_reference_table_grants.sql` is also written with the
|
|
156
|
+
* GRANT-controlled (NO RLS) DDL (08-rls § 7.6).
|
|
104
157
|
*/
|
|
105
158
|
export function migrateGen(input) {
|
|
106
159
|
const contents = input.stub
|
|
@@ -114,6 +167,7 @@ export function migrateGen(input) {
|
|
|
114
167
|
const path = join(outDir, phase, fileName);
|
|
115
168
|
mkdirSync(dirname(path), { recursive: true });
|
|
116
169
|
writeFileSync(path, contents);
|
|
170
|
+
const result = { path, contents };
|
|
117
171
|
// Platform-ops policies (08-rls § 7.6). Skipped in the stub path —
|
|
118
172
|
// the stub variant is the chicken-and-egg bootstrap and shouldn't
|
|
119
173
|
// create cross-tenant policies before the grants replica exists.
|
|
@@ -123,9 +177,21 @@ export function migrateGen(input) {
|
|
|
123
177
|
const platformOpsPath = join(outDir, phase, "0002_platform_ops_policies.sql");
|
|
124
178
|
mkdirSync(dirname(platformOpsPath), { recursive: true });
|
|
125
179
|
writeFileSync(platformOpsPath, platformOpsContents);
|
|
126
|
-
|
|
180
|
+
result.platformOpsPath = platformOpsPath;
|
|
181
|
+
result.platformOpsContents = platformOpsContents;
|
|
182
|
+
}
|
|
183
|
+
// Pure platform-global reference-table grants (08-rls § 7.6). Skipped in
|
|
184
|
+
// the stub path. Emits the GRANT-controlled (NO RLS) DDL.
|
|
185
|
+
const referenceTables = input.stub ? [] : (input.referenceTables ?? []);
|
|
186
|
+
if (referenceTables.length > 0) {
|
|
187
|
+
const referenceTablesContents = referenceTablesSql(input.serviceName, referenceTables);
|
|
188
|
+
const referenceTablesPath = join(outDir, phase, "0003_reference_table_grants.sql");
|
|
189
|
+
mkdirSync(dirname(referenceTablesPath), { recursive: true });
|
|
190
|
+
writeFileSync(referenceTablesPath, referenceTablesContents);
|
|
191
|
+
result.referenceTablesPath = referenceTablesPath;
|
|
192
|
+
result.referenceTablesContents = referenceTablesContents;
|
|
127
193
|
}
|
|
128
|
-
return
|
|
194
|
+
return result;
|
|
129
195
|
}
|
|
130
196
|
/**
|
|
131
197
|
* CLI entrypoint. Invoked via `npx @nodii/db-rls migrate-gen ...` or
|
package/dist/migrate-gen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-gen.js","sourceRoot":"","sources":["../src/migrate-gen.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,aAAa;AACb,EAAE;AACF,UAAU;AACV,6DAA6D;AAC7D,0EAA0E;AAC1E,iEAAiE;AACjE,EAAE;AACF,mEAAmE;AACnE,oEAAoE;AACpE,kEAAkE;AAClE,gEAAgE;AAChE,+DAA+D;AAC/D,EAAE;AACF,kEAAkE;AAClE,yEAAyE;AACzE,yEAAyE;AACzE,+DAA+D;AAC/D,mDAAmD;AACnD,EAAE;AACF,aAAa;AACb,+DAA+D;AAC/D,kEAAkE;AAClE,EAAE;AACF,yEAAyE;AACzE,oBAAoB;AAEpB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,
|
|
1
|
+
{"version":3,"file":"migrate-gen.js","sourceRoot":"","sources":["../src/migrate-gen.ts"],"names":[],"mappings":"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"}
|
package/dist/rls-policy-gen.d.ts
CHANGED
|
@@ -74,5 +74,48 @@ export declare function withPlatformOpsTenantSql(table: string, perms: PlatformO
|
|
|
74
74
|
* **platform-global** table (08-rls § 7.6).
|
|
75
75
|
*/
|
|
76
76
|
export declare function withPlatformOpsGlobalSql(table: string, perms: PlatformOpsPerVerbPermissions, opts?: WithPlatformOpsSqlOpts): string;
|
|
77
|
+
/** Roles that may receive `GRANT SELECT` on a reference table. */
|
|
78
|
+
declare const REFERENCE_TABLE_READ_ROLES: readonly ["nodii_services", "authenticated", "nodii_platform_ops"];
|
|
79
|
+
export type ReferenceTableReadRole = (typeof REFERENCE_TABLE_READ_ROLES)[number];
|
|
80
|
+
/** The doctrine-conformant skip-RLS marker comment line. Emitted in place of
|
|
81
|
+
* `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` so the migrate-gen + reviewers
|
|
82
|
+
* see the omission is intentional (08-rls § 7.6), not an oversight. */
|
|
83
|
+
export declare const REFERENCE_TABLE_SKIP_RLS_MARKER = "-- INTENTIONALLY OMITTED: ALTER TABLE ... ENABLE ROW LEVEL SECURITY (08-rls \u00A7 7.6 \u2014 reference data has no per-row confidentiality boundary).";
|
|
84
|
+
export interface ReferenceTableSqlOpts {
|
|
85
|
+
/** Read role(s) that get `GRANT SELECT` + `REVOKE` write. Defaults to
|
|
86
|
+
* `["nodii_services"]` (canonical 3-pool). 2-pool services may pass
|
|
87
|
+
* `["authenticated"]`; 4-pool services may add `"nodii_platform_ops"`. */
|
|
88
|
+
readRoles?: readonly ReferenceTableReadRole[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Thrown when a `tenant_id` column is declared on a reference-table-typed
|
|
92
|
+
* table. A pure platform-global reference table is platform-global by
|
|
93
|
+
* definition (08-rls § 7.6 property 1: no `tenant_id`); a `tenant_id` column
|
|
94
|
+
* is a category error — the table should use the canonical 5-policy RLS DDL
|
|
95
|
+
* (§ 4) instead. This is the doctrine's safety boundary.
|
|
96
|
+
*/
|
|
97
|
+
export declare class ReferenceTableTenantColumnError extends Error {
|
|
98
|
+
readonly table: string;
|
|
99
|
+
readonly column: string;
|
|
100
|
+
constructor(table: string, column: string);
|
|
101
|
+
}
|
|
102
|
+
/** Returns the tenant-scoped column name if `columns` contains one, else
|
|
103
|
+
* `null`. Case-insensitive. Used by the reference-table refusal guard. */
|
|
104
|
+
export declare function findTenantColumn(columns: readonly string[]): string | null;
|
|
105
|
+
/**
|
|
106
|
+
* Emits the canonical 08-rls § 7.6 GRANT/REVOKE DDL for a pure
|
|
107
|
+
* platform-global reference table. Does NOT include `CREATE TABLE` (the
|
|
108
|
+
* table shape is the consumer's; Drizzle/SQLAlchemy/sqlc emit it) and
|
|
109
|
+
* INTENTIONALLY does NOT include `ALTER TABLE ... ENABLE ROW LEVEL SECURITY`.
|
|
110
|
+
*
|
|
111
|
+
* Output ends with `\n`. Byte-equal across TS / Python / Go ports.
|
|
112
|
+
*
|
|
113
|
+
* Order (deterministic for parity-fence):
|
|
114
|
+
* 1. skip-RLS marker comment
|
|
115
|
+
* 2. GRANT SELECT to each read role (in `readRoles` order)
|
|
116
|
+
* 3. GRANT INSERT, UPDATE, DELETE to nodii_owner
|
|
117
|
+
* 4. REVOKE INSERT, UPDATE, DELETE from each read role (in `readRoles` order)
|
|
118
|
+
*/
|
|
119
|
+
export declare function referenceTableGrantsSql(table: string, opts?: ReferenceTableSqlOpts): string;
|
|
77
120
|
export {};
|
|
78
121
|
//# sourceMappingURL=rls-policy-gen.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rls-policy-gen.d.ts","sourceRoot":"","sources":["../src/rls-policy-gen.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,mEAAmE;IACnE,KAAK,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC3B,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,MAAM,CA0BrE;AAQD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,WAAgB,GACrB,MAAM,CASR;AAqDD,4CAA4C;AAC5C,QAAA,MAAM,kBAAkB,iDAAkD,CAAC;AAC3E,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE;;;qBAGqB;AACrB,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;AAED,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,mCAAmC,gCACjB,CAAC;AAGhC,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAOD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAED,0EAA0E;AAC1E,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,MAAM,GAChB,MAAM,CAUR;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,6BAA6B,EACpC,IAAI,GAAE,sBAA2B,GAChC,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,6BAA6B,EACpC,IAAI,GAAE,sBAA2B,GAChC,MAAM,CAER"}
|
|
1
|
+
{"version":3,"file":"rls-policy-gen.d.ts","sourceRoot":"","sources":["../src/rls-policy-gen.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,mEAAmE;IACnE,KAAK,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC3B,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,MAAM,CA0BrE;AAQD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,WAAgB,GACrB,MAAM,CASR;AAqDD,4CAA4C;AAC5C,QAAA,MAAM,kBAAkB,iDAAkD,CAAC;AAC3E,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE;;;qBAGqB;AACrB,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;AAED,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,mCAAmC,gCACjB,CAAC;AAGhC,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAOD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAED,0EAA0E;AAC1E,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,MAAM,GAChB,MAAM,CAUR;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,6BAA6B,EACpC,IAAI,GAAE,sBAA2B,GAChC,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,6BAA6B,EACpC,IAAI,GAAE,sBAA2B,GAChC,MAAM,CAER;AAiDD,kEAAkE;AAClE,QAAA,MAAM,0BAA0B,oEAItB,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAChC,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAK9C;;wEAEwE;AACxE,eAAO,MAAM,+BAA+B,2JACoG,CAAC;AAEjJ,MAAM,WAAW,qBAAqB;IACpC;;+EAE2E;IAC3E,SAAS,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAC/C;AAMD;;;;;;GAMG;AACH,qBAAa,+BAAgC,SAAQ,KAAK;aAEtC,KAAK,EAAE,MAAM;aACb,MAAM,EAAE,MAAM;gBADd,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;CAOjC;AAMD;2EAC2E;AAC3E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAK1E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,qBAA0B,GAC/B,MAAM,CAkBR"}
|
package/dist/rls-policy-gen.js
CHANGED
|
@@ -163,4 +163,97 @@ function platformOpsPolicyLines(table, perms, kind, opts) {
|
|
|
163
163
|
}
|
|
164
164
|
return lines.length > 0 ? `${lines.join("\n")}\n` : "";
|
|
165
165
|
}
|
|
166
|
+
// ----------------------------------------------------------------------------
|
|
167
|
+
// 08-rls § 7.6 — pure platform-global reference tables (GRANT-controlled, NO RLS).
|
|
168
|
+
//
|
|
169
|
+
// A pure platform-global reference table has ALL THREE properties:
|
|
170
|
+
// 1. No `tenant_id` column — rows are shared across every tenant.
|
|
171
|
+
// 2. Non-confidential — reference / catalog / lookup data.
|
|
172
|
+
// 3. Written via a controlled platform-admin path (nodii_owner migrations
|
|
173
|
+
// or a narrow operator-only RPC).
|
|
174
|
+
//
|
|
175
|
+
// Per § 7.6 such tables use GRANT-controlled access, NOT RLS:
|
|
176
|
+
// - INTENTIONALLY no `ALTER TABLE ... ENABLE ROW LEVEL SECURITY`.
|
|
177
|
+
// - `GRANT SELECT` to the read role (`nodii_services` by default; 2-pool
|
|
178
|
+
// services may use `authenticated`; 4-pool services may add
|
|
179
|
+
// `nodii_platform_ops`).
|
|
180
|
+
// - `GRANT INSERT, UPDATE, DELETE` to `nodii_owner` (the write path).
|
|
181
|
+
// - `REVOKE INSERT, UPDATE, DELETE` from the read role(s) — the integrity
|
|
182
|
+
// boundary: the read pool can never write.
|
|
183
|
+
//
|
|
184
|
+
// Single source of truth: `referenceTableGrantsSql` is reused by the Drizzle
|
|
185
|
+
// `referenceTable` table-builder helper AND by migrate-gen's
|
|
186
|
+
// `platform_global_reference` path — no forked GRANT DDL.
|
|
187
|
+
/** Roles that may receive `GRANT SELECT` on a reference table. */
|
|
188
|
+
const REFERENCE_TABLE_READ_ROLES = [
|
|
189
|
+
"nodii_services",
|
|
190
|
+
"authenticated",
|
|
191
|
+
"nodii_platform_ops",
|
|
192
|
+
];
|
|
193
|
+
const REFERENCE_TABLE_OWNER_ROLE = "nodii_owner";
|
|
194
|
+
const REFERENCE_TABLE_WRITE_VERBS = "INSERT, UPDATE, DELETE";
|
|
195
|
+
/** The doctrine-conformant skip-RLS marker comment line. Emitted in place of
|
|
196
|
+
* `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` so the migrate-gen + reviewers
|
|
197
|
+
* see the omission is intentional (08-rls § 7.6), not an oversight. */
|
|
198
|
+
export const REFERENCE_TABLE_SKIP_RLS_MARKER = "-- INTENTIONALLY OMITTED: ALTER TABLE ... ENABLE ROW LEVEL SECURITY (08-rls § 7.6 — reference data has no per-row confidentiality boundary).";
|
|
199
|
+
const DEFAULT_REFERENCE_READ_ROLES = [
|
|
200
|
+
"nodii_services",
|
|
201
|
+
];
|
|
202
|
+
/**
|
|
203
|
+
* Thrown when a `tenant_id` column is declared on a reference-table-typed
|
|
204
|
+
* table. A pure platform-global reference table is platform-global by
|
|
205
|
+
* definition (08-rls § 7.6 property 1: no `tenant_id`); a `tenant_id` column
|
|
206
|
+
* is a category error — the table should use the canonical 5-policy RLS DDL
|
|
207
|
+
* (§ 4) instead. This is the doctrine's safety boundary.
|
|
208
|
+
*/
|
|
209
|
+
export class ReferenceTableTenantColumnError extends Error {
|
|
210
|
+
table;
|
|
211
|
+
column;
|
|
212
|
+
constructor(table, column) {
|
|
213
|
+
super(`Reference table "${table}" declares a tenant-scoped column "${column}". A pure platform-global reference table (08-rls § 7.6) MUST NOT have a tenant_id column — it is platform-global by definition. Use the canonical 5-policy RLS DDL (withRls) for tenant-scoped tables instead.`);
|
|
214
|
+
this.table = table;
|
|
215
|
+
this.column = column;
|
|
216
|
+
this.name = "ReferenceTableTenantColumnError";
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/** Column names that mark a table as tenant-scoped (category error for a
|
|
220
|
+
* reference table). Case-insensitive match. */
|
|
221
|
+
const TENANT_COLUMN_NAMES = new Set(["tenant_id", "tenantid"]);
|
|
222
|
+
/** Returns the tenant-scoped column name if `columns` contains one, else
|
|
223
|
+
* `null`. Case-insensitive. Used by the reference-table refusal guard. */
|
|
224
|
+
export function findTenantColumn(columns) {
|
|
225
|
+
for (const col of columns) {
|
|
226
|
+
if (TENANT_COLUMN_NAMES.has(col.toLowerCase()))
|
|
227
|
+
return col;
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Emits the canonical 08-rls § 7.6 GRANT/REVOKE DDL for a pure
|
|
233
|
+
* platform-global reference table. Does NOT include `CREATE TABLE` (the
|
|
234
|
+
* table shape is the consumer's; Drizzle/SQLAlchemy/sqlc emit it) and
|
|
235
|
+
* INTENTIONALLY does NOT include `ALTER TABLE ... ENABLE ROW LEVEL SECURITY`.
|
|
236
|
+
*
|
|
237
|
+
* Output ends with `\n`. Byte-equal across TS / Python / Go ports.
|
|
238
|
+
*
|
|
239
|
+
* Order (deterministic for parity-fence):
|
|
240
|
+
* 1. skip-RLS marker comment
|
|
241
|
+
* 2. GRANT SELECT to each read role (in `readRoles` order)
|
|
242
|
+
* 3. GRANT INSERT, UPDATE, DELETE to nodii_owner
|
|
243
|
+
* 4. REVOKE INSERT, UPDATE, DELETE from each read role (in `readRoles` order)
|
|
244
|
+
*/
|
|
245
|
+
export function referenceTableGrantsSql(table, opts = {}) {
|
|
246
|
+
const readRoles = opts.readRoles && opts.readRoles.length > 0
|
|
247
|
+
? opts.readRoles
|
|
248
|
+
: DEFAULT_REFERENCE_READ_ROLES;
|
|
249
|
+
const lines = [REFERENCE_TABLE_SKIP_RLS_MARKER];
|
|
250
|
+
for (const role of readRoles) {
|
|
251
|
+
lines.push(`GRANT SELECT ON ${table} TO ${role};`);
|
|
252
|
+
}
|
|
253
|
+
lines.push(`GRANT ${REFERENCE_TABLE_WRITE_VERBS} ON ${table} TO ${REFERENCE_TABLE_OWNER_ROLE};`);
|
|
254
|
+
for (const role of readRoles) {
|
|
255
|
+
lines.push(`REVOKE ${REFERENCE_TABLE_WRITE_VERBS} ON ${table} FROM ${role};`);
|
|
256
|
+
}
|
|
257
|
+
return `${lines.join("\n")}\n`;
|
|
258
|
+
}
|
|
166
259
|
//# sourceMappingURL=rls-policy-gen.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rls-policy-gen.js","sourceRoot":"","sources":["../src/rls-policy-gen.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rls-policy-gen.js","sourceRoot":"","sources":["../src/rls-policy-gen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface RunVerifyRlsCliResult {
|
|
2
|
+
/** Process exit code: 0 = all covered, 1 = coverage failure, 2 = usage. */
|
|
3
|
+
code: number;
|
|
4
|
+
/** Human-readable line for stdout/stderr (caller prints). */
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Parses argv (without the leading `verify-rls` token) and runs the
|
|
9
|
+
* coverage check. Returns an exit code + message rather than calling
|
|
10
|
+
* `process.exit`, so it is unit-testable. The bin shim translates.
|
|
11
|
+
*
|
|
12
|
+
* Flags:
|
|
13
|
+
* --tables a,b,c (required) RLS-required tables (comma-separated)
|
|
14
|
+
* --ref c,d reference tables to exempt (§ 7.6)
|
|
15
|
+
* --schema public default schema for bare names (default: public)
|
|
16
|
+
* --db <url> connection string (else DATABASE_URL / DB_RLS_PG_URL)
|
|
17
|
+
* --help / -h
|
|
18
|
+
*/
|
|
19
|
+
export declare function runVerifyRlsCli(args: readonly string[]): Promise<RunVerifyRlsCliResult>;
|
|
20
|
+
//# sourceMappingURL=verify-rls-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-rls-cli.d.ts","sourceRoot":"","sources":["../src/verify-rls-cli.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,qBAAqB;IACpC,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,OAAO,CAAC,qBAAqB,CAAC,CAqDhC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// verify-rls CLI — `nodii-db-rls verify-rls --tables a,b [--ref c] [--schema public]`.
|
|
2
|
+
//
|
|
3
|
+
// Thin CLI around `verifyRls` so a service can wire a `db:verify-rls`
|
|
4
|
+
// script (or a CI step) without writing its own pg-connect boilerplate.
|
|
5
|
+
// The importable `verifyRls` function (src/verify-rls.ts) remains the core
|
|
6
|
+
// deliverable — this is the optional bin mirror of migrate-gen's CLI.
|
|
7
|
+
//
|
|
8
|
+
// Connection string comes from `--db <url>` or the `DATABASE_URL` /
|
|
9
|
+
// `DB_RLS_PG_URL` env var (in that order). `pg` is an optional peer dep;
|
|
10
|
+
// the CLI imports it lazily so importing the library does not require it.
|
|
11
|
+
import { RlsCoverageError, verifyRls } from "./verify-rls";
|
|
12
|
+
function splitList(value) {
|
|
13
|
+
if (!value)
|
|
14
|
+
return [];
|
|
15
|
+
return value
|
|
16
|
+
.split(",")
|
|
17
|
+
.map((s) => s.trim())
|
|
18
|
+
.filter((s) => s.length > 0);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parses argv (without the leading `verify-rls` token) and runs the
|
|
22
|
+
* coverage check. Returns an exit code + message rather than calling
|
|
23
|
+
* `process.exit`, so it is unit-testable. The bin shim translates.
|
|
24
|
+
*
|
|
25
|
+
* Flags:
|
|
26
|
+
* --tables a,b,c (required) RLS-required tables (comma-separated)
|
|
27
|
+
* --ref c,d reference tables to exempt (§ 7.6)
|
|
28
|
+
* --schema public default schema for bare names (default: public)
|
|
29
|
+
* --db <url> connection string (else DATABASE_URL / DB_RLS_PG_URL)
|
|
30
|
+
* --help / -h
|
|
31
|
+
*/
|
|
32
|
+
export async function runVerifyRlsCli(args) {
|
|
33
|
+
let tables;
|
|
34
|
+
let refs;
|
|
35
|
+
let schema;
|
|
36
|
+
let dbUrl;
|
|
37
|
+
for (let i = 0; i < args.length; i++) {
|
|
38
|
+
const a = args[i];
|
|
39
|
+
if (a === "--tables" && i + 1 < args.length)
|
|
40
|
+
tables = args[++i];
|
|
41
|
+
else if (a === "--ref" && i + 1 < args.length)
|
|
42
|
+
refs = args[++i];
|
|
43
|
+
else if (a === "--schema" && i + 1 < args.length)
|
|
44
|
+
schema = args[++i];
|
|
45
|
+
else if (a === "--db" && i + 1 < args.length)
|
|
46
|
+
dbUrl = args[++i];
|
|
47
|
+
else if (a === "--help" || a === "-h") {
|
|
48
|
+
return { code: 0, message: usage() };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const requiredTables = splitList(tables);
|
|
52
|
+
if (requiredTables.length === 0) {
|
|
53
|
+
return { code: 2, message: usage() };
|
|
54
|
+
}
|
|
55
|
+
const connectionString = dbUrl ?? process.env.DATABASE_URL ?? process.env.DB_RLS_PG_URL;
|
|
56
|
+
if (!connectionString) {
|
|
57
|
+
return {
|
|
58
|
+
code: 2,
|
|
59
|
+
message: "verify-rls: no connection string — pass --db <url> or set DATABASE_URL / DB_RLS_PG_URL.",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Lazy-import pg (optional peer dep). Keeps the library importable
|
|
63
|
+
// without pg installed; only the CLI path requires it.
|
|
64
|
+
const { Pool } = await import("pg");
|
|
65
|
+
const pool = new Pool({ connectionString, max: 1 });
|
|
66
|
+
try {
|
|
67
|
+
await verifyRls(pool, {
|
|
68
|
+
requiredTables,
|
|
69
|
+
schema,
|
|
70
|
+
referenceTables: splitList(refs),
|
|
71
|
+
});
|
|
72
|
+
return {
|
|
73
|
+
code: 0,
|
|
74
|
+
message: `verify-rls: OK — ${requiredTables.length} RLS-required table(s) covered.`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
if (err instanceof RlsCoverageError) {
|
|
79
|
+
return { code: 1, message: err.message };
|
|
80
|
+
}
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
await pool.end().catch(() => { });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function usage() {
|
|
88
|
+
return `usage: verify-rls --tables <a,b,c> [--ref <x,y>] [--schema <name>] [--db <url>]
|
|
89
|
+
|
|
90
|
+
Verifies every --tables relation has ROW LEVEL SECURITY enabled
|
|
91
|
+
(pg_class.relrowsecurity = true), exempting any --ref reference table
|
|
92
|
+
(08-rls § 7.6 — GRANT-controlled, NO RLS by design). Exits 1 (loud) if
|
|
93
|
+
any RLS-required table is missing RLS.
|
|
94
|
+
|
|
95
|
+
Connection string: --db <url>, else DATABASE_URL, else DB_RLS_PG_URL.
|
|
96
|
+
|
|
97
|
+
Spec: @nodii/db-rls 08-rls § A1 (RLS on every tenant-scoped table).`;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=verify-rls-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-rls-cli.js","sourceRoot":"","sources":["../src/verify-rls-cli.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,EAAE;AACF,sEAAsE;AACtE,wEAAwE;AACxE,2EAA2E;AAC3E,sEAAsE;AACtE,EAAE;AACF,oEAAoE;AACpE,yEAAyE;AACzE,0EAA0E;AAE1E,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAS3D,SAAS,SAAS,CAAC,KAAyB;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAuB;IAEvB,IAAI,MAA0B,CAAC;IAC/B,IAAI,IAAwB,CAAC;IAC7B,IAAI,MAA0B,CAAC;IAC/B,IAAI,KAAyB,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;YAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC3D,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;YAAE,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC3D,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;YAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAChE,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;YAAE,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC3D,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACtC,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;QACvC,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;IACvC,CAAC;IAED,MAAM,gBAAgB,GACpB,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACjE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO;YACL,IAAI,EAAE,CAAC;YACP,OAAO,EACL,yFAAyF;SAC5F,CAAC;IACJ,CAAC;IAED,mEAAmE;IACnE,uDAAuD;IACvD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,IAAI,EAAE;YACpB,cAAc;YACd,MAAM;YACN,eAAe,EAAE,SAAS,CAAC,IAAI,CAAC;SACjC,CAAC,CAAC;QACH,OAAO;YACL,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,oBAAoB,cAAc,CAAC,MAAM,iCAAiC;SACpF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,gBAAgB,EAAE,CAAC;YACpC,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;QAC3C,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED,SAAS,KAAK;IACZ,OAAO;;;;;;;;;oEAS2D,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { DbRlsError } from "./types";
|
|
2
|
+
/** Minimal query surface for the preflight catalog read. `pg.Pool` and
|
|
3
|
+
* `pg.PoolClient` both satisfy this; `PgClientPool` exposes `.rawPool`.
|
|
4
|
+
* We deliberately do NOT reuse the tx-bound `PgPool` — the preflight is a
|
|
5
|
+
* single read, not a GUC-scoped transaction. */
|
|
6
|
+
export interface RlsQuerier {
|
|
7
|
+
query<R = unknown>(sql: string, params?: readonly unknown[]): Promise<{
|
|
8
|
+
rows: R[];
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
/** A predicate that returns `true` when `table` is a reference table
|
|
12
|
+
* (GRANT-controlled, NO RLS by design — § 7.6) and must therefore be
|
|
13
|
+
* EXEMPT from the RLS-coverage check. `table` is the table name exactly
|
|
14
|
+
* as it appears in `requiredTables` (may be schema-qualified). */
|
|
15
|
+
export type ReferenceTablePredicate = (table: string) => boolean;
|
|
16
|
+
export interface VerifyRlsOpts {
|
|
17
|
+
/** Tables that REQUIRE RLS (the canonical 5-policy posture, § A1). Each
|
|
18
|
+
* may be bare (`orders`) or schema-qualified (`billing.orders`); a bare
|
|
19
|
+
* name resolves against `schema`. */
|
|
20
|
+
requiredTables: readonly string[];
|
|
21
|
+
/** Schema for bare (unqualified) table names. Defaults to `"public"`. */
|
|
22
|
+
schema?: string;
|
|
23
|
+
/** Reference tables to EXEMPT (§ 7.6 — GRANT-controlled, NO RLS by
|
|
24
|
+
* design). Supply EITHER this list OR `isReferenceTable`. Entries are
|
|
25
|
+
* matched against `requiredTables` after both are normalized to
|
|
26
|
+
* `schema.table`, so `["billing.country_codes"]` and a bare
|
|
27
|
+
* `["country_codes"]` (with `schema:"billing"`) both match. */
|
|
28
|
+
referenceTables?: readonly string[];
|
|
29
|
+
/** Alternative to `referenceTables` — a predicate receiving the table
|
|
30
|
+
* name as it appears in `requiredTables`. Use when the exempt set is
|
|
31
|
+
* computed (e.g. read from a registry). If both are supplied a table is
|
|
32
|
+
* exempt when EITHER matches. */
|
|
33
|
+
isReferenceTable?: ReferenceTablePredicate;
|
|
34
|
+
/** Back-compat alias kept intentionally undocumented in callers: when
|
|
35
|
+
* `false`, reference-table exemption is disabled and a reference table
|
|
36
|
+
* missing RLS WOULD be flagged. Defaults to `true` (exemptions on). */
|
|
37
|
+
allowReferenceTables?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/** One RLS-required table whose coverage is missing or whose catalog row
|
|
40
|
+
* could not be found. */
|
|
41
|
+
export interface RlsCoverageOffender {
|
|
42
|
+
/** Table name as supplied in `requiredTables`. */
|
|
43
|
+
table: string;
|
|
44
|
+
/** Resolved schema used for the catalog lookup. */
|
|
45
|
+
schema: string;
|
|
46
|
+
/** Resolved (unqualified) relation name used for the catalog lookup. */
|
|
47
|
+
relname: string;
|
|
48
|
+
/** Why this table is an offender:
|
|
49
|
+
* - `"rls_disabled"` — the table exists but `relrowsecurity = false`.
|
|
50
|
+
* - `"not_found"` — no `pg_class` row matched (table absent / wrong
|
|
51
|
+
* schema). Also a failure: a required table that doesn't exist can't
|
|
52
|
+
* be protected. */
|
|
53
|
+
reason: "rls_disabled" | "not_found";
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Thrown by `verifyRls` when one or more RLS-required tables are missing
|
|
57
|
+
* row-level security (or are absent). Carries the structured offender list
|
|
58
|
+
* so a `db:setup` gate can render a precise failure. Reference tables
|
|
59
|
+
* (§ 7.6) are NEVER offenders — they are exempt before this is thrown.
|
|
60
|
+
*/
|
|
61
|
+
export declare class RlsCoverageError extends DbRlsError {
|
|
62
|
+
readonly offenders: readonly RlsCoverageOffender[];
|
|
63
|
+
constructor(offenders: readonly RlsCoverageOffender[]);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Verifies that every table in `requiredTables` has row-level security
|
|
67
|
+
* enabled (`pg_class.relrowsecurity = true`), exempting any § 7.6
|
|
68
|
+
* reference table. Resolves OK (returns `void`) when all required tables
|
|
69
|
+
* are covered; throws `RlsCoverageError` listing the offenders otherwise.
|
|
70
|
+
*
|
|
71
|
+
* The query is a single read against `pg_class` joined to `pg_namespace`
|
|
72
|
+
* — read-only, no GUCs, no writes. Run it from a migration / `db:setup`
|
|
73
|
+
* gate against any pool (typically the owner/admin pool).
|
|
74
|
+
*/
|
|
75
|
+
export declare function verifyRls(pool: RlsQuerier, opts: VerifyRlsOpts): Promise<void>;
|
|
76
|
+
//# sourceMappingURL=verify-rls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-rls.d.ts","sourceRoot":"","sources":["../src/verify-rls.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC;;;iDAGiD;AACjD,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,CAAC,GAAG,OAAO,EACf,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAC1B,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;CAC3B;AAED;;;mEAGmE;AACnE,MAAM,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;AAEjE,MAAM,WAAW,aAAa;IAC5B;;0CAEsC;IACtC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;oEAIgE;IAChE,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;sCAGkC;IAClC,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;IAC3C;;4EAEwE;IACxE,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;0BAC0B;AAC1B,MAAM,WAAW,mBAAmB;IAClC,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB;;;;2BAIuB;IACvB,MAAM,EAAE,cAAc,GAAG,WAAW,CAAC;CACtC;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,QAAQ,CAAC,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;gBACvC,SAAS,EAAE,SAAS,mBAAmB,EAAE;CAKtD;AA2CD;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,IAAI,CAAC,CA4Ef"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// verify-rls — a preflight RLS-coverage guard (08-rls § A1 + § 7.6).
|
|
2
|
+
//
|
|
3
|
+
// A service's `scripts/db/verify-rls.ts` (and any `db:setup` gate) calls
|
|
4
|
+
// `verifyRls(pool, { requiredTables })` after migrations apply. It queries
|
|
5
|
+
// `pg_class.relrowsecurity` (joined with `pg_namespace` for the schema)
|
|
6
|
+
// for each table that REQUIRES RLS and FAILS LOUD — throwing
|
|
7
|
+
// `RlsCoverageError` listing the offenders — if any RLS-required table
|
|
8
|
+
// reports `relrowsecurity = false`.
|
|
9
|
+
//
|
|
10
|
+
// This catches the "drizzle snapshot RLS hazard": a migration that creates
|
|
11
|
+
// a tenant-scoped table but never `ALTER TABLE ... ENABLE ROW LEVEL
|
|
12
|
+
// SECURITY`. Without RLS the table leaks every tenant's rows to the
|
|
13
|
+
// services / authenticated pools — a silent tenant-isolation breach that
|
|
14
|
+
// the 5-policy DDL exists to prevent.
|
|
15
|
+
//
|
|
16
|
+
// Composition with 08-rls § 7.6 (db-rls 0.5.1) — a pure platform-global
|
|
17
|
+
// reference table is GRANT-controlled with NO RLS *by design*
|
|
18
|
+
// (`relrowsecurity = false` is the correct state, see `referenceTableGrantsSql`).
|
|
19
|
+
// Such tables MUST NOT be flagged. `verifyRls` therefore takes the set of
|
|
20
|
+
// reference tables (or a predicate) to EXEMPT: an RLS-required table missing
|
|
21
|
+
// RLS is an error; a reference table missing RLS is expected.
|
|
22
|
+
//
|
|
23
|
+
// The verify path is a single read-only catalog query — it does NOT need
|
|
24
|
+
// the GUC/tx-bound `PgPool` surface. It accepts any object exposing a
|
|
25
|
+
// `query(sql, params)` returning `{ rows }`, which `pg.Pool` /
|
|
26
|
+
// `PgClientPool.rawPool` satisfy directly. Byte-consistent error semantics
|
|
27
|
+
// across TS / Python / Go ports.
|
|
28
|
+
import { DbRlsError } from "./types";
|
|
29
|
+
/**
|
|
30
|
+
* Thrown by `verifyRls` when one or more RLS-required tables are missing
|
|
31
|
+
* row-level security (or are absent). Carries the structured offender list
|
|
32
|
+
* so a `db:setup` gate can render a precise failure. Reference tables
|
|
33
|
+
* (§ 7.6) are NEVER offenders — they are exempt before this is thrown.
|
|
34
|
+
*/
|
|
35
|
+
export class RlsCoverageError extends DbRlsError {
|
|
36
|
+
offenders;
|
|
37
|
+
constructor(offenders) {
|
|
38
|
+
super(formatMessage(offenders));
|
|
39
|
+
this.name = "RlsCoverageError";
|
|
40
|
+
this.offenders = offenders;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function formatMessage(offenders) {
|
|
44
|
+
const lines = offenders.map((o) => {
|
|
45
|
+
const qualified = `${o.schema}.${o.relname}`;
|
|
46
|
+
return o.reason === "not_found"
|
|
47
|
+
? ` - ${qualified} (NOT FOUND — required RLS table is absent from the catalog)`
|
|
48
|
+
: ` - ${qualified} (relrowsecurity = false — RLS not enabled)`;
|
|
49
|
+
});
|
|
50
|
+
return `rls_coverage: ${offenders.length} RLS-required table(s) missing row-level security (08-rls § A1). A migration created the table but never \`ALTER TABLE ... ENABLE ROW LEVEL SECURITY\` — these tables leak every tenant's rows to the services/authenticated pools. Offenders:\n${lines.join("\n")}\nFix: add the canonical 5-policy DDL (withRls) for each, or register it as a § 7.6 reference table if it is genuinely platform-global GRANT-controlled data.`;
|
|
51
|
+
}
|
|
52
|
+
/** Strip optional surrounding double-quotes from one identifier part. */
|
|
53
|
+
function unquote(part) {
|
|
54
|
+
return part.replace(/^"|"$/g, "");
|
|
55
|
+
}
|
|
56
|
+
/** Resolve a (possibly schema-qualified, possibly quoted) table name to
|
|
57
|
+
* `{ schema, relname }`. Bare names resolve against `defaultSchema`. */
|
|
58
|
+
function resolveTable(table, defaultSchema) {
|
|
59
|
+
if (table.includes(".")) {
|
|
60
|
+
const idx = table.indexOf(".");
|
|
61
|
+
const schema = unquote(table.slice(0, idx));
|
|
62
|
+
const relname = unquote(table.slice(idx + 1));
|
|
63
|
+
return { original: table, schema, relname };
|
|
64
|
+
}
|
|
65
|
+
return { original: table, schema: defaultSchema, relname: unquote(table) };
|
|
66
|
+
}
|
|
67
|
+
/** Normalized `schema.relname` key for exemption matching. */
|
|
68
|
+
function key(r) {
|
|
69
|
+
return `${r.schema}.${r.relname}`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Verifies that every table in `requiredTables` has row-level security
|
|
73
|
+
* enabled (`pg_class.relrowsecurity = true`), exempting any § 7.6
|
|
74
|
+
* reference table. Resolves OK (returns `void`) when all required tables
|
|
75
|
+
* are covered; throws `RlsCoverageError` listing the offenders otherwise.
|
|
76
|
+
*
|
|
77
|
+
* The query is a single read against `pg_class` joined to `pg_namespace`
|
|
78
|
+
* — read-only, no GUCs, no writes. Run it from a migration / `db:setup`
|
|
79
|
+
* gate against any pool (typically the owner/admin pool).
|
|
80
|
+
*/
|
|
81
|
+
export async function verifyRls(pool, opts) {
|
|
82
|
+
const defaultSchema = opts.schema ?? "public";
|
|
83
|
+
const exemptionsEnabled = opts.allowReferenceTables ?? true;
|
|
84
|
+
// Build the exempt set (normalized schema.relname keys) + predicate.
|
|
85
|
+
const exemptKeys = new Set();
|
|
86
|
+
if (exemptionsEnabled && opts.referenceTables) {
|
|
87
|
+
for (const t of opts.referenceTables) {
|
|
88
|
+
exemptKeys.add(key(resolveTable(t, defaultSchema)));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const predicate = exemptionsEnabled && opts.isReferenceTable
|
|
92
|
+
? opts.isReferenceTable
|
|
93
|
+
: undefined;
|
|
94
|
+
// Resolve + filter out exempt reference tables BEFORE querying.
|
|
95
|
+
const toCheck = [];
|
|
96
|
+
for (const original of opts.requiredTables) {
|
|
97
|
+
const resolved = resolveTable(original, defaultSchema);
|
|
98
|
+
const isExempt = exemptKeys.has(key(resolved)) ||
|
|
99
|
+
(predicate ? predicate(original) : false);
|
|
100
|
+
if (!isExempt)
|
|
101
|
+
toCheck.push(resolved);
|
|
102
|
+
}
|
|
103
|
+
if (toCheck.length === 0)
|
|
104
|
+
return;
|
|
105
|
+
// One catalog query covering all to-check tables. We pass parallel
|
|
106
|
+
// schema[] + relname[] arrays and join in SQL so a single round-trip
|
|
107
|
+
// resolves every table; missing rows are detected by set difference.
|
|
108
|
+
const schemas = toCheck.map((t) => t.schema);
|
|
109
|
+
const relnames = toCheck.map((t) => t.relname);
|
|
110
|
+
const res = await pool.query(`SELECT n.nspname, c.relname, c.relrowsecurity
|
|
111
|
+
FROM unnest($1::text[], $2::text[]) AS req(schemaname, tablename)
|
|
112
|
+
JOIN pg_namespace n ON n.nspname = req.schemaname
|
|
113
|
+
JOIN pg_class c ON c.relnamespace = n.oid
|
|
114
|
+
AND c.relname = req.tablename
|
|
115
|
+
AND c.relkind IN ('r', 'p')`, [schemas, relnames]);
|
|
116
|
+
// Index the catalog rows by schema.relname.
|
|
117
|
+
const found = new Map();
|
|
118
|
+
for (const row of res.rows) {
|
|
119
|
+
found.set(`${row.nspname}.${row.relname}`, row.relrowsecurity);
|
|
120
|
+
}
|
|
121
|
+
const offenders = [];
|
|
122
|
+
for (const t of toCheck) {
|
|
123
|
+
const k = key(t);
|
|
124
|
+
if (!found.has(k)) {
|
|
125
|
+
offenders.push({
|
|
126
|
+
table: t.original,
|
|
127
|
+
schema: t.schema,
|
|
128
|
+
relname: t.relname,
|
|
129
|
+
reason: "not_found",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else if (found.get(k) === false) {
|
|
133
|
+
offenders.push({
|
|
134
|
+
table: t.original,
|
|
135
|
+
schema: t.schema,
|
|
136
|
+
relname: t.relname,
|
|
137
|
+
reason: "rls_disabled",
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (offenders.length > 0) {
|
|
142
|
+
throw new RlsCoverageError(offenders);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=verify-rls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-rls.js","sourceRoot":"","sources":["../src/verify-rls.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodii/db-rls",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Three-pool RLS dispatch + GUC-set + entry-point helpers + RLS policy DDL generator for the Nodii microservice stack. Polyglot per D159 (TS + Python + Go). Spec: planning hub docKey=db-rls.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|