@stratum-hq/control-plane 1.0.1 → 1.2.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/README.md +4 -2
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +26 -0
- package/dist/config.js.map +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +6 -1
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/authorize.d.ts.map +1 -1
- package/dist/middleware/authorize.js +16 -6
- package/dist/middleware/authorize.js.map +1 -1
- package/dist/middleware/error-handler.d.ts +39 -0
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/error-handler.js +80 -14
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/middleware/per-key-rate-limit.d.ts +11 -1
- package/dist/middleware/per-key-rate-limit.d.ts.map +1 -1
- package/dist/middleware/per-key-rate-limit.js +14 -4
- package/dist/middleware/per-key-rate-limit.js.map +1 -1
- package/dist/middleware/rate-limit-redis.d.ts +2 -1
- package/dist/middleware/rate-limit-redis.d.ts.map +1 -1
- package/dist/middleware/rate-limit-redis.js +7 -4
- package/dist/middleware/rate-limit-redis.js.map +1 -1
- package/dist/middleware/telemetry.d.ts +1 -1
- package/dist/middleware/telemetry.d.ts.map +1 -1
- package/dist/middleware/telemetry.js +27 -8
- package/dist/middleware/telemetry.js.map +1 -1
- package/dist/middleware/tenant-scope.d.ts +19 -4
- package/dist/middleware/tenant-scope.d.ts.map +1 -1
- package/dist/middleware/tenant-scope.js +39 -9
- package/dist/middleware/tenant-scope.js.map +1 -1
- package/dist/redis.d.ts +3 -1
- package/dist/redis.d.ts.map +1 -1
- package/dist/redis.js +5 -6
- package/dist/redis.js.map +1 -1
- package/dist/routes/abac.d.ts.map +1 -1
- package/dist/routes/abac.js +3 -2
- package/dist/routes/abac.js.map +1 -1
- package/dist/routes/api-keys.d.ts.map +1 -1
- package/dist/routes/api-keys.js +20 -5
- package/dist/routes/api-keys.js.map +1 -1
- package/dist/routes/maintenance.js +3 -3
- package/dist/routes/maintenance.js.map +1 -1
- package/dist/routes/regions.d.ts.map +1 -1
- package/dist/routes/regions.js +5 -4
- package/dist/routes/regions.js.map +1 -1
- package/dist/routes/roles.d.ts.map +1 -1
- package/dist/routes/roles.js +18 -5
- package/dist/routes/roles.js.map +1 -1
- package/dist/routes/tenants.d.ts.map +1 -1
- package/dist/routes/tenants.js +97 -13
- package/dist/routes/tenants.js.map +1 -1
- package/dist/services/isolation-service.d.ts +6 -5
- package/dist/services/isolation-service.d.ts.map +1 -1
- package/dist/services/isolation-service.js +18 -12
- package/dist/services/isolation-service.js.map +1 -1
- package/package.json +6 -6
|
@@ -5,13 +5,21 @@ export type TenantIdExtractor = (req: FastifyRequest) => string | null;
|
|
|
5
5
|
/**
|
|
6
6
|
* A route's tenant-scope declaration:
|
|
7
7
|
* - an extractor: enforce that the caller's key may reach the extracted tenant;
|
|
8
|
-
* - "global":
|
|
9
|
-
*
|
|
8
|
+
* - "global": route with no single tenant target, or one that scopes itself
|
|
9
|
+
* in its handler. The middleware performs no tenant check.
|
|
10
|
+
* - "operator": route that acts across all tenants. Only global operator API
|
|
11
|
+
* keys (tenant_id === null) may call it; tenant-scoped callers are refused.
|
|
10
12
|
*/
|
|
11
|
-
export type TenantScopeDeclaration = TenantIdExtractor | "global";
|
|
13
|
+
export type TenantScopeDeclaration = TenantIdExtractor | "global" | "operator";
|
|
12
14
|
declare module "fastify" {
|
|
13
15
|
interface FastifyContextConfig {
|
|
14
16
|
tenantScope?: TenantScopeDeclaration;
|
|
17
|
+
/**
|
|
18
|
+
* Also accept a pending target in the tenant-scope check. A tenant whose
|
|
19
|
+
* storage provisioning failed stays pending. The key that created it must
|
|
20
|
+
* be able to remove it. Archived and suspended targets stay refused.
|
|
21
|
+
*/
|
|
22
|
+
tenantScopeIncludesPending?: boolean;
|
|
15
23
|
}
|
|
16
24
|
}
|
|
17
25
|
/**
|
|
@@ -24,8 +32,15 @@ declare module "fastify" {
|
|
|
24
32
|
*
|
|
25
33
|
* Exported for routes whose target tenant is not present in the request and
|
|
26
34
|
* must be resolved first (for example a role's owning tenant, looked up by id).
|
|
35
|
+
*
|
|
36
|
+
* @param includePending - also accept a pending target. An active target is
|
|
37
|
+
* always accepted. Archived and suspended targets are always refused.
|
|
27
38
|
*/
|
|
28
|
-
export declare function assertTenantInScope(stratum: Stratum, request: FastifyRequest, tenantId: string | null): Promise<void>;
|
|
39
|
+
export declare function assertTenantInScope(stratum: Stratum, request: FastifyRequest, tenantId: string | null, includePending?: boolean): Promise<void>;
|
|
40
|
+
/** True when the caller is a global operator API key (no tenant scope). */
|
|
41
|
+
export declare function isOperator(request: FastifyRequest): boolean;
|
|
42
|
+
/** Refuse the request unless the caller is a global operator API key. */
|
|
43
|
+
export declare function assertOperator(request: FastifyRequest): void;
|
|
29
44
|
/**
|
|
30
45
|
* Tenant-scope enforcement middleware for a single extractor.
|
|
31
46
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-scope.d.ts","sourceRoot":"","sources":["../../src/middleware/tenant-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAExE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,MAAM,GAAG,IAAI,CAAC;AAEvE
|
|
1
|
+
{"version":3,"file":"tenant-scope.d.ts","sourceRoot":"","sources":["../../src/middleware/tenant-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAExE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,MAAM,GAAG,IAAI,CAAC;AAEvE;;;;;;;GAOG;AACH,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/E,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,oBAAoB;QAC5B,WAAW,CAAC,EAAE,sBAAsB,CAAC;QACrC;;;;WAIG;QACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;KACtC;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,cAAc,UAAQ,GACrB,OAAO,CAAC,IAAI,CAAC,CAoCf;AAED,2EAA2E;AAC3E,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAE3D;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAI5D;AAcD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,iBAAiB,IAGhC,SAAS,cAAc,EACvB,QAAQ,YAAY,KACnB,OAAO,CAAC,IAAI,CAAC,CAGjB;AA6BD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,IAEpD,SAAS,cAAc,EACvB,QAAQ,YAAY,KACnB,OAAO,CAAC,IAAI,CAAC,CAIjB;AAKD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,IAEzD,SAAS,cAAc,EACvB,QAAQ,YAAY,KACnB,OAAO,CAAC,IAAI,CAAC,CAcjB;AAYD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,eAAe,EACpB,WAAW,EAAE,sBAAsB,GAClC,IAAI,CAON;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,IAEtD,SAAS,cAAc,EACvB,QAAQ,YAAY,KACnB,OAAO,CAAC,IAAI,CAAC,CAgBjB;AAID,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAE9D;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAEpE;AAED,0CAA0C;AAC1C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAEpE;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAEnE;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAEnE;AAED,0CAA0C;AAC1C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAEnE;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAEtE"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.assertTenantInScope = assertTenantInScope;
|
|
4
|
+
exports.isOperator = isOperator;
|
|
5
|
+
exports.assertOperator = assertOperator;
|
|
4
6
|
exports.createTenantScopeGuard = createTenantScopeGuard;
|
|
5
7
|
exports.createTenantCreateGuard = createTenantCreateGuard;
|
|
6
8
|
exports.createTenantBatchCreateGuard = createTenantBatchCreateGuard;
|
|
@@ -24,8 +26,11 @@ const core_1 = require("@stratum-hq/core");
|
|
|
24
26
|
*
|
|
25
27
|
* Exported for routes whose target tenant is not present in the request and
|
|
26
28
|
* must be resolved first (for example a role's owning tenant, looked up by id).
|
|
29
|
+
*
|
|
30
|
+
* @param includePending - also accept a pending target. An active target is
|
|
31
|
+
* always accepted. Archived and suspended targets are always refused.
|
|
27
32
|
*/
|
|
28
|
-
async function assertTenantInScope(stratum, request, tenantId) {
|
|
33
|
+
async function assertTenantInScope(stratum, request, tenantId, includePending = false) {
|
|
29
34
|
const apiKey = request.apiKey;
|
|
30
35
|
if (!apiKey)
|
|
31
36
|
return;
|
|
@@ -37,16 +42,19 @@ async function assertTenantInScope(stratum, request, tenantId) {
|
|
|
37
42
|
return;
|
|
38
43
|
throw new core_1.ForbiddenError("JWT authentication requires a tenant scope");
|
|
39
44
|
}
|
|
40
|
-
if (
|
|
45
|
+
if (tenantId === null)
|
|
41
46
|
return;
|
|
42
47
|
// Fast path: exact match
|
|
43
48
|
if (apiKey.tenant_id === tenantId)
|
|
44
49
|
return;
|
|
45
50
|
// Hierarchy check: target must be a descendant of the key's tenant
|
|
46
51
|
try {
|
|
47
|
-
|
|
52
|
+
// With includeArchived set, getTenant returns a row of any status, so the
|
|
53
|
+
// status check below decides which non-active targets pass.
|
|
54
|
+
const target = await stratum.getTenant(tenantId, includePending);
|
|
55
|
+
const statusAllowed = target.status === "active" || (includePending && target.status === "pending");
|
|
48
56
|
const ancestorIds = target.ancestry_path.split("/").filter(Boolean);
|
|
49
|
-
if (ancestorIds.includes(apiKey.tenant_id))
|
|
57
|
+
if (statusAllowed && ancestorIds.includes(apiKey.tenant_id))
|
|
50
58
|
return;
|
|
51
59
|
}
|
|
52
60
|
catch {
|
|
@@ -55,11 +63,21 @@ async function assertTenantInScope(stratum, request, tenantId) {
|
|
|
55
63
|
}
|
|
56
64
|
throw new core_1.ForbiddenError("API key tenant scope does not grant access to this tenant");
|
|
57
65
|
}
|
|
66
|
+
/** True when the caller is a global operator API key (no tenant scope). */
|
|
67
|
+
function isOperator(request) {
|
|
68
|
+
return request.authMethod === "api_key" && request.apiKey?.tenant_id === null;
|
|
69
|
+
}
|
|
70
|
+
/** Refuse the request unless the caller is a global operator API key. */
|
|
71
|
+
function assertOperator(request) {
|
|
72
|
+
if (!isOperator(request)) {
|
|
73
|
+
throw new core_1.ForbiddenError("This operation requires a global operator API key");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
58
76
|
/**
|
|
59
77
|
* Core tenant-scope check for a tenant id read from the request by `extractTenantId`.
|
|
60
78
|
*/
|
|
61
|
-
async function checkTenantScope(stratum, request, extractTenantId) {
|
|
62
|
-
await assertTenantInScope(stratum, request, extractTenantId(request));
|
|
79
|
+
async function checkTenantScope(stratum, request, extractTenantId, includePending = false) {
|
|
80
|
+
await assertTenantInScope(stratum, request, extractTenantId(request), includePending);
|
|
63
81
|
}
|
|
64
82
|
/**
|
|
65
83
|
* Tenant-scope enforcement middleware for a single extractor.
|
|
@@ -101,6 +119,8 @@ function createTenantCreateGuard(stratum) {
|
|
|
101
119
|
await authorizeCreateUnder(stratum, request, body?.parent_id ?? null);
|
|
102
120
|
};
|
|
103
121
|
}
|
|
122
|
+
/** Maximum number of tenants in one batch create. */
|
|
123
|
+
const MAX_BATCH_TENANTS = 100;
|
|
104
124
|
/**
|
|
105
125
|
* Guard for POST /tenants/batch: every tenant in the batch is authorized the
|
|
106
126
|
* same way a single create is, so the batch route cannot sidestep the subtree
|
|
@@ -110,8 +130,13 @@ function createTenantBatchCreateGuard(stratum) {
|
|
|
110
130
|
return async function tenantBatchCreateGuard(request, _reply) {
|
|
111
131
|
const body = request.body;
|
|
112
132
|
const tenants = Array.isArray(body?.tenants) ? body.tenants : [];
|
|
113
|
-
|
|
114
|
-
|
|
133
|
+
if (tenants.length > MAX_BATCH_TENANTS) {
|
|
134
|
+
throw new core_1.ValidationError(`Batch limited to ${MAX_BATCH_TENANTS} tenants`);
|
|
135
|
+
}
|
|
136
|
+
// Authorize each distinct parent once.
|
|
137
|
+
const parentIds = new Set(tenants.map((tenant) => tenant?.parent_id ?? null));
|
|
138
|
+
for (const parentId of parentIds) {
|
|
139
|
+
await authorizeCreateUnder(stratum, request, parentId);
|
|
115
140
|
}
|
|
116
141
|
};
|
|
117
142
|
}
|
|
@@ -153,7 +178,12 @@ function createTenantScopeEnforcer(stratum) {
|
|
|
153
178
|
}
|
|
154
179
|
if (declaration === "global")
|
|
155
180
|
return;
|
|
156
|
-
|
|
181
|
+
if (declaration === "operator") {
|
|
182
|
+
assertOperator(request);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const includePending = request.routeOptions?.config?.tenantScopeIncludesPending === true;
|
|
186
|
+
await checkTenantScope(stratum, request, declaration, includePending);
|
|
157
187
|
};
|
|
158
188
|
}
|
|
159
189
|
// --- Extractors ---
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-scope.js","sourceRoot":"","sources":["../../src/middleware/tenant-scope.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"tenant-scope.js","sourceRoot":"","sources":["../../src/middleware/tenant-scope.ts"],"names":[],"mappings":";;AA2CA,kDAyCC;AAGD,gCAEC;AAGD,wCAIC;AAoBD,wDAUC;AAgCD,0DAQC;AAUD,oEAkBC;AAkBD,gDAUC;AASD,8DAoBC;AAKD,kCAEC;AAGD,8CAEC;AAGD,8CAEC;AAGD,4CAEC;AAGD,4CAEC;AAGD,4CAEC;AAYD,kDAEC;AAxSD,2CAAmE;AA4BnE;;;;;;;;;;;;;GAaG;AACI,KAAK,UAAU,mBAAmB,CACvC,OAAgB,EAChB,OAAuB,EACvB,QAAuB,EACvB,cAAc,GAAG,KAAK;IAEtB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,yDAAyD;IACzD,iFAAiF;IACjF,qCAAqC;IACrC,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS;YAAE,OAAO;QAC7C,MAAM,IAAI,qBAAc,CAAC,4CAA4C,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO;IAE9B,yBAAyB;IACzB,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ;QAAE,OAAO;IAE1C,mEAAmE;IACnE,IAAI,CAAC;QACH,0EAA0E;QAC1E,4DAA4D;QAC5D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACjE,MAAM,aAAa,GACjB,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,cAAc,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;QAChF,MAAM,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpE,IAAI,aAAa,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;YAAE,OAAO;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;QAChD,MAAM,IAAI,qBAAc,CACtB,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,qBAAc,CACtB,2DAA2D,CAC5D,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,SAAgB,UAAU,CAAC,OAAuB;IAChD,OAAO,OAAO,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;AAChF,CAAC;AAED,yEAAyE;AACzE,SAAgB,cAAc,CAAC,OAAuB;IACpD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,qBAAc,CAAC,mDAAmD,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,gBAAgB,CAC7B,OAAgB,EAChB,OAAuB,EACvB,eAAkC,EAClC,cAAc,GAAG,KAAK;IAEtB,MAAM,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC;AACxF,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CACpC,OAAgB,EAChB,eAAkC;IAElC,OAAO,KAAK,UAAU,gBAAgB,CACpC,OAAuB,EACvB,MAAoB;QAEpB,MAAM,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;IAC5D,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,oBAAoB,CACjC,OAAgB,EAChB,OAAuB,EACvB,QAAuB;IAEvB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,6EAA6E;IAC7E,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO;IAE1E,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,qBAAc,CACtB,kDAAkD,CACnD,CAAC;IACJ,CAAC;IACD,MAAM,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB,CAAC,OAAgB;IACtD,OAAO,KAAK,UAAU,iBAAiB,CACrC,OAAuB,EACvB,MAAoB;QAEpB,MAAM,IAAI,GAAG,OAAO,CAAC,IAA4C,CAAC;QAClE,MAAM,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC,CAAC;IACxE,CAAC,CAAC;AACJ,CAAC;AAED,qDAAqD;AACrD,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;;;GAIG;AACH,SAAgB,4BAA4B,CAAC,OAAgB;IAC3D,OAAO,KAAK,UAAU,sBAAsB,CAC1C,OAAuB,EACvB,MAAoB;QAEpB,MAAM,IAAI,GAAG,OAAO,CAAC,IAEb,CAAC;QACT,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,IAAI,OAAO,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;YACvC,MAAM,IAAI,sBAAe,CAAC,oBAAoB,iBAAiB,UAAU,CAAC,CAAC;QAC7E,CAAC;QACD,uCAAuC;QACvC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC;QAC9E,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,wEAAwE;AACxE,6EAA6E;AAC7E,SAAS,qBAAqB,CAAC,GAAW;IACxC,OAAO,CACL,GAAG,KAAK,gBAAgB;QACxB,GAAG,CAAC,UAAU,CAAC,iBAAiB,CAAC;QACjC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAC5B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAChC,GAAoB,EACpB,WAAmC;IAEnC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,YAAY,EAAE,EAAE;QACtC,YAAY,CAAC,MAAM,GAAG;YACpB,GAAG,YAAY,CAAC,MAAM;YACtB,WAAW,EAAE,YAAY,CAAC,MAAM,EAAE,WAAW,IAAI,WAAW;SAC7D,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,yBAAyB,CAAC,OAAgB;IACxD,OAAO,KAAK,UAAU,mBAAmB,CACvC,OAAuB,EACvB,MAAoB;QAEpB,IAAI,qBAAqB,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO;QAE/C,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,CAAC;QAC9D,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,qBAAc,CAAC,uCAAuC,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,WAAW,KAAK,QAAQ;YAAE,OAAO;QACrC,IAAI,WAAW,KAAK,UAAU,EAAE,CAAC;YAC/B,cAAc,CAAC,OAAO,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;QAED,MAAM,cAAc,GAAG,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAC;QACzF,MAAM,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;IACxE,CAAC,CAAC;AACJ,CAAC;AAED,qBAAqB;AAErB,0EAA0E;AAC1E,SAAgB,WAAW,CAAC,GAAmB;IAC7C,OAAQ,GAAG,CAAC,MAAiC,CAAC,EAAE,IAAI,IAAI,CAAC;AAC3D,CAAC;AAED,+CAA+C;AAC/C,SAAgB,iBAAiB,CAAC,GAAmB;IACnD,OAAQ,GAAG,CAAC,MAAiC,CAAC,QAAQ,IAAI,IAAI,CAAC;AACjE,CAAC;AAED,0CAA0C;AAC1C,SAAgB,iBAAiB,CAAC,GAAmB;IACnD,OAAQ,GAAG,CAAC,KAAgC,CAAC,SAAS,IAAI,IAAI,CAAC;AACjE,CAAC;AAED,sEAAsE;AACtE,SAAgB,gBAAgB,CAAC,GAAmB;IAClD,OAAQ,GAAG,CAAC,KAAgC,CAAC,QAAQ,IAAI,IAAI,CAAC;AAChE,CAAC;AAED,uEAAuE;AACvE,SAAgB,gBAAgB,CAAC,GAAmB;IAClD,OAAQ,GAAG,CAAC,KAAgC,CAAC,QAAQ,IAAI,IAAI,CAAC;AAChE,CAAC;AAED,0CAA0C;AAC1C,SAAgB,gBAAgB,CAAC,GAAmB;IAClD,OAAQ,GAAG,CAAC,IAAsC,EAAE,SAAS,IAAI,IAAI,CAAC;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,mBAAmB,CAAC,GAAmB;IACrD,OAAQ,GAAG,CAAC,IAAsC,EAAE,aAAa,IAAI,IAAI,CAAC;AAC5E,CAAC"}
|
package/dist/redis.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ import Redis from "ioredis";
|
|
|
2
2
|
/**
|
|
3
3
|
* Create a Redis client from the REDIS_URL env var.
|
|
4
4
|
* Returns null if REDIS_URL is not configured.
|
|
5
|
-
* Connection errors are logged but never crash the process
|
|
5
|
+
* Connection errors are logged but never crash the process. The client keeps
|
|
6
|
+
* reconnecting with capped backoff; while it is down, per-key rate limiting
|
|
7
|
+
* falls back to the in-memory limiter.
|
|
6
8
|
*/
|
|
7
9
|
export declare function createRedisClient(): Redis | null;
|
|
8
10
|
/**
|
package/dist/redis.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../src/redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,SAAS,CAAC;AAK5B
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../src/redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,SAAS,CAAC;AAK5B;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,KAAK,GAAG,IAAI,CA8BhD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,KAAK,GAAG,IAAI,CAE7C;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,WAAW,GAAG,cAAc,GAAG,gBAAgB,CAAC,CAgBjG"}
|
package/dist/redis.js
CHANGED
|
@@ -12,7 +12,9 @@ let redisClient = null;
|
|
|
12
12
|
/**
|
|
13
13
|
* Create a Redis client from the REDIS_URL env var.
|
|
14
14
|
* Returns null if REDIS_URL is not configured.
|
|
15
|
-
* Connection errors are logged but never crash the process
|
|
15
|
+
* Connection errors are logged but never crash the process. The client keeps
|
|
16
|
+
* reconnecting with capped backoff; while it is down, per-key rate limiting
|
|
17
|
+
* falls back to the in-memory limiter.
|
|
16
18
|
*/
|
|
17
19
|
function createRedisClient() {
|
|
18
20
|
if (!config_js_1.config.redisUrl) {
|
|
@@ -21,11 +23,8 @@ function createRedisClient() {
|
|
|
21
23
|
const client = new ioredis_1.default(config_js_1.config.redisUrl, {
|
|
22
24
|
maxRetriesPerRequest: 1,
|
|
23
25
|
retryStrategy(times) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
return Math.min(times * 200, 2000);
|
|
26
|
+
// Never give up: returning null would stop reconnecting for good.
|
|
27
|
+
return Math.min(times * 200, 5000);
|
|
29
28
|
},
|
|
30
29
|
enableOfflineQueue: false,
|
|
31
30
|
lazyConnect: true,
|
package/dist/redis.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../src/redis.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../src/redis.ts"],"names":[],"mappings":";;;;;AAYA,8CA8BC;AAKD,wCAEC;AAKD,4CAgBC;AAtED,sDAA4B;AAC5B,2CAAqC;AAErC,IAAI,WAAW,GAAiB,IAAI,CAAC;AAErC;;;;;;GAMG;AACH,SAAgB,iBAAiB;IAC/B,IAAI,CAAC,kBAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,iBAAK,CAAC,kBAAM,CAAC,QAAQ,EAAE;QACxC,oBAAoB,EAAE,CAAC;QACvB,aAAa,CAAC,KAAa;YACzB,kEAAkE;YAClE,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,kBAAkB,EAAE,KAAK;QACzB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QACzB,OAAO,CAAC,IAAI,CAAC,+EAA+E,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7G,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QACxB,OAAO,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,6CAA6C;IAC7C,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QAC7B,OAAO,CAAC,IAAI,CAAC,uEAAuE,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACrG,CAAC,CAAC,CAAC;IAEH,WAAW,GAAG,MAAM,CAAC;IACrB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc;IAC5B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAChC,WAAW,CAAC,IAAI,EAAE;YAClB,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CACrD;SACF,CAAC,CAAC;QACH,OAAO,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abac.d.ts","sourceRoot":"","sources":["../../src/routes/abac.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"abac.d.ts","sourceRoot":"","sources":["../../src/routes/abac.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAK1C,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,IACd,KAAK,eAAe,KAAG,OAAO,CAAC,IAAI,CAAC,CA4CtE"}
|
package/dist/routes/abac.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createAbacRoutes = createAbacRoutes;
|
|
4
4
|
const core_1 = require("@stratum-hq/core");
|
|
5
5
|
const tenant_scope_js_1 = require("../middleware/tenant-scope.js");
|
|
6
|
+
const audit_logs_js_1 = require("./audit-logs.js");
|
|
6
7
|
function createAbacRoutes(stratum) {
|
|
7
8
|
return async function abacRoutes(app) {
|
|
8
9
|
// Tenant-scoped keys can only access ABAC policies for their own tenant subtree
|
|
@@ -10,7 +11,7 @@ function createAbacRoutes(stratum) {
|
|
|
10
11
|
// POST /api/v1/tenants/:tenantId/abac-policies — Create ABAC policy
|
|
11
12
|
app.post("/", async (request, reply) => {
|
|
12
13
|
const input = core_1.CreateAbacPolicyInputSchema.parse(request.body);
|
|
13
|
-
const policy = await stratum.createAbacPolicy(request.params.tenantId, input);
|
|
14
|
+
const policy = await stratum.createAbacPolicy(request.params.tenantId, input, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
14
15
|
reply.status(201).send(policy);
|
|
15
16
|
});
|
|
16
17
|
// GET /api/v1/tenants/:tenantId/abac-policies — List own ABAC policies
|
|
@@ -26,7 +27,7 @@ function createAbacRoutes(stratum) {
|
|
|
26
27
|
});
|
|
27
28
|
// DELETE /api/v1/tenants/:tenantId/abac-policies/:policyId — Delete ABAC policy
|
|
28
29
|
app.delete("/:policyId", async (request, reply) => {
|
|
29
|
-
await stratum.deleteAbacPolicy(request.params.tenantId, request.params.policyId);
|
|
30
|
+
await stratum.deleteAbacPolicy(request.params.tenantId, request.params.policyId, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
30
31
|
reply.status(204).send();
|
|
31
32
|
});
|
|
32
33
|
};
|
package/dist/routes/abac.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abac.js","sourceRoot":"","sources":["../../src/routes/abac.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"abac.js","sourceRoot":"","sources":["../../src/routes/abac.ts"],"names":[],"mappings":";;AAMA,4CA6CC;AAjDD,2CAAoJ;AACpJ,mEAAsF;AACtF,mDAAoD;AAEpD,SAAgB,gBAAgB,CAAC,OAAgB;IAC/C,OAAO,KAAK,UAAU,UAAU,CAAC,GAAoB;QACnD,gFAAgF;QAChF,IAAA,oCAAkB,EAAC,GAAG,EAAE,mCAAiB,CAAC,CAAC;QAE3C,oEAAoE;QACpE,GAAG,CAAC,IAAI,CAAmC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YACvE,MAAM,KAAK,GAAG,kCAA2B,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAA0B,CAAC;YACvF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAC3C,OAAO,CAAC,MAAM,CAAC,QAAQ,EACvB,KAAK,EACL,IAAA,iCAAiB,EAAC,OAAO,CAAC,CAC3B,CAAC;YACF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,uEAAuE;QACvE,GAAG,CAAC,GAAG,CAAmC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YACtE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACxE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,0EAA0E;QAC1E,GAAG,CAAC,IAAI,CAAmC,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YAC/E,MAAM,WAAW,GAAG,kCAA2B,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAA0B,CAAC;YAC7F,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,CACvC,OAAO,CAAC,MAAM,CAAC,QAAQ,EACvB,WAAW,CACZ,CAAC;YACF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,gFAAgF;QAChF,GAAG,CAAC,MAAM,CACR,YAAY,EACZ,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YACvB,MAAM,OAAO,CAAC,gBAAgB,CAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,EACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,EACvB,IAAA,iCAAiB,EAAC,OAAO,CAAC,CAC3B,CAAC;YACF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3B,CAAC,CACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-keys.d.ts","sourceRoot":"","sources":["../../src/routes/api-keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"api-keys.d.ts","sourceRoot":"","sources":["../../src/routes/api-keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAgB1C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,IACd,KAAK,eAAe,KAAG,OAAO,CAAC,IAAI,CAAC,CA4FxE"}
|
package/dist/routes/api-keys.js
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createApiKeyRoutes = createApiKeyRoutes;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const core_1 = require("@stratum-hq/core");
|
|
5
6
|
const tenant_scope_js_1 = require("../middleware/tenant-scope.js");
|
|
7
|
+
const per_key_rate_limit_js_1 = require("../middleware/per-key-rate-limit.js");
|
|
8
|
+
const config_js_1 = require("../config.js");
|
|
9
|
+
const audit_logs_js_1 = require("./audit-logs.js");
|
|
10
|
+
const error_handler_js_1 = require("../middleware/error-handler.js");
|
|
6
11
|
const createApiKeySchema = zod_1.z.object({
|
|
7
12
|
tenant_id: zod_1.z.string().uuid(),
|
|
8
13
|
name: zod_1.z.string().optional(),
|
|
9
14
|
rate_limit_max: zod_1.z.number().int().min(1).max(100_000).optional(),
|
|
10
|
-
rate_limit_window: zod_1.z.string().regex(
|
|
15
|
+
rate_limit_window: zod_1.z.string().regex(/^[1-9]\d*\s+(second|minute|hour|day)s?$/i).optional(),
|
|
11
16
|
});
|
|
12
17
|
function createApiKeyRoutes(stratum) {
|
|
13
18
|
return async function apiKeyRoutes(app) {
|
|
@@ -19,15 +24,25 @@ function createApiKeyRoutes(stratum) {
|
|
|
19
24
|
app.post("/", async (request, reply) => {
|
|
20
25
|
const parsed = createApiKeySchema.safeParse(request.body);
|
|
21
26
|
if (!parsed.success) {
|
|
22
|
-
reply.status(400).send(
|
|
27
|
+
reply.status(400).send((0, error_handler_js_1.legacyValidationErrorBody)("Invalid request body", parsed.error.issues));
|
|
23
28
|
return;
|
|
24
29
|
}
|
|
25
30
|
const { tenant_id, name, rate_limit_max, rate_limit_window } = parsed.data;
|
|
31
|
+
// A tenant-scoped caller may tighten a key's rate limit but not loosen it
|
|
32
|
+
// beyond the operator's configured default.
|
|
33
|
+
if (!(0, tenant_scope_js_1.isOperator)(request) && (rate_limit_max !== undefined || rate_limit_window !== undefined)) {
|
|
34
|
+
const defaultWindowMs = (0, per_key_rate_limit_js_1.parseWindow)(config_js_1.config.rateLimitWindow);
|
|
35
|
+
const max = rate_limit_max ?? config_js_1.config.rateLimitMax;
|
|
36
|
+
const windowMs = rate_limit_window ? (0, per_key_rate_limit_js_1.parseWindow)(rate_limit_window) : defaultWindowMs;
|
|
37
|
+
if (max > config_js_1.config.rateLimitMax || max * defaultWindowMs > config_js_1.config.rateLimitMax * windowMs) {
|
|
38
|
+
throw new core_1.ForbiddenError("Only operator keys may set a per-key rate limit above the configured default");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
26
41
|
const result = await stratum.createApiKey(tenant_id, {
|
|
27
42
|
name,
|
|
28
43
|
rateLimitMax: rate_limit_max,
|
|
29
44
|
rateLimitWindow: rate_limit_window,
|
|
30
|
-
});
|
|
45
|
+
}, undefined, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
31
46
|
reply.status(201).send(result);
|
|
32
47
|
});
|
|
33
48
|
// GET /api/v1/api-keys — List API keys (optional ?tenant_id=)
|
|
@@ -63,7 +78,7 @@ function createApiKeyRoutes(stratum) {
|
|
|
63
78
|
}
|
|
64
79
|
const rotateSchema = zod_1.z.object({ name: zod_1.z.string().max(255).optional() });
|
|
65
80
|
const parsed = rotateSchema.parse(request.body ?? {});
|
|
66
|
-
const result = await stratum.rotateApiKey(request.params.id, parsed.name);
|
|
81
|
+
const result = await stratum.rotateApiKey(request.params.id, parsed.name, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
67
82
|
reply.status(201).send(result);
|
|
68
83
|
});
|
|
69
84
|
// DELETE /api/v1/api-keys/:id — Revoke an API key
|
|
@@ -76,7 +91,7 @@ function createApiKeyRoutes(stratum) {
|
|
|
76
91
|
return;
|
|
77
92
|
}
|
|
78
93
|
}
|
|
79
|
-
const revoked = await stratum.revokeApiKey(request.params.id);
|
|
94
|
+
const revoked = await stratum.revokeApiKey(request.params.id, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
80
95
|
if (!revoked) {
|
|
81
96
|
reply.status(404).send({ error: { code: "NOT_FOUND", message: "API key not found or already revoked" } });
|
|
82
97
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-keys.js","sourceRoot":"","sources":["../../src/routes/api-keys.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"api-keys.js","sourceRoot":"","sources":["../../src/routes/api-keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,8 @@ const audit_logs_js_1 = require("./audit-logs.js");
|
|
|
5
5
|
const tenant_scope_js_1 = require("../middleware/tenant-scope.js");
|
|
6
6
|
function createMaintenanceRoutes(stratum) {
|
|
7
7
|
return async function maintenanceRoutes(app) {
|
|
8
|
-
//
|
|
9
|
-
(0, tenant_scope_js_1.declareTenantScope)(app, "
|
|
8
|
+
// Maintenance acts across all tenants: global operator keys only.
|
|
9
|
+
(0, tenant_scope_js_1.declareTenantScope)(app, "operator");
|
|
10
10
|
// POST /api/v1/maintenance/purge-expired — Purge expired data
|
|
11
11
|
app.post("/purge-expired", async (request, reply) => {
|
|
12
12
|
const rawDays = request.query.retention_days
|
|
@@ -15,7 +15,7 @@ function createMaintenanceRoutes(stratum) {
|
|
|
15
15
|
const retentionDays = rawDays !== undefined && (Number.isNaN(rawDays) || rawDays < 1)
|
|
16
16
|
? undefined
|
|
17
17
|
: rawDays !== undefined ? Math.min(rawDays, 3650) : undefined;
|
|
18
|
-
const result = await stratum.purgeExpiredData(retentionDays);
|
|
18
|
+
const result = await stratum.purgeExpiredData(retentionDays, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
19
19
|
reply.status(200).send(result);
|
|
20
20
|
});
|
|
21
21
|
// POST /api/v1/maintenance/rotate-encryption-key — Re-encrypt all sensitive data
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../src/routes/maintenance.ts"],"names":[],"mappings":";;AAKA,0DAgCC;AAnCD,mDAAoD;AACpD,mEAAmE;AAEnE,SAAgB,uBAAuB,CAAC,OAAgB;IACtD,OAAO,KAAK,UAAU,iBAAiB,CAAC,GAAoB;QAC1D,
|
|
1
|
+
{"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../src/routes/maintenance.ts"],"names":[],"mappings":";;AAKA,0DAgCC;AAnCD,mDAAoD;AACpD,mEAAmE;AAEnE,SAAgB,uBAAuB,CAAC,OAAgB;IACtD,OAAO,KAAK,UAAU,iBAAiB,CAAC,GAAoB;QAC1D,kEAAkE;QAClE,IAAA,oCAAkB,EAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAEpC,8DAA8D;QAC9D,GAAG,CAAC,IAAI,CAA+C,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YAChG,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc;gBAC1C,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC5C,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,aAAa,GAAG,OAAO,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;gBACnF,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAChE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAA,iCAAiB,EAAC,OAAO,CAAC,CAAC,CAAC;YACzF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,iFAAiF;QACjF,GAAG,CAAC,IAAI,CAAC,wBAAwB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAqD,CAAC;YAC3E,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;gBACrC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,2CAA2C,EAAE,EAAE,CAAC,CAAC;gBACtH,OAAO;YACT,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,sCAAsC,EAAE,EAAE,CAAC,CAAC;gBACjH,OAAO;YACT,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAA,iCAAiB,EAAC,OAAO,CAAC,CAAC,CAAC;YACzG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regions.d.ts","sourceRoot":"","sources":["../../src/routes/regions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAI1C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,IACd,KAAK,eAAe,KAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"regions.d.ts","sourceRoot":"","sources":["../../src/routes/regions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAI1C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,IACd,KAAK,eAAe,KAAG,OAAO,CAAC,IAAI,CAAC,CAqCxE"}
|
package/dist/routes/regions.js
CHANGED
|
@@ -6,8 +6,9 @@ const audit_logs_js_1 = require("./audit-logs.js");
|
|
|
6
6
|
const tenant_scope_js_1 = require("../middleware/tenant-scope.js");
|
|
7
7
|
function createRegionRoutes(stratum) {
|
|
8
8
|
return async function regionRoutes(app) {
|
|
9
|
-
//
|
|
10
|
-
|
|
9
|
+
// The region registry is shared by all tenants: changing it is limited to
|
|
10
|
+
// global operator keys. Reads declare "global" below.
|
|
11
|
+
(0, tenant_scope_js_1.declareTenantScope)(app, "operator");
|
|
11
12
|
// POST /api/v1/regions — Create region
|
|
12
13
|
app.post("/", async (request, reply) => {
|
|
13
14
|
const input = core_1.CreateRegionInputSchema.parse(request.body);
|
|
@@ -15,12 +16,12 @@ function createRegionRoutes(stratum) {
|
|
|
15
16
|
reply.status(201).send(region);
|
|
16
17
|
});
|
|
17
18
|
// GET /api/v1/regions — List regions
|
|
18
|
-
app.get("/", async (_request, reply) => {
|
|
19
|
+
app.get("/", { config: { tenantScope: "global" } }, async (_request, reply) => {
|
|
19
20
|
const regions = await stratum.listRegions();
|
|
20
21
|
reply.status(200).send(regions);
|
|
21
22
|
});
|
|
22
23
|
// GET /api/v1/regions/:id — Get region by ID
|
|
23
|
-
app.get("/:id", async (request, reply) => {
|
|
24
|
+
app.get("/:id", { config: { tenantScope: "global" } }, async (request, reply) => {
|
|
24
25
|
const region = await stratum.getRegion(request.params.id);
|
|
25
26
|
reply.status(200).send(region);
|
|
26
27
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regions.js","sourceRoot":"","sources":["../../src/routes/regions.ts"],"names":[],"mappings":";;AAMA,
|
|
1
|
+
{"version":3,"file":"regions.js","sourceRoot":"","sources":["../../src/routes/regions.ts"],"names":[],"mappings":";;AAMA,gDAsCC;AA3CD,2CAAoF;AAEpF,mDAAoD;AACpD,mEAAmE;AAEnE,SAAgB,kBAAkB,CAAC,OAAgB;IACjD,OAAO,KAAK,UAAU,YAAY,CAAC,GAAoB;QACrD,0EAA0E;QAC1E,sDAAsD;QACtD,IAAA,oCAAkB,EAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAEpC,uCAAuC;QACvC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,8BAAuB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,IAAA,iCAAiB,EAAC,OAAO,CAAC,CAAC,CAAC;YAC7E,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,qCAAqC;QACrC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;YAC5E,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YAC5C,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,6CAA6C;QAC7C,GAAG,CAAC,GAAG,CAA6B,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YAC1G,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1D,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,4CAA4C;QAC5C,GAAG,CAAC,KAAK,CAA6B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YACrE,MAAM,KAAK,GAAG,8BAAuB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,IAAA,iCAAiB,EAAC,OAAO,CAAC,CAAC,CAAC;YAChG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,6CAA6C;QAC7C,GAAG,CAAC,MAAM,CAA6B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YACtE,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,IAAA,iCAAiB,EAAC,OAAO,CAAC,CAAC,CAAC;YAC1E,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../src/routes/roles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../src/routes/roles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AA8B1C,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,IACd,KAAK,eAAe,KAAG,OAAO,CAAC,IAAI,CAAC,CAmItE"}
|
package/dist/routes/roles.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createRoleRoutes = createRoleRoutes;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const audit_logs_js_1 = require("./audit-logs.js");
|
|
6
|
+
const error_handler_js_1 = require("../middleware/error-handler.js");
|
|
6
7
|
const tenant_scope_js_1 = require("../middleware/tenant-scope.js");
|
|
7
8
|
const createRoleSchema = zod_1.z.object({
|
|
8
9
|
name: zod_1.z.string().min(1).max(100),
|
|
@@ -30,10 +31,16 @@ function createRoleRoutes(stratum) {
|
|
|
30
31
|
app.post("/", { config: { tenantScope: tenant_scope_js_1.fromBodyTenantId } }, async (request, reply) => {
|
|
31
32
|
const parsed = createRoleSchema.safeParse(request.body);
|
|
32
33
|
if (!parsed.success) {
|
|
33
|
-
reply.status(400).send(
|
|
34
|
+
reply.status(400).send((0, error_handler_js_1.legacyValidationErrorBody)("Invalid request body", parsed.error.issues));
|
|
34
35
|
return;
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
// Global roles (no tenant) are operator-only. A tenant-scoped caller that
|
|
38
|
+
// names no tenant creates the role in its own tenant.
|
|
39
|
+
const input = parsed.data;
|
|
40
|
+
if (!input.tenant_id && !(0, tenant_scope_js_1.isOperator)(request)) {
|
|
41
|
+
input.tenant_id = request.apiKey?.tenant_id ?? null;
|
|
42
|
+
}
|
|
43
|
+
const role = await stratum.createRole(input, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
37
44
|
reply.status(201).send(role);
|
|
38
45
|
});
|
|
39
46
|
// GET /api/v1/roles — List roles (optional ?tenant_id=). A provided tenant_id
|
|
@@ -59,7 +66,7 @@ function createRoleRoutes(stratum) {
|
|
|
59
66
|
app.patch("/:id", async (request, reply) => {
|
|
60
67
|
const parsed = updateRoleSchema.safeParse(request.body);
|
|
61
68
|
if (!parsed.success) {
|
|
62
|
-
reply.status(400).send(
|
|
69
|
+
reply.status(400).send((0, error_handler_js_1.legacyValidationErrorBody)("Invalid request body", parsed.error.issues));
|
|
63
70
|
return;
|
|
64
71
|
}
|
|
65
72
|
const existing = await stratum.getRole(request.params.id);
|
|
@@ -67,6 +74,9 @@ function createRoleRoutes(stratum) {
|
|
|
67
74
|
reply.status(404).send({ error: { code: "NOT_FOUND", message: "Role not found" } });
|
|
68
75
|
return;
|
|
69
76
|
}
|
|
77
|
+
// Global roles are shared by every tenant: only an operator may change them.
|
|
78
|
+
if (existing.tenant_id === null)
|
|
79
|
+
(0, tenant_scope_js_1.assertOperator)(request);
|
|
70
80
|
await (0, tenant_scope_js_1.assertTenantInScope)(stratum, request, existing.tenant_id);
|
|
71
81
|
const role = await stratum.updateRole(request.params.id, parsed.data, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
72
82
|
if (!role) {
|
|
@@ -82,6 +92,9 @@ function createRoleRoutes(stratum) {
|
|
|
82
92
|
reply.status(404).send({ error: { code: "NOT_FOUND", message: "Role not found" } });
|
|
83
93
|
return;
|
|
84
94
|
}
|
|
95
|
+
// Global roles are shared by every tenant: only an operator may change them.
|
|
96
|
+
if (existing.tenant_id === null)
|
|
97
|
+
(0, tenant_scope_js_1.assertOperator)(request);
|
|
85
98
|
await (0, tenant_scope_js_1.assertTenantInScope)(stratum, request, existing.tenant_id);
|
|
86
99
|
const deleted = await stratum.deleteRole(request.params.id, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
87
100
|
if (!deleted) {
|
|
@@ -110,7 +123,7 @@ function createRoleRoutes(stratum) {
|
|
|
110
123
|
return;
|
|
111
124
|
}
|
|
112
125
|
await (0, tenant_scope_js_1.assertTenantInScope)(stratum, request, role.tenant_id);
|
|
113
|
-
const success = await stratum.assignRoleToKey(request.params.keyId, parsed.data.role_id);
|
|
126
|
+
const success = await stratum.assignRoleToKey(request.params.keyId, parsed.data.role_id, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
114
127
|
if (!success) {
|
|
115
128
|
reply.status(404).send({ error: { code: "NOT_FOUND", message: "API key not found or already revoked" } });
|
|
116
129
|
return;
|
|
@@ -125,7 +138,7 @@ function createRoleRoutes(stratum) {
|
|
|
125
138
|
return;
|
|
126
139
|
}
|
|
127
140
|
await (0, tenant_scope_js_1.assertTenantInScope)(stratum, request, key.tenant_id);
|
|
128
|
-
const success = await stratum.removeRoleFromKey(request.params.keyId);
|
|
141
|
+
const success = await stratum.removeRoleFromKey(request.params.keyId, (0, audit_logs_js_1.buildAuditContext)(request));
|
|
129
142
|
if (!success) {
|
|
130
143
|
reply.status(404).send({ error: { code: "NOT_FOUND", message: "API key not found or already revoked" } });
|
|
131
144
|
return;
|
package/dist/routes/roles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roles.js","sourceRoot":"","sources":["../../src/routes/roles.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"roles.js","sourceRoot":"","sources":["../../src/routes/roles.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenants.d.ts","sourceRoot":"","sources":["../../src/routes/tenants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"tenants.d.ts","sourceRoot":"","sources":["../../src/routes/tenants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAe1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAW1C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,IAYd,KAAK,eAAe,KAAG,OAAO,CAAC,IAAI,CAAC,CAmOxE"}
|