@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.
- package/dist/__tests__/crypto.test.d.ts +2 -0
- package/dist/__tests__/crypto.test.d.ts.map +1 -0
- package/dist/__tests__/crypto.test.js +41 -0
- package/dist/__tests__/crypto.test.js.map +1 -0
- package/dist/crypto.d.ts +7 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +74 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/pool-helpers.d.ts +4 -0
- package/dist/pool-helpers.d.ts.map +1 -0
- package/dist/pool-helpers.js +31 -0
- package/dist/pool-helpers.js.map +1 -0
- package/dist/services/__tests__/audit-service.test.d.ts +2 -0
- package/dist/services/__tests__/audit-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/audit-service.test.js +220 -0
- package/dist/services/__tests__/audit-service.test.js.map +1 -0
- package/dist/services/__tests__/config-service.test.d.ts +2 -0
- package/dist/services/__tests__/config-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/config-service.test.js +555 -0
- package/dist/services/__tests__/config-service.test.js.map +1 -0
- package/dist/services/__tests__/consent-service.test.d.ts +2 -0
- package/dist/services/__tests__/consent-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/consent-service.test.js +159 -0
- package/dist/services/__tests__/consent-service.test.js.map +1 -0
- package/dist/services/__tests__/event-service.test.d.ts +2 -0
- package/dist/services/__tests__/event-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/event-service.test.js +151 -0
- package/dist/services/__tests__/event-service.test.js.map +1 -0
- package/dist/services/__tests__/permission-service.test.d.ts +2 -0
- package/dist/services/__tests__/permission-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/permission-service.test.js +470 -0
- package/dist/services/__tests__/permission-service.test.js.map +1 -0
- package/dist/services/__tests__/retention-service.test.d.ts +2 -0
- package/dist/services/__tests__/retention-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/retention-service.test.js +126 -0
- package/dist/services/__tests__/retention-service.test.js.map +1 -0
- package/dist/services/__tests__/tenant-service.test.d.ts +2 -0
- package/dist/services/__tests__/tenant-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/tenant-service.test.js +451 -0
- package/dist/services/__tests__/tenant-service.test.js.map +1 -0
- package/dist/services/__tests__/test-helpers.d.ts +9 -0
- package/dist/services/__tests__/test-helpers.d.ts.map +1 -0
- package/dist/services/__tests__/test-helpers.js +20 -0
- package/dist/services/__tests__/test-helpers.js.map +1 -0
- package/dist/services/__tests__/webhook-service.test.d.ts +2 -0
- package/dist/services/__tests__/webhook-service.test.d.ts.map +1 -0
- package/dist/services/__tests__/webhook-service.test.js +174 -0
- package/dist/services/__tests__/webhook-service.test.js.map +1 -0
- package/dist/services/api-key-service.d.ts +61 -0
- package/dist/services/api-key-service.d.ts.map +1 -0
- package/dist/services/api-key-service.js +164 -0
- package/dist/services/api-key-service.js.map +1 -0
- package/dist/services/audit-service.d.ts +6 -0
- package/dist/services/audit-service.d.ts.map +1 -0
- package/dist/services/audit-service.js +85 -0
- package/dist/services/audit-service.js.map +1 -0
- package/dist/services/config-service.d.ts +33 -0
- package/dist/services/config-service.d.ts.map +1 -0
- package/dist/services/config-service.js +271 -0
- package/dist/services/config-service.js.map +1 -0
- package/dist/services/consent-service.d.ts +7 -0
- package/dist/services/consent-service.d.ts.map +1 -0
- package/dist/services/consent-service.js +71 -0
- package/dist/services/consent-service.js.map +1 -0
- package/dist/services/event-service.d.ts +39 -0
- package/dist/services/event-service.d.ts.map +1 -0
- package/dist/services/event-service.js +331 -0
- package/dist/services/event-service.js.map +1 -0
- package/dist/services/key-rotation-service.d.ts +15 -0
- package/dist/services/key-rotation-service.d.ts.map +1 -0
- package/dist/services/key-rotation-service.js +41 -0
- package/dist/services/key-rotation-service.js.map +1 -0
- package/dist/services/permission-service.d.ts +21 -0
- package/dist/services/permission-service.d.ts.map +1 -0
- package/dist/services/permission-service.js +213 -0
- package/dist/services/permission-service.js.map +1 -0
- package/dist/services/region-service.d.ts +9 -0
- package/dist/services/region-service.d.ts.map +1 -0
- package/dist/services/region-service.js +105 -0
- package/dist/services/region-service.js.map +1 -0
- package/dist/services/retention-service.d.ts +19 -0
- package/dist/services/retention-service.d.ts.map +1 -0
- package/dist/services/retention-service.js +88 -0
- package/dist/services/retention-service.js.map +1 -0
- package/dist/services/role-service.d.ts +35 -0
- package/dist/services/role-service.d.ts.map +1 -0
- package/dist/services/role-service.js +101 -0
- package/dist/services/role-service.js.map +1 -0
- package/dist/services/tenant-service.d.ts +25 -0
- package/dist/services/tenant-service.d.ts.map +1 -0
- package/dist/services/tenant-service.js +335 -0
- package/dist/services/tenant-service.js.map +1 -0
- package/dist/services/webhook-service.d.ts +12 -0
- package/dist/services/webhook-service.d.ts.map +1 -0
- package/dist/services/webhook-service.js +129 -0
- package/dist/services/webhook-service.js.map +1 -0
- package/dist/stratum.d.ts +107 -0
- package/dist/stratum.d.ts.map +1 -0
- package/dist/stratum.js +531 -0
- package/dist/stratum.js.map +1 -0
- package/dist/telemetry.d.ts +27 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +94 -0
- package/dist/telemetry.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getConfigWithInheritance = exports.deleteConfig = exports.batchSetConfig = exports.setConfig = exports.resolveConfig = void 0;
|
|
4
|
+
const pool_helpers_js_1 = require("../pool-helpers.js");
|
|
5
|
+
const core_1 = require("@stratum-hq/core");
|
|
6
|
+
const crypto_js_1 = require("../crypto.js");
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the effective config for a tenant by batch-loading ancestor configs
|
|
9
|
+
* in a single query and walking root→leaf.
|
|
10
|
+
*/
|
|
11
|
+
async function resolveConfig(pool, tenantId) {
|
|
12
|
+
return (0, pool_helpers_js_1.withClient)(pool, async (client) => {
|
|
13
|
+
const tenantRes = await client.query(`SELECT ancestry_path FROM tenants WHERE id = $1 AND status != 'archived'`, [tenantId]);
|
|
14
|
+
if (tenantRes.rows.length === 0) {
|
|
15
|
+
// Distinguish archived vs truly missing
|
|
16
|
+
const archivedRes = await client.query(`SELECT id FROM tenants WHERE id = $1`, [tenantId]);
|
|
17
|
+
if (archivedRes.rows.length > 0) {
|
|
18
|
+
throw new core_1.TenantArchivedError(tenantId);
|
|
19
|
+
}
|
|
20
|
+
throw new core_1.TenantNotFoundError(tenantId);
|
|
21
|
+
}
|
|
22
|
+
const ancestryPath = tenantRes.rows[0].ancestry_path;
|
|
23
|
+
const ancestorIds = (0, core_1.parseAncestryPath)(ancestryPath);
|
|
24
|
+
const allIds = [...ancestorIds, tenantId];
|
|
25
|
+
// Single query: batch-load all config entries for the ancestor chain
|
|
26
|
+
// Only include non-archived tenants to prevent archived ancestors from participating in inheritance
|
|
27
|
+
const entriesRes = await client.query(`SELECT ce.* FROM config_entries ce
|
|
28
|
+
JOIN tenants t ON t.id = ce.tenant_id
|
|
29
|
+
WHERE ce.tenant_id = ANY($1) AND t.status != 'archived'`, [allIds]);
|
|
30
|
+
// Group by tenant_id preserving order
|
|
31
|
+
const byTenant = new Map();
|
|
32
|
+
for (const id of allIds) {
|
|
33
|
+
byTenant.set(id, []);
|
|
34
|
+
}
|
|
35
|
+
for (const entry of entriesRes.rows) {
|
|
36
|
+
const list = byTenant.get(entry.tenant_id);
|
|
37
|
+
if (list) {
|
|
38
|
+
list.push(entry);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Walk root→leaf: locked parent values propagate and block overrides
|
|
42
|
+
const resolved = new Map();
|
|
43
|
+
for (const currentTenantId of allIds) {
|
|
44
|
+
const entries = byTenant.get(currentTenantId) ?? [];
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
const existing = resolved.get(entry.key);
|
|
47
|
+
if (existing?.locked) {
|
|
48
|
+
// Key is locked by an ancestor — skip child overrides
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const isCurrentTenant = currentTenantId === tenantId;
|
|
52
|
+
const resolvedValue = entry.sensitive
|
|
53
|
+
? JSON.parse((0, crypto_js_1.decrypt)(JSON.parse(entry.value)))
|
|
54
|
+
: entry.value;
|
|
55
|
+
resolved.set(entry.key, {
|
|
56
|
+
key: entry.key,
|
|
57
|
+
value: resolvedValue,
|
|
58
|
+
source_tenant_id: entry.source_tenant_id,
|
|
59
|
+
inherited: !isCurrentTenant,
|
|
60
|
+
locked: entry.locked,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return Object.fromEntries(resolved);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
exports.resolveConfig = resolveConfig;
|
|
68
|
+
/**
|
|
69
|
+
* Set (upsert) a config key for a tenant.
|
|
70
|
+
* Rejects if the key is locked by an ancestor.
|
|
71
|
+
*/
|
|
72
|
+
async function setConfig(pool, tenantId, key, input) {
|
|
73
|
+
return (0, pool_helpers_js_1.withTransaction)(pool, async (client) => {
|
|
74
|
+
const tenantRes = await client.query(`SELECT ancestry_path FROM tenants WHERE id = $1`, [tenantId]);
|
|
75
|
+
if (tenantRes.rows.length === 0) {
|
|
76
|
+
throw new core_1.TenantNotFoundError(tenantId);
|
|
77
|
+
}
|
|
78
|
+
const ancestorIds = (0, core_1.parseAncestryPath)(tenantRes.rows[0].ancestry_path);
|
|
79
|
+
// Check ancestor locks (ancestry_path excludes self)
|
|
80
|
+
if (ancestorIds.length > 0) {
|
|
81
|
+
const lockedRes = await client.query(`SELECT * FROM config_entries
|
|
82
|
+
WHERE tenant_id = ANY($1)
|
|
83
|
+
AND key = $2
|
|
84
|
+
AND locked = true`, [ancestorIds, key]);
|
|
85
|
+
if (lockedRes.rows.length > 0) {
|
|
86
|
+
const locker = lockedRes.rows[0];
|
|
87
|
+
throw new core_1.ConfigLockedError(key, locker.source_tenant_id);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const sensitive = input.sensitive ?? false;
|
|
91
|
+
const storedValue = sensitive
|
|
92
|
+
? JSON.stringify((0, crypto_js_1.encrypt)(JSON.stringify(input.value)))
|
|
93
|
+
: JSON.stringify(input.value);
|
|
94
|
+
const res = await client.query(`INSERT INTO config_entries (tenant_id, key, value, locked, sensitive, source_tenant_id, inherited)
|
|
95
|
+
VALUES ($1, $2, $3, $4, $5, $1, false)
|
|
96
|
+
ON CONFLICT (tenant_id, key)
|
|
97
|
+
DO UPDATE SET
|
|
98
|
+
value = EXCLUDED.value,
|
|
99
|
+
locked = EXCLUDED.locked,
|
|
100
|
+
sensitive = EXCLUDED.sensitive,
|
|
101
|
+
updated_at = now()
|
|
102
|
+
RETURNING *`, [tenantId, key, storedValue, input.locked ?? false, sensitive]);
|
|
103
|
+
return res.rows[0];
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
exports.setConfig = setConfig;
|
|
107
|
+
/**
|
|
108
|
+
* Set multiple config keys for a tenant in a single transaction.
|
|
109
|
+
* Partial success: locked keys are skipped and reported as errors,
|
|
110
|
+
* while unlocked keys are set successfully within the same transaction.
|
|
111
|
+
*/
|
|
112
|
+
async function batchSetConfig(pool, tenantId, entries) {
|
|
113
|
+
return (0, pool_helpers_js_1.withTransaction)(pool, async (client) => {
|
|
114
|
+
const tenantRes = await client.query(`SELECT ancestry_path FROM tenants WHERE id = $1`, [tenantId]);
|
|
115
|
+
if (tenantRes.rows.length === 0) {
|
|
116
|
+
throw new core_1.TenantNotFoundError(tenantId);
|
|
117
|
+
}
|
|
118
|
+
const ancestorIds = (0, core_1.parseAncestryPath)(tenantRes.rows[0].ancestry_path);
|
|
119
|
+
const keys = entries.map((e) => e.key);
|
|
120
|
+
// Batch-load all ancestor locks in a single query
|
|
121
|
+
const lockedKeys = new Map();
|
|
122
|
+
if (ancestorIds.length > 0 && keys.length > 0) {
|
|
123
|
+
const lockedRes = await client.query(`SELECT * FROM config_entries
|
|
124
|
+
WHERE tenant_id = ANY($1)
|
|
125
|
+
AND key = ANY($2)
|
|
126
|
+
AND locked = true`, [ancestorIds, keys]);
|
|
127
|
+
for (const row of lockedRes.rows) {
|
|
128
|
+
lockedKeys.set(row.key, row.source_tenant_id);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const results = [];
|
|
132
|
+
let succeeded = 0;
|
|
133
|
+
let failed = 0;
|
|
134
|
+
for (const entry of entries) {
|
|
135
|
+
const lockerTenantId = lockedKeys.get(entry.key);
|
|
136
|
+
if (lockerTenantId) {
|
|
137
|
+
results.push({
|
|
138
|
+
key: entry.key,
|
|
139
|
+
status: "error",
|
|
140
|
+
error: `Config '${entry.key}' is locked by tenant ${lockerTenantId} and cannot be overridden`,
|
|
141
|
+
});
|
|
142
|
+
failed++;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const sensitive = entry.sensitive ?? false;
|
|
146
|
+
const storedValue = sensitive
|
|
147
|
+
? JSON.stringify((0, crypto_js_1.encrypt)(JSON.stringify(entry.value)))
|
|
148
|
+
: JSON.stringify(entry.value);
|
|
149
|
+
const res = await client.query(`INSERT INTO config_entries (tenant_id, key, value, locked, sensitive, source_tenant_id, inherited)
|
|
150
|
+
VALUES ($1, $2, $3, $4, $5, $1, false)
|
|
151
|
+
ON CONFLICT (tenant_id, key)
|
|
152
|
+
DO UPDATE SET
|
|
153
|
+
value = EXCLUDED.value,
|
|
154
|
+
locked = EXCLUDED.locked,
|
|
155
|
+
sensitive = EXCLUDED.sensitive,
|
|
156
|
+
updated_at = now()
|
|
157
|
+
RETURNING *`, [tenantId, entry.key, storedValue, entry.locked ?? false, sensitive]);
|
|
158
|
+
results.push({
|
|
159
|
+
key: entry.key,
|
|
160
|
+
status: "ok",
|
|
161
|
+
entry: res.rows[0],
|
|
162
|
+
});
|
|
163
|
+
succeeded++;
|
|
164
|
+
}
|
|
165
|
+
return { results, succeeded, failed };
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
exports.batchSetConfig = batchSetConfig;
|
|
169
|
+
/**
|
|
170
|
+
* Delete a config override for a tenant, revealing the inherited parent value.
|
|
171
|
+
*/
|
|
172
|
+
async function deleteConfig(pool, tenantId, key) {
|
|
173
|
+
return (0, pool_helpers_js_1.withTransaction)(pool, async (client) => {
|
|
174
|
+
const res = await client.query(`DELETE FROM config_entries WHERE tenant_id = $1 AND key = $2`, [tenantId, key]);
|
|
175
|
+
if (res.rowCount === 0) {
|
|
176
|
+
throw new core_1.ConfigNotFoundError(tenantId, key);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
exports.deleteConfig = deleteConfig;
|
|
181
|
+
/**
|
|
182
|
+
* Return all config entries for a tenant showing inheritance status:
|
|
183
|
+
* inherited (from ancestor), overridden (tenant has own value), or locked.
|
|
184
|
+
*/
|
|
185
|
+
async function getConfigWithInheritance(pool, tenantId) {
|
|
186
|
+
return (0, pool_helpers_js_1.withClient)(pool, async (client) => {
|
|
187
|
+
const tenantRes = await client.query(`SELECT ancestry_path FROM tenants WHERE id = $1`, [tenantId]);
|
|
188
|
+
if (tenantRes.rows.length === 0) {
|
|
189
|
+
throw new core_1.TenantNotFoundError(tenantId);
|
|
190
|
+
}
|
|
191
|
+
const ancestryPath = tenantRes.rows[0].ancestry_path;
|
|
192
|
+
const ancestorIds = (0, core_1.parseAncestryPath)(ancestryPath);
|
|
193
|
+
const allIds = [...ancestorIds, tenantId];
|
|
194
|
+
const entriesRes = await client.query(`SELECT * FROM config_entries WHERE tenant_id = ANY($1)`, [allIds]);
|
|
195
|
+
// Group entries by tenant_id for ordered traversal
|
|
196
|
+
const entriesByTenantId = new Map();
|
|
197
|
+
for (const entry of entriesRes.rows) {
|
|
198
|
+
const list = entriesByTenantId.get(entry.tenant_id) ?? [];
|
|
199
|
+
list.push(entry);
|
|
200
|
+
entriesByTenantId.set(entry.tenant_id, list);
|
|
201
|
+
}
|
|
202
|
+
// Walk allIds root→leaf to ensure correct ordering
|
|
203
|
+
const byKey = new Map();
|
|
204
|
+
for (const id of allIds) {
|
|
205
|
+
const entries = entriesByTenantId.get(id) ?? [];
|
|
206
|
+
for (const entry of entries) {
|
|
207
|
+
if (!byKey.has(entry.key)) {
|
|
208
|
+
byKey.set(entry.key, {
|
|
209
|
+
ancestorEntry: null,
|
|
210
|
+
tenantEntry: null,
|
|
211
|
+
lockedBy: null,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
const rec = byKey.get(entry.key);
|
|
215
|
+
if (id === tenantId) {
|
|
216
|
+
rec.tenantEntry = entry;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// Walking root→leaf, so later entries are deeper ancestors (closer to tenant)
|
|
220
|
+
rec.ancestorEntry = entry;
|
|
221
|
+
if (entry.locked && !rec.lockedBy) {
|
|
222
|
+
// First lock encountered (shallowest ancestor) takes precedence
|
|
223
|
+
rec.lockedBy = entry;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const decryptEntryValue = (entry) => entry.sensitive
|
|
229
|
+
? JSON.parse((0, crypto_js_1.decrypt)(JSON.parse(entry.value)))
|
|
230
|
+
: entry.value;
|
|
231
|
+
const result = {};
|
|
232
|
+
for (const [key, rec] of byKey) {
|
|
233
|
+
const lockedEntry = rec.lockedBy;
|
|
234
|
+
const tenantEntry = rec.tenantEntry;
|
|
235
|
+
const ancestorEntry = rec.ancestorEntry;
|
|
236
|
+
if (lockedEntry) {
|
|
237
|
+
// Key is locked — show ancestor's locked value regardless of tenant override
|
|
238
|
+
result[key] = {
|
|
239
|
+
key,
|
|
240
|
+
value: decryptEntryValue(lockedEntry),
|
|
241
|
+
source_tenant_id: lockedEntry.source_tenant_id,
|
|
242
|
+
inherited: true,
|
|
243
|
+
locked: true,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
else if (tenantEntry) {
|
|
247
|
+
// Tenant has its own value (override or own entry)
|
|
248
|
+
result[key] = {
|
|
249
|
+
key,
|
|
250
|
+
value: decryptEntryValue(tenantEntry),
|
|
251
|
+
source_tenant_id: tenantEntry.source_tenant_id,
|
|
252
|
+
inherited: false,
|
|
253
|
+
locked: tenantEntry.locked,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
else if (ancestorEntry) {
|
|
257
|
+
// Inherited from ancestor
|
|
258
|
+
result[key] = {
|
|
259
|
+
key,
|
|
260
|
+
value: decryptEntryValue(ancestorEntry),
|
|
261
|
+
source_tenant_id: ancestorEntry.source_tenant_id,
|
|
262
|
+
inherited: true,
|
|
263
|
+
locked: ancestorEntry.locked,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return result;
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
exports.getConfigWithInheritance = getConfigWithInheritance;
|
|
271
|
+
//# sourceMappingURL=config-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-service.js","sourceRoot":"","sources":["../../src/services/config-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import pg from "pg";
|
|
2
|
+
import type { ConsentRecord, GrantConsentInput } from "@stratum-hq/core";
|
|
3
|
+
export declare function grantConsent(pool: pg.Pool, tenantId: string, input: GrantConsentInput): Promise<ConsentRecord>;
|
|
4
|
+
export declare function revokeConsent(pool: pg.Pool, tenantId: string, subjectId: string, purpose: string): Promise<boolean>;
|
|
5
|
+
export declare function listConsent(pool: pg.Pool, tenantId: string, subjectId?: string): Promise<ConsentRecord[]>;
|
|
6
|
+
export declare function getActiveConsent(pool: pg.Pool, tenantId: string, subjectId: string, purpose: string): Promise<ConsentRecord | null>;
|
|
7
|
+
//# sourceMappingURL=consent-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent-service.d.ts","sourceRoot":"","sources":["../../src/services/consent-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEzE,wBAAsB,YAAY,CAChC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,aAAa,CAAC,CAuBxB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,EAAE,CAAC,CAuB1B;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAe/B"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getActiveConsent = exports.listConsent = exports.revokeConsent = exports.grantConsent = void 0;
|
|
4
|
+
const pool_helpers_js_1 = require("../pool-helpers.js");
|
|
5
|
+
async function grantConsent(pool, tenantId, input) {
|
|
6
|
+
return (0, pool_helpers_js_1.withTransaction)(pool, async (client) => {
|
|
7
|
+
const res = await client.query(`INSERT INTO consent_records (tenant_id, subject_id, purpose, granted, granted_at, revoked_at, expires_at, metadata)
|
|
8
|
+
VALUES ($1, $2, $3, true, now(), NULL, $4, $5)
|
|
9
|
+
ON CONFLICT (tenant_id, subject_id, purpose)
|
|
10
|
+
DO UPDATE SET granted = true, granted_at = now(), revoked_at = NULL,
|
|
11
|
+
expires_at = EXCLUDED.expires_at, metadata = EXCLUDED.metadata,
|
|
12
|
+
updated_at = now()
|
|
13
|
+
RETURNING id, tenant_id, subject_id, purpose, granted,
|
|
14
|
+
granted_at::text as granted_at, revoked_at::text as revoked_at,
|
|
15
|
+
expires_at::text as expires_at, metadata,
|
|
16
|
+
created_at::text as created_at, updated_at::text as updated_at`, [
|
|
17
|
+
tenantId,
|
|
18
|
+
input.subject_id,
|
|
19
|
+
input.purpose,
|
|
20
|
+
input.expires_at ?? null,
|
|
21
|
+
JSON.stringify(input.metadata ?? {}),
|
|
22
|
+
]);
|
|
23
|
+
return res.rows[0];
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
exports.grantConsent = grantConsent;
|
|
27
|
+
async function revokeConsent(pool, tenantId, subjectId, purpose) {
|
|
28
|
+
return (0, pool_helpers_js_1.withClient)(pool, async (client) => {
|
|
29
|
+
const res = await client.query(`UPDATE consent_records
|
|
30
|
+
SET granted = false, revoked_at = now(), updated_at = now()
|
|
31
|
+
WHERE tenant_id = $1 AND subject_id = $2 AND purpose = $3
|
|
32
|
+
RETURNING id`, [tenantId, subjectId, purpose]);
|
|
33
|
+
return res.rowCount !== null && res.rowCount > 0;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
exports.revokeConsent = revokeConsent;
|
|
37
|
+
async function listConsent(pool, tenantId, subjectId) {
|
|
38
|
+
return (0, pool_helpers_js_1.withClient)(pool, async (client) => {
|
|
39
|
+
const conditions = ["tenant_id = $1"];
|
|
40
|
+
const values = [tenantId];
|
|
41
|
+
if (subjectId !== undefined) {
|
|
42
|
+
conditions.push("subject_id = $2");
|
|
43
|
+
values.push(subjectId);
|
|
44
|
+
}
|
|
45
|
+
const where = conditions.join(" AND ");
|
|
46
|
+
const res = await client.query(`SELECT id, tenant_id, subject_id, purpose, granted,
|
|
47
|
+
granted_at::text as granted_at, revoked_at::text as revoked_at,
|
|
48
|
+
expires_at::text as expires_at, metadata,
|
|
49
|
+
created_at::text as created_at, updated_at::text as updated_at
|
|
50
|
+
FROM consent_records
|
|
51
|
+
WHERE ${where}
|
|
52
|
+
ORDER BY created_at DESC`, values);
|
|
53
|
+
return res.rows;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
exports.listConsent = listConsent;
|
|
57
|
+
async function getActiveConsent(pool, tenantId, subjectId, purpose) {
|
|
58
|
+
return (0, pool_helpers_js_1.withClient)(pool, async (client) => {
|
|
59
|
+
const res = await client.query(`SELECT id, tenant_id, subject_id, purpose, granted,
|
|
60
|
+
granted_at::text as granted_at, revoked_at::text as revoked_at,
|
|
61
|
+
expires_at::text as expires_at, metadata,
|
|
62
|
+
created_at::text as created_at, updated_at::text as updated_at
|
|
63
|
+
FROM consent_records
|
|
64
|
+
WHERE tenant_id = $1 AND subject_id = $2 AND purpose = $3
|
|
65
|
+
AND granted = true
|
|
66
|
+
AND (expires_at IS NULL OR expires_at > now())`, [tenantId, subjectId, purpose]);
|
|
67
|
+
return res.rows[0] ?? null;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
exports.getActiveConsent = getActiveConsent;
|
|
71
|
+
//# sourceMappingURL=consent-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent-service.js","sourceRoot":"","sources":["../../src/services/consent-service.ts"],"names":[],"mappings":";;;AACA,wDAAiE;AAG1D,KAAK,UAAU,YAAY,CAChC,IAAa,EACb,QAAgB,EAChB,KAAwB;IAExB,OAAO,IAAA,iCAAe,EAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAC5C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B;;;;;;;;;gFAS0E,EAC1E;YACE,QAAQ;YACR,KAAK,CAAC,UAAU;YAChB,KAAK,CAAC,OAAO;YACb,KAAK,CAAC,UAAU,IAAI,IAAI;YACxB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;SACrC,CACF,CAAC;QACF,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC;AA3BD,oCA2BC;AAEM,KAAK,UAAU,aAAa,CACjC,IAAa,EACb,QAAgB,EAChB,SAAiB,EACjB,OAAe;IAEf,OAAO,IAAA,4BAAU,EAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QACvC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B;;;oBAGc,EACd,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAC/B,CAAC;QACF,OAAO,GAAG,CAAC,QAAQ,KAAK,IAAI,IAAI,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC;AAhBD,sCAgBC;AAEM,KAAK,UAAU,WAAW,CAC/B,IAAa,EACb,QAAgB,EAChB,SAAkB;IAElB,OAAO,IAAA,4BAAU,EAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QACvC,MAAM,UAAU,GAAa,CAAC,gBAAgB,CAAC,CAAC;QAChD,MAAM,MAAM,GAAc,CAAC,QAAQ,CAAC,CAAC;QAErC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B;;;;;eAKS,KAAK;gCACY,EAC1B,MAAM,CACP,CAAC;QACF,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AA3BD,kCA2BC;AAEM,KAAK,UAAU,gBAAgB,CACpC,IAAa,EACb,QAAgB,EAChB,SAAiB,EACjB,OAAe;IAEf,OAAO,IAAA,4BAAU,EAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QACvC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B;;;;;;;4DAOsD,EACtD,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAC/B,CAAC;QACF,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AApBD,4CAoBC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import pg from "pg";
|
|
2
|
+
import type { TenantEvent } from "@stratum-hq/core";
|
|
3
|
+
interface WebhookEventRow {
|
|
4
|
+
id: string;
|
|
5
|
+
type: string;
|
|
6
|
+
tenant_id: string;
|
|
7
|
+
data: Record<string, unknown>;
|
|
8
|
+
created_at: string;
|
|
9
|
+
}
|
|
10
|
+
interface WebhookRow {
|
|
11
|
+
id: string;
|
|
12
|
+
tenant_id: string | null;
|
|
13
|
+
url: string;
|
|
14
|
+
secret_hash: string;
|
|
15
|
+
events: string[];
|
|
16
|
+
active: boolean;
|
|
17
|
+
description: string | null;
|
|
18
|
+
created_at: string;
|
|
19
|
+
updated_at: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function emitEvent(pool: pg.Pool, type: TenantEvent, tenantId: string, data: Record<string, unknown>): Promise<void>;
|
|
22
|
+
export declare function deliverWebhook(webhook: WebhookRow, event: WebhookEventRow, deliveryId: string): Promise<{
|
|
23
|
+
success: boolean;
|
|
24
|
+
responseCode: number | null;
|
|
25
|
+
error: string | null;
|
|
26
|
+
}>;
|
|
27
|
+
export declare function processDeliveries(pool: pg.Pool): Promise<void>;
|
|
28
|
+
export declare function retryFailedDeliveries(pool: pg.Pool, tenantId?: string): Promise<number>;
|
|
29
|
+
export declare function retryDelivery(pool: pg.Pool, deliveryId: string): Promise<boolean>;
|
|
30
|
+
export interface DeliveryStats {
|
|
31
|
+
total: number;
|
|
32
|
+
pending: number;
|
|
33
|
+
success: number;
|
|
34
|
+
failed: number;
|
|
35
|
+
}
|
|
36
|
+
export declare function getDeliveryStats(pool: pg.Pool, tenantId?: string): Promise<DeliveryStats>;
|
|
37
|
+
export declare function listFailedDeliveries(pool: pg.Pool, limit?: number, tenantId?: string): Promise<Record<string, unknown>[]>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=event-service.d.ts.map
|
|
@@ -0,0 +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;AAgIpD,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,CA2ClF;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"}
|