@nodii/db-rls 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/configure.d.ts +42 -8
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +87 -16
- package/dist/configure.js.map +1 -1
- package/dist/context.d.ts +36 -7
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +67 -6
- package/dist/context.js.map +1 -1
- package/dist/drizzle-client.d.ts +9 -2
- package/dist/drizzle-client.d.ts.map +1 -1
- package/dist/drizzle-client.js +28 -2
- package/dist/drizzle-client.js.map +1 -1
- package/dist/drizzle-grants.d.ts +203 -0
- package/dist/drizzle-grants.d.ts.map +1 -0
- package/dist/drizzle-grants.js +68 -0
- package/dist/drizzle-grants.js.map +1 -0
- package/dist/drizzle-policies.d.ts +90 -0
- package/dist/drizzle-policies.d.ts.map +1 -0
- package/dist/drizzle-policies.js +223 -0
- package/dist/drizzle-policies.js.map +1 -0
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -10
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +23 -5
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +38 -4
- package/dist/init.js.map +1 -1
- package/dist/metrics.d.ts +28 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +263 -0
- package/dist/metrics.js.map +1 -0
- package/dist/migrate-guard.d.ts +14 -0
- package/dist/migrate-guard.d.ts.map +1 -0
- package/dist/migrate-guard.js +33 -0
- package/dist/migrate-guard.js.map +1 -0
- package/dist/pg-pool-adapter.d.ts.map +1 -1
- package/dist/pg-pool-adapter.js +78 -25
- package/dist/pg-pool-adapter.js.map +1 -1
- package/dist/postgres-js-client.d.ts +60 -0
- package/dist/postgres-js-client.d.ts.map +1 -0
- package/dist/postgres-js-client.js +223 -0
- package/dist/postgres-js-client.js.map +1 -0
- package/dist/types.d.ts +68 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +31 -1
- package/dist/types.js.map +1 -1
- package/package.json +24 -5
package/dist/configure.d.ts
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
import type { Pool } from "pg";
|
|
2
|
-
import { DbRlsError, type PoolKind } from "./types";
|
|
2
|
+
import { type DbRlsMode, DbRlsError, type PoolKind } from "./types";
|
|
3
|
+
export interface ConfigureDbRlsPools {
|
|
4
|
+
owner: Pool;
|
|
5
|
+
services?: Pool;
|
|
6
|
+
authenticated?: Pool;
|
|
7
|
+
/** D185 platform-ops pool — required in `3-pool-with-platform-ops`
|
|
8
|
+
* mode, forbidden otherwise. Wire against the `nodii_platform_ops`
|
|
9
|
+
* Postgres role per D185 § 1. */
|
|
10
|
+
platformOps?: Pool;
|
|
11
|
+
}
|
|
3
12
|
export interface ConfigureDbRlsOpts {
|
|
4
13
|
/** Per `nodii-libs/telemetry.md` § 5.4. Used in error messages + spans. */
|
|
5
14
|
serviceName: string;
|
|
6
|
-
/** Underlying pg.Pool instances per role. Caller owns lifecycle.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
/** Underlying pg.Pool instances per role. Caller owns lifecycle. In
|
|
16
|
+
* `2-pool` mode only `owner` (and optionally `services`) are required;
|
|
17
|
+
* `authenticated` must be absent. */
|
|
18
|
+
pools: ConfigureDbRlsPools;
|
|
19
|
+
/** Pool topology mode. Defaults to `"3-pool"`. Set `"2-pool"` for
|
|
20
|
+
* nodii-auth-shape services per 08-rls § 7. */
|
|
21
|
+
mode?: DbRlsMode;
|
|
12
22
|
/** Enable role-name validation at boot (default true). Set false in
|
|
13
|
-
* unit tests that wire raw postgres without dedicated roles.
|
|
23
|
+
* unit tests that wire raw postgres without dedicated roles. In
|
|
24
|
+
* 2-pool mode, only the pools actually supplied are validated. */
|
|
14
25
|
validateRoles?: boolean;
|
|
15
26
|
/** Slow-acquire threshold in ms — propagated to PgClientPool. */
|
|
16
27
|
slowAcquireMs?: number;
|
|
@@ -41,5 +52,28 @@ export declare class PoolCredentialMismatch extends DbRlsError {
|
|
|
41
52
|
* per the spec's failure modes.
|
|
42
53
|
*/
|
|
43
54
|
export declare function configureDbRls(opts: ConfigureDbRlsOpts): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Convenience wrapper for services with a platform-ops surface
|
|
57
|
+
* per hub decision D185. Equivalent to
|
|
58
|
+
* `configureDbRls({ ..., mode: "3-pool-with-platform-ops" })`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function configureDbRls4Pool(opts: Omit<ConfigureDbRlsOpts, "mode"> & {
|
|
61
|
+
pools: {
|
|
62
|
+
owner: Pool;
|
|
63
|
+
services: Pool;
|
|
64
|
+
authenticated: Pool;
|
|
65
|
+
platformOps: Pool;
|
|
66
|
+
};
|
|
67
|
+
}): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Convenience wrapper for nodii-auth-shape services per 08-rls § 7.
|
|
70
|
+
* Equivalent to `configureDbRls({ ..., mode: "2-pool" })`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function configureDbRls2Pool(opts: Omit<ConfigureDbRlsOpts, "mode"> & {
|
|
73
|
+
pools: {
|
|
74
|
+
owner: Pool;
|
|
75
|
+
services?: Pool;
|
|
76
|
+
};
|
|
77
|
+
}): Promise<void>;
|
|
44
78
|
export declare function _resetConfigureForTests(): void;
|
|
45
79
|
//# sourceMappingURL=configure.d.ts.map
|
package/dist/configure.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,EAEL,KAAK,SAAS,EACd,UAAU,EACV,KAAK,QAAQ,EACd,MAAM,SAAS,CAAC;AAIjB,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,IAAI,CAAC;IACZ,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB;;sCAEkC;IAClC,WAAW,CAAC,EAAE,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB;;0CAEsC;IACtC,KAAK,EAAE,mBAAmB,CAAC;IAC3B;oDACgD;IAChD,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;uEAEmE;IACnE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvE,uDAAuD;IACvD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAClB,IAAI,EAAE,QAAQ,CAAC;QACf,OAAO,EAAE,WAAW,GAAG,aAAa,GAAG,OAAO,CAAC;QAC/C,UAAU,EAAE,MAAM,CAAC;KACpB,KAAK,IAAI,CAAC;CACZ;AASD,qBAAa,sBAAuB,SAAQ,UAAU;IACpD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAS7D;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyF5E;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,GAAG;IACvC,KAAK,EAAE;QACL,KAAK,EAAE,IAAI,CAAC;QACZ,QAAQ,EAAE,IAAI,CAAC;QACf,aAAa,EAAE,IAAI,CAAC;QACpB,WAAW,EAAE,IAAI,CAAC;KACnB,CAAC;CACH,GACA,OAAO,CAAC,IAAI,CAAC,CAKf;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,GAAG;IACvC,KAAK,EAAE;QAAE,KAAK,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;KAAE,CAAC;CACzC,GACA,OAAO,CAAC,IAAI,CAAC,CAMf;AAgBD,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
|
package/dist/configure.js
CHANGED
|
@@ -8,13 +8,17 @@
|
|
|
8
8
|
// wiring code.
|
|
9
9
|
// - Service name binding (currently used for log lines; future
|
|
10
10
|
// telemetry resource attribute).
|
|
11
|
-
|
|
11
|
+
//
|
|
12
|
+
// v0.2.x supports the `2-pool` mode per 08-rls § 7 — nodii-auth boots
|
|
13
|
+
// with owner + (optional) services only.
|
|
14
|
+
import { DbRlsConfigError, DbRlsError, } from "./types";
|
|
12
15
|
import { _resetForTests as resetInit, initDbRls } from "./init";
|
|
13
16
|
import { PgClientPool } from "./pg-pool-adapter";
|
|
14
17
|
const EXPECTED_ROLES = {
|
|
15
18
|
owner: "nodii_owner",
|
|
16
19
|
services: "nodii_services",
|
|
17
20
|
authenticated: "authenticated",
|
|
21
|
+
platform_ops: "nodii_platform_ops",
|
|
18
22
|
};
|
|
19
23
|
export class PoolCredentialMismatch extends DbRlsError {
|
|
20
24
|
pool;
|
|
@@ -37,11 +41,43 @@ export class PoolCredentialMismatch extends DbRlsError {
|
|
|
37
41
|
* per the spec's failure modes.
|
|
38
42
|
*/
|
|
39
43
|
export async function configureDbRls(opts) {
|
|
44
|
+
const mode = opts.mode ?? "3-pool";
|
|
40
45
|
const validate = opts.validateRoles ?? true;
|
|
46
|
+
if (mode === "3-pool") {
|
|
47
|
+
if (!opts.pools.services || !opts.pools.authenticated) {
|
|
48
|
+
throw new DbRlsConfigError("configureDbRls: 3-pool mode requires owner + services + authenticated pools. Either supply both, or set mode: '2-pool'.");
|
|
49
|
+
}
|
|
50
|
+
if (opts.pools.platformOps) {
|
|
51
|
+
throw new DbRlsConfigError("configureDbRls: 3-pool mode must not supply a 'platformOps' pool — use mode: '3-pool-with-platform-ops' per hub decision D185.");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (mode === "2-pool") {
|
|
55
|
+
if (opts.pools.authenticated) {
|
|
56
|
+
throw new DbRlsConfigError("configureDbRls: 2-pool mode must not supply an 'authenticated' pool — the 2-pool exception per 08-rls § 7 has no user-context. Use mode: '3-pool' instead.");
|
|
57
|
+
}
|
|
58
|
+
if (opts.pools.platformOps) {
|
|
59
|
+
throw new DbRlsConfigError("configureDbRls: 2-pool mode must not supply a 'platformOps' pool — the 2-pool exception per 08-rls § 7 has no platform-ops surface. Use mode: '3-pool-with-platform-ops' per D185.");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (mode === "3-pool-with-platform-ops") {
|
|
63
|
+
if (!opts.pools.services || !opts.pools.authenticated) {
|
|
64
|
+
throw new DbRlsConfigError("configureDbRls: '3-pool-with-platform-ops' mode requires owner + services + authenticated + platformOps pools (D185). All four are mandatory.");
|
|
65
|
+
}
|
|
66
|
+
if (!opts.pools.platformOps) {
|
|
67
|
+
throw new DbRlsConfigError("configureDbRls: '3-pool-with-platform-ops' mode requires a 'platformOps' pool wired against the nodii_platform_ops Postgres role (D185 § 1). Did you mean mode: '3-pool'?");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
41
70
|
if (validate) {
|
|
42
71
|
await assertPoolRole(opts.pools.owner, "owner");
|
|
43
|
-
|
|
44
|
-
|
|
72
|
+
if (opts.pools.services) {
|
|
73
|
+
await assertPoolRole(opts.pools.services, "services");
|
|
74
|
+
}
|
|
75
|
+
if (opts.pools.authenticated) {
|
|
76
|
+
await assertPoolRole(opts.pools.authenticated, "authenticated");
|
|
77
|
+
}
|
|
78
|
+
if (opts.pools.platformOps) {
|
|
79
|
+
await assertPoolRole(opts.pools.platformOps, "platform_ops");
|
|
80
|
+
}
|
|
45
81
|
}
|
|
46
82
|
const owner = new PgClientPool({
|
|
47
83
|
pool: opts.pools.owner,
|
|
@@ -50,21 +86,56 @@ export async function configureDbRls(opts) {
|
|
|
50
86
|
onSlowAcquire: opts.onSlowAcquire,
|
|
51
87
|
onTxFinish: opts.onTxFinish,
|
|
52
88
|
});
|
|
53
|
-
const services =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
89
|
+
const services = opts.pools.services
|
|
90
|
+
? new PgClientPool({
|
|
91
|
+
pool: opts.pools.services,
|
|
92
|
+
kind: "services",
|
|
93
|
+
slowAcquireMs: opts.slowAcquireMs,
|
|
94
|
+
onSlowAcquire: opts.onSlowAcquire,
|
|
95
|
+
onTxFinish: opts.onTxFinish,
|
|
96
|
+
})
|
|
97
|
+
: undefined;
|
|
98
|
+
const authenticated = opts.pools.authenticated
|
|
99
|
+
? new PgClientPool({
|
|
100
|
+
pool: opts.pools.authenticated,
|
|
101
|
+
kind: "authenticated",
|
|
102
|
+
slowAcquireMs: opts.slowAcquireMs,
|
|
103
|
+
onSlowAcquire: opts.onSlowAcquire,
|
|
104
|
+
onTxFinish: opts.onTxFinish,
|
|
105
|
+
})
|
|
106
|
+
: undefined;
|
|
107
|
+
const platformOps = opts.pools.platformOps
|
|
108
|
+
? new PgClientPool({
|
|
109
|
+
pool: opts.pools.platformOps,
|
|
110
|
+
kind: "platform_ops",
|
|
111
|
+
slowAcquireMs: opts.slowAcquireMs,
|
|
112
|
+
onSlowAcquire: opts.onSlowAcquire,
|
|
113
|
+
onTxFinish: opts.onTxFinish,
|
|
114
|
+
})
|
|
115
|
+
: undefined;
|
|
116
|
+
initDbRls({ owner, services, authenticated, platformOps, mode });
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Convenience wrapper for services with a platform-ops surface
|
|
120
|
+
* per hub decision D185. Equivalent to
|
|
121
|
+
* `configureDbRls({ ..., mode: "3-pool-with-platform-ops" })`.
|
|
122
|
+
*/
|
|
123
|
+
export async function configureDbRls4Pool(opts) {
|
|
124
|
+
return configureDbRls({
|
|
125
|
+
...opts,
|
|
126
|
+
mode: "3-pool-with-platform-ops",
|
|
59
127
|
});
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Convenience wrapper for nodii-auth-shape services per 08-rls § 7.
|
|
131
|
+
* Equivalent to `configureDbRls({ ..., mode: "2-pool" })`.
|
|
132
|
+
*/
|
|
133
|
+
export async function configureDbRls2Pool(opts) {
|
|
134
|
+
return configureDbRls({
|
|
135
|
+
...opts,
|
|
136
|
+
mode: "2-pool",
|
|
137
|
+
pools: { owner: opts.pools.owner, services: opts.pools.services },
|
|
66
138
|
});
|
|
67
|
-
initDbRls({ owner, services, authenticated });
|
|
68
139
|
}
|
|
69
140
|
async function assertPoolRole(pool, kind) {
|
|
70
141
|
const expected = EXPECTED_ROLES[kind];
|
package/dist/configure.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,wBAAwB;AACxB,yEAAyE;AACzE,6EAA6E;AAC7E,4EAA4E;AAC5E,qEAAqE;AACrE,mBAAmB;AACnB,iEAAiE;AACjE,qCAAqC;
|
|
1
|
+
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"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"}
|
package/dist/context.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type OwnerContextOpts } from "./migrate-guard";
|
|
2
|
+
import { type AutoDispatchOpts, type PgTx, type PlatformOpsContextOpts, type SystemContextOpts, type UserContextOpts } from "./types";
|
|
2
3
|
/**
|
|
3
4
|
* withUserContext — opens a tx on the `authenticated` pool, sets
|
|
4
5
|
* `auth.user_id` + `auth.tenant_id` (+ optional `auth.source_ip`) via
|
|
@@ -19,13 +20,41 @@ export declare function withSystemContext<T>(opts: SystemContextOpts, fn: (tx: P
|
|
|
19
20
|
* withOwnerContext — opens a tx on the `owner` (nodii_owner BYPASSRLS)
|
|
20
21
|
* pool. No GUCs are set — owner is the migrations-only context.
|
|
21
22
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* Per `08-rls-doctrine § 10.2`, callers MUST satisfy the migrate guard:
|
|
24
|
+
* - `NODII_ENV=migrate` (typical migration runner shape), OR
|
|
25
|
+
* - explicit `{ allowOutsideMigrate: true, reason: "..." }` with an
|
|
26
|
+
* operator-attested reason (ops tooling shape).
|
|
27
|
+
*
|
|
28
|
+
* Throws `OwnerContextOutsideMigrate` if neither is satisfied.
|
|
29
|
+
*/
|
|
30
|
+
export declare function withOwnerContext<T>(fnOrOpts: OwnerContextOpts | ((tx: PgTx) => Promise<T>), maybeFn?: (tx: PgTx) => Promise<T>): Promise<T>;
|
|
31
|
+
/**
|
|
32
|
+
* withPlatformOps — opens a tx on the `platform_ops` pool
|
|
33
|
+
* (nodii_platform_ops Postgres role) per hub decision D185.
|
|
34
|
+
*
|
|
35
|
+
* Sets the three transaction-local GUCs the platform-ops RLS
|
|
36
|
+
* predicates read (D185 § 4):
|
|
37
|
+
* - `app.user_id` — verified principal id (sub) from JWT.
|
|
38
|
+
* - `app.platform_ops_service_id` — which consumer service's
|
|
39
|
+
* platform-ops surface this request is exercising.
|
|
40
|
+
* - `app.platform_ops_permission` — the specific catalog entry
|
|
41
|
+
* being exercised (e.g. `"modules.write"`).
|
|
42
|
+
*
|
|
43
|
+
* The policies on the table being accessed join against
|
|
44
|
+
* `platform_ops_grants_replica` to decide allow/deny per-row. Unlike
|
|
45
|
+
* `nodii_owner` (BYPASSRLS escape hatch), the platform_ops pool is
|
|
46
|
+
* RLS-bound — it just uses a different predicate shape.
|
|
47
|
+
*
|
|
48
|
+
* `grantId` and `supportTicketId` are optional audit-trail bindings;
|
|
49
|
+
* they are emitted as span attributes for forensic tracing but are
|
|
50
|
+
* NOT pushed into GUCs (the policy predicate doesn't read them).
|
|
51
|
+
*
|
|
52
|
+
* Throws `DbRlsNotInitialized` if `initDbRls` hasn't run.
|
|
53
|
+
* Throws `PoolUnavailable("platform_ops")` if db-rls was initialized
|
|
54
|
+
* in 3-pool / 2-pool mode (no platformOps pool wired).
|
|
55
|
+
* Wraps any error thrown by `fn` in `TransactionRolledBack`.
|
|
27
56
|
*/
|
|
28
|
-
export declare function
|
|
57
|
+
export declare function withPlatformOps<T>(opts: PlatformOpsContextOpts, fn: (tx: PgTx) => Promise<T>): Promise<T>;
|
|
29
58
|
/**
|
|
30
59
|
* autoDispatch — chooses the right pool based on what's bound.
|
|
31
60
|
*
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AASA,OAAO,EAAwB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,IAAI,EACT,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EACrB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;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,CAcZ;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;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;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,CAYZ;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
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
// commits / rollbacks per the underlying PgPool's withTransaction
|
|
6
6
|
// contract.
|
|
7
7
|
import { requirePool } from "./init";
|
|
8
|
+
import { recordOwnerContextInvocation } from "./metrics";
|
|
9
|
+
import { assertMigrateAllowed } from "./migrate-guard";
|
|
8
10
|
import { MissingTenantContext, TransactionRolledBack, } from "./types";
|
|
9
11
|
/**
|
|
10
12
|
* withUserContext — opens a tx on the `authenticated` pool, sets
|
|
@@ -52,13 +54,23 @@ export async function withSystemContext(opts, fn) {
|
|
|
52
54
|
* withOwnerContext — opens a tx on the `owner` (nodii_owner BYPASSRLS)
|
|
53
55
|
* pool. No GUCs are set — owner is the migrations-only context.
|
|
54
56
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
57
|
+
* Per `08-rls-doctrine § 10.2`, callers MUST satisfy the migrate guard:
|
|
58
|
+
* - `NODII_ENV=migrate` (typical migration runner shape), OR
|
|
59
|
+
* - explicit `{ allowOutsideMigrate: true, reason: "..." }` with an
|
|
60
|
+
* operator-attested reason (ops tooling shape).
|
|
61
|
+
*
|
|
62
|
+
* Throws `OwnerContextOutsideMigrate` if neither is satisfied.
|
|
60
63
|
*/
|
|
61
|
-
export async function withOwnerContext(
|
|
64
|
+
export async function withOwnerContext(fnOrOpts, maybeFn) {
|
|
65
|
+
const { opts, fn } = normalizeOwnerArgs(fnOrOpts, maybeFn);
|
|
66
|
+
try {
|
|
67
|
+
assertMigrateAllowed(opts);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
recordOwnerContextInvocation("refused");
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
recordOwnerContextInvocation("allowed");
|
|
62
74
|
const pool = requirePool("owner");
|
|
63
75
|
return pool.withTransaction(async (tx) => {
|
|
64
76
|
try {
|
|
@@ -69,6 +81,55 @@ export async function withOwnerContext(fn) {
|
|
|
69
81
|
}
|
|
70
82
|
});
|
|
71
83
|
}
|
|
84
|
+
function normalizeOwnerArgs(fnOrOpts, maybeFn) {
|
|
85
|
+
if (typeof fnOrOpts === "function") {
|
|
86
|
+
return { opts: {}, fn: fnOrOpts };
|
|
87
|
+
}
|
|
88
|
+
if (!maybeFn) {
|
|
89
|
+
throw new TypeError("withOwnerContext: when opts are passed, the second argument must be the callback.");
|
|
90
|
+
}
|
|
91
|
+
return { opts: fnOrOpts, fn: maybeFn };
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* withPlatformOps — opens a tx on the `platform_ops` pool
|
|
95
|
+
* (nodii_platform_ops Postgres role) per hub decision D185.
|
|
96
|
+
*
|
|
97
|
+
* Sets the three transaction-local GUCs the platform-ops RLS
|
|
98
|
+
* predicates read (D185 § 4):
|
|
99
|
+
* - `app.user_id` — verified principal id (sub) from JWT.
|
|
100
|
+
* - `app.platform_ops_service_id` — which consumer service's
|
|
101
|
+
* platform-ops surface this request is exercising.
|
|
102
|
+
* - `app.platform_ops_permission` — the specific catalog entry
|
|
103
|
+
* being exercised (e.g. `"modules.write"`).
|
|
104
|
+
*
|
|
105
|
+
* The policies on the table being accessed join against
|
|
106
|
+
* `platform_ops_grants_replica` to decide allow/deny per-row. Unlike
|
|
107
|
+
* `nodii_owner` (BYPASSRLS escape hatch), the platform_ops pool is
|
|
108
|
+
* RLS-bound — it just uses a different predicate shape.
|
|
109
|
+
*
|
|
110
|
+
* `grantId` and `supportTicketId` are optional audit-trail bindings;
|
|
111
|
+
* they are emitted as span attributes for forensic tracing but are
|
|
112
|
+
* NOT pushed into GUCs (the policy predicate doesn't read them).
|
|
113
|
+
*
|
|
114
|
+
* Throws `DbRlsNotInitialized` if `initDbRls` hasn't run.
|
|
115
|
+
* Throws `PoolUnavailable("platform_ops")` if db-rls was initialized
|
|
116
|
+
* in 3-pool / 2-pool mode (no platformOps pool wired).
|
|
117
|
+
* Wraps any error thrown by `fn` in `TransactionRolledBack`.
|
|
118
|
+
*/
|
|
119
|
+
export async function withPlatformOps(opts, fn) {
|
|
120
|
+
const pool = requirePool("platform_ops");
|
|
121
|
+
return pool.withTransaction(async (tx) => {
|
|
122
|
+
await tx.setConfig("app.user_id", opts.userId);
|
|
123
|
+
await tx.setConfig("app.platform_ops_service_id", opts.serviceId);
|
|
124
|
+
await tx.setConfig("app.platform_ops_permission", opts.permission);
|
|
125
|
+
try {
|
|
126
|
+
return await fn(tx);
|
|
127
|
+
}
|
|
128
|
+
catch (cause) {
|
|
129
|
+
throw new TransactionRolledBack(cause);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
72
133
|
/**
|
|
73
134
|
* autoDispatch — chooses the right pool based on what's bound.
|
|
74
135
|
*
|
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,QAAQ,CAAC;AACrC,OAAO,EAEL,oBAAoB,
|
|
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,4 +1,5 @@
|
|
|
1
1
|
import { type NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
2
|
+
import { type OwnerContextOpts } from "./migrate-guard";
|
|
2
3
|
import type { SystemContextOpts, UserContextOpts } from "./types";
|
|
3
4
|
type DrizzleClient<TSchema extends Record<string, unknown> = Record<string, unknown>> = NodePgDatabase<TSchema>;
|
|
4
5
|
/**
|
|
@@ -15,8 +16,14 @@ export declare function withUserContextDb<T, TSchema extends Record<string, unkn
|
|
|
15
16
|
export declare function withSystemContextDb<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(opts: SystemContextOpts, fn: (db: DrizzleClient<TSchema>) => Promise<T>): Promise<T>;
|
|
16
17
|
/**
|
|
17
18
|
* withOwnerContext (Drizzle variant) — opens a tx on the `owner`
|
|
18
|
-
* (BYPASSRLS) pool; no GUCs.
|
|
19
|
+
* (BYPASSRLS) pool; no GUCs.
|
|
20
|
+
*
|
|
21
|
+
* Per `08-rls-doctrine § 10.2`, callers MUST satisfy the migrate guard:
|
|
22
|
+
* - `NODII_ENV=migrate`, OR
|
|
23
|
+
* - explicit `{ allowOutsideMigrate: true, reason: "..." }`.
|
|
24
|
+
*
|
|
25
|
+
* Throws `OwnerContextOutsideMigrate` if neither is satisfied.
|
|
19
26
|
*/
|
|
20
|
-
export declare function withOwnerContextDb<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(
|
|
27
|
+
export declare function withOwnerContextDb<T, TSchema extends Record<string, unknown> = Record<string, unknown>>(fnOrOpts: OwnerContextOpts | ((db: DrizzleClient<TSchema>) => Promise<T>), maybeFn?: (db: DrizzleClient<TSchema>) => Promise<T>): Promise<T>;
|
|
21
28
|
export type { DrizzleClient, NodePgDatabase };
|
|
22
29
|
//# sourceMappingURL=drizzle-client.d.ts.map
|
|
@@ -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,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAOlE,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;AAmD5B;;;;;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;;;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
|
|
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,EAAwB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAOlE,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;AAmD5B;;;;;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;;;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"}
|
package/dist/drizzle-client.js
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
// services using the raw `PgTx` surface.
|
|
19
19
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
20
20
|
import { requirePool } from "./init";
|
|
21
|
+
import { recordOwnerContextInvocation } from "./metrics";
|
|
22
|
+
import { assertMigrateAllowed } from "./migrate-guard";
|
|
21
23
|
import { PgClientPool } from "./pg-pool-adapter";
|
|
22
24
|
import { MissingTenantContext, TransactionRolledBack } from "./types";
|
|
23
25
|
function clientFor(_pool) {
|
|
@@ -100,10 +102,34 @@ export async function withSystemContextDb(opts, fn) {
|
|
|
100
102
|
}
|
|
101
103
|
/**
|
|
102
104
|
* withOwnerContext (Drizzle variant) — opens a tx on the `owner`
|
|
103
|
-
* (BYPASSRLS) pool; no GUCs.
|
|
105
|
+
* (BYPASSRLS) pool; no GUCs.
|
|
106
|
+
*
|
|
107
|
+
* Per `08-rls-doctrine § 10.2`, callers MUST satisfy the migrate guard:
|
|
108
|
+
* - `NODII_ENV=migrate`, OR
|
|
109
|
+
* - explicit `{ allowOutsideMigrate: true, reason: "..." }`.
|
|
110
|
+
*
|
|
111
|
+
* Throws `OwnerContextOutsideMigrate` if neither is satisfied.
|
|
104
112
|
*/
|
|
105
|
-
export async function withOwnerContextDb(
|
|
113
|
+
export async function withOwnerContextDb(fnOrOpts, maybeFn) {
|
|
114
|
+
const { opts, fn } = normalizeOwnerDbArgs(fnOrOpts, maybeFn);
|
|
115
|
+
try {
|
|
116
|
+
assertMigrateAllowed(opts);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
recordOwnerContextInvocation("refused");
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
recordOwnerContextInvocation("allowed");
|
|
106
123
|
const pool = requireRealPool("owner");
|
|
107
124
|
return withRealTx(pool, async () => { }, (db) => fn(db));
|
|
108
125
|
}
|
|
126
|
+
function normalizeOwnerDbArgs(fnOrOpts, maybeFn) {
|
|
127
|
+
if (typeof fnOrOpts === "function") {
|
|
128
|
+
return { opts: {}, fn: fnOrOpts };
|
|
129
|
+
}
|
|
130
|
+
if (!maybeFn) {
|
|
131
|
+
throw new TypeError("withOwnerContextDb: when opts are passed, the second argument must be the callback.");
|
|
132
|
+
}
|
|
133
|
+
return { opts: fnOrOpts, fn: maybeFn };
|
|
134
|
+
}
|
|
109
135
|
//# sourceMappingURL=drizzle-client.js.map
|
|
@@ -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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"}
|