@stratum-hq/lib 1.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crypto.d.ts +6 -2
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +23 -6
- package/dist/crypto.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/migrate-schemas.d.ts.map +1 -1
- package/dist/migrate-schemas.js +19 -8
- package/dist/migrate-schemas.js.map +1 -1
- package/dist/migrations/022_roles_name_per_tenant.sql +10 -0
- package/dist/migrations/024_propagate_ancestry_ltree.sql +42 -0
- package/dist/migrations/025_redact_sensitive_config_audit.sql +19 -0
- package/dist/migrations/026_redact_webhook_secret_audit.sql +28 -0
- package/dist/migrations/027_tenant_status_pending.sql +8 -0
- package/dist/migrations/028_ancestry_path_prefix_index.sql +12 -0
- package/dist/pool-helpers.d.ts.map +1 -1
- package/dist/pool-helpers.js +20 -4
- package/dist/pool-helpers.js.map +1 -1
- package/dist/services/abac-service.d.ts +1 -1
- package/dist/services/abac-service.d.ts.map +1 -1
- package/dist/services/abac-service.js +64 -43
- package/dist/services/abac-service.js.map +1 -1
- package/dist/services/api-key-service.d.ts +6 -0
- package/dist/services/api-key-service.d.ts.map +1 -1
- package/dist/services/api-key-service.js +84 -33
- package/dist/services/api-key-service.js.map +1 -1
- package/dist/services/audit-service.d.ts.map +1 -1
- package/dist/services/audit-service.js +2 -1
- package/dist/services/audit-service.js.map +1 -1
- package/dist/services/config-service.d.ts.map +1 -1
- package/dist/services/config-service.js +14 -6
- package/dist/services/config-service.js.map +1 -1
- package/dist/services/consent-service.d.ts +2 -2
- package/dist/services/consent-service.d.ts.map +1 -1
- package/dist/services/consent-service.js +4 -1
- package/dist/services/consent-service.js.map +1 -1
- package/dist/services/event-service.d.ts +12 -0
- package/dist/services/event-service.d.ts.map +1 -1
- package/dist/services/event-service.js +240 -79
- package/dist/services/event-service.js.map +1 -1
- package/dist/services/key-rotation-service.d.ts +18 -1
- package/dist/services/key-rotation-service.d.ts.map +1 -1
- package/dist/services/key-rotation-service.js +57 -9
- package/dist/services/key-rotation-service.js.map +1 -1
- package/dist/services/permission-service.d.ts.map +1 -1
- package/dist/services/permission-service.js +42 -18
- package/dist/services/permission-service.js.map +1 -1
- package/dist/services/region-service.d.ts.map +1 -1
- package/dist/services/region-service.js +8 -7
- package/dist/services/region-service.js.map +1 -1
- package/dist/services/retention-service.d.ts +7 -1
- package/dist/services/retention-service.d.ts.map +1 -1
- package/dist/services/retention-service.js +47 -7
- package/dist/services/retention-service.js.map +1 -1
- package/dist/services/role-service.d.ts +7 -0
- package/dist/services/role-service.d.ts.map +1 -1
- package/dist/services/role-service.js +25 -11
- package/dist/services/role-service.js.map +1 -1
- package/dist/services/tenant-service.d.ts +24 -3
- package/dist/services/tenant-service.d.ts.map +1 -1
- package/dist/services/tenant-service.js +132 -61
- package/dist/services/tenant-service.js.map +1 -1
- package/dist/services/webhook-service.d.ts +5 -0
- package/dist/services/webhook-service.d.ts.map +1 -1
- package/dist/services/webhook-service.js +14 -0
- package/dist/services/webhook-service.js.map +1 -1
- package/dist/stratum-tables.d.ts +12 -0
- package/dist/stratum-tables.d.ts.map +1 -0
- package/dist/stratum-tables.js +31 -0
- package/dist/stratum-tables.js.map +1 -0
- package/dist/stratum.d.ts +30 -12
- package/dist/stratum.d.ts.map +1 -1
- package/dist/stratum.js +138 -43
- package/dist/stratum.js.map +1 -1
- package/dist/validation.d.ts +25 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +23 -0
- package/dist/validation.js.map +1 -0
- package/package.json +5 -5
|
@@ -8,6 +8,8 @@ exports.createAbacPolicy = createAbacPolicy;
|
|
|
8
8
|
exports.getAbacPolicies = getAbacPolicies;
|
|
9
9
|
exports.deleteAbacPolicy = deleteAbacPolicy;
|
|
10
10
|
const pool_helpers_js_1 = require("../pool-helpers.js");
|
|
11
|
+
const tenant_service_js_1 = require("./tenant-service.js");
|
|
12
|
+
const validation_js_1 = require("../validation.js");
|
|
11
13
|
const core_1 = require("@stratum-hq/core");
|
|
12
14
|
// ---------------------------------------------------------------------------
|
|
13
15
|
// Pure evaluation functions
|
|
@@ -85,48 +87,32 @@ async function resolveAbacPolicies(pool, tenantId) {
|
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
// Walk root→leaf applying LOCKED/INHERITED/DELEGATED mode semantics.
|
|
88
|
-
// We track
|
|
89
|
-
//
|
|
90
|
+
// We track policies by (resource_type + action + name) composite key so
|
|
91
|
+
// that descendants cannot override a LOCKED policy. A descendant's policies
|
|
92
|
+
// replace an ancestor's for the same composite, but every policy a single
|
|
93
|
+
// tenant holds for that composite is kept, so a same-name deny is never
|
|
94
|
+
// dropped in favour of a same-name allow from the same tenant.
|
|
90
95
|
const resolvedMap = new Map();
|
|
91
96
|
for (const currentTenantId of allIds) {
|
|
92
97
|
const policies = byTenant.get(currentTenantId) ?? [];
|
|
93
98
|
for (const policy of policies) {
|
|
94
99
|
const compositeKey = `${policy.resource_type}:${policy.action}:${policy.name}`;
|
|
95
|
-
const existing = resolvedMap.get(compositeKey);
|
|
96
|
-
if (existing
|
|
100
|
+
const existing = resolvedMap.get(compositeKey) ?? [];
|
|
101
|
+
if (existing.some((r) => r.locked && r.source_tenant_id !== currentTenantId)) {
|
|
97
102
|
// Locked by an ancestor — descendants cannot override it
|
|
98
103
|
continue;
|
|
99
104
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
break;
|
|
109
|
-
case "DELEGATED":
|
|
110
|
-
resolvedMap.set(compositeKey, {
|
|
111
|
-
policy,
|
|
112
|
-
source_tenant_id: currentTenantId,
|
|
113
|
-
locked: false,
|
|
114
|
-
delegated: true,
|
|
115
|
-
});
|
|
116
|
-
break;
|
|
117
|
-
case "INHERITED":
|
|
118
|
-
default:
|
|
119
|
-
resolvedMap.set(compositeKey, {
|
|
120
|
-
policy,
|
|
121
|
-
source_tenant_id: currentTenantId,
|
|
122
|
-
locked: false,
|
|
123
|
-
delegated: false,
|
|
124
|
-
});
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
105
|
+
const resolvedPolicy = {
|
|
106
|
+
policy,
|
|
107
|
+
source_tenant_id: currentTenantId,
|
|
108
|
+
locked: policy.mode === "LOCKED",
|
|
109
|
+
delegated: policy.mode === "DELEGATED",
|
|
110
|
+
};
|
|
111
|
+
const sameTenant = existing.filter((r) => r.source_tenant_id === currentTenantId);
|
|
112
|
+
resolvedMap.set(compositeKey, [...sameTenant, resolvedPolicy]);
|
|
127
113
|
}
|
|
128
114
|
}
|
|
129
|
-
return Array.from(resolvedMap.values());
|
|
115
|
+
return Array.from(resolvedMap.values()).flat();
|
|
130
116
|
});
|
|
131
117
|
}
|
|
132
118
|
// ---------------------------------------------------------------------------
|
|
@@ -151,11 +137,39 @@ async function evaluateAbac(pool, tenantId, request) {
|
|
|
151
137
|
if (matching.length === 0) {
|
|
152
138
|
return { allowed: false, reason: "no_matching_policy" };
|
|
153
139
|
}
|
|
154
|
-
// Build
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
140
|
+
// Build the attribute context. Subject and resource keep separate namespaces:
|
|
141
|
+
// `subject.<name>` and `resource.<name>` always read their own side. A bare
|
|
142
|
+
// `<name>` reads whichever side carries it; when both do, the reference is
|
|
143
|
+
// ambiguous and the request is denied rather than letting one side's value
|
|
144
|
+
// stand in for the other's.
|
|
145
|
+
const context = {};
|
|
146
|
+
const ambiguous = new Set();
|
|
147
|
+
const isQualified = (key) => key.startsWith("subject.") || key.startsWith("resource.");
|
|
148
|
+
for (const [key, value] of Object.entries(request.subject)) {
|
|
149
|
+
if (!isQualified(key))
|
|
150
|
+
context[key] = value;
|
|
151
|
+
}
|
|
152
|
+
for (const [key, value] of Object.entries(request.resource)) {
|
|
153
|
+
if (isQualified(key))
|
|
154
|
+
continue;
|
|
155
|
+
if (Object.prototype.hasOwnProperty.call(request.subject, key)) {
|
|
156
|
+
ambiguous.add(key);
|
|
157
|
+
delete context[key];
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
context[key] = value;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
for (const [key, value] of Object.entries(request.subject)) {
|
|
164
|
+
context[`subject.${key}`] = value;
|
|
165
|
+
}
|
|
166
|
+
for (const [key, value] of Object.entries(request.resource)) {
|
|
167
|
+
context[`resource.${key}`] = value;
|
|
168
|
+
}
|
|
169
|
+
const usesAmbiguousAttribute = matching.some(({ policy }) => policy.conditions.some((c) => ambiguous.has(c.attribute)));
|
|
170
|
+
if (usesAmbiguousAttribute) {
|
|
171
|
+
return { allowed: false, reason: "ambiguous_attribute" };
|
|
172
|
+
}
|
|
159
173
|
// Sort by priority descending
|
|
160
174
|
const sorted = [...matching].sort((a, b) => b.policy.priority - a.policy.priority);
|
|
161
175
|
// Evaluate each policy; collect matches
|
|
@@ -195,7 +209,8 @@ async function evaluateAbac(pool, tenantId, request) {
|
|
|
195
209
|
* Create a new ABAC policy for a tenant.
|
|
196
210
|
* Rejects if an ancestor policy with the same composite key is LOCKED.
|
|
197
211
|
*/
|
|
198
|
-
async function createAbacPolicy(pool, tenantId,
|
|
212
|
+
async function createAbacPolicy(pool, tenantId, rawInput) {
|
|
213
|
+
const input = (0, validation_js_1.parseInput)(core_1.CreateAbacPolicyInputSchema, rawInput);
|
|
199
214
|
return (0, pool_helpers_js_1.withTransaction)(pool, async (client) => {
|
|
200
215
|
const tenantRes = await client.query(`SELECT ancestry_path FROM tenants WHERE id = $1`, [tenantId]);
|
|
201
216
|
if (tenantRes.rows.length === 0) {
|
|
@@ -251,13 +266,19 @@ async function deleteAbacPolicy(pool, tenantId, policyId) {
|
|
|
251
266
|
}
|
|
252
267
|
const policy = existing.rows[0];
|
|
253
268
|
// Cascade: delete from all descendants. Match descendants by the stable,
|
|
254
|
-
// ID-based ancestry_path
|
|
255
|
-
// every descendant) so revocation reaches all current descendants
|
|
269
|
+
// ID-based ancestry_path so revocation reaches all current descendants
|
|
256
270
|
// regardless of any slug rename. ancestry_ltree is derived from slugs and
|
|
257
|
-
// must not scope revocation.
|
|
271
|
+
// must not scope revocation. A prefix match lets
|
|
272
|
+
// idx_tenant_ancestry_path_prefix (028) serve the query.
|
|
273
|
+
await (0, tenant_service_js_1.lockTree)(client, "shared");
|
|
274
|
+
const tenantRes = await client.query(`SELECT ancestry_path FROM tenants WHERE id = $1`, [tenantId]);
|
|
275
|
+
// A concurrent purge can remove the tenant after the policy was read.
|
|
276
|
+
if (tenantRes.rows.length === 0) {
|
|
277
|
+
throw new core_1.TenantNotFoundError(tenantId);
|
|
278
|
+
}
|
|
279
|
+
const subtreePath = (0, core_1.appendToPath)(tenantRes.rows[0].ancestry_path, tenantId);
|
|
258
280
|
const descendantsRes = await client.query(`SELECT id FROM tenants
|
|
259
|
-
WHERE
|
|
260
|
-
AND (ancestry_path LIKE '%/' || $1 || '/%' OR ancestry_path LIKE '%/' || $1)`, [tenantId]);
|
|
281
|
+
WHERE ancestry_path = $1 OR ancestry_path LIKE $2`, [subtreePath, `${subtreePath}/%`]);
|
|
261
282
|
const descendantIds = descendantsRes.rows.map((r) => r.id);
|
|
262
283
|
if (descendantIds.length > 0) {
|
|
263
284
|
await client.query(`DELETE FROM abac_policies
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abac-service.js","sourceRoot":"","sources":["../../src/services/abac-service.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"abac-service.js","sourceRoot":"","sources":["../../src/services/abac-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -65,6 +65,12 @@ export declare function getApiKey(pool: pg.Pool, id: string): Promise<{
|
|
|
65
65
|
revoked_at: Date | null;
|
|
66
66
|
expires_at: Date | null;
|
|
67
67
|
} | null>;
|
|
68
|
+
/**
|
|
69
|
+
* List the unrevoked keys not used for `dormantDays` days.
|
|
70
|
+
* validateApiKey refreshes last_used_at at most once a minute, so a key can
|
|
71
|
+
* look up to one minute older than its latest use. That does not change a
|
|
72
|
+
* result measured in days.
|
|
73
|
+
*/
|
|
68
74
|
export declare function listDormantKeys(pool: pg.Pool, dormantDays?: number): Promise<Array<{
|
|
69
75
|
id: string;
|
|
70
76
|
tenant_id: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-key-service.d.ts","sourceRoot":"","sources":["../../src/services/api-key-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;IACjB,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;IACjB,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;CACvB;AAiCD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAK7G;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,GAAG,mBAAmB,EAC5C,SAAS,CAAC,EAAE,IAAI,GACf,OAAO,CAAC,aAAa,CAAC,CAyBxB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;
|
|
1
|
+
{"version":3,"file":"api-key-service.d.ts","sourceRoot":"","sources":["../../src/services/api-key-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -66,6 +66,17 @@ async function createApiKey(pool, keyPrefix, tenantId, nameOrOptions, expiresAt)
|
|
|
66
66
|
};
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* A validation stamps last_used_at only when the stored value is older than
|
|
71
|
+
* this. Concurrent requests with one key then do not all wait on its row lock.
|
|
72
|
+
* The cost: last_used_at can lag the latest use by up to this interval.
|
|
73
|
+
*/
|
|
74
|
+
const STAMP_INTERVAL_SECONDS = 60;
|
|
75
|
+
/**
|
|
76
|
+
* The longest time a validation waits for its last_used_at stamp. A stamp
|
|
77
|
+
* that waits on a row lock then cannot delay authentication for longer.
|
|
78
|
+
*/
|
|
79
|
+
const STAMP_TIMEOUT_MS = 1000;
|
|
69
80
|
async function validateApiKey(pool, key) {
|
|
70
81
|
const hmacSecret = getHmacSecret();
|
|
71
82
|
// Build candidate hashes: try HMAC first (if secret is set), then SHA-256 fallback
|
|
@@ -74,41 +85,68 @@ async function validateApiKey(pool, key) {
|
|
|
74
85
|
candidates.push({ hash: hmacHash(key, hmacSecret), version: HASH_V2_HMAC });
|
|
75
86
|
}
|
|
76
87
|
candidates.push({ hash: sha256Hash(key), version: HASH_V1_SHA256 });
|
|
77
|
-
|
|
88
|
+
// Everything below runs on one pooled connection: nothing here may acquire a
|
|
89
|
+
// second connection while this one is held.
|
|
90
|
+
const found = await (0, pool_helpers_js_1.withClient)(pool, async (client) => {
|
|
78
91
|
for (const candidate of candidates) {
|
|
79
|
-
|
|
80
|
-
|
|
92
|
+
// A tenant-bound key authenticates only while its tenant and every
|
|
93
|
+
// ancestor are active. Global keys (tenant_id NULL) have no tenant.
|
|
94
|
+
const res = await client.query(`SELECT ak.id, ak.tenant_id, ak.key_hash, ak.key_prefix, ak.name, ak.created_at, ak.last_used_at, ak.revoked_at, ak.expires_at, ak.scopes, ak.rate_limit_max, ak.rate_limit_window, ak.hash_version,
|
|
95
|
+
(ak.last_used_at IS NULL OR ak.last_used_at < now() - make_interval(secs => $2)) AS stamp_due
|
|
96
|
+
FROM api_keys ak
|
|
97
|
+
LEFT JOIN tenants t ON t.id = ak.tenant_id
|
|
98
|
+
WHERE ak.key_hash = $1 AND ak.revoked_at IS NULL AND (ak.expires_at IS NULL OR ak.expires_at > now())
|
|
99
|
+
AND (ak.tenant_id IS NULL OR (
|
|
100
|
+
t.status = 'active'
|
|
101
|
+
AND NOT EXISTS (
|
|
102
|
+
SELECT 1 FROM tenants anc
|
|
103
|
+
WHERE anc.id = ANY (string_to_array(trim(both '/' from t.ancestry_path), '/')::uuid[])
|
|
104
|
+
AND anc.status <> 'active'
|
|
105
|
+
)
|
|
106
|
+
))`, [candidate.hash, STAMP_INTERVAL_SECONDS]);
|
|
81
107
|
if (res.rows.length === 0)
|
|
82
108
|
continue;
|
|
83
109
|
const row = res.rows[0];
|
|
84
|
-
// Transparent upgrade: if we matched via legacy SHA-256 but HMAC secret is available,
|
|
85
|
-
// re-hash with HMAC and update the stored hash in-place
|
|
86
|
-
if (row.hash_version === HASH_V1_SHA256 && hmacSecret) {
|
|
87
|
-
const upgradedHash = hmacHash(key, hmacSecret);
|
|
88
|
-
pool
|
|
89
|
-
.query(`UPDATE api_keys SET key_hash = $1, hash_version = $2, last_used_at = now() WHERE id = $3`, [upgradedHash, HASH_V2_HMAC, row.id])
|
|
90
|
-
.catch(() => {
|
|
91
|
-
// Non-critical: upgrade will happen on next request
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
// Update last_used_at — fire-and-forget
|
|
96
|
-
pool
|
|
97
|
-
.query(`UPDATE api_keys SET last_used_at = now() WHERE id = $1`, [row.id])
|
|
98
|
-
.catch(() => { });
|
|
99
|
-
}
|
|
100
110
|
return {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
row,
|
|
112
|
+
validated: {
|
|
113
|
+
tenant_id: row.tenant_id,
|
|
114
|
+
key_id: row.id,
|
|
115
|
+
// Resolve through the single source so an assigned role governs the
|
|
116
|
+
// key's scopes at the auth boundary, exactly as resolveKeyScopes does.
|
|
117
|
+
scopes: await (0, role_service_js_1.resolveEffectiveScopesOnClient)(client, row.id),
|
|
118
|
+
rate_limit_max: row.rate_limit_max,
|
|
119
|
+
rate_limit_window: row.rate_limit_window,
|
|
120
|
+
},
|
|
108
121
|
};
|
|
109
122
|
}
|
|
110
123
|
return null;
|
|
111
124
|
});
|
|
125
|
+
if (!found)
|
|
126
|
+
return null;
|
|
127
|
+
// The bookkeeping starts only after the validation connection is released,
|
|
128
|
+
// so a single-connection pool cannot deadlock. withClient gives it the RLS bypass.
|
|
129
|
+
// When a stamp is due, we await it so that a read made after validateApiKey
|
|
130
|
+
// resolves sees the new last_used_at. Without the await, listDormantKeys can
|
|
131
|
+
// report a just-used key.
|
|
132
|
+
// Transparent upgrade: if we matched via legacy SHA-256 but HMAC secret is
|
|
133
|
+
// available, re-hash with HMAC and update the stored hash in-place.
|
|
134
|
+
const { row } = found;
|
|
135
|
+
const upgrade = row.hash_version === HASH_V1_SHA256 && hmacSecret;
|
|
136
|
+
if (!upgrade && !row.stamp_due)
|
|
137
|
+
return found.validated;
|
|
138
|
+
await (0, pool_helpers_js_1.withClient)(pool, async (client) => {
|
|
139
|
+
// SET LOCAL ends with this transaction, so the pooled connection keeps its own timeout.
|
|
140
|
+
await client.query(`SET LOCAL statement_timeout = ${STAMP_TIMEOUT_MS}`);
|
|
141
|
+
return upgrade
|
|
142
|
+
? client.query(`UPDATE api_keys SET key_hash = $1, hash_version = $2, last_used_at = now() WHERE id = $3`, [hmacHash(key, hmacSecret), HASH_V2_HMAC, row.id])
|
|
143
|
+
: // The condition repeats the check, so a concurrent request that stamped first wins.
|
|
144
|
+
client.query(`UPDATE api_keys SET last_used_at = now()
|
|
145
|
+
WHERE id = $1 AND (last_used_at IS NULL OR last_used_at < now() - make_interval(secs => $2))`, [row.id, STAMP_INTERVAL_SECONDS]);
|
|
146
|
+
}).catch(() => {
|
|
147
|
+
// A failed or timed-out stamp must not fail authentication. A later request retries it.
|
|
148
|
+
});
|
|
149
|
+
return found.validated;
|
|
112
150
|
}
|
|
113
151
|
async function revokeApiKey(pool, keyId) {
|
|
114
152
|
return (0, pool_helpers_js_1.withTransaction)(pool, async (client) => {
|
|
@@ -118,17 +156,24 @@ async function revokeApiKey(pool, keyId) {
|
|
|
118
156
|
}
|
|
119
157
|
async function rotateApiKey(pool, keyPrefix, oldKeyId, newName) {
|
|
120
158
|
return (0, pool_helpers_js_1.withTransaction)(pool, async (client) => {
|
|
121
|
-
// Verify old key exists and
|
|
122
|
-
const oldRes = await client.query(`SELECT id, tenant_id, name, key_prefix
|
|
159
|
+
// Verify old key exists, is not revoked and has not expired
|
|
160
|
+
const oldRes = await client.query(`SELECT id, tenant_id, name, key_prefix, scopes, role_id, expires_at, rate_limit_max, rate_limit_window
|
|
161
|
+
FROM api_keys
|
|
162
|
+
WHERE id = $1 AND revoked_at IS NULL AND (expires_at IS NULL OR expires_at > now())
|
|
163
|
+
FOR UPDATE`, [oldKeyId]);
|
|
123
164
|
if (oldRes.rows.length === 0) {
|
|
124
|
-
throw new Error(`API key not found or already revoked: ${oldKeyId}`);
|
|
165
|
+
throw new Error(`API key not found, expired or already revoked: ${oldKeyId}`);
|
|
125
166
|
}
|
|
126
167
|
const old = oldRes.rows[0];
|
|
127
|
-
// Create new key for same tenant
|
|
168
|
+
// Create the new key for the same tenant with the same restrictions: scopes,
|
|
169
|
+
// role, expiry and rate limit carry over, so rotation never widens access.
|
|
128
170
|
const { plaintextKey, keyHash, hashVersion } = generateKey(keyPrefix);
|
|
129
|
-
const res = await client.query(`INSERT INTO api_keys (tenant_id, key_hash, key_prefix, name, hash_version)
|
|
130
|
-
VALUES ($1, $2, $3, $4, $5)
|
|
131
|
-
RETURNING id, tenant_id, name, key_prefix, created_at`, [
|
|
171
|
+
const res = await client.query(`INSERT INTO api_keys (tenant_id, key_hash, key_prefix, name, hash_version, scopes, role_id, expires_at, rate_limit_max, rate_limit_window)
|
|
172
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
|
173
|
+
RETURNING id, tenant_id, name, key_prefix, created_at`, [
|
|
174
|
+
old.tenant_id, keyHash, keyPrefix, newName ?? `${old.name ?? "key"} (rotated)`, hashVersion,
|
|
175
|
+
old.scopes, old.role_id, old.expires_at, old.rate_limit_max, old.rate_limit_window,
|
|
176
|
+
]);
|
|
132
177
|
// Revoke old key
|
|
133
178
|
await client.query(`UPDATE api_keys SET revoked_at = now() WHERE id = $1`, [oldKeyId]);
|
|
134
179
|
const row = res.rows[0];
|
|
@@ -166,6 +211,12 @@ async function getApiKey(pool, id) {
|
|
|
166
211
|
return res.rows[0] ?? null;
|
|
167
212
|
});
|
|
168
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* List the unrevoked keys not used for `dormantDays` days.
|
|
216
|
+
* validateApiKey refreshes last_used_at at most once a minute, so a key can
|
|
217
|
+
* look up to one minute older than its latest use. That does not change a
|
|
218
|
+
* result measured in days.
|
|
219
|
+
*/
|
|
169
220
|
async function listDormantKeys(pool, dormantDays = 90) {
|
|
170
221
|
return (0, pool_helpers_js_1.withClient)(pool, async (client) => {
|
|
171
222
|
const res = await client.query(`SELECT id, tenant_id, name, last_used_at, created_at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-key-service.js","sourceRoot":"","sources":["../../src/services/api-key-service.ts"],"names":[],"mappings":";;;;;AA2DA,kCAKC;AASD,oCA+BC;
|
|
1
|
+
{"version":3,"file":"api-key-service.js","sourceRoot":"","sources":["../../src/services/api-key-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-service.d.ts","sourceRoot":"","sources":["../../src/services/audit-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"audit-service.d.ts","sourceRoot":"","sources":["../../src/services/audit-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,qBAAqB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EAC5C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAC/B,OAAO,CAAC,UAAU,CAAC,CAyBrB;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,UAAU,CAAC,CAmBrB;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC,UAAU,EAAE,CAAC,CAkDvB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAY5B"}
|
|
@@ -5,6 +5,7 @@ exports.recordAuditEvent = recordAuditEvent;
|
|
|
5
5
|
exports.queryAuditLogs = queryAuditLogs;
|
|
6
6
|
exports.getAuditEntry = getAuditEntry;
|
|
7
7
|
const pool_helpers_js_1 = require("../pool-helpers.js");
|
|
8
|
+
const validation_js_1 = require("../validation.js");
|
|
8
9
|
const core_1 = require("@stratum-hq/core");
|
|
9
10
|
async function createAuditEntry(pool, context, action, resourceType, resourceId, tenantId, beforeState, afterState, metadata, createdAt) {
|
|
10
11
|
return (0, pool_helpers_js_1.withClient)(pool, async (client) => {
|
|
@@ -37,7 +38,7 @@ async function createAuditEntry(pool, context, action, resourceType, resourceId,
|
|
|
37
38
|
* for input.tenantId and no other tenant.
|
|
38
39
|
*/
|
|
39
40
|
async function recordAuditEvent(pool, input) {
|
|
40
|
-
const parsed = core_1.RecordAuditEventInputSchema
|
|
41
|
+
const parsed = (0, validation_js_1.parseInput)(core_1.RecordAuditEventInputSchema, input);
|
|
41
42
|
const context = {
|
|
42
43
|
actor_id: parsed.actorId,
|
|
43
44
|
actor_type: parsed.actorType,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-service.js","sourceRoot":"","sources":["../../src/services/audit-service.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"audit-service.js","sourceRoot":"","sources":["../../src/services/audit-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-service.d.ts","sourceRoot":"","sources":["../../src/services/config-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EAExB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAO1B,MAAM,kBAAkB,CAAC;AAG1B;;;GAGG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAyE5F;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,WAAW,CAAC,CAiDtB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,EAAE,GAC7B,OAAO,CAAC,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"config-service.d.ts","sourceRoot":"","sources":["../../src/services/config-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EAExB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAO1B,MAAM,kBAAkB,CAAC;AAG1B;;;GAGG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAyE5F;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,WAAW,CAAC,CAiDtB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,EAAE,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA0E/B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,CAAC,CA+GzB"}
|
|
@@ -122,13 +122,16 @@ async function batchSetConfig(pool, tenantId, entries) {
|
|
|
122
122
|
}
|
|
123
123
|
const ancestorIds = (0, core_1.parseAncestryPath)(tenantRes.rows[0].ancestry_path);
|
|
124
124
|
const keys = entries.map((e) => e.key);
|
|
125
|
-
// Batch-load all ancestor locks in a single query
|
|
125
|
+
// Batch-load all ancestor locks in a single query.
|
|
126
|
+
// Only enforce locks from non-archived ancestors — consistent with setConfig.
|
|
126
127
|
const lockedKeys = new Map();
|
|
127
128
|
if (ancestorIds.length > 0 && keys.length > 0) {
|
|
128
|
-
const lockedRes = await client.query(`SELECT
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
AND
|
|
129
|
+
const lockedRes = await client.query(`SELECT ce.* FROM config_entries ce
|
|
130
|
+
JOIN tenants t ON t.id = ce.tenant_id
|
|
131
|
+
WHERE ce.tenant_id = ANY($1)
|
|
132
|
+
AND ce.key = ANY($2)
|
|
133
|
+
AND ce.locked = true
|
|
134
|
+
AND t.status != 'archived'`, [ancestorIds, keys]);
|
|
132
135
|
for (const row of lockedRes.rows) {
|
|
133
136
|
lockedKeys.set(row.key, row.source_tenant_id);
|
|
134
137
|
}
|
|
@@ -194,7 +197,12 @@ async function getConfigWithInheritance(pool, tenantId) {
|
|
|
194
197
|
const ancestryPath = tenantRes.rows[0].ancestry_path;
|
|
195
198
|
const ancestorIds = (0, core_1.parseAncestryPath)(ancestryPath);
|
|
196
199
|
const allIds = [...ancestorIds, tenantId];
|
|
197
|
-
|
|
200
|
+
// Archived ancestors do not participate in inheritance or locking —
|
|
201
|
+
// consistent with resolveConfig and setConfig.
|
|
202
|
+
const entriesRes = await client.query(`SELECT ce.* FROM config_entries ce
|
|
203
|
+
JOIN tenants t ON t.id = ce.tenant_id
|
|
204
|
+
WHERE ce.tenant_id = ANY($1)
|
|
205
|
+
AND (ce.tenant_id = $2 OR t.status != 'archived')`, [allIds, tenantId]);
|
|
198
206
|
// Group entries by tenant_id for ordered traversal
|
|
199
207
|
const entriesByTenantId = new Map();
|
|
200
208
|
for (const entry of entriesRes.rows) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-service.js","sourceRoot":"","sources":["../../src/services/config-service.ts"],"names":[],"mappings":";;AAsBA,sCAyEC;AAMD,8BAsDC;AAOD,
|
|
1
|
+
{"version":3,"file":"config-service.js","sourceRoot":"","sources":["../../src/services/config-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pg from "pg";
|
|
2
|
-
import type
|
|
3
|
-
export declare function grantConsent(pool: pg.Pool, tenantId: string,
|
|
2
|
+
import { type ConsentRecord, type GrantConsentInput } from "@stratum-hq/core";
|
|
3
|
+
export declare function grantConsent(pool: pg.Pool, tenantId: string, rawInput: GrantConsentInput): Promise<ConsentRecord>;
|
|
4
4
|
export declare function revokeConsent(pool: pg.Pool, tenantId: string, subjectId: string, purpose: string): Promise<boolean>;
|
|
5
5
|
export declare function listConsent(pool: pg.Pool, tenantId: string, subjectId?: string): Promise<ConsentRecord[]>;
|
|
6
6
|
export declare function getActiveConsent(pool: pg.Pool, tenantId: string, subjectId: string, purpose: string): Promise<ConsentRecord | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-service.d.ts","sourceRoot":"","sources":["../../src/services/consent-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"consent-service.d.ts","sourceRoot":"","sources":["../../src/services/consent-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,OAAO,EAA2B,KAAK,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEvG,wBAAsB,YAAY,CAChC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,aAAa,CAAC,CAwBxB;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"}
|
|
@@ -5,7 +5,10 @@ exports.revokeConsent = revokeConsent;
|
|
|
5
5
|
exports.listConsent = listConsent;
|
|
6
6
|
exports.getActiveConsent = getActiveConsent;
|
|
7
7
|
const pool_helpers_js_1 = require("../pool-helpers.js");
|
|
8
|
-
|
|
8
|
+
const validation_js_1 = require("../validation.js");
|
|
9
|
+
const core_1 = require("@stratum-hq/core");
|
|
10
|
+
async function grantConsent(pool, tenantId, rawInput) {
|
|
11
|
+
const input = (0, validation_js_1.parseInput)(core_1.GrantConsentInputSchema, rawInput);
|
|
9
12
|
return (0, pool_helpers_js_1.withTransaction)(pool, async (client) => {
|
|
10
13
|
const res = await client.query(`INSERT INTO consent_records (tenant_id, subject_id, purpose, granted, granted_at, revoked_at, expires_at, metadata)
|
|
11
14
|
VALUES ($1, $2, $3, true, now(), NULL, $4, $5)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-service.js","sourceRoot":"","sources":["../../src/services/consent-service.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"consent-service.js","sourceRoot":"","sources":["../../src/services/consent-service.ts"],"names":[],"mappings":";;AAKA,oCA4BC;AAED,sCAgBC;AAED,kCA2BC;AAED,4CAoBC;AArGD,wDAAiE;AACjE,oDAA8C;AAC9C,2CAAuG;AAEhG,KAAK,UAAU,YAAY,CAChC,IAAa,EACb,QAAgB,EAChB,QAA2B;IAE3B,MAAM,KAAK,GAAG,IAAA,0BAAU,EAAC,8BAAuB,EAAE,QAAQ,CAAC,CAAC;IAC5D,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;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;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;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"}
|