@nodii/db-rls 0.13.0 → 0.14.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.
- package/README.md +79 -1
- package/dist/claims-context.d.ts +100 -0
- package/dist/claims-context.d.ts.map +1 -0
- package/dist/claims-context.js +262 -0
- package/dist/claims-context.js.map +1 -0
- package/dist/context.d.ts +56 -15
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +56 -34
- package/dist/context.js.map +1 -1
- package/dist/drizzle-client.d.ts +21 -3
- package/dist/drizzle-client.d.ts.map +1 -1
- package/dist/drizzle-client.js +28 -7
- package/dist/drizzle-client.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/postgres-js-client.d.ts +26 -4
- package/dist/postgres-js-client.d.ts.map +1 -1
- package/dist/postgres-js-client.js +36 -8
- package/dist/postgres-js-client.js.map +1 -1
- package/dist/types.d.ts +161 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +126 -3
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
package/dist/context.js
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
// the canonical GUCs via `set_config(..., true)` (tx-scoped), yields, and
|
|
5
5
|
// commits / rollbacks per the underlying PgPool's withTransaction
|
|
6
6
|
// contract.
|
|
7
|
+
import { assertNoTenantArgument, assertSystemContextEscapeAllowed, requireVerifiedTenantClaims, } from "./claims-context.js";
|
|
7
8
|
import { requirePool } from "./init.js";
|
|
8
|
-
import { recordOwnerContextInvocation } from "./metrics.js";
|
|
9
|
+
import { recordCrossPoolNesting, recordOwnerContextInvocation, } from "./metrics.js";
|
|
9
10
|
import { assertMigrateAllowed, } from "./migrate-guard.js";
|
|
10
11
|
import { TENANT_FENCE_GATE_CALL_SQL } from "./tenant-fence-gate.js";
|
|
11
12
|
import { CrossTenantSessionRefused, MissingTenantContext, TransactionRolledBack, } from "./types.js";
|
|
@@ -69,20 +70,29 @@ async function assertFenceOnce(tx) {
|
|
|
69
70
|
* `set_config(..., true)` tx-scoped GUCs, yields the tx, commits/rolls
|
|
70
71
|
* back per the PgPool contract.
|
|
71
72
|
*
|
|
73
|
+
* BREAKING (unforgeable tenant binding): the tenant is NO LONGER an
|
|
74
|
+
* argument. It is read from the request's verified claims, bound once by
|
|
75
|
+
* auth middleware via `runWithVerifiedTenantClaims`. The previous shape,
|
|
76
|
+
* `withUserContext({ userId, tenantId }, fn)`, let a handler pass a
|
|
77
|
+
* request-derived tenant instead of the verified claim and silently defeat
|
|
78
|
+
* RLS — the database layer accepted `app.tenant_id` without ever proving
|
|
79
|
+
* the principal held it. The callback is now the only argument, so every
|
|
80
|
+
* call site is a compile error until it has been examined.
|
|
81
|
+
*
|
|
72
82
|
* On the FIRST call in a process it also runs the tenant-fence gate (see
|
|
73
83
|
* {@link assertFenceOnce}) and refuses to yield the tx if the fence is broken.
|
|
74
84
|
*
|
|
85
|
+
* Throws `NoVerifiedTenantClaims` if no claims are bound — never falls back
|
|
86
|
+
* to a default or to a passed value.
|
|
75
87
|
* Throws `DbRlsNotInitialized` if `initDbRls` hasn't run.
|
|
76
88
|
* Wraps any error thrown by `fn` in `TransactionRolledBack`.
|
|
77
89
|
*/
|
|
78
|
-
export async function withUserContext(
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (!opts?.tenantId)
|
|
85
|
-
throw new MissingTenantContext();
|
|
90
|
+
export async function withUserContext(fn) {
|
|
91
|
+
assertNoTenantArgument("withUserContext", fn);
|
|
92
|
+
// Blank principal / tenant were rejected at BIND time by
|
|
93
|
+
// runWithVerifiedTenantClaims, so a bound claim set is always usable
|
|
94
|
+
// here — no re-validation, and nothing to fall back to.
|
|
95
|
+
const opts = requireVerifiedTenantClaims("withUserContext");
|
|
86
96
|
const pool = requirePool("authenticated");
|
|
87
97
|
return pool.withTransaction(async (tx) => {
|
|
88
98
|
// Canonical GUC namespace is `app.*` (08-rls §2/§6): the generated
|
|
@@ -129,8 +139,11 @@ export async function withUserContext(opts, fn) {
|
|
|
129
139
|
* task, got HTTP 200, and released a 250,000 INR refund. Rewriting predicates
|
|
130
140
|
* while leaving this callable would have changed nothing for any caller of it.
|
|
131
141
|
*
|
|
132
|
-
* Migrate to `withUserContext(
|
|
133
|
-
*
|
|
142
|
+
* Migrate to `withUserContext(fn)` — the same pool, with the tenant the
|
|
143
|
+
* request's VERIFIED claims resolved to. That tenant is bound once by auth
|
|
144
|
+
* middleware (`runWithVerifiedTenantClaims`) and is no longer an argument at
|
|
145
|
+
* all, so the "pass the tenant the request resolved to" step this docblock
|
|
146
|
+
* used to ask for cannot be got wrong. If a caller genuinely needs to
|
|
134
147
|
* know which tenants a user belongs to (a tenant switcher, a login
|
|
135
148
|
* tenant-picker), query `auth.user_tenant_ids` directly from a services-pool
|
|
136
149
|
* context; that function is deliberately left intact and still answers exactly
|
|
@@ -148,8 +161,28 @@ export async function withUserMembershipContext(_opts, _fn) {
|
|
|
148
161
|
* withSystemContext — opens a tx on the `services` (nodii_services) pool,
|
|
149
162
|
* sets `app.tenant_id` via tx-scoped `set_config`, yields the tx, commits
|
|
150
163
|
* / rolls back per the PgPool contract.
|
|
164
|
+
*
|
|
165
|
+
* THE STEP-1 FENCE (panel finding). The services-pool predicate is the bare
|
|
166
|
+
* `tenant_id = auth.get_tenant_id()` — no membership proof — so an
|
|
167
|
+
* authenticated request that falls through to this helper can aim the
|
|
168
|
+
* session at ANY tenant. That fall-through is the un-fenced seam where the
|
|
169
|
+
* ₹250,000 cross-tenant refund reproduced. Therefore:
|
|
170
|
+
*
|
|
171
|
+
* - **Claims UNBOUND** (boot, cron, workers, S2S, webhooks): unchanged.
|
|
172
|
+
* This is the compat property that keeps the fence from breaking every
|
|
173
|
+
* worker in the fleet.
|
|
174
|
+
* - **Claims BOUND** (`hasVerifiedTenantClaims()` is true): REFUSED with
|
|
175
|
+
* {@link SystemContextUnderClaimsRefused} — a throw, before any pool is
|
|
176
|
+
* acquired — unless the caller passes an explicit non-blank
|
|
177
|
+
* `{ reason }`. A sanctioned escape is emitted to telemetry as
|
|
178
|
+
* `db_rls.cross_pool_nesting_total{outer=authenticated,inner=services,reason}`
|
|
179
|
+
* so every crossing is named, counted, and audit-greppable.
|
|
151
180
|
*/
|
|
152
181
|
export async function withSystemContext(opts, fn) {
|
|
182
|
+
const sanctioned = assertSystemContextEscapeAllowed("withSystemContext", opts);
|
|
183
|
+
if (sanctioned) {
|
|
184
|
+
recordCrossPoolNesting("authenticated", "services", sanctioned.reason);
|
|
185
|
+
}
|
|
153
186
|
const pool = requirePool("services");
|
|
154
187
|
return pool.withTransaction(async (tx) => {
|
|
155
188
|
await tx.setConfig("app.tenant_id", opts.tenantId);
|
|
@@ -274,30 +307,19 @@ export async function withPlatformOps(opts, fn) {
|
|
|
274
307
|
}
|
|
275
308
|
return withPlatformOpsContext(opts, fn);
|
|
276
309
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
* - neither → throw `MissingTenantContext`.
|
|
284
|
-
*
|
|
285
|
-
* This mirrors `withRequestContext` from the spec § 5.4 with one
|
|
286
|
-
* simplification: the auth context is passed explicitly rather than
|
|
287
|
-
* being read from ALS. Real auth-sdk integration lands in v0.1.x —
|
|
288
|
-
* `// TODO db-rls-v0.1.x: ALS-bound auto-dispatch`.
|
|
289
|
-
*/
|
|
290
|
-
export async function autoDispatch(opts, fn) {
|
|
291
|
-
if (opts.authContext) {
|
|
292
|
-
return withUserContext({
|
|
293
|
-
userId: opts.authContext.userId,
|
|
294
|
-
tenantId: opts.authContext.tenantId,
|
|
295
|
-
sourceIp: opts.authContext.sourceIp,
|
|
296
|
-
}, fn);
|
|
310
|
+
export async function autoDispatch(optsOrFn, maybeFn) {
|
|
311
|
+
if (typeof optsOrFn === "function") {
|
|
312
|
+
return withUserContext(optsOrFn);
|
|
313
|
+
}
|
|
314
|
+
if (typeof maybeFn !== "function") {
|
|
315
|
+
throw new TypeError("autoDispatch: when opts are passed, the second argument must be the callback.");
|
|
297
316
|
}
|
|
298
|
-
|
|
299
|
-
|
|
317
|
+
// Explicit, non-blank, no fallback: `systemTenantId` is required by the
|
|
318
|
+
// type, and a blank one is refused rather than defaulted.
|
|
319
|
+
if (typeof optsOrFn?.systemTenantId !== "string" ||
|
|
320
|
+
optsOrFn.systemTenantId.trim() === "") {
|
|
321
|
+
throw new MissingTenantContext("autoDispatch({ systemTenantId }, fn) needs a non-blank systemTenantId for the services-pool leg. For the authenticated leg call autoDispatch(fn) with no opts — the tenant comes from the request's verified claims.");
|
|
300
322
|
}
|
|
301
|
-
|
|
323
|
+
return withSystemContext({ tenantId: optsOrFn.systemTenantId, reason: optsOrFn.reason }, maybeFn);
|
|
302
324
|
}
|
|
303
325
|
//# sourceMappingURL=context.js.map
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/drizzle-client.d.ts
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { type NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
2
2
|
import { type OwnerContextOpts } from "./migrate-guard.js";
|
|
3
|
-
import type { SystemContextOpts,
|
|
3
|
+
import type { SystemContextOpts, UserMembershipContextOpts } from "./types.js";
|
|
4
4
|
type DrizzleClient<TSchema extends Record<string, unknown> = Record<string, unknown>> = NodePgDatabase<TSchema>;
|
|
5
5
|
/**
|
|
6
6
|
* withUserContext (Drizzle variant) — opens a tx on the `authenticated`
|
|
7
7
|
* pool, sets `app.user_id` + `app.tenant_id` via `auth.init(...)` (the
|
|
8
8
|
* canonical helper from § 5.7), yields a Drizzle client bound to the tx,
|
|
9
9
|
* commits/rolls back.
|
|
10
|
+
*
|
|
11
|
+
* BREAKING (unforgeable tenant binding): the tenant is NO LONGER an
|
|
12
|
+
* argument — it is read from the request's verified claims, bound once by
|
|
13
|
+
* auth middleware via `runWithVerifiedTenantClaims`. See
|
|
14
|
+
* {@link withUserContext} in `src/context.ts` for the full rationale.
|
|
15
|
+
*
|
|
16
|
+
* Throws `NoVerifiedTenantClaims` if no claims are bound.
|
|
10
17
|
*/
|
|
11
|
-
export declare function withUserContextDb<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(
|
|
18
|
+
export declare function withUserContextDb<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(fn: (db: DrizzleClient<TSchema>) => Promise<T>): Promise<T>;
|
|
12
19
|
/**
|
|
13
20
|
* @deprecated REMOVED — always throws {@link CrossTenantSessionRefused}.
|
|
14
21
|
*
|
|
@@ -19,7 +26,9 @@ export declare function withUserContextDb<T, TSchema extends Record<string, unkn
|
|
|
19
26
|
* a legitimate tenant-A session transitioned a tenant-B approval task, got
|
|
20
27
|
* HTTP 200, and released a 250,000 INR refund.
|
|
21
28
|
*
|
|
22
|
-
* Migrate to `withUserContextDb(
|
|
29
|
+
* Migrate to `withUserContextDb(fn)` — the same pool, with the tenant the
|
|
30
|
+
* request's VERIFIED claims resolved to (bound by auth middleware via
|
|
31
|
+
* `runWithVerifiedTenantClaims`; it is no longer an argument).
|
|
23
32
|
* To LIST a user's tenants (switcher / login picker), query
|
|
24
33
|
* `auth.user_tenant_ids` from a services-pool context — that function is
|
|
25
34
|
* intact; what is gone is opening a DATA session that spans them.
|
|
@@ -31,6 +40,15 @@ export declare function withUserMembershipContextDb<T, TSchema extends Record<st
|
|
|
31
40
|
/**
|
|
32
41
|
* withSystemContext (Drizzle variant) — opens a tx on the `services` pool
|
|
33
42
|
* with `app.tenant_id` GUC bound; yields a Drizzle client.
|
|
43
|
+
*
|
|
44
|
+
* Carries the STEP-1 FENCE: with verified claims bound
|
|
45
|
+
* (`hasVerifiedTenantClaims()` true) this throws
|
|
46
|
+
* `SystemContextUnderClaimsRefused` before touching a pool unless the
|
|
47
|
+
* caller passes an explicit non-blank `{ reason }` — the services-pool
|
|
48
|
+
* predicate is the bare `tenant_id = auth.get_tenant_id()` with no
|
|
49
|
+
* membership proof, the seam where the ₹250,000 cross-tenant refund
|
|
50
|
+
* reproduced. Unbound contexts (workers, cron, boot) are unchanged.
|
|
51
|
+
* See {@link withSystemContext} in `src/context.ts`.
|
|
34
52
|
*/
|
|
35
53
|
export declare function withSystemContextDb<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(opts: SystemContextOpts, fn: (db: DrizzleClient<TSchema>) => Promise<T>): Promise<T>;
|
|
36
54
|
/**
|
|
@@ -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;
|
|
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;AAczE,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAW/E,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;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,CAAC,EACD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAoB5D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;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;;;;;;;;;;;;GAYG;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,CAiBZ;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"}
|
package/dist/drizzle-client.js
CHANGED
|
@@ -17,8 +17,9 @@
|
|
|
17
17
|
// original `withUserContext` (in src/context.ts) still works for
|
|
18
18
|
// services using the raw `PgTx` surface.
|
|
19
19
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
20
|
+
import { assertNoTenantArgument, assertSystemContextEscapeAllowed, requireVerifiedTenantClaims, } from "./claims-context.js";
|
|
20
21
|
import { requirePool } from "./init.js";
|
|
21
|
-
import { recordOwnerContextInvocation, withTxSpan } from "./metrics.js";
|
|
22
|
+
import { recordCrossPoolNesting, recordOwnerContextInvocation, withTxSpan, } from "./metrics.js";
|
|
22
23
|
import { assertMigrateAllowed, } from "./migrate-guard.js";
|
|
23
24
|
import { PgClientPool } from "./pg-pool-adapter.js";
|
|
24
25
|
import { CrossTenantSessionRefused, MissingTenantContext, TransactionRolledBack, } from "./types.js";
|
|
@@ -76,12 +77,17 @@ function requireRealPool(kind) {
|
|
|
76
77
|
* pool, sets `app.user_id` + `app.tenant_id` via `auth.init(...)` (the
|
|
77
78
|
* canonical helper from § 5.7), yields a Drizzle client bound to the tx,
|
|
78
79
|
* commits/rolls back.
|
|
80
|
+
*
|
|
81
|
+
* BREAKING (unforgeable tenant binding): the tenant is NO LONGER an
|
|
82
|
+
* argument — it is read from the request's verified claims, bound once by
|
|
83
|
+
* auth middleware via `runWithVerifiedTenantClaims`. See
|
|
84
|
+
* {@link withUserContext} in `src/context.ts` for the full rationale.
|
|
85
|
+
*
|
|
86
|
+
* Throws `NoVerifiedTenantClaims` if no claims are bound.
|
|
79
87
|
*/
|
|
80
|
-
export async function withUserContextDb(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (!opts.tenantId)
|
|
84
|
-
throw new MissingTenantContext();
|
|
88
|
+
export async function withUserContextDb(fn) {
|
|
89
|
+
assertNoTenantArgument("withUserContextDb", fn);
|
|
90
|
+
const opts = requireVerifiedTenantClaims("withUserContextDb");
|
|
85
91
|
const pool = requireRealPool("authenticated");
|
|
86
92
|
return withRealTx(pool, async (client) => {
|
|
87
93
|
// Set both GUCs via the canonical auth.init helper.
|
|
@@ -106,7 +112,9 @@ export async function withUserContextDb(opts, fn) {
|
|
|
106
112
|
* a legitimate tenant-A session transitioned a tenant-B approval task, got
|
|
107
113
|
* HTTP 200, and released a 250,000 INR refund.
|
|
108
114
|
*
|
|
109
|
-
* Migrate to `withUserContextDb(
|
|
115
|
+
* Migrate to `withUserContextDb(fn)` — the same pool, with the tenant the
|
|
116
|
+
* request's VERIFIED claims resolved to (bound by auth middleware via
|
|
117
|
+
* `runWithVerifiedTenantClaims`; it is no longer an argument).
|
|
110
118
|
* To LIST a user's tenants (switcher / login picker), query
|
|
111
119
|
* `auth.user_tenant_ids` from a services-pool context — that function is
|
|
112
120
|
* intact; what is gone is opening a DATA session that spans them.
|
|
@@ -120,10 +128,23 @@ export async function withUserMembershipContextDb(_opts, _fn) {
|
|
|
120
128
|
/**
|
|
121
129
|
* withSystemContext (Drizzle variant) — opens a tx on the `services` pool
|
|
122
130
|
* with `app.tenant_id` GUC bound; yields a Drizzle client.
|
|
131
|
+
*
|
|
132
|
+
* Carries the STEP-1 FENCE: with verified claims bound
|
|
133
|
+
* (`hasVerifiedTenantClaims()` true) this throws
|
|
134
|
+
* `SystemContextUnderClaimsRefused` before touching a pool unless the
|
|
135
|
+
* caller passes an explicit non-blank `{ reason }` — the services-pool
|
|
136
|
+
* predicate is the bare `tenant_id = auth.get_tenant_id()` with no
|
|
137
|
+
* membership proof, the seam where the ₹250,000 cross-tenant refund
|
|
138
|
+
* reproduced. Unbound contexts (workers, cron, boot) are unchanged.
|
|
139
|
+
* See {@link withSystemContext} in `src/context.ts`.
|
|
123
140
|
*/
|
|
124
141
|
export async function withSystemContextDb(opts, fn) {
|
|
125
142
|
if (!opts.tenantId)
|
|
126
143
|
throw new MissingTenantContext();
|
|
144
|
+
const sanctioned = assertSystemContextEscapeAllowed("withSystemContextDb", opts);
|
|
145
|
+
if (sanctioned) {
|
|
146
|
+
recordCrossPoolNesting("authenticated", "services", sanctioned.reason);
|
|
147
|
+
}
|
|
127
148
|
const pool = requireRealPool("services");
|
|
128
149
|
return withRealTx(pool, async (client) => {
|
|
129
150
|
await client.query("SELECT auth.init_tenant($1::uuid)", [opts.tenantId]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drizzle-client.js","sourceRoot":"","sources":["../src/drizzle-client.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,yEAAyE;AACzE,wEAAwE;AACxE,iEAAiE;AACjE,uEAAuE;AACvE,2DAA2D;AAC3D,EAAE;AACF,iBAAiB;AACjB,0EAA0E;AAC1E,sEAAsE;AACtE,0BAA0B;AAC1B,sEAAsE;AACtE,wCAAwC;AACxC,8DAA8D;AAC9D,sEAAsE;AACtE,qEAAqE;AACrE,6CAA6C;AAE7C,OAAO,EAAE,OAAO,EAAuB,MAAM,2BAA2B,CAAC;AAGzE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,
|
|
1
|
+
{"version":3,"file":"drizzle-client.js","sourceRoot":"","sources":["../src/drizzle-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { configureDbRls, configureDbRls2Pool, configureDbRls4Pool, PoolCredentia
|
|
|
6
6
|
export type { ConfigureDbRlsOpts, ConfigureDbRlsPools, } from "./configure.js";
|
|
7
7
|
export { PgClientPool } from "./pg-pool-adapter.js";
|
|
8
8
|
export type { PgPoolAdapterOpts } from "./pg-pool-adapter.js";
|
|
9
|
+
export { assertNoTenantArgument, assertSystemContextEscapeAllowed, getVerifiedTenantClaimsOrNull, hasVerifiedTenantClaims, requireVerifiedTenantClaims, runWithVerifiedTenantClaims, } from "./claims-context.js";
|
|
9
10
|
export { withUserContext, withUserMembershipContext, withSystemContext, withOwnerContext, withPlatformOpsContext, withPlatformOps, _resetWithPlatformOpsDeprecationWarnedForTests, autoDispatch, } from "./context.js";
|
|
10
11
|
export type { OwnerContextOpts } from "./migrate-guard.js";
|
|
11
12
|
export { assertMigrateAllowed } from "./migrate-guard.js";
|
|
@@ -22,8 +23,8 @@ export { generateRlsPolicy, authSchemaHelpers } from "./rls-policy.js";
|
|
|
22
23
|
export { InMemoryPgPool } from "./in-memory-pool.js";
|
|
23
24
|
export type { TranscriptEntry } from "./in-memory-pool.js";
|
|
24
25
|
export { DB_RLS_METRIC_VOCABULARY, _resetMetricsWarnLedgerForTests, } from "./metrics.js";
|
|
25
|
-
export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, CrossTenantSessionRefused, MissingTenantContext, OwnerContextOutsideMigrate, PoolUnavailable, TransactionRolledBack, } from "./types.js";
|
|
26
|
-
export type {
|
|
26
|
+
export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, CrossTenantSessionRefused, InvalidVerifiedTenantClaims, MissingTenantContext, NoVerifiedTenantClaims, OwnerContextOutsideMigrate, PoolUnavailable, SystemContextUnderClaimsRefused, TenantArgumentRefused, TransactionRolledBack, VerifiedTenantClaimsAlreadyBound, } from "./types.js";
|
|
27
|
+
export type { AutoDispatchOpts, DbRlsMode, GenerateRlsPolicyOpts, PgPool, PgTx, PlatformOpsContextOpts, PoolKind, SystemContextOpts, UserMembershipContextOpts, VerifiedTenantClaims, } from "./types.js";
|
|
27
28
|
export { classifyAuthPolicy, consultsMembershipUnion, isStubMembershipHelper, resolvesThroughSession, TenantFenceError, verifyTenantFence, } from "./tenant-fence.js";
|
|
28
29
|
export type { TenantFenceOffender, TenantFenceReason, VerifyTenantFenceOpts, } from "./tenant-fence.js";
|
|
29
30
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmCA,eAAO,MAAM,QAAQ,WAAW,CAAC;AAejC,eAAO,MAAM,OAAO,EAAE,MAAoB,CAAC;AAE3C,OAAO,EACL,SAAS,EACT,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAEhE,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,14 @@ export const VERSION = pkg.version;
|
|
|
49
49
|
export { initDbRls, requireDbRls, getDbRlsOrNull, requirePool, _resetForTests, } from "./init.js";
|
|
50
50
|
export { configureDbRls, configureDbRls2Pool, configureDbRls4Pool, PoolCredentialMismatch, _resetConfigureForTests, } from "./configure.js";
|
|
51
51
|
export { PgClientPool } from "./pg-pool-adapter.js";
|
|
52
|
+
// Unforgeable tenant binding — the request-scoped VERIFIED-claims context
|
|
53
|
+
// the authenticated-pool helpers derive their tenant from. `runWith…` is
|
|
54
|
+
// the ONLY way to establish it, and auth middleware is the only thing that
|
|
55
|
+
// should call it. See the migration note in README.md § "Unforgeable tenant
|
|
56
|
+
// binding". `assertSystemContextEscapeAllowed` is the step-1 fence the
|
|
57
|
+
// system-pool helpers run — exported so a bespoke wrapper can carry the
|
|
58
|
+
// same fence rather than silently bypassing it.
|
|
59
|
+
export { assertNoTenantArgument, assertSystemContextEscapeAllowed, getVerifiedTenantClaimsOrNull, hasVerifiedTenantClaims, requireVerifiedTenantClaims, runWithVerifiedTenantClaims, } from "./claims-context.js";
|
|
52
60
|
export { withUserContext, withUserMembershipContext, withSystemContext, withOwnerContext, withPlatformOpsContext,
|
|
53
61
|
// Deprecated re-export alias of `withPlatformOpsContext`, kept for one
|
|
54
62
|
// minor (v0.4.1) for v0.4.0 adopters; removed in v0.5.0. Canonical name
|
|
@@ -96,6 +104,6 @@ export { migrateGen, runMigrateGenCli, userTenantIdsRealSql, userTenantIdsStubSq
|
|
|
96
104
|
export { generateRlsPolicy, authSchemaHelpers } from "./rls-policy.js";
|
|
97
105
|
export { InMemoryPgPool } from "./in-memory-pool.js";
|
|
98
106
|
export { DB_RLS_METRIC_VOCABULARY, _resetMetricsWarnLedgerForTests, } from "./metrics.js";
|
|
99
|
-
export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, CrossTenantSessionRefused, MissingTenantContext, OwnerContextOutsideMigrate, PoolUnavailable, TransactionRolledBack, } from "./types.js";
|
|
107
|
+
export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, CrossTenantSessionRefused, InvalidVerifiedTenantClaims, MissingTenantContext, NoVerifiedTenantClaims, OwnerContextOutsideMigrate, PoolUnavailable, SystemContextUnderClaimsRefused, TenantArgumentRefused, TransactionRolledBack, VerifiedTenantClaimsAlreadyBound, } from "./types.js";
|
|
100
108
|
export { classifyAuthPolicy, consultsMembershipUnion, isStubMembershipHelper, resolvesThroughSession, TenantFenceError, verifyTenantFence, } from "./tenant-fence.js";
|
|
101
109
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
2
2
|
import type { Sql } from "postgres";
|
|
3
3
|
import { type OwnerContextOpts } from "./migrate-guard.js";
|
|
4
|
-
import { type PgPool, type PgTx, type PlatformOpsContextOpts, type PoolKind, type SystemContextOpts, type
|
|
4
|
+
import { type PgPool, type PgTx, type PlatformOpsContextOpts, type PoolKind, type SystemContextOpts, type UserMembershipContextOpts } from "./types.js";
|
|
5
5
|
type PostgresJsDrizzleClient<TSchema extends Record<string, unknown> = Record<string, unknown>> = PostgresJsDatabase<TSchema>;
|
|
6
6
|
/**
|
|
7
7
|
* PgPool adapter wrapping a postgres-js `Sql` instance. Caller owns the
|
|
@@ -64,8 +64,17 @@ export declare class PgPostgresJsPool implements PgPool {
|
|
|
64
64
|
* postgres-js Drizzle variant of `withUserContext`. Opens a tx on the
|
|
65
65
|
* `authenticated` pool, sets `app.user_id` + `app.tenant_id` via the
|
|
66
66
|
* canonical `auth.init(...)` helper, yields a Drizzle client.
|
|
67
|
+
*
|
|
68
|
+
* BREAKING (unforgeable tenant binding): the tenant is NO LONGER an
|
|
69
|
+
* argument — it is read from the request's verified claims, bound once by
|
|
70
|
+
* auth middleware via `runWithVerifiedTenantClaims`. See
|
|
71
|
+
* {@link withUserContext} in `src/context.ts` for the full rationale.
|
|
72
|
+
* This is the fleet-default driver, so this is the variant most of the
|
|
73
|
+
* 271 call sites go through.
|
|
74
|
+
*
|
|
75
|
+
* Throws `NoVerifiedTenantClaims` if no claims are bound.
|
|
67
76
|
*/
|
|
68
|
-
export declare function withUserContextDbPostgresJs<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(
|
|
77
|
+
export declare function withUserContextDbPostgresJs<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(fn: (db: PostgresJsDrizzleClient<TSchema>) => Promise<T>): Promise<T>;
|
|
69
78
|
/**
|
|
70
79
|
* @deprecated REMOVED — always throws {@link CrossTenantSessionRefused}.
|
|
71
80
|
*
|
|
@@ -76,7 +85,9 @@ export declare function withUserContextDbPostgresJs<T, TSchema extends Record<st
|
|
|
76
85
|
* a legitimate tenant-A session transitioned a tenant-B approval task, got
|
|
77
86
|
* HTTP 200, and released a 250,000 INR refund.
|
|
78
87
|
*
|
|
79
|
-
* Migrate to `withUserContextDbPostgresJs(
|
|
88
|
+
* Migrate to `withUserContextDbPostgresJs(fn)` — the same pool, with the
|
|
89
|
+
* tenant the request's VERIFIED claims resolved to (bound by auth middleware
|
|
90
|
+
* via `runWithVerifiedTenantClaims`; it is no longer an argument).
|
|
80
91
|
* To LIST a user's tenants (switcher / login picker), query
|
|
81
92
|
* `auth.user_tenant_ids` from a services-pool context — that function is
|
|
82
93
|
* intact; what is gone is opening a DATA session that spans them.
|
|
@@ -88,6 +99,15 @@ export declare function withUserMembershipContextDbPostgresJs<T, TSchema extends
|
|
|
88
99
|
/**
|
|
89
100
|
* postgres-js Drizzle variant of `withSystemContext`. Opens a tx on the
|
|
90
101
|
* `services` pool with `app.tenant_id` GUC bound; yields a Drizzle client.
|
|
102
|
+
*
|
|
103
|
+
* Carries the STEP-1 FENCE: with verified claims bound
|
|
104
|
+
* (`hasVerifiedTenantClaims()` true) this throws
|
|
105
|
+
* `SystemContextUnderClaimsRefused` before touching a pool unless the
|
|
106
|
+
* caller passes an explicit non-blank `{ reason }` — the services-pool
|
|
107
|
+
* predicate is the bare `tenant_id = auth.get_tenant_id()` with no
|
|
108
|
+
* membership proof, the seam where the ₹250,000 cross-tenant refund
|
|
109
|
+
* reproduced. Unbound contexts (workers, cron, boot) are unchanged.
|
|
110
|
+
* See {@link withSystemContext} in `src/context.ts`.
|
|
91
111
|
*/
|
|
92
112
|
export declare function withSystemContextDbPostgresJs<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(opts: SystemContextOpts, fn: (db: PostgresJsDrizzleClient<TSchema>) => Promise<T>): Promise<T>;
|
|
93
113
|
/**
|
|
@@ -121,7 +141,9 @@ export declare function withOwnerContextDbPostgresJs<T, TSchema extends Record<s
|
|
|
121
141
|
export type { PostgresJsDrizzleClient };
|
|
122
142
|
export { _resetForTests, getDbRlsOrNull, type InitDbRlsConfig, initDbRls, requireDbRls, requirePool, type ResolvedDbRls, } from "./init.js";
|
|
123
143
|
export { assertMigrateAllowed } from "./migrate-guard.js";
|
|
144
|
+
export { assertNoTenantArgument, assertSystemContextEscapeAllowed, getVerifiedTenantClaimsOrNull, hasVerifiedTenantClaims, requireVerifiedTenantClaims, runWithVerifiedTenantClaims, } from "./claims-context.js";
|
|
124
145
|
export { DB_RLS_METRIC_VOCABULARY } from "./metrics.js";
|
|
125
146
|
export { generateTableGrants, withRls } from "./rls-policy-gen.js";
|
|
126
|
-
export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, MissingTenantContext, OwnerContextOutsideMigrate, PoolUnavailable, TransactionRolledBack, } from "./types.js";
|
|
147
|
+
export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, InvalidVerifiedTenantClaims, MissingTenantContext, NoVerifiedTenantClaims, OwnerContextOutsideMigrate, PoolUnavailable, SystemContextUnderClaimsRefused, TenantArgumentRefused, TransactionRolledBack, VerifiedTenantClaimsAlreadyBound, } from "./types.js";
|
|
148
|
+
export type { VerifiedTenantClaims } from "./types.js";
|
|
127
149
|
//# sourceMappingURL=postgres-js-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-js-client.d.ts","sourceRoot":"","sources":["../src/postgres-js-client.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAW,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,KAAK,EAAE,GAAG,EAAkB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"postgres-js-client.d.ts","sourceRoot":"","sources":["../src/postgres-js-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,8 +24,9 @@
|
|
|
24
24
|
// internally inside `sql.begin(...)`.
|
|
25
25
|
import { sql as drizzleSql } from "drizzle-orm";
|
|
26
26
|
import { drizzle } from "drizzle-orm/postgres-js";
|
|
27
|
+
import { assertNoTenantArgument, assertSystemContextEscapeAllowed, requireVerifiedTenantClaims, } from "./claims-context.js";
|
|
27
28
|
import { requirePool } from "./init.js";
|
|
28
|
-
import { emitSlowAcquireSpan, recordAcquisition, recordAcquisitionDuration, recordGucSetFailure, recordOwnerContextInvocation, recordTxDuration, withTxSpan, } from "./metrics.js";
|
|
29
|
+
import { emitSlowAcquireSpan, recordAcquisition, recordAcquisitionDuration, recordCrossPoolNesting, recordGucSetFailure, recordOwnerContextInvocation, recordTxDuration, withTxSpan, } from "./metrics.js";
|
|
29
30
|
import { assertMigrateAllowed, } from "./migrate-guard.js";
|
|
30
31
|
import { MissingTenantContext, TransactionRolledBack, CrossTenantSessionRefused, } from "./types.js";
|
|
31
32
|
/**
|
|
@@ -248,12 +249,19 @@ async function withPostgresJsTx(pool, setup, fn) {
|
|
|
248
249
|
* postgres-js Drizzle variant of `withUserContext`. Opens a tx on the
|
|
249
250
|
* `authenticated` pool, sets `app.user_id` + `app.tenant_id` via the
|
|
250
251
|
* canonical `auth.init(...)` helper, yields a Drizzle client.
|
|
252
|
+
*
|
|
253
|
+
* BREAKING (unforgeable tenant binding): the tenant is NO LONGER an
|
|
254
|
+
* argument — it is read from the request's verified claims, bound once by
|
|
255
|
+
* auth middleware via `runWithVerifiedTenantClaims`. See
|
|
256
|
+
* {@link withUserContext} in `src/context.ts` for the full rationale.
|
|
257
|
+
* This is the fleet-default driver, so this is the variant most of the
|
|
258
|
+
* 271 call sites go through.
|
|
259
|
+
*
|
|
260
|
+
* Throws `NoVerifiedTenantClaims` if no claims are bound.
|
|
251
261
|
*/
|
|
252
|
-
export async function withUserContextDbPostgresJs(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if (!opts.tenantId)
|
|
256
|
-
throw new MissingTenantContext();
|
|
262
|
+
export async function withUserContextDbPostgresJs(fn) {
|
|
263
|
+
assertNoTenantArgument("withUserContextDbPostgresJs", fn);
|
|
264
|
+
const opts = requireVerifiedTenantClaims("withUserContextDbPostgresJs");
|
|
257
265
|
const pool = requirePostgresJsPool("authenticated");
|
|
258
266
|
return withPostgresJsTx(pool, async (db) => {
|
|
259
267
|
await db.execute(drizzleSql `SELECT auth.init(${opts.userId}::uuid, ${opts.tenantId}::uuid)`);
|
|
@@ -272,7 +280,9 @@ export async function withUserContextDbPostgresJs(opts, fn) {
|
|
|
272
280
|
* a legitimate tenant-A session transitioned a tenant-B approval task, got
|
|
273
281
|
* HTTP 200, and released a 250,000 INR refund.
|
|
274
282
|
*
|
|
275
|
-
* Migrate to `withUserContextDbPostgresJs(
|
|
283
|
+
* Migrate to `withUserContextDbPostgresJs(fn)` — the same pool, with the
|
|
284
|
+
* tenant the request's VERIFIED claims resolved to (bound by auth middleware
|
|
285
|
+
* via `runWithVerifiedTenantClaims`; it is no longer an argument).
|
|
276
286
|
* To LIST a user's tenants (switcher / login picker), query
|
|
277
287
|
* `auth.user_tenant_ids` from a services-pool context — that function is
|
|
278
288
|
* intact; what is gone is opening a DATA session that spans them.
|
|
@@ -286,10 +296,23 @@ export async function withUserMembershipContextDbPostgresJs(_opts, _fn) {
|
|
|
286
296
|
/**
|
|
287
297
|
* postgres-js Drizzle variant of `withSystemContext`. Opens a tx on the
|
|
288
298
|
* `services` pool with `app.tenant_id` GUC bound; yields a Drizzle client.
|
|
299
|
+
*
|
|
300
|
+
* Carries the STEP-1 FENCE: with verified claims bound
|
|
301
|
+
* (`hasVerifiedTenantClaims()` true) this throws
|
|
302
|
+
* `SystemContextUnderClaimsRefused` before touching a pool unless the
|
|
303
|
+
* caller passes an explicit non-blank `{ reason }` — the services-pool
|
|
304
|
+
* predicate is the bare `tenant_id = auth.get_tenant_id()` with no
|
|
305
|
+
* membership proof, the seam where the ₹250,000 cross-tenant refund
|
|
306
|
+
* reproduced. Unbound contexts (workers, cron, boot) are unchanged.
|
|
307
|
+
* See {@link withSystemContext} in `src/context.ts`.
|
|
289
308
|
*/
|
|
290
309
|
export async function withSystemContextDbPostgresJs(opts, fn) {
|
|
291
310
|
if (!opts.tenantId)
|
|
292
311
|
throw new MissingTenantContext();
|
|
312
|
+
const sanctioned = assertSystemContextEscapeAllowed("withSystemContextDbPostgresJs", opts);
|
|
313
|
+
if (sanctioned) {
|
|
314
|
+
recordCrossPoolNesting("authenticated", "services", sanctioned.reason);
|
|
315
|
+
}
|
|
293
316
|
const pool = requirePostgresJsPool("services");
|
|
294
317
|
return withPostgresJsTx(pool, async (db) => {
|
|
295
318
|
await db.execute(drizzleSql `SELECT auth.init_tenant(${opts.tenantId}::uuid)`);
|
|
@@ -365,6 +388,11 @@ function normalizeOwnerArgs(fnOrOpts, maybeFn) {
|
|
|
365
388
|
// ergonomics gap 01371c61.
|
|
366
389
|
export { _resetForTests, getDbRlsOrNull, initDbRls, requireDbRls, requirePool, } from "./init.js";
|
|
367
390
|
export { assertMigrateAllowed } from "./migrate-guard.js";
|
|
391
|
+
// Unforgeable tenant binding. `claims-context.ts` imports only
|
|
392
|
+
// `node:async_hooks` + `./types.js`, so postgres-js-only services (the
|
|
393
|
+
// fleet default — no `pg` installed) can bind verified claims in their auth
|
|
394
|
+
// middleware without reaching for the pg-coupled entry points.
|
|
395
|
+
export { assertNoTenantArgument, assertSystemContextEscapeAllowed, getVerifiedTenantClaimsOrNull, hasVerifiedTenantClaims, requireVerifiedTenantClaims, runWithVerifiedTenantClaims, } from "./claims-context.js";
|
|
368
396
|
// DB_RLS_METRIC_VOCABULARY is a pure const (its module imports only
|
|
369
397
|
// @nodii/telemetry + a type), so pg-free services can merge it into
|
|
370
398
|
// initTelemetry({ vocabularyRegistry }) without pulling in `pg`. Without this
|
|
@@ -373,5 +401,5 @@ export { assertMigrateAllowed } from "./migrate-guard.js";
|
|
|
373
401
|
// db-rls's own metrics swallowed as 'not_in_vocabulary' (request 95a860a1).
|
|
374
402
|
export { DB_RLS_METRIC_VOCABULARY } from "./metrics.js";
|
|
375
403
|
export { generateTableGrants, withRls } from "./rls-policy-gen.js";
|
|
376
|
-
export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, MissingTenantContext, OwnerContextOutsideMigrate, PoolUnavailable, TransactionRolledBack, } from "./types.js";
|
|
404
|
+
export { DbRlsConfigError, DbRlsError, DbRlsNotInitialized, InvalidVerifiedTenantClaims, MissingTenantContext, NoVerifiedTenantClaims, OwnerContextOutsideMigrate, PoolUnavailable, SystemContextUnderClaimsRefused, TenantArgumentRefused, TransactionRolledBack, VerifiedTenantClaimsAlreadyBound, } from "./types.js";
|
|
377
405
|
//# sourceMappingURL=postgres-js-client.js.map
|