@stratum-hq/lib 0.5.1 → 0.7.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/__tests__/webhook-signature.test.d.ts +2 -0
- package/dist/__tests__/webhook-signature.test.d.ts.map +1 -0
- package/dist/__tests__/webhook-signature.test.js +103 -0
- package/dist/__tests__/webhook-signature.test.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/migrations/019_rls_policies.sql +236 -0
- package/dist/pool-helpers.d.ts.map +1 -1
- package/dist/pool-helpers.js +31 -1
- package/dist/pool-helpers.js.map +1 -1
- package/dist/services/__tests__/api-key-service.test.d.ts +2 -0
- package/dist/services/__tests__/api-key-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/api-key-service.test.js +76 -0
- package/dist/services/__tests__/api-key-service.test.js.map +1 -0
- package/dist/services/__tests__/event-service.test.js +32 -0
- package/dist/services/__tests__/event-service.test.js.map +1 -1
- package/dist/services/__tests__/key-rotation-service.test.d.ts +2 -0
- package/dist/services/__tests__/key-rotation-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/key-rotation-service.test.js +132 -0
- package/dist/services/__tests__/key-rotation-service.test.js.map +1 -0
- package/dist/services/__tests__/tenant-service.test.js +34 -0
- package/dist/services/__tests__/tenant-service.test.js.map +1 -1
- package/dist/services/abac-service.d.ts.map +1 -1
- package/dist/services/abac-service.js +7 -3
- package/dist/services/abac-service.js.map +1 -1
- package/dist/services/api-key-service.d.ts +14 -0
- package/dist/services/api-key-service.d.ts.map +1 -1
- package/dist/services/api-key-service.js +13 -0
- package/dist/services/api-key-service.js.map +1 -1
- package/dist/services/event-service.d.ts.map +1 -1
- package/dist/services/event-service.js +34 -22
- package/dist/services/event-service.js.map +1 -1
- package/dist/services/key-rotation-service.d.ts +3 -2
- package/dist/services/key-rotation-service.d.ts.map +1 -1
- package/dist/services/key-rotation-service.js +17 -7
- package/dist/services/key-rotation-service.js.map +1 -1
- package/dist/services/permission-service.d.ts.map +1 -1
- package/dist/services/permission-service.js +7 -4
- package/dist/services/permission-service.js.map +1 -1
- package/dist/services/tenant-service.d.ts +21 -1
- package/dist/services/tenant-service.d.ts.map +1 -1
- package/dist/services/tenant-service.js +24 -3
- package/dist/services/tenant-service.js.map +1 -1
- package/dist/stratum.d.ts +15 -1
- package/dist/stratum.d.ts.map +1 -1
- package/dist/stratum.js +12 -4
- package/dist/stratum.js.map +1 -1
- package/dist/webhook-signature.d.ts +36 -0
- package/dist/webhook-signature.d.ts.map +1 -0
- package/dist/webhook-signature.js +55 -0
- package/dist/webhook-signature.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-signature.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/webhook-signature.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const webhook_signature_js_1 = require("../webhook-signature.js");
|
|
5
|
+
const SECRET = "whsec_test_secret";
|
|
6
|
+
const PAYLOAD = JSON.stringify({ id: "evt_1", type: "tenant.created" });
|
|
7
|
+
(0, vitest_1.describe)("signWebhookPayload", () => {
|
|
8
|
+
(0, vitest_1.it)("binds the timestamp into the signature", () => {
|
|
9
|
+
const t1 = "2026-07-24T00:00:00.000Z";
|
|
10
|
+
const t2 = "2026-07-24T00:00:01.000Z";
|
|
11
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.signWebhookPayload)(SECRET, t1, PAYLOAD)).not.toBe((0, webhook_signature_js_1.signWebhookPayload)(SECRET, t2, PAYLOAD));
|
|
12
|
+
});
|
|
13
|
+
(0, vitest_1.it)("produces a sha256= prefixed hex digest", () => {
|
|
14
|
+
const sig = (0, webhook_signature_js_1.signWebhookPayload)(SECRET, "2026-07-24T00:00:00.000Z", PAYLOAD);
|
|
15
|
+
(0, vitest_1.expect)(sig).toMatch(/^sha256=[0-9a-f]{64}$/);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
(0, vitest_1.describe)("verifyWebhookSignature", () => {
|
|
19
|
+
const now = Date.parse("2026-07-24T12:00:00.000Z");
|
|
20
|
+
const timestamp = "2026-07-24T12:00:00.000Z";
|
|
21
|
+
const signature = (0, webhook_signature_js_1.signWebhookPayload)(SECRET, timestamp, PAYLOAD);
|
|
22
|
+
(0, vitest_1.it)("accepts a fresh, correctly signed delivery", () => {
|
|
23
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.verifyWebhookSignature)({ secret: SECRET, payload: PAYLOAD, signature, timestamp, now })).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
(0, vitest_1.it)("rejects a tampered payload", () => {
|
|
26
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.verifyWebhookSignature)({
|
|
27
|
+
secret: SECRET,
|
|
28
|
+
payload: PAYLOAD + "x",
|
|
29
|
+
signature,
|
|
30
|
+
timestamp,
|
|
31
|
+
now,
|
|
32
|
+
})).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
(0, vitest_1.it)("rejects a wrong secret", () => {
|
|
35
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.verifyWebhookSignature)({
|
|
36
|
+
secret: "whsec_wrong",
|
|
37
|
+
payload: PAYLOAD,
|
|
38
|
+
signature,
|
|
39
|
+
timestamp,
|
|
40
|
+
now,
|
|
41
|
+
})).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
(0, vitest_1.it)("rejects a replayed delivery once it ages past the window", () => {
|
|
44
|
+
const stale = now + (webhook_signature_js_1.DEFAULT_WEBHOOK_TOLERANCE_SECONDS + 1) * 1000;
|
|
45
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.verifyWebhookSignature)({
|
|
46
|
+
secret: SECRET,
|
|
47
|
+
payload: PAYLOAD,
|
|
48
|
+
signature,
|
|
49
|
+
timestamp,
|
|
50
|
+
now: stale,
|
|
51
|
+
})).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
(0, vitest_1.it)("rejects a timestamp too far in the future", () => {
|
|
54
|
+
const future = now - (webhook_signature_js_1.DEFAULT_WEBHOOK_TOLERANCE_SECONDS + 1) * 1000;
|
|
55
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.verifyWebhookSignature)({
|
|
56
|
+
secret: SECRET,
|
|
57
|
+
payload: PAYLOAD,
|
|
58
|
+
signature,
|
|
59
|
+
timestamp,
|
|
60
|
+
now: future,
|
|
61
|
+
})).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
(0, vitest_1.it)("accepts a delivery at the edge of the window", () => {
|
|
64
|
+
const edge = now + webhook_signature_js_1.DEFAULT_WEBHOOK_TOLERANCE_SECONDS * 1000;
|
|
65
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.verifyWebhookSignature)({
|
|
66
|
+
secret: SECRET,
|
|
67
|
+
payload: PAYLOAD,
|
|
68
|
+
signature,
|
|
69
|
+
timestamp,
|
|
70
|
+
now: edge,
|
|
71
|
+
})).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
(0, vitest_1.it)("respects a custom tolerance", () => {
|
|
74
|
+
const drift = now + 10_000; // 10s later
|
|
75
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.verifyWebhookSignature)({
|
|
76
|
+
secret: SECRET,
|
|
77
|
+
payload: PAYLOAD,
|
|
78
|
+
signature,
|
|
79
|
+
timestamp,
|
|
80
|
+
toleranceSeconds: 5,
|
|
81
|
+
now: drift,
|
|
82
|
+
})).toBe(false);
|
|
83
|
+
});
|
|
84
|
+
(0, vitest_1.it)("fails closed on a malformed timestamp", () => {
|
|
85
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.verifyWebhookSignature)({
|
|
86
|
+
secret: SECRET,
|
|
87
|
+
payload: PAYLOAD,
|
|
88
|
+
signature,
|
|
89
|
+
timestamp: "not-a-date",
|
|
90
|
+
now,
|
|
91
|
+
})).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
(0, vitest_1.it)("rejects a malformed signature without throwing", () => {
|
|
94
|
+
(0, vitest_1.expect)((0, webhook_signature_js_1.verifyWebhookSignature)({
|
|
95
|
+
secret: SECRET,
|
|
96
|
+
payload: PAYLOAD,
|
|
97
|
+
signature: "sha256=deadbeef",
|
|
98
|
+
timestamp,
|
|
99
|
+
now,
|
|
100
|
+
})).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=webhook-signature.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-signature.test.js","sourceRoot":"","sources":["../../src/__tests__/webhook-signature.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { Stratum, type StratumOptions } from "./stratum.js";
|
|
|
2
2
|
export { migrate, type MigrateOptions } from "./migrate.js";
|
|
3
3
|
export { migrateAllSchemas, type MigrateSchemasOptions, type MigrateSchemasResult, } from "./migrate-schemas.js";
|
|
4
4
|
export { withClient, withTransaction } from "./pool-helpers.js";
|
|
5
|
+
export { verifyWebhookSignature, signWebhookPayload, DEFAULT_WEBHOOK_TOLERANCE_SECONDS, type VerifyWebhookOptions, } from "./webhook-signature.js";
|
|
5
6
|
export { traced, getTracer, isTracingEnabled } from "./telemetry.js";
|
|
6
7
|
export type { TenantNode, TenantContext, CreateTenantInput, UpdateTenantInput, MoveTenantInput, PaginationInput, PaginatedResult, ConfigEntry, SetConfigInput, ResolvedConfigEntry, ResolvedConfig, PermissionPolicy, CreatePermissionInput, UpdatePermissionInput, ResolvedPermission, } from "@stratum-hq/core";
|
|
7
8
|
export type { ApiKeyRecord, CreatedApiKey, ValidatedApiKey, CreateApiKeyOptions } from "./services/api-key-service.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EACL,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,YAAY,EACV,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACvH,YAAY,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAGzF,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EACL,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,iCAAiC,EACjC,KAAK,oBAAoB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,YAAY,EACV,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACvH,YAAY,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAGzF,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.noopLogger = exports.defaultLogger = exports.isTracingEnabled = exports.getTracer = exports.traced = exports.withTransaction = exports.withClient = exports.migrateAllSchemas = exports.migrate = exports.Stratum = void 0;
|
|
3
|
+
exports.noopLogger = exports.defaultLogger = exports.isTracingEnabled = exports.getTracer = exports.traced = exports.DEFAULT_WEBHOOK_TOLERANCE_SECONDS = exports.signWebhookPayload = exports.verifyWebhookSignature = exports.withTransaction = exports.withClient = exports.migrateAllSchemas = exports.migrate = exports.Stratum = void 0;
|
|
4
4
|
var stratum_js_1 = require("./stratum.js");
|
|
5
5
|
Object.defineProperty(exports, "Stratum", { enumerable: true, get: function () { return stratum_js_1.Stratum; } });
|
|
6
6
|
var migrate_js_1 = require("./migrate.js");
|
|
@@ -10,6 +10,10 @@ Object.defineProperty(exports, "migrateAllSchemas", { enumerable: true, get: fun
|
|
|
10
10
|
var pool_helpers_js_1 = require("./pool-helpers.js");
|
|
11
11
|
Object.defineProperty(exports, "withClient", { enumerable: true, get: function () { return pool_helpers_js_1.withClient; } });
|
|
12
12
|
Object.defineProperty(exports, "withTransaction", { enumerable: true, get: function () { return pool_helpers_js_1.withTransaction; } });
|
|
13
|
+
var webhook_signature_js_1 = require("./webhook-signature.js");
|
|
14
|
+
Object.defineProperty(exports, "verifyWebhookSignature", { enumerable: true, get: function () { return webhook_signature_js_1.verifyWebhookSignature; } });
|
|
15
|
+
Object.defineProperty(exports, "signWebhookPayload", { enumerable: true, get: function () { return webhook_signature_js_1.signWebhookPayload; } });
|
|
16
|
+
Object.defineProperty(exports, "DEFAULT_WEBHOOK_TOLERANCE_SECONDS", { enumerable: true, get: function () { return webhook_signature_js_1.DEFAULT_WEBHOOK_TOLERANCE_SECONDS; } });
|
|
13
17
|
var telemetry_js_1 = require("./telemetry.js");
|
|
14
18
|
Object.defineProperty(exports, "traced", { enumerable: true, get: function () { return telemetry_js_1.traced; } });
|
|
15
19
|
Object.defineProperty(exports, "getTracer", { enumerable: true, get: function () { return telemetry_js_1.getTracer; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAA4D;AAAnD,qGAAA,OAAO,OAAA;AAChB,2CAA4D;AAAnD,qGAAA,OAAO,OAAA;AAChB,2DAI8B;AAH5B,uHAAA,iBAAiB,OAAA;AAInB,qDAAgE;AAAvD,6GAAA,UAAU,OAAA;AAAE,kHAAA,eAAe,OAAA;AACpC,+CAAqE;AAA5D,sGAAA,MAAM,OAAA;AAAE,yGAAA,SAAS,OAAA;AAAE,gHAAA,gBAAgB,OAAA;AA8B5C,yCAAwD;AAA/C,0GAAA,aAAa,OAAA;AAAE,uGAAA,UAAU,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAA4D;AAAnD,qGAAA,OAAO,OAAA;AAChB,2CAA4D;AAAnD,qGAAA,OAAO,OAAA;AAChB,2DAI8B;AAH5B,uHAAA,iBAAiB,OAAA;AAInB,qDAAgE;AAAvD,6GAAA,UAAU,OAAA;AAAE,kHAAA,eAAe,OAAA;AACpC,+DAKgC;AAJ9B,8HAAA,sBAAsB,OAAA;AACtB,0HAAA,kBAAkB,OAAA;AAClB,yIAAA,iCAAiC,OAAA;AAGnC,+CAAqE;AAA5D,sGAAA,MAAM,OAAA;AAAE,yGAAA,SAAS,OAAA;AAAE,gHAAA,gBAAgB,OAAA;AA8B5C,yCAAwD;AAA/C,0GAAA,aAAa,OAAA;AAAE,uGAAA,UAAU,OAAA"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
-- Migration 019: Real Postgres row-level security for the SHARED_RLS strategy.
|
|
2
|
+
--
|
|
3
|
+
-- Backs the `isolation_strategy = 'SHARED_RLS'` literal (001_init.sql) with
|
|
4
|
+
-- database-enforced tenant isolation. This is a SECOND, independent layer; the
|
|
5
|
+
-- application control-plane authorization stays the primary enforcement. See
|
|
6
|
+
-- docs/adr/0001-postgres-rls-defense-in-depth.md for the full design.
|
|
7
|
+
--
|
|
8
|
+
-- Context model:
|
|
9
|
+
-- * Tenant context: SET LOCAL app.current_tenant_id (transaction scoped).
|
|
10
|
+
-- * System bypass: SET LOCAL app.bypass_rls = 'on' (control-plane path).
|
|
11
|
+
-- Both are set with set_config(..., true) / SET LOCAL so they cannot leak
|
|
12
|
+
-- across pooled connections.
|
|
13
|
+
--
|
|
14
|
+
-- Every policy is fail closed: with no context set,
|
|
15
|
+
-- NULLIF(current_setting('app.current_tenant_id', true), '')::uuid -> NULL,
|
|
16
|
+
-- so the scope predicate is NULL (not true) and zero rows are visible; a write
|
|
17
|
+
-- with no context is rejected. current_setting(name, true) returns NULL instead
|
|
18
|
+
-- of raising when the GUC is unset.
|
|
19
|
+
--
|
|
20
|
+
-- ENABLE + FORCE: FORCE applies the policy to the table owner too. Note that a
|
|
21
|
+
-- Postgres SUPERUSER or a role with BYPASSRLS always skips RLS regardless of
|
|
22
|
+
-- FORCE; the application role must be neither (see docker/init-db.sql:
|
|
23
|
+
-- stratum_app is NOSUPERUSER NOBYPASSRLS).
|
|
24
|
+
--
|
|
25
|
+
-- DROP POLICY IF EXISTS before CREATE makes the migration safe to re-run.
|
|
26
|
+
|
|
27
|
+
-- Reusable predicate (documented once; inlined per policy below because Postgres
|
|
28
|
+
-- policies cannot reference a shared expression):
|
|
29
|
+
-- current_setting('app.bypass_rls', true) = 'on'
|
|
30
|
+
-- OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
31
|
+
|
|
32
|
+
-- ---------------------------------------------------------------------------
|
|
33
|
+
-- Direct tenant_id tables: exact-tenant scope.
|
|
34
|
+
-- ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
-- config_entries
|
|
37
|
+
ALTER TABLE config_entries ENABLE ROW LEVEL SECURITY;
|
|
38
|
+
ALTER TABLE config_entries FORCE ROW LEVEL SECURITY;
|
|
39
|
+
DROP POLICY IF EXISTS tenant_isolation ON config_entries;
|
|
40
|
+
CREATE POLICY tenant_isolation ON config_entries FOR ALL
|
|
41
|
+
USING (
|
|
42
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
43
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
44
|
+
)
|
|
45
|
+
WITH CHECK (
|
|
46
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
47
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
-- permission_policies
|
|
51
|
+
ALTER TABLE permission_policies ENABLE ROW LEVEL SECURITY;
|
|
52
|
+
ALTER TABLE permission_policies FORCE ROW LEVEL SECURITY;
|
|
53
|
+
DROP POLICY IF EXISTS tenant_isolation ON permission_policies;
|
|
54
|
+
CREATE POLICY tenant_isolation ON permission_policies FOR ALL
|
|
55
|
+
USING (
|
|
56
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
57
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
58
|
+
)
|
|
59
|
+
WITH CHECK (
|
|
60
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
61
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
-- audit_logs (tenant_id nullable: ON DELETE SET NULL; NULL rows visible only under bypass)
|
|
65
|
+
ALTER TABLE audit_logs ENABLE ROW LEVEL SECURITY;
|
|
66
|
+
ALTER TABLE audit_logs FORCE ROW LEVEL SECURITY;
|
|
67
|
+
DROP POLICY IF EXISTS tenant_isolation ON audit_logs;
|
|
68
|
+
CREATE POLICY tenant_isolation ON audit_logs FOR ALL
|
|
69
|
+
USING (
|
|
70
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
71
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
72
|
+
)
|
|
73
|
+
WITH CHECK (
|
|
74
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
75
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
-- webhook_events
|
|
79
|
+
ALTER TABLE webhook_events ENABLE ROW LEVEL SECURITY;
|
|
80
|
+
ALTER TABLE webhook_events FORCE ROW LEVEL SECURITY;
|
|
81
|
+
DROP POLICY IF EXISTS tenant_isolation ON webhook_events;
|
|
82
|
+
CREATE POLICY tenant_isolation ON webhook_events FOR ALL
|
|
83
|
+
USING (
|
|
84
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
85
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
86
|
+
)
|
|
87
|
+
WITH CHECK (
|
|
88
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
89
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
-- webhooks (tenant_id nullable)
|
|
93
|
+
ALTER TABLE webhooks ENABLE ROW LEVEL SECURITY;
|
|
94
|
+
ALTER TABLE webhooks FORCE ROW LEVEL SECURITY;
|
|
95
|
+
DROP POLICY IF EXISTS tenant_isolation ON webhooks;
|
|
96
|
+
CREATE POLICY tenant_isolation ON webhooks FOR ALL
|
|
97
|
+
USING (
|
|
98
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
99
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
100
|
+
)
|
|
101
|
+
WITH CHECK (
|
|
102
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
103
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
-- consent_records
|
|
107
|
+
ALTER TABLE consent_records ENABLE ROW LEVEL SECURITY;
|
|
108
|
+
ALTER TABLE consent_records FORCE ROW LEVEL SECURITY;
|
|
109
|
+
DROP POLICY IF EXISTS tenant_isolation ON consent_records;
|
|
110
|
+
CREATE POLICY tenant_isolation ON consent_records FOR ALL
|
|
111
|
+
USING (
|
|
112
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
113
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
114
|
+
)
|
|
115
|
+
WITH CHECK (
|
|
116
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
117
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
-- abac_policies
|
|
121
|
+
ALTER TABLE abac_policies ENABLE ROW LEVEL SECURITY;
|
|
122
|
+
ALTER TABLE abac_policies FORCE ROW LEVEL SECURITY;
|
|
123
|
+
DROP POLICY IF EXISTS tenant_isolation ON abac_policies;
|
|
124
|
+
CREATE POLICY tenant_isolation ON abac_policies FOR ALL
|
|
125
|
+
USING (
|
|
126
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
127
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
128
|
+
)
|
|
129
|
+
WITH CHECK (
|
|
130
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
131
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
-- api_keys (auth table; tenant_id nullable. Read by the control plane before a
|
|
135
|
+
-- tenant context exists, so it is safe only because the control plane bypasses.
|
|
136
|
+
-- Global keys (tenant_id NULL) are visible only under bypass.)
|
|
137
|
+
ALTER TABLE api_keys ENABLE ROW LEVEL SECURITY;
|
|
138
|
+
ALTER TABLE api_keys FORCE ROW LEVEL SECURITY;
|
|
139
|
+
DROP POLICY IF EXISTS tenant_isolation ON api_keys;
|
|
140
|
+
CREATE POLICY tenant_isolation ON api_keys FOR ALL
|
|
141
|
+
USING (
|
|
142
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
143
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
144
|
+
)
|
|
145
|
+
WITH CHECK (
|
|
146
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
147
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
-- roles (auth table; tenant_id nullable for global roles, visible only under bypass)
|
|
151
|
+
ALTER TABLE roles ENABLE ROW LEVEL SECURITY;
|
|
152
|
+
ALTER TABLE roles FORCE ROW LEVEL SECURITY;
|
|
153
|
+
DROP POLICY IF EXISTS tenant_isolation ON roles;
|
|
154
|
+
CREATE POLICY tenant_isolation ON roles FOR ALL
|
|
155
|
+
USING (
|
|
156
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
157
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
158
|
+
)
|
|
159
|
+
WITH CHECK (
|
|
160
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
161
|
+
OR tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
-- ---------------------------------------------------------------------------
|
|
165
|
+
-- tenants registry: self-scope on id. The ancestry source; no tenant_id column.
|
|
166
|
+
-- A data-plane context reads only its own registry row and cannot enumerate the
|
|
167
|
+
-- tree. All tree / ancestry mutations are control-plane and run under bypass.
|
|
168
|
+
-- ---------------------------------------------------------------------------
|
|
169
|
+
ALTER TABLE tenants ENABLE ROW LEVEL SECURITY;
|
|
170
|
+
ALTER TABLE tenants FORCE ROW LEVEL SECURITY;
|
|
171
|
+
DROP POLICY IF EXISTS tenant_isolation ON tenants;
|
|
172
|
+
CREATE POLICY tenant_isolation ON tenants FOR ALL
|
|
173
|
+
USING (
|
|
174
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
175
|
+
OR id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
176
|
+
)
|
|
177
|
+
WITH CHECK (
|
|
178
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
179
|
+
OR id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
-- ---------------------------------------------------------------------------
|
|
183
|
+
-- Indirect tables (no tenant_id): scoped through their tenant-bearing parent.
|
|
184
|
+
-- The parent subquery is itself RLS-filtered under a tenant context, which
|
|
185
|
+
-- composes correctly. No policy recursion: neither parent references back.
|
|
186
|
+
-- ---------------------------------------------------------------------------
|
|
187
|
+
|
|
188
|
+
-- webhook_deliveries -> webhook_events.tenant_id
|
|
189
|
+
ALTER TABLE webhook_deliveries ENABLE ROW LEVEL SECURITY;
|
|
190
|
+
ALTER TABLE webhook_deliveries FORCE ROW LEVEL SECURITY;
|
|
191
|
+
DROP POLICY IF EXISTS tenant_isolation ON webhook_deliveries;
|
|
192
|
+
CREATE POLICY tenant_isolation ON webhook_deliveries FOR ALL
|
|
193
|
+
USING (
|
|
194
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
195
|
+
OR EXISTS (
|
|
196
|
+
SELECT 1 FROM webhook_events we
|
|
197
|
+
WHERE we.id = webhook_deliveries.event_id
|
|
198
|
+
AND we.tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
WITH CHECK (
|
|
202
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
203
|
+
OR EXISTS (
|
|
204
|
+
SELECT 1 FROM webhook_events we
|
|
205
|
+
WHERE we.id = webhook_deliveries.event_id
|
|
206
|
+
AND we.tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
207
|
+
)
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
-- principal_roles -> roles.tenant_id (global-role assignments visible only under bypass)
|
|
211
|
+
ALTER TABLE principal_roles ENABLE ROW LEVEL SECURITY;
|
|
212
|
+
ALTER TABLE principal_roles FORCE ROW LEVEL SECURITY;
|
|
213
|
+
DROP POLICY IF EXISTS tenant_isolation ON principal_roles;
|
|
214
|
+
CREATE POLICY tenant_isolation ON principal_roles FOR ALL
|
|
215
|
+
USING (
|
|
216
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
217
|
+
OR EXISTS (
|
|
218
|
+
SELECT 1 FROM roles r
|
|
219
|
+
WHERE r.id = principal_roles.role_id
|
|
220
|
+
AND r.tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
WITH CHECK (
|
|
224
|
+
current_setting('app.bypass_rls', true) = 'on'
|
|
225
|
+
OR EXISTS (
|
|
226
|
+
SELECT 1 FROM roles r
|
|
227
|
+
WHERE r.id = principal_roles.role_id
|
|
228
|
+
AND r.tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::uuid
|
|
229
|
+
)
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
-- ---------------------------------------------------------------------------
|
|
233
|
+
-- Intentionally NOT protected (documented in the ADR):
|
|
234
|
+
-- * regions -- global infrastructure catalog, no tenant_id, not tenant-private
|
|
235
|
+
-- * _migrations -- internal migration bookkeeping
|
|
236
|
+
-- ---------------------------------------------------------------------------
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool-helpers.d.ts","sourceRoot":"","sources":["../src/pool-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"pool-helpers.d.ts","sourceRoot":"","sources":["../src/pool-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAyBpB,wBAAsB,UAAU,CAAC,CAAC,EAChC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,GACxC,OAAO,CAAC,CAAC,CAAC,CAcZ;AAED,wBAAsB,eAAe,CAAC,CAAC,EACrC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,GACxC,OAAO,CAAC,CAAC,CAAC,CAcZ"}
|
package/dist/pool-helpers.js
CHANGED
|
@@ -2,10 +2,39 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.withClient = withClient;
|
|
4
4
|
exports.withTransaction = withTransaction;
|
|
5
|
+
// The Stratum library is the trusted CONTROL PLANE: it manages the whole tenant
|
|
6
|
+
// tree (authenticating keys before any tenant is known, resolving inherited
|
|
7
|
+
// config up the ancestry chain, listing descendants, moving subtrees, cascade
|
|
8
|
+
// ops). By construction it reads and writes across tenant boundaries, so it runs
|
|
9
|
+
// under the RLS bypass.
|
|
10
|
+
//
|
|
11
|
+
// Both helpers open a transaction and issue `SET LOCAL app.bypass_rls = 'on'`
|
|
12
|
+
// before running the caller's work. SET LOCAL (set_config third arg `true`) is
|
|
13
|
+
// transaction scoped, so the flag cannot leak into a later request that reuses
|
|
14
|
+
// the same pooled connection. Row-level security stays enforced on the separate
|
|
15
|
+
// data-plane path (packages/db-adapters, withTenantContext); see
|
|
16
|
+
// docs/adr/0001-postgres-rls-defense-in-depth.md.
|
|
17
|
+
//
|
|
18
|
+
// This is the single chokepoint for all lib database access: every service goes
|
|
19
|
+
// through withClient / withTransaction, so no service function needs to change.
|
|
20
|
+
async function enterBypass(client) {
|
|
21
|
+
// SET LOCAL (not session SET) so the flag is transaction scoped and cannot
|
|
22
|
+
// leak across pooled connections. Equivalent to
|
|
23
|
+
// set_config('app.bypass_rls', 'on', true).
|
|
24
|
+
await client.query("SET LOCAL app.bypass_rls = 'on'");
|
|
25
|
+
}
|
|
5
26
|
async function withClient(pool, fn) {
|
|
6
27
|
const client = await pool.connect();
|
|
7
28
|
try {
|
|
8
|
-
|
|
29
|
+
await client.query("BEGIN");
|
|
30
|
+
await enterBypass(client);
|
|
31
|
+
const result = await fn(client);
|
|
32
|
+
await client.query("COMMIT");
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
await client.query("ROLLBACK");
|
|
37
|
+
throw err;
|
|
9
38
|
}
|
|
10
39
|
finally {
|
|
11
40
|
client.release();
|
|
@@ -15,6 +44,7 @@ async function withTransaction(pool, fn) {
|
|
|
15
44
|
const client = await pool.connect();
|
|
16
45
|
try {
|
|
17
46
|
await client.query("BEGIN");
|
|
47
|
+
await enterBypass(client);
|
|
18
48
|
const result = await fn(client);
|
|
19
49
|
await client.query("COMMIT");
|
|
20
50
|
return result;
|
package/dist/pool-helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool-helpers.js","sourceRoot":"","sources":["../src/pool-helpers.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"pool-helpers.js","sourceRoot":"","sources":["../src/pool-helpers.ts"],"names":[],"mappings":";;AAyBA,gCAiBC;AAED,0CAiBC;AA3DD,gFAAgF;AAChF,4EAA4E;AAC5E,8EAA8E;AAC9E,iFAAiF;AACjF,wBAAwB;AACxB,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,+EAA+E;AAC/E,gFAAgF;AAChF,iEAAiE;AACjE,kDAAkD;AAClD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAEhF,KAAK,UAAU,WAAW,CAAC,MAAqB;IAC9C,2EAA2E;IAC3E,gDAAgD;IAChD,4CAA4C;IAC5C,MAAM,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;AACxD,CAAC;AAEM,KAAK,UAAU,UAAU,CAC9B,IAAa,EACb,EAAyC;IAEzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5B,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;QAChC,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/B,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,eAAe,CACnC,IAAa,EACb,EAAyC;IAEzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5B,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;QAChC,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/B,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key-service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/api-key-service.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const vitest_1 = require("vitest");
|
|
37
|
+
// Mock pool-helpers before importing api-key-service
|
|
38
|
+
vitest_1.vi.mock("../../pool-helpers.js", () => ({
|
|
39
|
+
withClient: vitest_1.vi.fn(),
|
|
40
|
+
withTransaction: vitest_1.vi.fn(),
|
|
41
|
+
}));
|
|
42
|
+
const poolHelpers = __importStar(require("../../pool-helpers.js"));
|
|
43
|
+
const apiKeyService = __importStar(require("../api-key-service.js"));
|
|
44
|
+
const test_helpers_js_1 = require("./test-helpers.js");
|
|
45
|
+
/** Wire withClient to call the callback with a { query } client. */
|
|
46
|
+
function withMockQuery(mockQuery) {
|
|
47
|
+
vitest_1.vi.mocked(poolHelpers.withClient).mockImplementation(async (_pool, fn) => {
|
|
48
|
+
const client = { query: mockQuery };
|
|
49
|
+
return fn(client);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
(0, vitest_1.beforeEach)(() => {
|
|
53
|
+
vitest_1.vi.clearAllMocks();
|
|
54
|
+
});
|
|
55
|
+
(0, vitest_1.describe)("getApiKey", () => {
|
|
56
|
+
(0, vitest_1.it)("selects a key by id and returns its owning tenant", async () => {
|
|
57
|
+
const pool = (0, test_helpers_js_1.makeMockPool)();
|
|
58
|
+
const row = { id: "key-1", tenant_id: "tenant-1", name: null, created_at: new Date(), last_used_at: null, revoked_at: null, expires_at: null };
|
|
59
|
+
const mockQuery = vitest_1.vi.fn().mockResolvedValueOnce({ rows: [row] });
|
|
60
|
+
withMockQuery(mockQuery);
|
|
61
|
+
const result = await apiKeyService.getApiKey(pool, "key-1");
|
|
62
|
+
(0, vitest_1.expect)(result).toEqual(row);
|
|
63
|
+
const [sql, params] = mockQuery.mock.calls[0];
|
|
64
|
+
(0, vitest_1.expect)(sql).toContain("FROM api_keys WHERE id = $1");
|
|
65
|
+
(0, vitest_1.expect)(sql).toContain("tenant_id");
|
|
66
|
+
(0, vitest_1.expect)(params).toEqual(["key-1"]);
|
|
67
|
+
});
|
|
68
|
+
(0, vitest_1.it)("returns null when no key has that id", async () => {
|
|
69
|
+
const pool = (0, test_helpers_js_1.makeMockPool)();
|
|
70
|
+
const mockQuery = vitest_1.vi.fn().mockResolvedValueOnce({ rows: [] });
|
|
71
|
+
withMockQuery(mockQuery);
|
|
72
|
+
const result = await apiKeyService.getApiKey(pool, "ghost");
|
|
73
|
+
(0, vitest_1.expect)(result).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=api-key-service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key-service.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/api-key-service.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mCAA8D;AAE9D,qDAAqD;AACrD,WAAE,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC;IACtC,UAAU,EAAE,WAAE,CAAC,EAAE,EAAE;IACnB,eAAe,EAAE,WAAE,CAAC,EAAE,EAAE;CACzB,CAAC,CAAC,CAAC;AAEJ,mEAAqD;AACrD,qEAAuD;AACvD,uDAAiD;AAEjD,oEAAoE;AACpE,SAAS,aAAa,CAAC,SAAmC;IACxD,WAAE,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QACvE,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,SAAS,EAAwC,CAAC;QAC1E,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAA,mBAAU,EAAC,GAAG,EAAE;IACd,WAAE,CAAC,aAAa,EAAE,CAAC;AACrB,CAAC,CAAC,CAAC;AAEH,IAAA,iBAAQ,EAAC,WAAW,EAAE,GAAG,EAAE;IACzB,IAAA,WAAE,EAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,IAAI,GAAG,IAAA,8BAAY,GAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QAC/I,MAAM,SAAS,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjE,aAAa,CAAC,SAAS,CAAC,CAAC;QAEzB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAE5D,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAA,eAAM,EAAC,GAAG,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;QACrD,IAAA,eAAM,EAAC,GAAG,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACnC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,IAAI,GAAG,IAAA,8BAAY,GAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9D,aAAa,CAAC,SAAS,CAAC,CAAC;QAEzB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5D,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -82,6 +82,38 @@ function signPayload(secret, payload) {
|
|
|
82
82
|
(0, vitest_1.expect)(sig1).not.toBe(sig2);
|
|
83
83
|
});
|
|
84
84
|
});
|
|
85
|
+
(0, vitest_1.describe)("webhook egress filter (SSRF protection)", () => {
|
|
86
|
+
// Regression: bracketed IPv6 literals must be rejected in every notation.
|
|
87
|
+
// The URL parser exposes IPv6 hosts wrapped in brackets, so a filter that
|
|
88
|
+
// only matches the unbracketed textual form lets internal targets through.
|
|
89
|
+
const mustReject = [
|
|
90
|
+
["bracketed IPv6 loopback", "http://[::1]/hook"],
|
|
91
|
+
["expanded IPv6 loopback", "http://[0:0:0:0:0:0:0:1]/hook"],
|
|
92
|
+
["IPv6 link-local", "http://[fe80::1]/hook"],
|
|
93
|
+
["IPv6 unique-local", "http://[fd00:ec2::254]/hook"],
|
|
94
|
+
["IPv4-mapped loopback", "http://[::ffff:127.0.0.1]/hook"],
|
|
95
|
+
["IPv4-mapped metadata address", "http://[::ffff:169.254.169.254]/hook"],
|
|
96
|
+
["unspecified IPv6 address", "http://[::]/hook"],
|
|
97
|
+
["integer-coerced loopback", "http://2130706433/hook"],
|
|
98
|
+
];
|
|
99
|
+
for (const [label, url] of mustReject) {
|
|
100
|
+
(0, vitest_1.it)(`rejects ${label}`, () => {
|
|
101
|
+
(0, vitest_1.expect)(() => eventService.validateWebhookUrl(url)).toThrow();
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
// Unbracketed forms that already worked must keep working.
|
|
105
|
+
(0, vitest_1.it)("still rejects IPv4 loopback and metadata", () => {
|
|
106
|
+
(0, vitest_1.expect)(() => eventService.validateWebhookUrl("http://127.0.0.1/hook")).toThrow();
|
|
107
|
+
(0, vitest_1.expect)(() => eventService.validateWebhookUrl("http://169.254.169.254/hook")).toThrow();
|
|
108
|
+
(0, vitest_1.expect)(() => eventService.validateWebhookUrl("http://localhost/hook")).toThrow();
|
|
109
|
+
});
|
|
110
|
+
(0, vitest_1.it)("allows a public https target", () => {
|
|
111
|
+
(0, vitest_1.expect)(() => eventService.validateWebhookUrl("https://example.com/hook")).not.toThrow();
|
|
112
|
+
});
|
|
113
|
+
(0, vitest_1.it)("fails closed on an unparseable URL", () => {
|
|
114
|
+
(0, vitest_1.expect)(() => eventService.validateWebhookUrl("http://[not-an-ip/hook")).toThrow();
|
|
115
|
+
});
|
|
116
|
+
});
|
|
85
117
|
(0, vitest_1.describe)("retry backoff calculation", () => {
|
|
86
118
|
// attempts^2 * 5000ms
|
|
87
119
|
const cases = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-service.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/event-service.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"event-service.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/event-service.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-rotation-service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/key-rotation-service.test.ts"],"names":[],"mappings":""}
|