@stratum-hq/lib 0.2.3 → 0.2.4
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__/migrate-schemas.test.d.ts +2 -0
- package/dist/__tests__/migrate-schemas.test.d.ts.map +1 -0
- package/dist/__tests__/migrate-schemas.test.js +225 -0
- package/dist/__tests__/migrate-schemas.test.js.map +1 -0
- package/dist/__tests__/stratum-als.test.d.ts +2 -0
- package/dist/__tests__/stratum-als.test.d.ts.map +1 -0
- package/dist/__tests__/stratum-als.test.js +49 -0
- package/dist/__tests__/stratum-als.test.js.map +1 -0
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +9 -3
- package/dist/crypto.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/migrate-schemas.d.ts +22 -0
- package/dist/migrate-schemas.d.ts.map +1 -0
- package/dist/migrate-schemas.js +128 -0
- package/dist/migrate-schemas.js.map +1 -0
- package/dist/migrations/001_init.sql +12 -3
- package/dist/services/event-service.d.ts +7 -0
- package/dist/services/event-service.d.ts.map +1 -1
- package/dist/services/event-service.js +2 -0
- package/dist/services/event-service.js.map +1 -1
- package/dist/stratum.d.ts +16 -3
- package/dist/stratum.d.ts.map +1 -1
- package/dist/stratum.js +30 -23
- package/dist/stratum.js.map +1 -1
- package/package.json +20 -1
- package/dist/migrations/migrations/001_init.sql +0 -145
- package/dist/migrations/migrations/002_schema_isolation.sql +0 -6
- package/dist/migrations/migrations/003_db_isolation.sql +0 -12
- package/dist/migrations/migrations/004_webhooks.sql +0 -53
- package/dist/migrations/migrations/005_audit_logs.sql +0 -21
- package/dist/migrations/migrations/006_api_key_scopes.sql +0 -2
- package/dist/migrations/migrations/007_sensitive_config.sql +0 -1
- package/dist/migrations/migrations/008_api_key_management.sql +0 -7
- package/dist/migrations/migrations/009_consent.sql +0 -18
- package/dist/migrations/migrations/010_multi_region.sql +0 -19
- package/dist/migrations/migrations/011_demo_bootstrap.sql +0 -5
- package/dist/migrations/migrations/012_roles.sql +0 -18
- package/dist/migrations/migrations/013_api_key_hmac.sql +0 -4
- package/dist/migrations/migrations/014_sort_order.sql +0 -5
- package/dist/migrations/migrations/015_region_url_encryption.sql +0 -5
- package/dist/migrations/migrations/016_migration_alias.sql +0 -8
- /package/dist/migrations/{migrations/017_abac_policies.sql → 017_abac_policies.sql} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-schemas.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/migrate-schemas.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const migrate_schemas_js_1 = require("../migrate-schemas.js");
|
|
5
|
+
// Mock fs and path so we don't need real migration files
|
|
6
|
+
vitest_1.vi.mock("node:fs", () => ({
|
|
7
|
+
default: {
|
|
8
|
+
existsSync: vitest_1.vi.fn().mockReturnValue(true),
|
|
9
|
+
readdirSync: vitest_1.vi.fn().mockReturnValue(["001_init.sql", "002_schema.sql"]),
|
|
10
|
+
readFileSync: vitest_1.vi.fn().mockImplementation((_path) => {
|
|
11
|
+
if (_path.includes("001_init"))
|
|
12
|
+
return "CREATE TABLE test1 (id INT);";
|
|
13
|
+
return "CREATE TABLE test2 (id INT);";
|
|
14
|
+
}),
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
17
|
+
function createMockClient() {
|
|
18
|
+
const applied = new Set();
|
|
19
|
+
return {
|
|
20
|
+
query: vitest_1.vi.fn().mockImplementation((sql, params) => {
|
|
21
|
+
// Track SET search_path calls
|
|
22
|
+
if (typeof sql === "string" && sql.includes("search_path")) {
|
|
23
|
+
return Promise.resolve({ rows: [] });
|
|
24
|
+
}
|
|
25
|
+
// Check if migration already applied
|
|
26
|
+
if (typeof sql === "string" &&
|
|
27
|
+
sql.includes("SELECT 1 FROM _migrations") &&
|
|
28
|
+
params) {
|
|
29
|
+
const name = params[0];
|
|
30
|
+
if (applied.has(name)) {
|
|
31
|
+
return Promise.resolve({ rows: [{ "?column?": 1 }] });
|
|
32
|
+
}
|
|
33
|
+
return Promise.resolve({ rows: [] });
|
|
34
|
+
}
|
|
35
|
+
// Record applied migration
|
|
36
|
+
if (typeof sql === "string" &&
|
|
37
|
+
sql.includes("INSERT INTO _migrations") &&
|
|
38
|
+
params) {
|
|
39
|
+
applied.add(params[0]);
|
|
40
|
+
return Promise.resolve({ rows: [] });
|
|
41
|
+
}
|
|
42
|
+
return Promise.resolve({ rows: [] });
|
|
43
|
+
}),
|
|
44
|
+
release: vitest_1.vi.fn(),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function createMockPool(schemas, opts) {
|
|
48
|
+
const clients = [];
|
|
49
|
+
const pool = {
|
|
50
|
+
query: vitest_1.vi.fn().mockImplementation((sql) => {
|
|
51
|
+
if (sql.includes("SELECT slug FROM tenants")) {
|
|
52
|
+
return Promise.resolve({
|
|
53
|
+
rows: schemas.map((s) => ({ slug: s })),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return Promise.resolve({ rows: [] });
|
|
57
|
+
}),
|
|
58
|
+
connect: vitest_1.vi.fn().mockImplementation(() => {
|
|
59
|
+
const client = createMockClient();
|
|
60
|
+
if (opts?.failSchema) {
|
|
61
|
+
const origQuery = client.query;
|
|
62
|
+
client.query = vitest_1.vi.fn().mockImplementation((sql, params) => {
|
|
63
|
+
// Fail on the actual migration SQL for the target schema
|
|
64
|
+
if (typeof sql === "string" &&
|
|
65
|
+
sql.includes("search_path") &&
|
|
66
|
+
sql.includes(`tenant_${opts.failSchema}`)) {
|
|
67
|
+
// Let the search_path call succeed, but fail on the next migration SQL
|
|
68
|
+
const innerQuery = vitest_1.vi.fn().mockImplementation((innerSql, innerParams) => {
|
|
69
|
+
if (innerSql.startsWith("CREATE TABLE test")) {
|
|
70
|
+
return Promise.reject(new Error(`Migration failed for schema tenant_${opts.failSchema}`));
|
|
71
|
+
}
|
|
72
|
+
return origQuery(innerSql, innerParams);
|
|
73
|
+
});
|
|
74
|
+
// Replace query for subsequent calls
|
|
75
|
+
client.query = innerQuery;
|
|
76
|
+
return Promise.resolve({ rows: [] });
|
|
77
|
+
}
|
|
78
|
+
return origQuery(sql, params);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
clients.push(client);
|
|
82
|
+
return Promise.resolve(client);
|
|
83
|
+
}),
|
|
84
|
+
_clients: clients,
|
|
85
|
+
};
|
|
86
|
+
return pool;
|
|
87
|
+
}
|
|
88
|
+
(0, vitest_1.beforeEach)(() => {
|
|
89
|
+
vitest_1.vi.clearAllMocks();
|
|
90
|
+
});
|
|
91
|
+
(0, vitest_1.describe)("migrateAllSchemas", () => {
|
|
92
|
+
(0, vitest_1.it)("discovers schemas from tenants table", async () => {
|
|
93
|
+
const pool = createMockPool(["acme", "globex"]);
|
|
94
|
+
await (0, migrate_schemas_js_1.migrateAllSchemas)({ pool });
|
|
95
|
+
(0, vitest_1.expect)(pool.query).toHaveBeenCalledWith(vitest_1.expect.stringContaining("SELECT slug FROM tenants"));
|
|
96
|
+
});
|
|
97
|
+
(0, vitest_1.it)("runs migrations per schema with correct search_path", async () => {
|
|
98
|
+
const pool = createMockPool(["acme"]);
|
|
99
|
+
const result = await (0, migrate_schemas_js_1.migrateAllSchemas)({ pool });
|
|
100
|
+
(0, vitest_1.expect)(result.succeeded).toContain("tenant_acme");
|
|
101
|
+
(0, vitest_1.expect)(result.failed).toHaveLength(0);
|
|
102
|
+
// Verify search_path was set for the schema
|
|
103
|
+
const allCalls = pool._clients.flatMap((c) => c.query.mock.calls.map((call) => call[0]));
|
|
104
|
+
const searchPathCalls = allCalls.filter((s) => typeof s === "string" && s.includes("search_path"));
|
|
105
|
+
(0, vitest_1.expect)(searchPathCalls.some((s) => s.includes("tenant_acme"))).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
(0, vitest_1.it)("continue-on-error: collects failures in result.failed[]", async () => {
|
|
108
|
+
// Create a pool where one schema will fail
|
|
109
|
+
const pool = createMockPool(["acme", "badco"]);
|
|
110
|
+
// Override connect to fail for badco's migration
|
|
111
|
+
let callCount = 0;
|
|
112
|
+
const origConnect = pool.connect;
|
|
113
|
+
pool.connect = vitest_1.vi.fn().mockImplementation(() => {
|
|
114
|
+
callCount++;
|
|
115
|
+
const client = createMockClient();
|
|
116
|
+
// Make every other set of clients fail for badco
|
|
117
|
+
const origQuery = client.query;
|
|
118
|
+
let currentSchema = "";
|
|
119
|
+
client.query = vitest_1.vi.fn().mockImplementation((sql, params) => {
|
|
120
|
+
if (typeof sql === "string" && sql.includes("search_path")) {
|
|
121
|
+
if (sql.includes("tenant_badco")) {
|
|
122
|
+
currentSchema = "badco";
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
currentSchema = "";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (currentSchema === "badco" &&
|
|
129
|
+
typeof sql === "string" &&
|
|
130
|
+
sql.startsWith("CREATE TABLE test")) {
|
|
131
|
+
return Promise.reject(new Error("Schema migration failed"));
|
|
132
|
+
}
|
|
133
|
+
return origQuery(sql, params);
|
|
134
|
+
});
|
|
135
|
+
pool._clients.push(client);
|
|
136
|
+
return Promise.resolve(client);
|
|
137
|
+
});
|
|
138
|
+
const result = await (0, migrate_schemas_js_1.migrateAllSchemas)({ pool });
|
|
139
|
+
(0, vitest_1.expect)(result.succeeded).toContain("tenant_acme");
|
|
140
|
+
(0, vitest_1.expect)(result.failed.length).toBeGreaterThan(0);
|
|
141
|
+
(0, vitest_1.expect)(result.failed[0].schema).toBe("tenant_badco");
|
|
142
|
+
(0, vitest_1.expect)(result.failed[0].error).toBeInstanceOf(Error);
|
|
143
|
+
});
|
|
144
|
+
(0, vitest_1.it)("progress callback called with correct args", async () => {
|
|
145
|
+
const pool = createMockPool(["acme", "globex"]);
|
|
146
|
+
const progress = vitest_1.vi.fn();
|
|
147
|
+
await (0, migrate_schemas_js_1.migrateAllSchemas)({ pool, onProgress: progress });
|
|
148
|
+
(0, vitest_1.expect)(progress).toHaveBeenCalledTimes(2);
|
|
149
|
+
// Each call should have (schema, index, total)
|
|
150
|
+
const calls = progress.mock.calls;
|
|
151
|
+
for (const call of calls) {
|
|
152
|
+
(0, vitest_1.expect)(typeof call[0]).toBe("string");
|
|
153
|
+
(0, vitest_1.expect)(typeof call[1]).toBe("number");
|
|
154
|
+
(0, vitest_1.expect)(call[2]).toBe(2);
|
|
155
|
+
}
|
|
156
|
+
// Indices should be 1 and 2 (completed count)
|
|
157
|
+
const indices = calls.map((c) => c[1]).sort();
|
|
158
|
+
(0, vitest_1.expect)(indices).toEqual([1, 2]);
|
|
159
|
+
});
|
|
160
|
+
(0, vitest_1.it)("idempotent re-run: already-applied migrations skipped", async () => {
|
|
161
|
+
// Create pool with a client that reports migrations as already applied
|
|
162
|
+
const pool = createMockPool(["acme"]);
|
|
163
|
+
const origConnect = pool.connect;
|
|
164
|
+
pool.connect = vitest_1.vi.fn().mockImplementation(() => {
|
|
165
|
+
const client = createMockClient();
|
|
166
|
+
// Override: all migrations already applied
|
|
167
|
+
const origQuery = client.query;
|
|
168
|
+
client.query = vitest_1.vi.fn().mockImplementation((sql, params) => {
|
|
169
|
+
if (typeof sql === "string" &&
|
|
170
|
+
sql.includes("SELECT 1 FROM _migrations") &&
|
|
171
|
+
params) {
|
|
172
|
+
return Promise.resolve({ rows: [{ "?column?": 1 }] });
|
|
173
|
+
}
|
|
174
|
+
return origQuery(sql, params);
|
|
175
|
+
});
|
|
176
|
+
pool._clients.push(client);
|
|
177
|
+
return Promise.resolve(client);
|
|
178
|
+
});
|
|
179
|
+
const result = await (0, migrate_schemas_js_1.migrateAllSchemas)({ pool });
|
|
180
|
+
(0, vitest_1.expect)(result.succeeded).toContain("tenant_acme");
|
|
181
|
+
(0, vitest_1.expect)(result.failed).toHaveLength(0);
|
|
182
|
+
// No INSERT should have been called (migrations skipped)
|
|
183
|
+
const allCalls = pool._clients.flatMap((c) => c.query.mock.calls.map((call) => call[0]));
|
|
184
|
+
const inserts = allCalls.filter((s) => typeof s === "string" && s.includes("INSERT INTO _migrations"));
|
|
185
|
+
(0, vitest_1.expect)(inserts).toHaveLength(0);
|
|
186
|
+
});
|
|
187
|
+
(0, vitest_1.it)("empty schema list returns empty result", async () => {
|
|
188
|
+
const pool = createMockPool([]);
|
|
189
|
+
const result = await (0, migrate_schemas_js_1.migrateAllSchemas)({ pool });
|
|
190
|
+
(0, vitest_1.expect)(result.succeeded).toEqual([]);
|
|
191
|
+
(0, vitest_1.expect)(result.failed).toEqual([]);
|
|
192
|
+
});
|
|
193
|
+
(0, vitest_1.it)("respects concurrency limit", async () => {
|
|
194
|
+
const schemas = Array.from({ length: 10 }, (_, i) => `tenant${i}`);
|
|
195
|
+
const pool = createMockPool(schemas);
|
|
196
|
+
let maxConcurrent = 0;
|
|
197
|
+
let currentConcurrent = 0;
|
|
198
|
+
const origConnect = pool.connect;
|
|
199
|
+
pool.connect = vitest_1.vi.fn().mockImplementation(async () => {
|
|
200
|
+
currentConcurrent++;
|
|
201
|
+
if (currentConcurrent > maxConcurrent) {
|
|
202
|
+
maxConcurrent = currentConcurrent;
|
|
203
|
+
}
|
|
204
|
+
const client = createMockClient();
|
|
205
|
+
// Add a small delay to simulate work
|
|
206
|
+
const origQuery = client.query;
|
|
207
|
+
client.query = vitest_1.vi.fn().mockImplementation(async (sql, params) => {
|
|
208
|
+
if (typeof sql === "string" && sql.includes("COMMIT")) {
|
|
209
|
+
// Small delay on commit
|
|
210
|
+
await new Promise((r) => setTimeout(r, 5));
|
|
211
|
+
currentConcurrent--;
|
|
212
|
+
}
|
|
213
|
+
return origQuery(sql, params);
|
|
214
|
+
});
|
|
215
|
+
pool._clients.push(client);
|
|
216
|
+
return client;
|
|
217
|
+
});
|
|
218
|
+
await (0, migrate_schemas_js_1.migrateAllSchemas)({ pool, concurrency: 3 });
|
|
219
|
+
// maxConcurrent should not exceed concurrency * migrations_per_schema
|
|
220
|
+
// but the schema-level concurrency should be limited
|
|
221
|
+
// Due to the semaphore, we expect at most 3 schemas in flight
|
|
222
|
+
(0, vitest_1.expect)(maxConcurrent).toBeLessThanOrEqual(3 * 2); // 3 concurrent * 2 migration files
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
//# sourceMappingURL=migrate-schemas.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-schemas.test.js","sourceRoot":"","sources":["../../src/__tests__/migrate-schemas.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stratum-als.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/stratum-als.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const stratum_js_1 = require("../stratum.js");
|
|
5
|
+
const mockContext = {
|
|
6
|
+
tenant_id: "t_abc-123",
|
|
7
|
+
ancestry_path: "/t_abc-123",
|
|
8
|
+
depth: 0,
|
|
9
|
+
resolved_config: { feature_x: true },
|
|
10
|
+
resolved_permissions: {},
|
|
11
|
+
isolation_strategy: "SHARED_RLS",
|
|
12
|
+
};
|
|
13
|
+
(0, vitest_1.describe)("Stratum ALS convenience methods", () => {
|
|
14
|
+
(0, vitest_1.it)("currentTenantId() returns tenant ID inside runWithTenant", () => {
|
|
15
|
+
const result = stratum_js_1.Stratum.runWithTenant(mockContext, () => {
|
|
16
|
+
return stratum_js_1.Stratum.currentTenantId();
|
|
17
|
+
});
|
|
18
|
+
(0, vitest_1.expect)(result).toBe("t_abc-123");
|
|
19
|
+
});
|
|
20
|
+
(0, vitest_1.it)("currentTenantId() returns undefined outside any context", () => {
|
|
21
|
+
(0, vitest_1.expect)(stratum_js_1.Stratum.currentTenantId()).toBeUndefined();
|
|
22
|
+
});
|
|
23
|
+
(0, vitest_1.it)("currentTenantContext() returns full context object", () => {
|
|
24
|
+
const result = stratum_js_1.Stratum.runWithTenant(mockContext, () => {
|
|
25
|
+
return stratum_js_1.Stratum.currentTenantContext();
|
|
26
|
+
});
|
|
27
|
+
(0, vitest_1.expect)(result).toEqual(mockContext);
|
|
28
|
+
});
|
|
29
|
+
(0, vitest_1.it)("currentTenantContext() returns undefined outside any context", () => {
|
|
30
|
+
(0, vitest_1.expect)(stratum_js_1.Stratum.currentTenantContext()).toBeUndefined();
|
|
31
|
+
});
|
|
32
|
+
(0, vitest_1.it)("runWithTenant() executes the function and returns its value", () => {
|
|
33
|
+
const result = stratum_js_1.Stratum.runWithTenant(mockContext, () => 42);
|
|
34
|
+
(0, vitest_1.expect)(result).toBe(42);
|
|
35
|
+
});
|
|
36
|
+
(0, vitest_1.it)("nested runWithTenant() uses innermost context", () => {
|
|
37
|
+
const inner = {
|
|
38
|
+
...mockContext,
|
|
39
|
+
tenant_id: "t_inner-456",
|
|
40
|
+
};
|
|
41
|
+
const result = stratum_js_1.Stratum.runWithTenant(mockContext, () => {
|
|
42
|
+
return stratum_js_1.Stratum.runWithTenant(inner, () => {
|
|
43
|
+
return stratum_js_1.Stratum.currentTenantId();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
(0, vitest_1.expect)(result).toBe("t_inner-456");
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=stratum-als.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stratum-als.test.js","sourceRoot":"","sources":["../../src/__tests__/stratum-als.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,8CAAwC;AAGxC,MAAM,WAAW,GAAwB;IACvC,SAAS,EAAE,WAAW;IACtB,aAAa,EAAE,YAAY;IAC3B,KAAK,EAAE,CAAC;IACR,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE;IACpC,oBAAoB,EAAE,EAAE;IACxB,kBAAkB,EAAE,YAAY;CACjC,CAAC;AAEF,IAAA,iBAAQ,EAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,IAAA,WAAE,EAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,MAAM,GAAG,oBAAO,CAAC,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE;YACrD,OAAO,oBAAO,CAAC,eAAe,EAAE,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,IAAA,eAAM,EAAC,oBAAO,CAAC,eAAe,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,MAAM,GAAG,oBAAO,CAAC,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE;YACrD,OAAO,oBAAO,CAAC,oBAAoB,EAAE,CAAC;QACxC,CAAC,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,IAAA,eAAM,EAAC,oBAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,MAAM,GAAG,oBAAO,CAAC,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5D,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,KAAK,GAAwB;YACjC,GAAG,WAAW;YACd,SAAS,EAAE,aAAa;SACzB,CAAC;QACF,MAAM,MAAM,GAAG,oBAAO,CAAC,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE;YACrD,OAAO,oBAAO,CAAC,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE;gBACvC,OAAO,oBAAO,CAAC,eAAe,EAAE,CAAC;YACnC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/crypto.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAmEA,qFAAqF;AACrF,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;yDAEyD;AACzD,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED,uHAAuH;AACvH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAGnG"}
|
package/dist/crypto.js
CHANGED
|
@@ -11,9 +11,15 @@ const ALGORITHM = "aes-256-gcm";
|
|
|
11
11
|
const IV_LENGTH = 12;
|
|
12
12
|
const AUTH_TAG_LENGTH = 16;
|
|
13
13
|
const CURRENT_KEY_VERSION = "v1";
|
|
14
|
-
const HKDF_SALT =
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const HKDF_SALT = (() => {
|
|
15
|
+
if (process.env.STRATUM_HKDF_SALT) {
|
|
16
|
+
return Buffer.from(process.env.STRATUM_HKDF_SALT, "hex");
|
|
17
|
+
}
|
|
18
|
+
if (process.env.NODE_ENV === "production") {
|
|
19
|
+
throw new Error("STRATUM_HKDF_SALT must be set in production");
|
|
20
|
+
}
|
|
21
|
+
return node_crypto_1.default.randomBytes(32);
|
|
22
|
+
})();
|
|
17
23
|
function hkdfDeriveKey(keyMaterial, info = "stratum-aes-key") {
|
|
18
24
|
return Buffer.from(node_crypto_1.default.hkdfSync("sha256", Buffer.from(keyMaterial, "utf8"), HKDF_SALT, info, 32));
|
|
19
25
|
}
|
package/dist/crypto.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { Stratum, type StratumOptions } from "./stratum.js";
|
|
2
2
|
export { migrate, type MigrateOptions } from "./migrate.js";
|
|
3
|
+
export { migrateAllSchemas, type MigrateSchemasOptions, type MigrateSchemasResult, } from "./migrate-schemas.js";
|
|
3
4
|
export { withClient, withTransaction } from "./pool-helpers.js";
|
|
4
5
|
export { traced, getTracer, isTracingEnabled } from "./telemetry.js";
|
|
5
6
|
export type { TenantNode, TenantContext, CreateTenantInput, UpdateTenantInput, MoveTenantInput, PaginationInput, PaginatedResult, ConfigEntry, SetConfigInput, ResolvedConfigEntry, ResolvedConfig, PermissionPolicy, CreatePermissionInput, UpdatePermissionInput, ResolvedPermission, } from "@stratum-hq/core";
|
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,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,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,10 +1,12 @@
|
|
|
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.migrate = exports.Stratum = void 0;
|
|
3
|
+
exports.noopLogger = exports.defaultLogger = exports.isTracingEnabled = exports.getTracer = exports.traced = 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");
|
|
7
7
|
Object.defineProperty(exports, "migrate", { enumerable: true, get: function () { return migrate_js_1.migrate; } });
|
|
8
|
+
var migrate_schemas_js_1 = require("./migrate-schemas.js");
|
|
9
|
+
Object.defineProperty(exports, "migrateAllSchemas", { enumerable: true, get: function () { return migrate_schemas_js_1.migrateAllSchemas; } });
|
|
8
10
|
var pool_helpers_js_1 = require("./pool-helpers.js");
|
|
9
11
|
Object.defineProperty(exports, "withClient", { enumerable: true, get: function () { return pool_helpers_js_1.withClient; } });
|
|
10
12
|
Object.defineProperty(exports, "withTransaction", { enumerable: true, get: function () { return pool_helpers_js_1.withTransaction; } });
|
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,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,+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,22 @@
|
|
|
1
|
+
import pg from "pg";
|
|
2
|
+
export interface MigrateSchemasOptions {
|
|
3
|
+
pool: pg.Pool;
|
|
4
|
+
concurrency?: number;
|
|
5
|
+
onProgress?: (schema: string, index: number, total: number) => void;
|
|
6
|
+
enforceRls?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface MigrateSchemasResult {
|
|
9
|
+
succeeded: string[];
|
|
10
|
+
failed: {
|
|
11
|
+
schema: string;
|
|
12
|
+
error: Error;
|
|
13
|
+
}[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Discover all tenant schemas (tenants with SCHEMA_PER_TENANT isolation)
|
|
17
|
+
* and run the standard migration set against each one.
|
|
18
|
+
*
|
|
19
|
+
* Continues on error: schemas that fail are collected in result.failed[].
|
|
20
|
+
*/
|
|
21
|
+
export declare function migrateAllSchemas(options: MigrateSchemasOptions): Promise<MigrateSchemasResult>;
|
|
22
|
+
//# sourceMappingURL=migrate-schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-schemas.d.ts","sourceRoot":"","sources":["../src/migrate-schemas.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,EAAE,CAAC;CAC5C;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA2D/B"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.migrateAllSchemas = migrateAllSchemas;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
/**
|
|
10
|
+
* Discover all tenant schemas (tenants with SCHEMA_PER_TENANT isolation)
|
|
11
|
+
* and run the standard migration set against each one.
|
|
12
|
+
*
|
|
13
|
+
* Continues on error: schemas that fail are collected in result.failed[].
|
|
14
|
+
*/
|
|
15
|
+
async function migrateAllSchemas(options) {
|
|
16
|
+
const { pool, concurrency = 5, onProgress, enforceRls } = options;
|
|
17
|
+
// Discover tenant schemas
|
|
18
|
+
const { rows } = await pool.query(`SELECT slug FROM tenants WHERE isolation_strategy = 'SCHEMA_PER_TENANT' AND (deleted_at IS NULL) ORDER BY slug`);
|
|
19
|
+
const schemas = rows.map((r) => `tenant_${r.slug}`);
|
|
20
|
+
const result = { succeeded: [], failed: [] };
|
|
21
|
+
if (schemas.length === 0) {
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
// Load migration files once
|
|
25
|
+
const migrationsDir = node_path_1.default.resolve(__dirname, "migrations");
|
|
26
|
+
if (!node_fs_1.default.existsSync(migrationsDir)) {
|
|
27
|
+
throw new Error(`Migration files not found at ${migrationsDir}. Ensure the package was built with 'npm run build'.`);
|
|
28
|
+
}
|
|
29
|
+
const files = node_fs_1.default
|
|
30
|
+
.readdirSync(migrationsDir)
|
|
31
|
+
.filter((f) => f.endsWith(".sql"))
|
|
32
|
+
.sort();
|
|
33
|
+
const migrationSql = files.map((file) => ({
|
|
34
|
+
name: file,
|
|
35
|
+
sql: node_fs_1.default.readFileSync(node_path_1.default.join(migrationsDir, file), "utf-8"),
|
|
36
|
+
}));
|
|
37
|
+
// Process schemas in chunks of `concurrency` size
|
|
38
|
+
let completed = 0;
|
|
39
|
+
for (let i = 0; i < schemas.length; i += concurrency) {
|
|
40
|
+
const chunk = schemas.slice(i, i + concurrency);
|
|
41
|
+
const results = await Promise.allSettled(chunk.map((schema) => migrateSchema(pool, schema, migrationSql, enforceRls)));
|
|
42
|
+
for (let j = 0; j < results.length; j++) {
|
|
43
|
+
const schema = chunk[j];
|
|
44
|
+
const outcome = results[j];
|
|
45
|
+
if (outcome.status === "fulfilled") {
|
|
46
|
+
result.succeeded.push(schema);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const err = outcome.reason;
|
|
50
|
+
result.failed.push({
|
|
51
|
+
schema,
|
|
52
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
completed++;
|
|
56
|
+
onProgress?.(schema, completed, schemas.length);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
async function migrateSchema(pool, schema, migrations, enforceRls) {
|
|
62
|
+
// Use a hash of the schema name for a unique advisory lock key per schema
|
|
63
|
+
const lockKey = hashSchemaLock(schema);
|
|
64
|
+
for (const migration of migrations) {
|
|
65
|
+
const client = await pool.connect();
|
|
66
|
+
try {
|
|
67
|
+
await client.query("BEGIN");
|
|
68
|
+
// Advisory lock scoped to this schema
|
|
69
|
+
await client.query(`SELECT pg_advisory_xact_lock($1)`, [lockKey]);
|
|
70
|
+
// Set search_path to the tenant schema
|
|
71
|
+
await client.query(`SET LOCAL search_path = ${quoteIdent(schema)}, public`);
|
|
72
|
+
// Ensure _migrations table exists in this schema
|
|
73
|
+
await client.query(`
|
|
74
|
+
CREATE TABLE IF NOT EXISTS _migrations (
|
|
75
|
+
id SERIAL PRIMARY KEY,
|
|
76
|
+
name TEXT NOT NULL UNIQUE,
|
|
77
|
+
applied_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
78
|
+
)
|
|
79
|
+
`);
|
|
80
|
+
// Check if already applied
|
|
81
|
+
const { rows } = await client.query("SELECT 1 FROM _migrations WHERE name = $1", [migration.name]);
|
|
82
|
+
if (rows.length > 0) {
|
|
83
|
+
await client.query("COMMIT");
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (enforceRls) {
|
|
87
|
+
await client.query("SET LOCAL stratum.enforce_rls = 'on'");
|
|
88
|
+
}
|
|
89
|
+
await client.query(migration.sql);
|
|
90
|
+
await client.query("INSERT INTO _migrations (name) VALUES ($1)", [
|
|
91
|
+
migration.name,
|
|
92
|
+
]);
|
|
93
|
+
await client.query("COMMIT");
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
try {
|
|
97
|
+
await client.query("ROLLBACK");
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
/* ignore rollback failure */
|
|
101
|
+
}
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
client.release();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Produce a stable int32 advisory lock key from a schema name.
|
|
111
|
+
* Uses a simple djb2-style hash.
|
|
112
|
+
*/
|
|
113
|
+
function hashSchemaLock(schema) {
|
|
114
|
+
let hash = 5381;
|
|
115
|
+
for (let i = 0; i < schema.length; i++) {
|
|
116
|
+
hash = ((hash << 5) + hash + schema.charCodeAt(i)) | 0;
|
|
117
|
+
}
|
|
118
|
+
// Offset from the base migrate lock (8675309) to avoid collision
|
|
119
|
+
return (hash ^ 0x5354524d) | 0; // XOR with "STRM"
|
|
120
|
+
}
|
|
121
|
+
function quoteIdent(name) {
|
|
122
|
+
// Simple identifier quoting — disallow anything that could break out
|
|
123
|
+
if (!/^[a-z_][a-z0-9_]*$/i.test(name)) {
|
|
124
|
+
throw new Error(`Invalid schema name: ${name}`);
|
|
125
|
+
}
|
|
126
|
+
return `"${name}"`;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=migrate-schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-schemas.js","sourceRoot":"","sources":["../src/migrate-schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
-- Extensions
|
|
2
|
-
|
|
3
|
-
CREATE EXTENSION IF NOT EXISTS "
|
|
1
|
+
-- Extensions (require superuser or CREATE privilege; gracefully warn if unavailable)
|
|
2
|
+
DO $$ BEGIN
|
|
3
|
+
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
4
|
+
EXCEPTION WHEN insufficient_privilege THEN
|
|
5
|
+
RAISE WARNING 'Cannot create uuid-ossp extension — insufficient privileges. Ask a database administrator to run: CREATE EXTENSION IF NOT EXISTS "uuid-ossp";';
|
|
6
|
+
END $$;
|
|
7
|
+
|
|
8
|
+
DO $$ BEGIN
|
|
9
|
+
CREATE EXTENSION IF NOT EXISTS "ltree";
|
|
10
|
+
EXCEPTION WHEN insufficient_privilege THEN
|
|
11
|
+
RAISE WARNING 'Cannot create ltree extension — insufficient privileges. Ask a database administrator to run: CREATE EXTENSION IF NOT EXISTS "ltree";';
|
|
12
|
+
END $$;
|
|
4
13
|
|
|
5
14
|
-- Warn if application role has BYPASSRLS privilege.
|
|
6
15
|
-- In production, set stratum.enforce_rls = 'on' to make this a hard error.
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import pg from "pg";
|
|
2
2
|
import type { TenantEvent } from "@stratum-hq/core";
|
|
3
|
+
/** Validates that a webhook URL does not target internal/private networks. */
|
|
4
|
+
export declare function validateWebhookUrl(url: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* DNS-rebinding-safe validation: resolve hostname and check all resolved IPs
|
|
7
|
+
* against blocked ranges. Call this at delivery time, not just registration.
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateWebhookUrlWithDns(url: string): Promise<void>;
|
|
3
10
|
interface WebhookEventRow {
|
|
4
11
|
id: string;
|
|
5
12
|
type: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-service.d.ts","sourceRoot":"","sources":["../../src/services/event-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"event-service.d.ts","sourceRoot":"","sources":["../../src/services/event-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAgCpD,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAwBpD;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsC1E;AA2BD,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,SAAS,CAC7B,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC,CAkCf;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CA4ClF;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAmFpE;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4B7F;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBvF;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA0B/F;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,KAAK,SAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CA0BpC"}
|
|
@@ -3,6 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateWebhookUrl = validateWebhookUrl;
|
|
7
|
+
exports.validateWebhookUrlWithDns = validateWebhookUrlWithDns;
|
|
6
8
|
exports.emitEvent = emitEvent;
|
|
7
9
|
exports.deliverWebhook = deliverWebhook;
|
|
8
10
|
exports.processDeliveries = processDeliveries;
|