@nodii/db-rls 0.11.0 → 0.13.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 (53) hide show
  1. package/bin/migrate-gen.mjs +11 -0
  2. package/dist/auth-schema.d.ts +207 -1
  3. package/dist/auth-schema.d.ts.map +1 -1
  4. package/dist/auth-schema.js +331 -4
  5. package/dist/auth-schema.js.map +1 -1
  6. package/dist/context.d.ts +31 -8
  7. package/dist/context.d.ts.map +1 -1
  8. package/dist/context.js +103 -24
  9. package/dist/context.js.map +1 -1
  10. package/dist/drizzle-client.d.ts +17 -5
  11. package/dist/drizzle-client.d.ts.map +1 -1
  12. package/dist/drizzle-client.js +19 -18
  13. package/dist/drizzle-client.js.map +1 -1
  14. package/dist/fence-cli.d.ts +21 -0
  15. package/dist/fence-cli.d.ts.map +1 -0
  16. package/dist/fence-cli.js +191 -0
  17. package/dist/fence-cli.js.map +1 -0
  18. package/dist/index.d.ts +7 -4
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +31 -7
  21. package/dist/index.js.map +1 -1
  22. package/dist/postgres-js-client.d.ts +17 -10
  23. package/dist/postgres-js-client.d.ts.map +1 -1
  24. package/dist/postgres-js-client.js +19 -21
  25. package/dist/postgres-js-client.js.map +1 -1
  26. package/dist/rls-policy-gen.d.ts +43 -27
  27. package/dist/rls-policy-gen.d.ts.map +1 -1
  28. package/dist/rls-policy-gen.js +40 -15
  29. package/dist/rls-policy-gen.js.map +1 -1
  30. package/dist/rls-policy.d.ts +11 -1
  31. package/dist/rls-policy.d.ts.map +1 -1
  32. package/dist/rls-policy.js +31 -4
  33. package/dist/rls-policy.js.map +1 -1
  34. package/dist/tenant-fence-gate.d.ts +54 -0
  35. package/dist/tenant-fence-gate.d.ts.map +1 -0
  36. package/dist/tenant-fence-gate.js +291 -0
  37. package/dist/tenant-fence-gate.js.map +1 -0
  38. package/dist/tenant-fence.d.ts +165 -0
  39. package/dist/tenant-fence.d.ts.map +1 -0
  40. package/dist/tenant-fence.js +542 -0
  41. package/dist/tenant-fence.js.map +1 -0
  42. package/dist/types.d.ts +18 -0
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/types.js +22 -0
  45. package/dist/types.js.map +1 -1
  46. package/dist/verify-rls-cli.d.ts.map +1 -1
  47. package/dist/verify-rls-cli.js +86 -10
  48. package/dist/verify-rls-cli.js.map +1 -1
  49. package/dist/verify-rls.d.ts +26 -5
  50. package/dist/verify-rls.d.ts.map +1 -1
  51. package/dist/verify-rls.js +73 -5
  52. package/dist/verify-rls.js.map +1 -1
  53. package/package.json +2 -2
package/dist/context.d.ts CHANGED
@@ -1,25 +1,48 @@
1
1
  import { type OwnerContextOpts } from "./migrate-guard.js";
2
2
  import { type AutoDispatchOpts, type PgTx, type PlatformOpsContextOpts, type SystemContextOpts, type UserContextOpts, type UserMembershipContextOpts } from "./types.js";
3
+ /** Test-only. Not exported through the public barrel. */
4
+ export declare function _resetFenceGateForTests(): void;
3
5
  /**
4
6
  * withUserContext — opens a tx on the `authenticated` pool, sets
5
7
  * `app.user_id` + `app.tenant_id` (+ optional `app.source_ip`) via
6
8
  * `set_config(..., true)` tx-scoped GUCs, yields the tx, commits/rolls
7
9
  * back per the PgPool contract.
8
10
  *
11
+ * On the FIRST call in a process it also runs the tenant-fence gate (see
12
+ * {@link assertFenceOnce}) and refuses to yield the tx if the fence is broken.
13
+ *
9
14
  * Throws `DbRlsNotInitialized` if `initDbRls` hasn't run.
10
15
  * Wraps any error thrown by `fn` in `TransactionRolledBack`.
11
16
  */
12
17
  export declare function withUserContext<T>(opts: UserContextOpts, fn: (tx: PgTx) => Promise<T>): Promise<T>;
13
18
  /**
14
- * withUserMembershipContext — the doctrine 08-rls §4 multi-membership
15
- * variant of `withUserContext`. Opens a tx on the `authenticated` pool and
16
- * sets ONLY `app.user_id` (no `app.tenant_id` pin), so the authenticated
17
- * predicate `tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id()))`
18
- * resolves across ALL of the user's tenant memberships. Use this for §4
19
- * multi-membership query paths (e.g. task-tracking); use `withUserContext`
20
- * when a single tenant must be pinned.
19
+ * @deprecated REMOVED — always throws {@link CrossTenantSessionRefused}.
20
+ *
21
+ * This helper opened an `authenticated`-pool transaction binding ONLY
22
+ * `app.user_id`, deliberately leaving `app.tenant_id` unset so that the old
23
+ * union predicate `tenant_id IN (SELECT auth.user_tenant_ids(...))` would
24
+ * resolve across EVERY tenant the principal was an active member of. Its own
25
+ * docblock named task-tracking as the use case.
26
+ *
27
+ * That is not a policy bug that the predicate fix cleans up incidentally — it
28
+ * is the MECHANISM of the incident, sitting in the library. Reproduced
29
+ * end-to-end: a legitimate tenant-A session transitioned a tenant-B approval
30
+ * task, got HTTP 200, and released a 250,000 INR refund. Rewriting predicates
31
+ * while leaving this callable would have changed nothing for any caller of it.
32
+ *
33
+ * Migrate to `withUserContext({ userId, tenantId }, fn)` — the same pool, with
34
+ * the tenant the request actually resolved to. If a caller genuinely needs to
35
+ * know which tenants a user belongs to (a tenant switcher, a login
36
+ * tenant-picker), query `auth.user_tenant_ids` directly from a services-pool
37
+ * context; that function is deliberately left intact and still answers exactly
38
+ * that question. What is no longer available is opening a DATA session that
39
+ * spans them.
40
+ *
41
+ * The symbol is retained rather than deleted so a JavaScript consumer (no
42
+ * typechecker) gets this explanation at runtime instead of
43
+ * `undefined is not a function`.
21
44
  */
22
- export declare function withUserMembershipContext<T>(opts: UserMembershipContextOpts, fn: (tx: PgTx) => Promise<T>): Promise<T>;
45
+ export declare function withUserMembershipContext<T>(_opts: UserMembershipContextOpts, _fn: (tx: PgTx) => Promise<T>): Promise<T>;
23
46
  /**
24
47
  * withSystemContext — opens a tx on the `services` (nodii_services) pool,
25
48
  * sets `app.tenant_id` via tx-scoped `set_config`, yields the tx, commits
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,IAAI,EACT,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC/B,MAAM,YAAY,CAAC;AAEpB;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,IAAI,EAAE,eAAe,EACrB,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAoBZ;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAAC,CAAC,EAC/C,IAAI,EAAE,yBAAyB,EAC/B,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAeZ;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,IAAI,EAAE,iBAAiB,EACvB,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,QAAQ,EAAE,gBAAgB,GAAG,CAAC,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EACvD,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GACjC,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,IAAI,EAAE,sBAAsB,EAC5B,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAYZ;AAMD,4DAA4D;AAC5D,wBAAgB,8CAA8C,IAAI,IAAI,CAErE;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,IAAI,EAAE,sBAAsB,EAC5B,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAWZ;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,IAAI,EAAE,gBAAgB,EACtB,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAeZ"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,KAAK,gBAAgB,EAGrB,KAAK,IAAI,EACT,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC/B,MAAM,YAAY,CAAC;AAepB,yDAAyD;AACzD,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAyCD;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,IAAI,EAAE,eAAe,EACrB,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAmCZ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,yBAAyB,CAAC,CAAC,EAC/C,KAAK,EAAE,yBAAyB,EAChC,GAAG,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC5B,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,IAAI,EAAE,iBAAiB,EACvB,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,QAAQ,EAAE,gBAAgB,GAAG,CAAC,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EACvD,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GACjC,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,IAAI,EAAE,sBAAsB,EAC5B,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAYZ;AAMD,4DAA4D;AAC5D,wBAAgB,8CAA8C,IAAI,IAAI,CAErE;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,IAAI,EAAE,sBAAsB,EAC5B,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAWZ;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,IAAI,EAAE,gBAAgB,EACtB,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC,CAeZ"}
package/dist/context.js CHANGED
@@ -7,17 +7,82 @@
7
7
  import { requirePool } from "./init.js";
8
8
  import { recordOwnerContextInvocation } from "./metrics.js";
9
9
  import { assertMigrateAllowed, } from "./migrate-guard.js";
10
- import { MissingTenantContext, TransactionRolledBack, } from "./types.js";
10
+ import { TENANT_FENCE_GATE_CALL_SQL } from "./tenant-fence-gate.js";
11
+ import { CrossTenantSessionRefused, MissingTenantContext, TransactionRolledBack, } from "./types.js";
12
+ /**
13
+ * Process-local latch for the first-use fence gate. `null` until the gate has
14
+ * run; thereafter the settled promise, so the check costs one round-trip per
15
+ * PROCESS rather than one per transaction.
16
+ *
17
+ * A REJECTED promise is retained deliberately. A broken fence is not a
18
+ * transient condition — it is a property of the schema — so re-checking on
19
+ * every subsequent request would turn one clear failure into a storm of
20
+ * identical ones while adding a catalog scan to each. The service stays down
21
+ * and says the same thing every time, which is the intended behaviour.
22
+ */
23
+ let fenceGate = null;
24
+ /** Test-only. Not exported through the public barrel. */
25
+ export function _resetFenceGateForTests() {
26
+ fenceGate = null;
27
+ }
28
+ /**
29
+ * THE GATE. Runs `auth.assert_tenant_fence()` once per process, on the first
30
+ * authenticated-pool checkout.
31
+ *
32
+ * WHY HERE, AND NOT IN A DEPLOY SCRIPT.
33
+ *
34
+ * The obvious home is a `db:verify` step in each service's deploy. It does not
35
+ * work, and this is measured rather than argued: SIX of the ten services this
36
+ * release has to reach — billing, kyc, notification, task-tracking, tenant and
37
+ * geo — have NO database step in `deploy-dev.yml` at all. Their `db:setup`
38
+ * runs in `ci.yml` against a throwaway Postgres. A gate wired there is green
39
+ * forever on the services that need it most, and reported as a pass.
40
+ *
41
+ * WHY NOT `initDbRls`. Boot order forbids it. billing runs `applySagaMigrations`
42
+ * and `applyDsarMigrations` at boot, AFTER its pools are constructed — a check
43
+ * at `initDbRls` time would fire against a schema that is about to be fixed
44
+ * two statements later and fail every deploy.
45
+ *
46
+ * First-authenticated-use is the earliest point that is both after all boot
47
+ * migrations and before any tenant row is served, and it is reached by
48
+ * construction: there is no way to open an authenticated transaction without
49
+ * passing through here. That is the "cannot forget to opt in" property. It is
50
+ * not a flag, a config key, or a script somebody adds to a pipeline — it is the
51
+ * function you must call to get the connection.
52
+ *
53
+ * WHY IT IS NOT THE `verifyRls` SHAPE. `verifyRls` takes `requiredTables` from
54
+ * the caller, and the author who forgets `ENABLE ROW LEVEL SECURITY` forgets
55
+ * the list entry in the same migration — so it sits wired and green while
56
+ * unprotected tables accumulate behind it. `auth.assert_tenant_fence()` asks
57
+ * the catalog which tables carry a tenant column. Nobody maintains a list,
58
+ * so nobody can omit the entry that mattered.
59
+ */
60
+ async function assertFenceOnce(tx) {
61
+ if (fenceGate === null) {
62
+ fenceGate = tx.exec(TENANT_FENCE_GATE_CALL_SQL);
63
+ }
64
+ return fenceGate;
65
+ }
11
66
  /**
12
67
  * withUserContext — opens a tx on the `authenticated` pool, sets
13
68
  * `app.user_id` + `app.tenant_id` (+ optional `app.source_ip`) via
14
69
  * `set_config(..., true)` tx-scoped GUCs, yields the tx, commits/rolls
15
70
  * back per the PgPool contract.
16
71
  *
72
+ * On the FIRST call in a process it also runs the tenant-fence gate (see
73
+ * {@link assertFenceOnce}) and refuses to yield the tx if the fence is broken.
74
+ *
17
75
  * Throws `DbRlsNotInitialized` if `initDbRls` hasn't run.
18
76
  * Wraps any error thrown by `fn` in `TransactionRolledBack`.
19
77
  */
20
78
  export async function withUserContext(opts, fn) {
79
+ // Reject a blank principal or tenant HERE rather than binding an empty GUC
80
+ // and letting `auth.session_tenant_ids()` raise 42501 on the first query.
81
+ // Both fail closed, but this one names the caller instead of a policy.
82
+ if (!opts?.userId)
83
+ throw new MissingTenantContext();
84
+ if (!opts?.tenantId)
85
+ throw new MissingTenantContext();
21
86
  const pool = requirePool("authenticated");
22
87
  return pool.withTransaction(async (tx) => {
23
88
  // Canonical GUC namespace is `app.*` (08-rls §2/§6): the generated
@@ -31,6 +96,16 @@ export async function withUserContext(opts, fn) {
31
96
  if (opts.sourceIp !== undefined) {
32
97
  await tx.setConfig("app.source_ip", opts.sourceIp);
33
98
  }
99
+ // BEFORE `fn`, deliberately. The point of the gate is that no tenant row is
100
+ // served through a broken fence — running it afterwards would mean the
101
+ // first request reads cross-tenant data and THEN reports the problem.
102
+ //
103
+ // NOT wrapped in TransactionRolledBack: that wrapper exists to mark "the
104
+ // caller's own code threw". This is the library refusing to hand over the
105
+ // transaction, and it must surface with its own message and SQLSTATE
106
+ // intact so the on-call engineer sees the offender list rather than a
107
+ // generic rollback.
108
+ await assertFenceOnce(tx);
34
109
  try {
35
110
  return await fn(tx);
36
111
  }
@@ -40,30 +115,34 @@ export async function withUserContext(opts, fn) {
40
115
  });
41
116
  }
42
117
  /**
43
- * withUserMembershipContext — the doctrine 08-rls §4 multi-membership
44
- * variant of `withUserContext`. Opens a tx on the `authenticated` pool and
45
- * sets ONLY `app.user_id` (no `app.tenant_id` pin), so the authenticated
46
- * predicate `tenant_id IN (SELECT auth.user_tenant_ids(auth.get_user_id()))`
47
- * resolves across ALL of the user's tenant memberships. Use this for §4
48
- * multi-membership query paths (e.g. task-tracking); use `withUserContext`
49
- * when a single tenant must be pinned.
118
+ * @deprecated REMOVED — always throws {@link CrossTenantSessionRefused}.
119
+ *
120
+ * This helper opened an `authenticated`-pool transaction binding ONLY
121
+ * `app.user_id`, deliberately leaving `app.tenant_id` unset so that the old
122
+ * union predicate `tenant_id IN (SELECT auth.user_tenant_ids(...))` would
123
+ * resolve across EVERY tenant the principal was an active member of. Its own
124
+ * docblock named task-tracking as the use case.
125
+ *
126
+ * That is not a policy bug that the predicate fix cleans up incidentally — it
127
+ * is the MECHANISM of the incident, sitting in the library. Reproduced
128
+ * end-to-end: a legitimate tenant-A session transitioned a tenant-B approval
129
+ * task, got HTTP 200, and released a 250,000 INR refund. Rewriting predicates
130
+ * while leaving this callable would have changed nothing for any caller of it.
131
+ *
132
+ * Migrate to `withUserContext({ userId, tenantId }, fn)` — the same pool, with
133
+ * the tenant the request actually resolved to. If a caller genuinely needs to
134
+ * know which tenants a user belongs to (a tenant switcher, a login
135
+ * tenant-picker), query `auth.user_tenant_ids` directly from a services-pool
136
+ * context; that function is deliberately left intact and still answers exactly
137
+ * that question. What is no longer available is opening a DATA session that
138
+ * spans them.
139
+ *
140
+ * The symbol is retained rather than deleted so a JavaScript consumer (no
141
+ * typechecker) gets this explanation at runtime instead of
142
+ * `undefined is not a function`.
50
143
  */
51
- export async function withUserMembershipContext(opts, fn) {
52
- const pool = requirePool("authenticated");
53
- return pool.withTransaction(async (tx) => {
54
- // ONLY app.user_id — leaving app.tenant_id unset is intentional: the §4
55
- // predicate keys on user_tenant_ids(get_user_id()), not a pinned tenant.
56
- await tx.setConfig("app.user_id", opts.userId);
57
- if (opts.sourceIp !== undefined) {
58
- await tx.setConfig("app.source_ip", opts.sourceIp);
59
- }
60
- try {
61
- return await fn(tx);
62
- }
63
- catch (cause) {
64
- throw new TransactionRolledBack(cause);
65
- }
66
- });
144
+ export async function withUserMembershipContext(_opts, _fn) {
145
+ throw new CrossTenantSessionRefused("withUserMembershipContext");
67
146
  }
68
147
  /**
69
148
  * withSystemContext — opens a tx on the `services` (nodii_services) pool,
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,uEAAuE;AACvE,0EAA0E;AAC1E,kEAAkE;AAClE,YAAY;AAEZ,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EACL,oBAAoB,GAErB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAEL,yBAAyB,EACzB,oBAAoB,EAIpB,qBAAqB,GAGtB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;GAUG;AACH,IAAI,SAAS,GAAyB,IAAI,CAAC;AAE3C,yDAAyD;AACzD,MAAM,UAAU,uBAAuB;IACrC,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,KAAK,UAAU,eAAe,CAAC,EAAQ;IACrC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,SAAS,GAAG,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAqB,EACrB,EAA4B;IAE5B,2EAA2E;IAC3E,0EAA0E;IAC1E,uEAAuE;IACvE,IAAI,CAAC,IAAI,EAAE,MAAM;QAAE,MAAM,IAAI,oBAAoB,EAAE,CAAC;IACpD,IAAI,CAAC,IAAI,EAAE,QAAQ;QAAE,MAAM,IAAI,oBAAoB,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,WAAW,CAAC,eAAe,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACvC,mEAAmE;QACnE,yEAAyE;QACzE,6EAA6E;QAC7E,8EAA8E;QAC9E,8EAA8E;QAC9E,4EAA4E;QAC5E,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrD,CAAC;QACD,4EAA4E;QAC5E,uEAAuE;QACvE,sEAAsE;QACtE,EAAE;QACF,yEAAyE;QACzE,0EAA0E;QAC1E,qEAAqE;QACrE,sEAAsE;QACtE,oBAAoB;QACpB,MAAM,eAAe,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAAgC,EAChC,GAA6B;IAE7B,MAAM,IAAI,yBAAyB,CAAC,2BAA2B,CAAC,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAuB,EACvB,EAA4B;IAE5B,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACvC,MAAM,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAuD,EACvD,OAAkC;IAElC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3D,IAAI,CAAC;QACH,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4BAA4B,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,4BAA4B,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACvC,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CACzB,QAAuD,EACvD,OAAkC;IAElC,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;IACpC,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CACjB,mFAAmF,CACpF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;AACzC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAA4B,EAC5B,EAA4B;IAE5B,MAAM,IAAI,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACvC,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,EAAE,CAAC,SAAS,CAAC,6BAA6B,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAClE,MAAM,EAAE,CAAC,SAAS,CAAC,6BAA6B,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACnE,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mEAAmE;AACnE,0CAA0C;AAC1C,IAAI,iCAAiC,GAAG,KAAK,CAAC;AAE9C,4DAA4D;AAC5D,MAAM,UAAU,8CAA8C;IAC5D,iCAAiC,GAAG,KAAK,CAAC;AAC5C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAA4B,EAC5B,EAA4B;IAE5B,IAAI,CAAC,iCAAiC,EAAE,CAAC;QACvC,iCAAiC,GAAG,IAAI,CAAC;QACzC,sCAAsC;QACtC,OAAO,CAAC,IAAI,CACV,uDAAuD;YACrD,+DAA+D;YAC/D,0CAA0C,CAC7C,CAAC;IACJ,CAAC;IACD,OAAO,sBAAsB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAsB,EACtB,EAA4B;IAE5B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,OAAO,eAAe,CACpB;YACE,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM;YAC/B,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ;YACnC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ;SACpC,EACD,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,iBAAiB,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,IAAI,oBAAoB,EAAE,CAAC;AACnC,CAAC"}
@@ -10,12 +10,24 @@ type DrizzleClient<TSchema extends Record<string, unknown> = Record<string, unkn
10
10
  */
11
11
  export declare function withUserContextDb<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(opts: UserContextOpts, fn: (db: DrizzleClient<TSchema>) => Promise<T>): Promise<T>;
12
12
  /**
13
- * withUserMembershipContextDb — the doctrine 08-rls §4 multi-membership
14
- * Drizzle variant. Sets ONLY `app.user_id` via the canonical
15
- * `auth.set_user_id(...)` helper (no `auth.init` tenant pin), so the
16
- * authenticated predicate spans all of the user's tenant memberships.
13
+ * @deprecated REMOVED — always throws {@link CrossTenantSessionRefused}.
14
+ *
15
+ * Opened an `authenticated`-pool transaction binding ONLY `app.user_id`,
16
+ * leaving `app.tenant_id` deliberately unset so the old union predicate
17
+ * resolved across EVERY tenant the principal belonged to. That is the
18
+ * mechanism of the cross-tenant approval incident, not a side effect of it:
19
+ * a legitimate tenant-A session transitioned a tenant-B approval task, got
20
+ * HTTP 200, and released a 250,000 INR refund.
21
+ *
22
+ * Migrate to `withUserContextDb({ userId, tenantId }, fn)`.
23
+ * To LIST a user's tenants (switcher / login picker), query
24
+ * `auth.user_tenant_ids` from a services-pool context — that function is
25
+ * intact; what is gone is opening a DATA session that spans them.
26
+ *
27
+ * Retained as a throwing stub rather than deleted so a JavaScript consumer
28
+ * gets this explanation instead of `undefined is not a function`.
17
29
  */
18
- export declare function withUserMembershipContextDb<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(opts: UserMembershipContextOpts, fn: (db: DrizzleClient<TSchema>) => Promise<T>): Promise<T>;
30
+ export declare function withUserMembershipContextDb<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(_opts: UserMembershipContextOpts, _fn: (db: DrizzleClient<TSchema>) => Promise<T>): Promise<T>;
19
31
  /**
20
32
  * withSystemContext (Drizzle variant) — opens a tx on the `services` pool
21
33
  * with `app.tenant_id` GUC bound; yields a Drizzle client.
@@ -1 +1 @@
1
- {"version":3,"file":"drizzle-client.d.ts","sourceRoot":"","sources":["../src/drizzle-client.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAKzE,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAOpB,KAAK,aAAa,CAChB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC/D,cAAc,CAAC,OAAO,CAAC,CAAC;AA2D5B;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,CAAC,EACD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjE,IAAI,EAAE,eAAe,EACrB,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,CAAC,CAAC,CAoBZ;AAED;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,CAAC,EACD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjE,IAAI,EAAE,yBAAyB,EAC/B,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,CAAC,EACD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjE,IAAI,EAAE,iBAAiB,EACvB,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,CAAC,EACD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjE,QAAQ,EAAE,gBAAgB,GAAG,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EACzE,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACnD,OAAO,CAAC,CAAC,CAAC,CAeZ;AAoBD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"drizzle-client.d.ts","sourceRoot":"","sources":["../src/drizzle-client.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAKzE,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAWpB,KAAK,aAAa,CAChB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC/D,cAAc,CAAC,OAAO,CAAC,CAAC;AA2D5B;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,CAAC,EACD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjE,IAAI,EAAE,eAAe,EACrB,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,CAAC,CAAC,CAoBZ;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,2BAA2B,CAC/C,CAAC,EACD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjE,KAAK,EAAE,yBAAyB,EAChC,GAAG,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9C,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,CAAC,EACD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjE,IAAI,EAAE,iBAAiB,EACvB,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,CAAC,EACD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjE,QAAQ,EAAE,gBAAgB,GAAG,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EACzE,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACnD,OAAO,CAAC,CAAC,CAAC,CAeZ;AAoBD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC"}
@@ -21,7 +21,7 @@ import { requirePool } from "./init.js";
21
21
  import { recordOwnerContextInvocation, withTxSpan } from "./metrics.js";
22
22
  import { assertMigrateAllowed, } from "./migrate-guard.js";
23
23
  import { PgClientPool } from "./pg-pool-adapter.js";
24
- import { MissingTenantContext, TransactionRolledBack } from "./types.js";
24
+ import { CrossTenantSessionRefused, MissingTenantContext, TransactionRolledBack, } from "./types.js";
25
25
  function clientFor(_pool) {
26
26
  // Only PgClientPool exposes a real pg PoolClient. In-memory pools don't.
27
27
  // The caller is responsible for using *Db helpers only against real pools.
@@ -97,24 +97,25 @@ export async function withUserContextDb(opts, fn) {
97
97
  }, (db) => fn(db));
98
98
  }
99
99
  /**
100
- * withUserMembershipContextDb — the doctrine 08-rls §4 multi-membership
101
- * Drizzle variant. Sets ONLY `app.user_id` via the canonical
102
- * `auth.set_user_id(...)` helper (no `auth.init` tenant pin), so the
103
- * authenticated predicate spans all of the user's tenant memberships.
100
+ * @deprecated REMOVED — always throws {@link CrossTenantSessionRefused}.
101
+ *
102
+ * Opened an `authenticated`-pool transaction binding ONLY `app.user_id`,
103
+ * leaving `app.tenant_id` deliberately unset so the old union predicate
104
+ * resolved across EVERY tenant the principal belonged to. That is the
105
+ * mechanism of the cross-tenant approval incident, not a side effect of it:
106
+ * a legitimate tenant-A session transitioned a tenant-B approval task, got
107
+ * HTTP 200, and released a 250,000 INR refund.
108
+ *
109
+ * Migrate to `withUserContextDb({ userId, tenantId }, fn)`.
110
+ * To LIST a user's tenants (switcher / login picker), query
111
+ * `auth.user_tenant_ids` from a services-pool context — that function is
112
+ * intact; what is gone is opening a DATA session that spans them.
113
+ *
114
+ * Retained as a throwing stub rather than deleted so a JavaScript consumer
115
+ * gets this explanation instead of `undefined is not a function`.
104
116
  */
105
- export async function withUserMembershipContextDb(opts, fn) {
106
- if (!opts.userId)
107
- throw new MissingTenantContext();
108
- const pool = requireRealPool("authenticated");
109
- return withRealTx(pool, async (client) => {
110
- // ONLY app.user_id — set_user_id, not init, so no tenant is pinned.
111
- await client.query("SELECT auth.set_user_id($1::uuid)", [opts.userId]);
112
- if (opts.sourceIp !== undefined) {
113
- await client.query("SELECT set_config('app.source_ip', $1, true)", [
114
- opts.sourceIp,
115
- ]);
116
- }
117
- }, (db) => fn(db));
117
+ export async function withUserMembershipContextDb(_opts, _fn) {
118
+ throw new CrossTenantSessionRefused("withUserMembershipContextDb");
118
119
  }
119
120
  /**
120
121
  * withSystemContext (Drizzle variant) — opens a tx on the `services` pool
@@ -1 +1 @@
1
- {"version":3,"file":"drizzle-client.js","sourceRoot":"","sources":["../src/drizzle-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"drizzle-client.js","sourceRoot":"","sources":["../src/drizzle-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface FenceCliResult {
2
+ /** 0 = clean, 1 = fence defect, 2 = usage / connection error. */
3
+ code: number;
4
+ message: string;
5
+ }
6
+ /**
7
+ * `install-fence` — apply the delivery unit (resolver + gate).
8
+ *
9
+ * Idempotent and re-runnable. Must be run with OWNER credentials: it creates
10
+ * functions in the `auth` schema. Safe to run on every deploy; safe to run
11
+ * twice; and re-running is how a service that has since landed a membership
12
+ * mirror upgrades itself from the degraded body to the strict one.
13
+ */
14
+ export declare function runInstallFenceCli(args: readonly string[]): Promise<FenceCliResult>;
15
+ /**
16
+ * `verify-fence` — assert the fence from the CATALOG, using the TypeScript
17
+ * verifier (which reports EVERY offender at once rather than raising on the
18
+ * first, and covers the unique-index check the SQL gate leaves to deploy time).
19
+ */
20
+ export declare function runVerifyFenceCli(args: readonly string[]): Promise<FenceCliResult>;
21
+ //# sourceMappingURL=fence-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fence-cli.d.ts","sourceRoot":"","sources":["../src/fence-cli.ts"],"names":[],"mappings":"AA+BA,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAkDD;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,OAAO,CAAC,cAAc,CAAC,CAsCzB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,OAAO,CAAC,cAAc,CAAC,CAkCzB"}
@@ -0,0 +1,191 @@
1
+ // `nodii-db-rls install-fence` and `nodii-db-rls verify-fence`.
2
+ //
3
+ // The eager, pipeline-facing half of the gate. `withUserContext` runs
4
+ // `auth.assert_tenant_fence()` on first authenticated use, which is the
5
+ // unforgettable check — but "unforgettable" is not the same as "early", and a
6
+ // deploy that can fail at 09:00 rather than on the first customer request at
7
+ // 09:04 should.
8
+ //
9
+ // THIS IS NOT OFFERED AS THE PRIMARY MECHANISM, and the reason is measured
10
+ // rather than stylistic. Of the ten services that call neither
11
+ // `applyAuthSchemaMigrations` nor `authSchemaHelpers`, SIX — billing, kyc,
12
+ // notification, task-tracking, tenant and geo — have NO database step in
13
+ // `deploy-dev.yml`. Wiring the fence exclusively into a deploy script would
14
+ // leave those six permanently unchecked while reporting green, which is the
15
+ // precise failure mode this release exists to end. So the CLI is the
16
+ // belt-and-braces for pipelines that DO have a database step, and the runtime
17
+ // gate is the floor for everyone.
18
+ //
19
+ // `install-fence` exists because the delivery unit has to be applicable to a
20
+ // service that is on none of the library paths — one command, owner
21
+ // credentials, no code change:
22
+ //
23
+ // bunx @nodii/db-rls install-fence --db "$DATABASE_URL"
24
+ import { SESSION_FENCE_BOOTSTRAP_SQL, SESSION_TENANT_IDS_GRANTS_SQL, } from "./auth-schema.js";
25
+ import { TENANT_FENCE_GATE_GRANTS_SQL } from "./tenant-fence-gate.js";
26
+ import { TenantFenceError, verifyTenantFence } from "./tenant-fence.js";
27
+ function splitList(value) {
28
+ if (!value)
29
+ return [];
30
+ return value
31
+ .split(",")
32
+ .map((s) => s.trim())
33
+ .filter((s) => s.length > 0);
34
+ }
35
+ function parse(args) {
36
+ const out = {
37
+ allowDegraded: true,
38
+ skipGrants: false,
39
+ help: false,
40
+ };
41
+ for (let i = 0; i < args.length; i++) {
42
+ const a = args[i];
43
+ if (a === "--db" && i + 1 < args.length)
44
+ out.dbUrl = args[++i];
45
+ else if (a === "--schema" && i + 1 < args.length)
46
+ out.schema = args[++i];
47
+ else if (a === "--exempt-policies" && i + 1 < args.length)
48
+ out.exemptPolicies = args[++i];
49
+ else if (a === "--exempt-tables" && i + 1 < args.length)
50
+ out.exemptTables = args[++i];
51
+ // Default is to ACCEPT the degraded resolver: it is the D415-sanctioned
52
+ // terminal state for a service with no membership mirror, and a gate that
53
+ // is red on a legitimate configuration gets switched off. `--strict-only`
54
+ // is for a service that HAS a mirror and wants to prove it never silently
55
+ // regresses to fence-only.
56
+ else if (a === "--strict-only")
57
+ out.allowDegraded = false;
58
+ else if (a === "--skip-grants")
59
+ out.skipGrants = true;
60
+ else if (a === "--help" || a === "-h")
61
+ out.help = true;
62
+ }
63
+ return out;
64
+ }
65
+ function connectionString(parsed) {
66
+ return parsed.dbUrl ?? process.env.DATABASE_URL ?? process.env.DB_RLS_PG_URL;
67
+ }
68
+ /**
69
+ * `install-fence` — apply the delivery unit (resolver + gate).
70
+ *
71
+ * Idempotent and re-runnable. Must be run with OWNER credentials: it creates
72
+ * functions in the `auth` schema. Safe to run on every deploy; safe to run
73
+ * twice; and re-running is how a service that has since landed a membership
74
+ * mirror upgrades itself from the degraded body to the strict one.
75
+ */
76
+ export async function runInstallFenceCli(args) {
77
+ const parsed = parse(args);
78
+ if (parsed.help)
79
+ return { code: 0, message: installUsage() };
80
+ const conn = connectionString(parsed);
81
+ if (!conn) {
82
+ return {
83
+ code: 2,
84
+ message: "install-fence: no connection string — pass --db <url> or set DATABASE_URL / DB_RLS_PG_URL.",
85
+ };
86
+ }
87
+ const { Pool } = await import("pg");
88
+ const pool = new Pool({ connectionString: conn, max: 1 });
89
+ try {
90
+ await pool.query(SESSION_FENCE_BOOTSTRAP_SQL);
91
+ if (!parsed.skipGrants) {
92
+ await pool.query(SESSION_TENANT_IDS_GRANTS_SQL);
93
+ await pool.query(TENANT_FENCE_GATE_GRANTS_SQL);
94
+ }
95
+ const { rows } = await pool.query(`SELECT prosrc FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
96
+ WHERE n.nspname = 'auth' AND p.proname = 'session_tenant_ids'`);
97
+ const body = rows[0]?.prosrc ?? "";
98
+ const variant = body.includes("DB_RLS_DEGRADED_NO_MEMBERSHIP_MIRROR")
99
+ ? "DEGRADED (fence-only, D415) — auth.user_tenant_ids is absent or still the bootstrap stub"
100
+ : "STRICT — session tenant INTERSECT server-resolved membership";
101
+ return {
102
+ code: 0,
103
+ message: `install-fence: OK. auth.session_tenant_ids() installed as ${variant}\ninstall-fence: auth.assert_tenant_fence() installed.`,
104
+ };
105
+ }
106
+ catch (err) {
107
+ return { code: 2, message: `install-fence: ${err.message}` };
108
+ }
109
+ finally {
110
+ await pool.end().catch(() => { });
111
+ }
112
+ }
113
+ /**
114
+ * `verify-fence` — assert the fence from the CATALOG, using the TypeScript
115
+ * verifier (which reports EVERY offender at once rather than raising on the
116
+ * first, and covers the unique-index check the SQL gate leaves to deploy time).
117
+ */
118
+ export async function runVerifyFenceCli(args) {
119
+ const parsed = parse(args);
120
+ if (parsed.help)
121
+ return { code: 0, message: verifyUsage() };
122
+ const conn = connectionString(parsed);
123
+ if (!conn) {
124
+ return {
125
+ code: 2,
126
+ message: "verify-fence: no connection string — pass --db <url> or set DATABASE_URL / DB_RLS_PG_URL.",
127
+ };
128
+ }
129
+ const { Pool } = await import("pg");
130
+ const pool = new Pool({ connectionString: conn, max: 1 });
131
+ try {
132
+ await verifyTenantFence(pool, {
133
+ schema: parsed.schema,
134
+ exemptPolicies: splitList(parsed.exemptPolicies),
135
+ exemptTables: splitList(parsed.exemptTables),
136
+ allowDegradedResolver: parsed.allowDegraded,
137
+ });
138
+ return {
139
+ code: 0,
140
+ message: "verify-fence: OK — every authenticated policy resolves through auth.session_tenant_ids(), every tenant-scoped relation is protected.",
141
+ };
142
+ }
143
+ catch (err) {
144
+ if (err instanceof TenantFenceError)
145
+ return { code: 1, message: err.message };
146
+ return { code: 2, message: `verify-fence: ${err.message}` };
147
+ }
148
+ finally {
149
+ await pool.end().catch(() => { });
150
+ }
151
+ }
152
+ function installUsage() {
153
+ return `usage: install-fence [--db <url>] [--skip-grants]
154
+
155
+ Applies the tenant-fence delivery unit with OWNER credentials:
156
+ - auth.session_tenant_ids() — the authenticated-pool resolver. The STRICT
157
+ body (session tenant INTERSECT membership) is installed where a real
158
+ auth.user_tenant_ids exists; the DEGRADED fence-only body (D415) where it
159
+ is absent or still the bootstrap stub. Derived from the catalog on every
160
+ run — there is no per-service list to get wrong, and re-running after a
161
+ membership mirror lands upgrades degraded to strict automatically.
162
+ - auth.assert_tenant_fence() — the runtime gate @nodii/db-rls calls on the
163
+ first authenticated-pool checkout.
164
+
165
+ Idempotent. Safe on every deploy. Run BEFORE any migration that creates a
166
+ policy referencing the resolver: Postgres validates the reference at CREATE
167
+ POLICY time, so an absent resolver fails the migration with 42883.
168
+
169
+ Connection string: --db <url>, else DATABASE_URL, else DB_RLS_PG_URL.`;
170
+ }
171
+ function verifyUsage() {
172
+ return `usage: verify-fence [--db <url>] [--schema <name>] [--strict-only]
173
+ [--exempt-policies <a.b,c>] [--exempt-tables <x,y>]
174
+
175
+ Asserts from the CATALOG that every permissive policy applying to the
176
+ 'authenticated' role resolves through auth.session_tenant_ids(), that every
177
+ relation carrying a tenant column can enforce RLS, and that the resolver is
178
+ installed, loud, and SECURITY DEFINER. Exits 1 (loud) listing every offender.
179
+
180
+ Tables are DISCOVERED from the catalog, never supplied by the caller: the
181
+ author who forgets ENABLE ROW LEVEL SECURITY forgets the list entry in the
182
+ same migration, which is why a caller-supplied list is blind to exactly the
183
+ tables at risk.
184
+
185
+ --strict-only additionally rejects the DEGRADED fence-only resolver. The
186
+ default accepts it: it is the D415-sanctioned terminal state for a service
187
+ with no membership mirror.
188
+
189
+ Connection string: --db <url>, else DATABASE_URL, else DB_RLS_PG_URL.`;
190
+ }
191
+ //# sourceMappingURL=fence-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fence-cli.js","sourceRoot":"","sources":["../src/fence-cli.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -10,10 +10,11 @@ export { withUserContext, withUserMembershipContext, withSystemContext, withOwne
10
10
  export type { OwnerContextOpts } from "./migrate-guard.js";
11
11
  export { assertMigrateAllowed } from "./migrate-guard.js";
12
12
  export { RlsCoverageError, verifyRls } from "./verify-rls.js";
13
- export type { ReferenceTablePredicate, RlsCoverageOffender, RlsQuerier, VerifyRlsOpts, } from "./verify-rls.js";
14
- export { AUTH_SCHEMA_SQL, AUTH_SCHEMA_GRANTS_SQL, applyAuthSchemaMigrations, authSchemaFullSql, } from "./auth-schema.js";
13
+ export type { AnyRlsQuerier, ReferenceTablePredicate, RlsCoverageOffender, RlsQuerier, RlsQuerierPostgresJs, VerifyRlsOpts, } from "./verify-rls.js";
14
+ export { AUTH_SCHEMA_SQL, AUTH_SCHEMA_GRANTS_SQL, applyAuthSchemaMigrations, authSchemaFullSql, SESSION_TENANT_IDS_DEGRADED_MARKER, SESSION_TENANT_IDS_DEGRADED_SQL, SESSION_TENANT_IDS_GRANTS_SQL, SESSION_TENANT_IDS_SQL, applySessionFenceBootstrap, INSTALL_SESSION_RESOLVER_SQL, SESSION_FENCE_BOOTSTRAP_SQL, } from "./auth-schema.js";
15
15
  export type { SqlExecutor } from "./auth-schema.js";
16
- export { withRls, generateTableGrants, authenticatedPredicate, withPlatformOpsTenantSql, withPlatformOpsGlobalSql, platformOpsTenantPredicateSql, platformOpsGlobalPredicateSql, platformOpsVerbClauseSql, sqlLiteral, PLATFORM_OPS_GRANTS_REPLICA_DEFAULT, referenceTableGrantsSql, findTenantColumn, ReferenceTableTenantColumnError, REFERENCE_TABLE_SKIP_RLS_MARKER, } from "./rls-policy-gen.js";
16
+ export { TENANT_FENCE_GATE_CALL_SQL, TENANT_FENCE_GATE_GRANTS_SQL, TENANT_FENCE_GATE_SQL, sessionFenceBootstrapSql, } from "./tenant-fence-gate.js";
17
+ export { withRls, generateTableGrants, authenticatedPredicate, SESSION_TENANT_IDS_CALL, SESSION_TENANT_IDS_SUBQUERY, withPlatformOpsTenantSql, withPlatformOpsGlobalSql, platformOpsTenantPredicateSql, platformOpsGlobalPredicateSql, platformOpsVerbClauseSql, sqlLiteral, PLATFORM_OPS_GRANTS_REPLICA_DEFAULT, referenceTableGrantsSql, findTenantColumn, ReferenceTableTenantColumnError, REFERENCE_TABLE_SKIP_RLS_MARKER, } from "./rls-policy-gen.js";
17
18
  export type { RlsVerb, WithRlsOpts, AuthPoolMode, PlatformOpsVerb, PlatformOpsPerVerbPermissions, WithPlatformOpsSqlOpts, ReferenceTableReadRole, ReferenceTableSqlOpts, } from "./rls-policy-gen.js";
18
19
  export { migrateGen, runMigrateGenCli, userTenantIdsRealSql, userTenantIdsStubSql, platformOpsPoliciesSql, referenceTablesSql, } from "./migrate-gen.js";
19
20
  export type { MigrateGenInput, MigrateGenResult, PlatformOpsTableSpec, ReferenceTableSpec, } from "./migrate-gen.js";
@@ -21,6 +22,8 @@ export { generateRlsPolicy, authSchemaHelpers } from "./rls-policy.js";
21
22
  export { InMemoryPgPool } from "./in-memory-pool.js";
22
23
  export type { TranscriptEntry } from "./in-memory-pool.js";
23
24
  export { DB_RLS_METRIC_VOCABULARY, _resetMetricsWarnLedgerForTests, } from "./metrics.js";
24
- export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, MissingTenantContext, OwnerContextOutsideMigrate, PoolUnavailable, TransactionRolledBack, } from "./types.js";
25
+ export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, CrossTenantSessionRefused, MissingTenantContext, OwnerContextOutsideMigrate, PoolUnavailable, TransactionRolledBack, } from "./types.js";
25
26
  export type { AuthContext, AutoDispatchOpts, DbRlsMode, GenerateRlsPolicyOpts, PgPool, PgTx, PlatformOpsContextOpts, PoolKind, SystemContextOpts, UserContextOpts, UserMembershipContextOpts, } from "./types.js";
27
+ export { classifyAuthPolicy, consultsMembershipUnion, isStubMembershipHelper, resolvesThroughSession, TenantFenceError, verifyTenantFence, } from "./tenant-fence.js";
28
+ export type { TenantFenceOffender, TenantFenceReason, VerifyTenantFenceOpts, } from "./tenant-fence.js";
26
29
  //# sourceMappingURL=index.d.ts.map