@stratum-hq/lib 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/__tests__/crypto.test.d.ts +2 -0
  2. package/dist/__tests__/crypto.test.d.ts.map +1 -0
  3. package/dist/__tests__/crypto.test.js +41 -0
  4. package/dist/__tests__/crypto.test.js.map +1 -0
  5. package/dist/crypto.d.ts +7 -0
  6. package/dist/crypto.d.ts.map +1 -0
  7. package/dist/crypto.js +74 -0
  8. package/dist/crypto.js.map +1 -0
  9. package/dist/index.d.ts +11 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +13 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/pool-helpers.d.ts +4 -0
  14. package/dist/pool-helpers.d.ts.map +1 -0
  15. package/dist/pool-helpers.js +31 -0
  16. package/dist/pool-helpers.js.map +1 -0
  17. package/dist/services/__tests__/audit-service.test.d.ts +2 -0
  18. package/dist/services/__tests__/audit-service.test.d.ts.map +1 -0
  19. package/dist/services/__tests__/audit-service.test.js +220 -0
  20. package/dist/services/__tests__/audit-service.test.js.map +1 -0
  21. package/dist/services/__tests__/config-service.test.d.ts +2 -0
  22. package/dist/services/__tests__/config-service.test.d.ts.map +1 -0
  23. package/dist/services/__tests__/config-service.test.js +555 -0
  24. package/dist/services/__tests__/config-service.test.js.map +1 -0
  25. package/dist/services/__tests__/consent-service.test.d.ts +2 -0
  26. package/dist/services/__tests__/consent-service.test.d.ts.map +1 -0
  27. package/dist/services/__tests__/consent-service.test.js +159 -0
  28. package/dist/services/__tests__/consent-service.test.js.map +1 -0
  29. package/dist/services/__tests__/event-service.test.d.ts +2 -0
  30. package/dist/services/__tests__/event-service.test.d.ts.map +1 -0
  31. package/dist/services/__tests__/event-service.test.js +151 -0
  32. package/dist/services/__tests__/event-service.test.js.map +1 -0
  33. package/dist/services/__tests__/permission-service.test.d.ts +2 -0
  34. package/dist/services/__tests__/permission-service.test.d.ts.map +1 -0
  35. package/dist/services/__tests__/permission-service.test.js +470 -0
  36. package/dist/services/__tests__/permission-service.test.js.map +1 -0
  37. package/dist/services/__tests__/retention-service.test.d.ts +2 -0
  38. package/dist/services/__tests__/retention-service.test.d.ts.map +1 -0
  39. package/dist/services/__tests__/retention-service.test.js +126 -0
  40. package/dist/services/__tests__/retention-service.test.js.map +1 -0
  41. package/dist/services/__tests__/tenant-service.test.d.ts +2 -0
  42. package/dist/services/__tests__/tenant-service.test.d.ts.map +1 -0
  43. package/dist/services/__tests__/tenant-service.test.js +451 -0
  44. package/dist/services/__tests__/tenant-service.test.js.map +1 -0
  45. package/dist/services/__tests__/test-helpers.d.ts +9 -0
  46. package/dist/services/__tests__/test-helpers.d.ts.map +1 -0
  47. package/dist/services/__tests__/test-helpers.js +20 -0
  48. package/dist/services/__tests__/test-helpers.js.map +1 -0
  49. package/dist/services/__tests__/webhook-service.test.d.ts +2 -0
  50. package/dist/services/__tests__/webhook-service.test.d.ts.map +1 -0
  51. package/dist/services/__tests__/webhook-service.test.js +174 -0
  52. package/dist/services/__tests__/webhook-service.test.js.map +1 -0
  53. package/dist/services/api-key-service.d.ts +61 -0
  54. package/dist/services/api-key-service.d.ts.map +1 -0
  55. package/dist/services/api-key-service.js +164 -0
  56. package/dist/services/api-key-service.js.map +1 -0
  57. package/dist/services/audit-service.d.ts +6 -0
  58. package/dist/services/audit-service.d.ts.map +1 -0
  59. package/dist/services/audit-service.js +85 -0
  60. package/dist/services/audit-service.js.map +1 -0
  61. package/dist/services/config-service.d.ts +33 -0
  62. package/dist/services/config-service.d.ts.map +1 -0
  63. package/dist/services/config-service.js +271 -0
  64. package/dist/services/config-service.js.map +1 -0
  65. package/dist/services/consent-service.d.ts +7 -0
  66. package/dist/services/consent-service.d.ts.map +1 -0
  67. package/dist/services/consent-service.js +71 -0
  68. package/dist/services/consent-service.js.map +1 -0
  69. package/dist/services/event-service.d.ts +39 -0
  70. package/dist/services/event-service.d.ts.map +1 -0
  71. package/dist/services/event-service.js +331 -0
  72. package/dist/services/event-service.js.map +1 -0
  73. package/dist/services/key-rotation-service.d.ts +15 -0
  74. package/dist/services/key-rotation-service.d.ts.map +1 -0
  75. package/dist/services/key-rotation-service.js +41 -0
  76. package/dist/services/key-rotation-service.js.map +1 -0
  77. package/dist/services/permission-service.d.ts +21 -0
  78. package/dist/services/permission-service.d.ts.map +1 -0
  79. package/dist/services/permission-service.js +213 -0
  80. package/dist/services/permission-service.js.map +1 -0
  81. package/dist/services/region-service.d.ts +9 -0
  82. package/dist/services/region-service.d.ts.map +1 -0
  83. package/dist/services/region-service.js +105 -0
  84. package/dist/services/region-service.js.map +1 -0
  85. package/dist/services/retention-service.d.ts +19 -0
  86. package/dist/services/retention-service.d.ts.map +1 -0
  87. package/dist/services/retention-service.js +88 -0
  88. package/dist/services/retention-service.js.map +1 -0
  89. package/dist/services/role-service.d.ts +35 -0
  90. package/dist/services/role-service.d.ts.map +1 -0
  91. package/dist/services/role-service.js +101 -0
  92. package/dist/services/role-service.js.map +1 -0
  93. package/dist/services/tenant-service.d.ts +25 -0
  94. package/dist/services/tenant-service.d.ts.map +1 -0
  95. package/dist/services/tenant-service.js +335 -0
  96. package/dist/services/tenant-service.js.map +1 -0
  97. package/dist/services/webhook-service.d.ts +12 -0
  98. package/dist/services/webhook-service.d.ts.map +1 -0
  99. package/dist/services/webhook-service.js +129 -0
  100. package/dist/services/webhook-service.js.map +1 -0
  101. package/dist/stratum.d.ts +107 -0
  102. package/dist/stratum.d.ts.map +1 -0
  103. package/dist/stratum.js +531 -0
  104. package/dist/stratum.js.map +1 -0
  105. package/dist/telemetry.d.ts +27 -0
  106. package/dist/telemetry.d.ts.map +1 -0
  107. package/dist/telemetry.js +94 -0
  108. package/dist/telemetry.js.map +1 -0
  109. package/package.json +46 -0
@@ -0,0 +1,470 @@
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 (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const vitest_1 = require("vitest");
27
+ // Mock pool-helpers before importing permission-service
28
+ vitest_1.vi.mock("../../pool-helpers.js", () => ({
29
+ withClient: vitest_1.vi.fn(),
30
+ withTransaction: vitest_1.vi.fn(),
31
+ }));
32
+ const poolHelpers = __importStar(require("../../pool-helpers.js"));
33
+ const permissionService = __importStar(require("../permission-service.js"));
34
+ const test_helpers_js_1 = require("./test-helpers.js");
35
+ const core_1 = require("@stratum-hq/core");
36
+ (0, vitest_1.beforeEach)(() => {
37
+ vitest_1.vi.clearAllMocks();
38
+ });
39
+ // ---------------------------------------------------------------------------
40
+ // resolvePermissions
41
+ // ---------------------------------------------------------------------------
42
+ (0, vitest_1.describe)("resolvePermissions", () => {
43
+ (0, vitest_1.it)("LOCKED mode: child cannot override", async () => {
44
+ const pool = (0, test_helpers_js_1.makeMockPool)();
45
+ const mockQuery = vitest_1.vi.fn();
46
+ // Query 1: ancestry_path for child
47
+ mockQuery.mockResolvedValueOnce({
48
+ rows: [{ ancestry_path: "/parent-id" }],
49
+ });
50
+ // Query 2: batch-load all policies
51
+ mockQuery.mockResolvedValueOnce({
52
+ rows: [
53
+ {
54
+ id: "policy-1",
55
+ tenant_id: "parent-id",
56
+ key: "can_export",
57
+ value: JSON.stringify(false),
58
+ mode: core_1.PermissionMode.LOCKED,
59
+ revocation_mode: core_1.RevocationMode.CASCADE,
60
+ source_tenant_id: "parent-id",
61
+ created_at: "2024-01-01T00:00:00.000Z",
62
+ updated_at: "2024-01-01T00:00:00.000Z",
63
+ },
64
+ // Child attempts to set the same key
65
+ {
66
+ id: "policy-2",
67
+ tenant_id: "child-id",
68
+ key: "can_export",
69
+ value: JSON.stringify(true),
70
+ mode: core_1.PermissionMode.INHERITED,
71
+ revocation_mode: core_1.RevocationMode.CASCADE,
72
+ source_tenant_id: "child-id",
73
+ created_at: "2024-01-01T00:00:00.000Z",
74
+ updated_at: "2024-01-01T00:00:00.000Z",
75
+ },
76
+ ],
77
+ });
78
+ vitest_1.vi.mocked(poolHelpers.withClient).mockImplementation(async (_pool, fn) => {
79
+ const client = { query: mockQuery };
80
+ return fn(client);
81
+ });
82
+ const result = await permissionService.resolvePermissions(pool, "child-id");
83
+ // Parent's LOCKED value wins
84
+ (0, vitest_1.expect)(result.can_export.value).toBe(JSON.stringify(false));
85
+ (0, vitest_1.expect)(result.can_export.locked).toBe(true);
86
+ (0, vitest_1.expect)(result.can_export.delegated).toBe(false);
87
+ (0, vitest_1.expect)(result.can_export.source_tenant_id).toBe("parent-id");
88
+ (0, vitest_1.expect)(result.can_export.mode).toBe(core_1.PermissionMode.LOCKED);
89
+ });
90
+ (0, vitest_1.it)("INHERITED mode: child can override", async () => {
91
+ const pool = (0, test_helpers_js_1.makeMockPool)();
92
+ const mockQuery = vitest_1.vi.fn();
93
+ mockQuery.mockResolvedValueOnce({
94
+ rows: [{ ancestry_path: "/parent-id" }],
95
+ });
96
+ mockQuery.mockResolvedValueOnce({
97
+ rows: [
98
+ {
99
+ id: "policy-1",
100
+ tenant_id: "parent-id",
101
+ key: "theme_preference",
102
+ value: JSON.stringify("default"),
103
+ mode: core_1.PermissionMode.INHERITED,
104
+ revocation_mode: core_1.RevocationMode.CASCADE,
105
+ source_tenant_id: "parent-id",
106
+ created_at: "2024-01-01T00:00:00.000Z",
107
+ updated_at: "2024-01-01T00:00:00.000Z",
108
+ },
109
+ {
110
+ id: "policy-2",
111
+ tenant_id: "child-id",
112
+ key: "theme_preference",
113
+ value: JSON.stringify("custom"),
114
+ mode: core_1.PermissionMode.INHERITED,
115
+ revocation_mode: core_1.RevocationMode.CASCADE,
116
+ source_tenant_id: "child-id",
117
+ created_at: "2024-01-01T00:00:00.000Z",
118
+ updated_at: "2024-01-01T00:00:00.000Z",
119
+ },
120
+ ],
121
+ });
122
+ vitest_1.vi.mocked(poolHelpers.withClient).mockImplementation(async (_pool, fn) => {
123
+ const client = { query: mockQuery };
124
+ return fn(client);
125
+ });
126
+ const result = await permissionService.resolvePermissions(pool, "child-id");
127
+ // Child override prevails
128
+ (0, vitest_1.expect)(result.theme_preference.value).toBe(JSON.stringify("custom"));
129
+ (0, vitest_1.expect)(result.theme_preference.locked).toBe(false);
130
+ (0, vitest_1.expect)(result.theme_preference.delegated).toBe(false);
131
+ (0, vitest_1.expect)(result.theme_preference.source_tenant_id).toBe("child-id");
132
+ });
133
+ (0, vitest_1.it)("DELEGATED mode: child can override and re-delegate", async () => {
134
+ const pool = (0, test_helpers_js_1.makeMockPool)();
135
+ const mockQuery = vitest_1.vi.fn();
136
+ // 3-level hierarchy: root -> msp -> client
137
+ mockQuery.mockResolvedValueOnce({
138
+ rows: [{ ancestry_path: "/root-id/msp-id" }],
139
+ });
140
+ mockQuery.mockResolvedValueOnce({
141
+ rows: [
142
+ // Root sets a DELEGATED permission
143
+ {
144
+ id: "policy-root",
145
+ tenant_id: "root-id",
146
+ key: "billing_access",
147
+ value: JSON.stringify(true),
148
+ mode: core_1.PermissionMode.DELEGATED,
149
+ revocation_mode: core_1.RevocationMode.CASCADE,
150
+ source_tenant_id: "root-id",
151
+ created_at: "2024-01-01T00:00:00.000Z",
152
+ updated_at: "2024-01-01T00:00:00.000Z",
153
+ },
154
+ // MSP overrides with its own DELEGATED policy
155
+ {
156
+ id: "policy-msp",
157
+ tenant_id: "msp-id",
158
+ key: "billing_access",
159
+ value: JSON.stringify(false),
160
+ mode: core_1.PermissionMode.DELEGATED,
161
+ revocation_mode: core_1.RevocationMode.CASCADE,
162
+ source_tenant_id: "msp-id",
163
+ created_at: "2024-01-01T00:00:00.000Z",
164
+ updated_at: "2024-01-01T00:00:00.000Z",
165
+ },
166
+ // Client overrides again
167
+ {
168
+ id: "policy-client",
169
+ tenant_id: "client-id",
170
+ key: "billing_access",
171
+ value: JSON.stringify(true),
172
+ mode: core_1.PermissionMode.INHERITED,
173
+ revocation_mode: core_1.RevocationMode.CASCADE,
174
+ source_tenant_id: "client-id",
175
+ created_at: "2024-01-01T00:00:00.000Z",
176
+ updated_at: "2024-01-01T00:00:00.000Z",
177
+ },
178
+ ],
179
+ });
180
+ vitest_1.vi.mocked(poolHelpers.withClient).mockImplementation(async (_pool, fn) => {
181
+ const client = { query: mockQuery };
182
+ return fn(client);
183
+ });
184
+ const result = await permissionService.resolvePermissions(pool, "client-id");
185
+ // Client's final override wins since MSP was DELEGATED (not LOCKED)
186
+ (0, vitest_1.expect)(result.billing_access.value).toBe(JSON.stringify(true));
187
+ (0, vitest_1.expect)(result.billing_access.source_tenant_id).toBe("client-id");
188
+ (0, vitest_1.expect)(result.billing_access.locked).toBe(false);
189
+ });
190
+ (0, vitest_1.it)("permission resolution walks ancestor chain correctly", async () => {
191
+ const pool = (0, test_helpers_js_1.makeMockPool)();
192
+ const mockQuery = vitest_1.vi.fn();
193
+ // 4-level hierarchy: root -> org -> team -> user
194
+ mockQuery.mockResolvedValueOnce({
195
+ rows: [{ ancestry_path: "/root-id/org-id/team-id" }],
196
+ });
197
+ mockQuery.mockResolvedValueOnce({
198
+ rows: [
199
+ {
200
+ id: "p1",
201
+ tenant_id: "root-id",
202
+ key: "feature_a",
203
+ value: JSON.stringify(true),
204
+ mode: core_1.PermissionMode.INHERITED,
205
+ revocation_mode: core_1.RevocationMode.CASCADE,
206
+ source_tenant_id: "root-id",
207
+ created_at: "2024-01-01T00:00:00.000Z",
208
+ updated_at: "2024-01-01T00:00:00.000Z",
209
+ },
210
+ {
211
+ id: "p2",
212
+ tenant_id: "org-id",
213
+ key: "feature_b",
214
+ value: JSON.stringify("org-value"),
215
+ mode: core_1.PermissionMode.INHERITED,
216
+ revocation_mode: core_1.RevocationMode.CASCADE,
217
+ source_tenant_id: "org-id",
218
+ created_at: "2024-01-01T00:00:00.000Z",
219
+ updated_at: "2024-01-01T00:00:00.000Z",
220
+ },
221
+ {
222
+ id: "p3",
223
+ tenant_id: "team-id",
224
+ key: "feature_a",
225
+ value: JSON.stringify(false),
226
+ mode: core_1.PermissionMode.INHERITED,
227
+ revocation_mode: core_1.RevocationMode.CASCADE,
228
+ source_tenant_id: "team-id",
229
+ created_at: "2024-01-01T00:00:00.000Z",
230
+ updated_at: "2024-01-01T00:00:00.000Z",
231
+ },
232
+ // user-id has no policies
233
+ ],
234
+ });
235
+ vitest_1.vi.mocked(poolHelpers.withClient).mockImplementation(async (_pool, fn) => {
236
+ const client = { query: mockQuery };
237
+ return fn(client);
238
+ });
239
+ const result = await permissionService.resolvePermissions(pool, "user-id");
240
+ // feature_a: team overrides root
241
+ (0, vitest_1.expect)(result.feature_a.value).toBe(JSON.stringify(false));
242
+ (0, vitest_1.expect)(result.feature_a.source_tenant_id).toBe("team-id");
243
+ // feature_b: inherited from org
244
+ (0, vitest_1.expect)(result.feature_b.value).toBe(JSON.stringify("org-value"));
245
+ (0, vitest_1.expect)(result.feature_b.source_tenant_id).toBe("org-id");
246
+ });
247
+ (0, vitest_1.it)("throws TenantNotFoundError for unknown tenant", async () => {
248
+ const pool = (0, test_helpers_js_1.makeMockPool)();
249
+ const mockQuery = vitest_1.vi.fn().mockResolvedValueOnce({ rows: [] });
250
+ vitest_1.vi.mocked(poolHelpers.withClient).mockImplementation(async (_pool, fn) => {
251
+ const client = { query: mockQuery };
252
+ return fn(client);
253
+ });
254
+ await (0, vitest_1.expect)(permissionService.resolvePermissions(pool, "nonexistent")).rejects.toThrow(core_1.TenantNotFoundError);
255
+ });
256
+ });
257
+ // ---------------------------------------------------------------------------
258
+ // Revocation CASCADE
259
+ // ---------------------------------------------------------------------------
260
+ (0, vitest_1.describe)("deletePermission", () => {
261
+ (0, vitest_1.it)("CASCADE: removing parent permission removes children", async () => {
262
+ const pool = (0, test_helpers_js_1.makeMockPool)();
263
+ const mockQuery = vitest_1.vi.fn();
264
+ // Query 1: load the policy being deleted
265
+ mockQuery.mockResolvedValueOnce({
266
+ rows: [
267
+ {
268
+ id: "policy-parent",
269
+ tenant_id: "parent-id",
270
+ key: "can_access_reports",
271
+ value: JSON.stringify(true),
272
+ mode: core_1.PermissionMode.INHERITED,
273
+ revocation_mode: core_1.RevocationMode.CASCADE,
274
+ source_tenant_id: "parent-id",
275
+ created_at: "2024-01-01T00:00:00.000Z",
276
+ updated_at: "2024-01-01T00:00:00.000Z",
277
+ },
278
+ ],
279
+ });
280
+ // Query 2: find descendants
281
+ mockQuery.mockResolvedValueOnce({
282
+ rows: [{ id: "child-1" }, { id: "child-2" }],
283
+ });
284
+ // Query 3: DELETE from descendants
285
+ mockQuery.mockResolvedValueOnce({ rowCount: 2 });
286
+ // Query 4: DELETE the parent policy itself
287
+ mockQuery.mockResolvedValueOnce({ rowCount: 1 });
288
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
289
+ const client = { query: mockQuery };
290
+ return fn(client);
291
+ });
292
+ await permissionService.deletePermission(pool, "parent-id", "policy-parent");
293
+ // Verify descendant deletion query was called
294
+ const descendantDeleteCall = mockQuery.mock.calls[2];
295
+ (0, vitest_1.expect)(descendantDeleteCall[0]).toContain("DELETE FROM permission_policies");
296
+ (0, vitest_1.expect)(descendantDeleteCall[1]).toEqual([["child-1", "child-2"], "can_access_reports"]);
297
+ // Verify parent policy deletion
298
+ const parentDeleteCall = mockQuery.mock.calls[3];
299
+ (0, vitest_1.expect)(parentDeleteCall[0]).toContain("DELETE FROM permission_policies WHERE id");
300
+ (0, vitest_1.expect)(parentDeleteCall[1]).toEqual(["policy-parent"]);
301
+ });
302
+ (0, vitest_1.it)("PERMANENT: cannot revoke a PERMANENT permission", async () => {
303
+ const pool = (0, test_helpers_js_1.makeMockPool)();
304
+ const mockQuery = vitest_1.vi.fn();
305
+ mockQuery.mockResolvedValueOnce({
306
+ rows: [
307
+ {
308
+ id: "policy-perm",
309
+ tenant_id: "tenant-id",
310
+ key: "immutable_perm",
311
+ value: JSON.stringify(true),
312
+ mode: core_1.PermissionMode.INHERITED,
313
+ revocation_mode: core_1.RevocationMode.PERMANENT,
314
+ source_tenant_id: "tenant-id",
315
+ created_at: "2024-01-01T00:00:00.000Z",
316
+ updated_at: "2024-01-01T00:00:00.000Z",
317
+ },
318
+ ],
319
+ });
320
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
321
+ const client = { query: mockQuery };
322
+ return fn(client);
323
+ });
324
+ await (0, vitest_1.expect)(permissionService.deletePermission(pool, "tenant-id", "policy-perm")).rejects.toThrow(core_1.PermissionRevocationDeniedError);
325
+ });
326
+ (0, vitest_1.it)("SOFT: deletes only the policy, leaving descendants intact", async () => {
327
+ const pool = (0, test_helpers_js_1.makeMockPool)();
328
+ const mockQuery = vitest_1.vi.fn();
329
+ mockQuery.mockResolvedValueOnce({
330
+ rows: [
331
+ {
332
+ id: "policy-soft",
333
+ tenant_id: "tenant-id",
334
+ key: "soft_perm",
335
+ value: JSON.stringify(true),
336
+ mode: core_1.PermissionMode.INHERITED,
337
+ revocation_mode: core_1.RevocationMode.SOFT,
338
+ source_tenant_id: "tenant-id",
339
+ created_at: "2024-01-01T00:00:00.000Z",
340
+ updated_at: "2024-01-01T00:00:00.000Z",
341
+ },
342
+ ],
343
+ });
344
+ // Only one DELETE for the policy itself
345
+ mockQuery.mockResolvedValueOnce({ rowCount: 1 });
346
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
347
+ const client = { query: mockQuery };
348
+ return fn(client);
349
+ });
350
+ await permissionService.deletePermission(pool, "tenant-id", "policy-soft");
351
+ // Only 2 queries: select existing + delete self
352
+ (0, vitest_1.expect)(mockQuery).toHaveBeenCalledTimes(2);
353
+ (0, vitest_1.expect)(mockQuery.mock.calls[1][0]).toContain("DELETE FROM permission_policies WHERE id");
354
+ });
355
+ (0, vitest_1.it)("throws PermissionNotFoundError when policy does not exist", async () => {
356
+ const pool = (0, test_helpers_js_1.makeMockPool)();
357
+ const mockQuery = vitest_1.vi.fn().mockResolvedValueOnce({ rows: [] });
358
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
359
+ const client = { query: mockQuery };
360
+ return fn(client);
361
+ });
362
+ await (0, vitest_1.expect)(permissionService.deletePermission(pool, "tenant-id", "nonexistent")).rejects.toThrow(core_1.PermissionNotFoundError);
363
+ });
364
+ });
365
+ // ---------------------------------------------------------------------------
366
+ // createPermission
367
+ // ---------------------------------------------------------------------------
368
+ (0, vitest_1.describe)("createPermission", () => {
369
+ (0, vitest_1.it)("rejects when ancestor has LOCKED the key", async () => {
370
+ const pool = (0, test_helpers_js_1.makeMockPool)();
371
+ const mockQuery = vitest_1.vi.fn();
372
+ // Query 1: ancestry_path
373
+ mockQuery.mockResolvedValueOnce({
374
+ rows: [{ ancestry_path: "/ancestor-id" }],
375
+ });
376
+ // Query 2: ancestor lock check
377
+ mockQuery.mockResolvedValueOnce({
378
+ rows: [
379
+ {
380
+ id: "locked-policy",
381
+ tenant_id: "ancestor-id",
382
+ key: "locked_perm",
383
+ mode: core_1.PermissionMode.LOCKED,
384
+ source_tenant_id: "ancestor-id",
385
+ },
386
+ ],
387
+ });
388
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
389
+ const client = { query: mockQuery };
390
+ return fn(client);
391
+ });
392
+ await (0, vitest_1.expect)(permissionService.createPermission(pool, "child-id", {
393
+ key: "locked_perm",
394
+ value: true,
395
+ mode: core_1.PermissionMode.INHERITED,
396
+ revocation_mode: core_1.RevocationMode.CASCADE,
397
+ })).rejects.toThrow(core_1.PermissionLockedError);
398
+ });
399
+ (0, vitest_1.it)("creates permission successfully when no ancestor lock exists", async () => {
400
+ const pool = (0, test_helpers_js_1.makeMockPool)();
401
+ const mockQuery = vitest_1.vi.fn();
402
+ // ancestry_path
403
+ mockQuery.mockResolvedValueOnce({
404
+ rows: [{ ancestry_path: "/parent-id" }],
405
+ });
406
+ // no locked ancestors
407
+ mockQuery.mockResolvedValueOnce({ rows: [] });
408
+ // INSERT returning new policy
409
+ const newPolicy = {
410
+ id: "new-policy-id",
411
+ tenant_id: "child-id",
412
+ key: "new_perm",
413
+ value: JSON.stringify(true),
414
+ mode: core_1.PermissionMode.INHERITED,
415
+ revocation_mode: core_1.RevocationMode.CASCADE,
416
+ source_tenant_id: "child-id",
417
+ created_at: "2024-01-01T00:00:00.000Z",
418
+ updated_at: "2024-01-01T00:00:00.000Z",
419
+ };
420
+ mockQuery.mockResolvedValueOnce({ rows: [newPolicy] });
421
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
422
+ const client = { query: mockQuery };
423
+ return fn(client);
424
+ });
425
+ const result = await permissionService.createPermission(pool, "child-id", {
426
+ key: "new_perm",
427
+ value: true,
428
+ mode: core_1.PermissionMode.INHERITED,
429
+ revocation_mode: core_1.RevocationMode.CASCADE,
430
+ });
431
+ (0, vitest_1.expect)(result.id).toBe("new-policy-id");
432
+ (0, vitest_1.expect)(result.key).toBe("new_perm");
433
+ });
434
+ (0, vitest_1.it)("root tenant skips ancestor lock check", async () => {
435
+ const pool = (0, test_helpers_js_1.makeMockPool)();
436
+ const mockQuery = vitest_1.vi.fn();
437
+ // Root has ancestry_path "/"
438
+ mockQuery.mockResolvedValueOnce({
439
+ rows: [{ ancestry_path: "/" }],
440
+ });
441
+ // No lock check query issued (ancestorIds.length === 0)
442
+ // Direct to INSERT
443
+ const newPolicy = {
444
+ id: "root-policy",
445
+ tenant_id: "root-id",
446
+ key: "admin_access",
447
+ value: JSON.stringify(true),
448
+ mode: core_1.PermissionMode.LOCKED,
449
+ revocation_mode: core_1.RevocationMode.CASCADE,
450
+ source_tenant_id: "root-id",
451
+ created_at: "2024-01-01T00:00:00.000Z",
452
+ updated_at: "2024-01-01T00:00:00.000Z",
453
+ };
454
+ mockQuery.mockResolvedValueOnce({ rows: [newPolicy] });
455
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
456
+ const client = { query: mockQuery };
457
+ return fn(client);
458
+ });
459
+ const result = await permissionService.createPermission(pool, "root-id", {
460
+ key: "admin_access",
461
+ value: true,
462
+ mode: core_1.PermissionMode.LOCKED,
463
+ revocation_mode: core_1.RevocationMode.CASCADE,
464
+ });
465
+ (0, vitest_1.expect)(result.id).toBe("root-policy");
466
+ // Only 2 queries: ancestry + INSERT (no lock check)
467
+ (0, vitest_1.expect)(mockQuery).toHaveBeenCalledTimes(2);
468
+ });
469
+ });
470
+ //# sourceMappingURL=permission-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-service.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/permission-service.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=retention-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention-service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/retention-service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,126 @@
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 (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const vitest_1 = require("vitest");
27
+ vitest_1.vi.mock("../../pool-helpers.js", () => ({
28
+ withClient: vitest_1.vi.fn(),
29
+ withTransaction: vitest_1.vi.fn(),
30
+ }));
31
+ const poolHelpers = __importStar(require("../../pool-helpers.js"));
32
+ const retentionService = __importStar(require("../retention-service.js"));
33
+ function makeMockPool() {
34
+ return {};
35
+ }
36
+ (0, vitest_1.beforeEach)(() => {
37
+ vitest_1.vi.clearAllMocks();
38
+ });
39
+ (0, vitest_1.describe)("purgeExpiredData", () => {
40
+ (0, vitest_1.it)("deletes expired records and returns total count", async () => {
41
+ const pool = makeMockPool();
42
+ const mockQuery = vitest_1.vi.fn()
43
+ .mockResolvedValueOnce({ rowCount: 5 }) // webhook_deliveries
44
+ .mockResolvedValueOnce({ rowCount: 3 }) // webhook_events
45
+ .mockResolvedValueOnce({ rowCount: 10 }); // audit_logs
46
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
47
+ const client = { query: mockQuery };
48
+ return fn(client);
49
+ });
50
+ const result = await retentionService.purgeExpiredData(pool, 30);
51
+ (0, vitest_1.expect)(result).toEqual({ deleted_count: 18 });
52
+ (0, vitest_1.expect)(mockQuery).toHaveBeenCalledTimes(3);
53
+ (0, vitest_1.expect)(mockQuery.mock.calls[0][0]).toContain("webhook_deliveries");
54
+ (0, vitest_1.expect)(mockQuery.mock.calls[1][0]).toContain("webhook_events");
55
+ (0, vitest_1.expect)(mockQuery.mock.calls[2][0]).toContain("audit_logs");
56
+ });
57
+ (0, vitest_1.it)("uses default 90-day retention when not specified", async () => {
58
+ const pool = makeMockPool();
59
+ const mockQuery = vitest_1.vi.fn().mockResolvedValue({ rowCount: 0 });
60
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
61
+ const client = { query: mockQuery };
62
+ return fn(client);
63
+ });
64
+ await retentionService.purgeExpiredData(pool);
65
+ (0, vitest_1.expect)(mockQuery).toHaveBeenCalledTimes(3);
66
+ });
67
+ });
68
+ (0, vitest_1.describe)("purgeTenant", () => {
69
+ (0, vitest_1.it)("deletes all tenant data in FK-safe order", async () => {
70
+ const pool = makeMockPool();
71
+ const mockQuery = vitest_1.vi.fn().mockResolvedValue({ rowCount: 0, rows: [] });
72
+ vitest_1.vi.mocked(poolHelpers.withTransaction).mockImplementation(async (_pool, fn) => {
73
+ const client = { query: mockQuery };
74
+ return fn(client);
75
+ });
76
+ await retentionService.purgeTenant(pool, "tenant-123");
77
+ (0, vitest_1.expect)(mockQuery).toHaveBeenCalledTimes(8);
78
+ // Verify FK order: config, permissions, api_keys before webhooks/audit before tenant
79
+ (0, vitest_1.expect)(mockQuery.mock.calls[0][0]).toContain("config_entries");
80
+ (0, vitest_1.expect)(mockQuery.mock.calls[1][0]).toContain("permission_policies");
81
+ (0, vitest_1.expect)(mockQuery.mock.calls[2][0]).toContain("api_keys");
82
+ (0, vitest_1.expect)(mockQuery.mock.calls[7][0]).toContain("tenants");
83
+ // Verify tenant_id parameter
84
+ (0, vitest_1.expect)(mockQuery.mock.calls[0][1]).toEqual(["tenant-123"]);
85
+ });
86
+ });
87
+ (0, vitest_1.describe)("exportTenantData", () => {
88
+ (0, vitest_1.it)("returns structured data for the tenant", async () => {
89
+ const pool = makeMockPool();
90
+ const tenantRow = { id: "tenant-123", name: "Test Corp" };
91
+ const mockQuery = vitest_1.vi.fn()
92
+ .mockResolvedValueOnce({ rows: [tenantRow] }) // tenants
93
+ .mockResolvedValueOnce({ rows: [] }) // config_entries
94
+ .mockResolvedValueOnce({ rows: [] }) // permission_policies
95
+ .mockResolvedValueOnce({ rows: [] }) // api_keys
96
+ .mockResolvedValueOnce({ rows: [] }) // webhooks
97
+ .mockResolvedValueOnce({ rows: [] }) // webhook_events
98
+ .mockResolvedValueOnce({ rows: [] }) // webhook_deliveries
99
+ .mockResolvedValueOnce({ rows: [] }); // audit_logs
100
+ vitest_1.vi.mocked(poolHelpers.withClient).mockImplementation(async (_pool, fn) => {
101
+ const client = { query: mockQuery };
102
+ return fn(client);
103
+ });
104
+ const result = await retentionService.exportTenantData(pool, "tenant-123");
105
+ (0, vitest_1.expect)(result.tenant).toEqual(tenantRow);
106
+ (0, vitest_1.expect)(result.config_entries).toEqual([]);
107
+ (0, vitest_1.expect)(result.permission_policies).toEqual([]);
108
+ (0, vitest_1.expect)(result.api_keys).toEqual([]);
109
+ (0, vitest_1.expect)(result.webhooks).toEqual([]);
110
+ (0, vitest_1.expect)(result.webhook_events).toEqual([]);
111
+ (0, vitest_1.expect)(result.webhook_deliveries).toEqual([]);
112
+ (0, vitest_1.expect)(result.audit_logs).toEqual([]);
113
+ });
114
+ (0, vitest_1.it)("returns null tenant when not found", async () => {
115
+ const pool = makeMockPool();
116
+ const mockQuery = vitest_1.vi.fn().mockResolvedValue({ rows: [] });
117
+ vitest_1.vi.mocked(poolHelpers.withClient).mockImplementation(async (_pool, fn) => {
118
+ const client = { query: mockQuery };
119
+ return fn(client);
120
+ });
121
+ const result = await retentionService.exportTenantData(pool, "nonexistent");
122
+ (0, vitest_1.expect)(result.tenant).toBeNull();
123
+ (0, vitest_1.expect)(mockQuery).toHaveBeenCalledTimes(8);
124
+ });
125
+ });
126
+ //# sourceMappingURL=retention-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention-service.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/retention-service.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tenant-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/tenant-service.test.ts"],"names":[],"mappings":""}