@getstrata/bootstrap 2.2.0 → 2.2.1
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/CHANGELOG.md +7 -0
- package/dist/bootstrap/config.d.ts +1 -1
- package/dist/bootstrap/httpKernel.d.ts +6 -2
- package/dist/entries/buildModuleRoutes.js +6 -4
- package/dist/entries/buildWebModuleRoutes.js +6 -4
- package/dist/entries/config.js +2 -0
- package/dist/entries/context.js +1 -0
- package/dist/entries/createWebRoutes.js +6 -4
- package/dist/entries/dependencies.js +1 -0
- package/dist/entries/health.js +1 -0
- package/dist/entries/httpKernel.js +6 -4
- package/dist/entries/providers.js +1 -0
- package/dist/entries/secretsGuard.js +2 -2
- package/dist/entries/web/routing.js +6 -4
- package/dist/entries/web/server.js +2 -0
- package/dist/index.js +10 -6
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @getstrata/bootstrap changelog
|
|
2
2
|
|
|
3
|
+
## 2.2.1
|
|
4
|
+
|
|
5
|
+
F02 — complete queue durability. Queues have leased reservations, recovery and fenced acknowledgement, but still use Redis lists. Persisted retry schedules, execution deadlines, cancellation and the planned Streams migration remain unfinished. Retries currently wait inside the running worker.
|
|
6
|
+
F10 — production public-route tenancy. Separate anonymous access from development tenant headers, support a trusted-host resolver, reject unknown hosts, and accept forwarded hosts only through configured trusted proxies. The shop still lacks the approved-domain mapping.
|
|
7
|
+
F12 — initial administrator provisioning and migration guidance. Automatic demo seeding is fixed. Secure initial-admin provisioning and a consolidated upgrade/operations guide remain.
|
|
8
|
+
Distributed qualification. Cache generations/fill leases, scheduler ownership, OpenTelemetry, body limits and lifecycle controls now exist. Their implementation should no longer be described as entirely pending, but broader failure and capacity qualification is still required.
|
|
9
|
+
|
|
3
10
|
## 2.2.0
|
|
4
11
|
|
|
5
12
|
Consistent model scopes.
|
|
@@ -4,7 +4,7 @@ declare const CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
|
4
4
|
declare const CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
5
5
|
declare const REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
6
6
|
declare const DATABASE_URL_CONFIG_KEY = "database.url";
|
|
7
|
-
export { CORE_ABILITY_CHECKER_TOKEN, CORE_AUTH_TOKEN, CORE_AUTH_USER_DIRECTORY_TOKEN, CORE_CACHE_TOKEN, CORE_CONFIG_TOKEN, CORE_EVENT_BUS_TOKEN, CORE_HTTP_CLEANUP_TOKEN, CORE_POLICY_GATE_TOKEN, CORE_QUEUE_TOKEN, CORE_TENANT_RESOLVER_TOKEN, CORE_THROTTLE_QUOTA_POLICY_TOKEN, CORE_TOKEN_SERVICE_TOKEN, } from "@getstrata/core/contracts/serviceTokens";
|
|
7
|
+
export { CORE_ABILITY_CHECKER_TOKEN, CORE_AUTH_TOKEN, CORE_AUTH_USER_DIRECTORY_TOKEN, CORE_CACHE_TOKEN, CORE_CONFIG_TOKEN, CORE_EVENT_BUS_TOKEN, CORE_HTTP_CLEANUP_TOKEN, CORE_POLICY_GATE_TOKEN, CORE_PUBLIC_TENANCY_TOKEN, CORE_QUEUE_TOKEN, CORE_TENANT_RESOLVER_TOKEN, CORE_THROTTLE_QUOTA_POLICY_TOKEN, CORE_TOKEN_SERVICE_TOKEN, } from "@getstrata/core/contracts/serviceTokens";
|
|
8
8
|
declare const AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
9
9
|
declare const DEFAULT_APP_PORT = 3000;
|
|
10
10
|
declare const DEFAULT_CACHE_TTL_MS = 3600000;
|
|
@@ -19,7 +19,9 @@ declare class HttpKernel {
|
|
|
19
19
|
wrapWeb<TRequest extends Request = Request>(handler: RouteHandler<TRequest>): RouteHandler<TRequest>;
|
|
20
20
|
/** Signed-in HTML users redirect to `home` instead of seeing guest pages. */
|
|
21
21
|
wrapWebGuest<TRequest extends Request = Request>(handler: RouteHandler<TRequest>, home?: WebGuestHome): RouteHandler<TRequest>;
|
|
22
|
-
wrapWebPublicRead<TRequest extends Request = Request>(handler: RouteHandler<TRequest
|
|
22
|
+
wrapWebPublicRead<TRequest extends Request = Request>(handler: RouteHandler<TRequest>, options?: {
|
|
23
|
+
allowAnonymous?: boolean;
|
|
24
|
+
}): RouteHandler<TRequest>;
|
|
23
25
|
wrapWebAuthenticated<TRequest extends Request = Request>(handler: RouteHandler<TRequest>): RouteHandler<TRequest>;
|
|
24
26
|
/** Signed-in HTML without the email-verified gate (logout, verification notice). */
|
|
25
27
|
wrapWebAuthenticatedAllowUnverified<TRequest extends Request = Request>(handler: RouteHandler<TRequest>): RouteHandler<TRequest>;
|
|
@@ -31,7 +33,9 @@ declare class HttpKernel {
|
|
|
31
33
|
wrapAuthenticated<TRequest extends Request = Request>(handler: RouteHandler<TRequest>): RouteHandler<TRequest>;
|
|
32
34
|
/** JSON routes that require a verified email. No-op when `FEATURE_EMAIL_VERIFICATION` is off. */
|
|
33
35
|
wrapVerified<TRequest extends Request = Request>(handler: RouteHandler<TRequest>): RouteHandler<TRequest>;
|
|
34
|
-
wrapPublicRead<TRequest extends Request = Request>(handler: RouteHandler<TRequest
|
|
36
|
+
wrapPublicRead<TRequest extends Request = Request>(handler: RouteHandler<TRequest>, options?: {
|
|
37
|
+
allowAnonymous?: boolean;
|
|
38
|
+
}): RouteHandler<TRequest>;
|
|
35
39
|
wrapGlobalAdmin<TRequest extends Request = Request>(handler: RouteHandler<TRequest>): RouteHandler<TRequest>;
|
|
36
40
|
wrapAbility<TRequest extends Request = Request>(ability: string, handler: RouteHandler<TRequest>): RouteHandler<TRequest>;
|
|
37
41
|
wrapPolicy<TRequest extends Request = Request>(resource: string, action: keyof Policy, handler: RouteHandler<TRequest>): RouteHandler<TRequest>;
|
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
CORE_EVENT_BUS_TOKEN,
|
|
53
53
|
CORE_HTTP_CLEANUP_TOKEN,
|
|
54
54
|
CORE_POLICY_GATE_TOKEN,
|
|
55
|
+
CORE_PUBLIC_TENANCY_TOKEN,
|
|
55
56
|
CORE_QUEUE_TOKEN,
|
|
56
57
|
CORE_TENANT_RESOLVER_TOKEN,
|
|
57
58
|
CORE_THROTTLE_QUOTA_POLICY_TOKEN,
|
|
@@ -168,6 +169,7 @@ class HttpKernel {
|
|
|
168
169
|
createAuthMiddleware(auth),
|
|
169
170
|
createMembershipMiddleware(),
|
|
170
171
|
createTenantMiddleware({
|
|
172
|
+
publicTenancy: this.dependencies.container.has(CORE_PUBLIC_TENANCY_TOKEN) ? this.dependencies.container.resolve(CORE_PUBLIC_TENANCY_TOKEN) : undefined,
|
|
171
173
|
resolveTenant: this.dependencies.container.has(CORE_TENANT_RESOLVER_TOKEN) ? this.dependencies.container.resolve(CORE_TENANT_RESOLVER_TOKEN) : undefined
|
|
172
174
|
})
|
|
173
175
|
];
|
|
@@ -242,8 +244,8 @@ class HttpKernel {
|
|
|
242
244
|
return handler(request);
|
|
243
245
|
});
|
|
244
246
|
}
|
|
245
|
-
wrapWebPublicRead(handler) {
|
|
246
|
-
if (isPublicReadsEnabled()) {
|
|
247
|
+
wrapWebPublicRead(handler, options = {}) {
|
|
248
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
247
249
|
return this.wrapWeb(handler);
|
|
248
250
|
}
|
|
249
251
|
return this.wrapWebAuthenticated(handler);
|
|
@@ -289,8 +291,8 @@ class HttpKernel {
|
|
|
289
291
|
const middleware = [...this.group("authenticated"), ...this.verifiedMiddleware()];
|
|
290
292
|
return withMiddleware(...middleware)(handler);
|
|
291
293
|
}
|
|
292
|
-
wrapPublicRead(handler) {
|
|
293
|
-
if (isPublicReadsEnabled()) {
|
|
294
|
+
wrapPublicRead(handler, options = {}) {
|
|
295
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
294
296
|
return handler;
|
|
295
297
|
}
|
|
296
298
|
return this.wrapAuthenticated(handler);
|
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
CORE_EVENT_BUS_TOKEN,
|
|
56
56
|
CORE_HTTP_CLEANUP_TOKEN,
|
|
57
57
|
CORE_POLICY_GATE_TOKEN,
|
|
58
|
+
CORE_PUBLIC_TENANCY_TOKEN,
|
|
58
59
|
CORE_QUEUE_TOKEN,
|
|
59
60
|
CORE_TENANT_RESOLVER_TOKEN,
|
|
60
61
|
CORE_THROTTLE_QUOTA_POLICY_TOKEN,
|
|
@@ -171,6 +172,7 @@ class HttpKernel {
|
|
|
171
172
|
createAuthMiddleware(auth),
|
|
172
173
|
createMembershipMiddleware(),
|
|
173
174
|
createTenantMiddleware({
|
|
175
|
+
publicTenancy: this.dependencies.container.has(CORE_PUBLIC_TENANCY_TOKEN) ? this.dependencies.container.resolve(CORE_PUBLIC_TENANCY_TOKEN) : undefined,
|
|
174
176
|
resolveTenant: this.dependencies.container.has(CORE_TENANT_RESOLVER_TOKEN) ? this.dependencies.container.resolve(CORE_TENANT_RESOLVER_TOKEN) : undefined
|
|
175
177
|
})
|
|
176
178
|
];
|
|
@@ -245,8 +247,8 @@ class HttpKernel {
|
|
|
245
247
|
return handler(request);
|
|
246
248
|
});
|
|
247
249
|
}
|
|
248
|
-
wrapWebPublicRead(handler) {
|
|
249
|
-
if (isPublicReadsEnabled()) {
|
|
250
|
+
wrapWebPublicRead(handler, options = {}) {
|
|
251
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
250
252
|
return this.wrapWeb(handler);
|
|
251
253
|
}
|
|
252
254
|
return this.wrapWebAuthenticated(handler);
|
|
@@ -292,8 +294,8 @@ class HttpKernel {
|
|
|
292
294
|
const middleware = [...this.group("authenticated"), ...this.verifiedMiddleware()];
|
|
293
295
|
return withMiddleware(...middleware)(handler);
|
|
294
296
|
}
|
|
295
|
-
wrapPublicRead(handler) {
|
|
296
|
-
if (isPublicReadsEnabled()) {
|
|
297
|
+
wrapPublicRead(handler, options = {}) {
|
|
298
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
297
299
|
return handler;
|
|
298
300
|
}
|
|
299
301
|
return this.wrapAuthenticated(handler);
|
package/dist/entries/config.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
CORE_EVENT_BUS_TOKEN,
|
|
10
10
|
CORE_HTTP_CLEANUP_TOKEN,
|
|
11
11
|
CORE_POLICY_GATE_TOKEN,
|
|
12
|
+
CORE_PUBLIC_TENANCY_TOKEN,
|
|
12
13
|
CORE_QUEUE_TOKEN,
|
|
13
14
|
CORE_TENANT_RESOLVER_TOKEN,
|
|
14
15
|
CORE_THROTTLE_QUOTA_POLICY_TOKEN,
|
|
@@ -41,6 +42,7 @@ export {
|
|
|
41
42
|
CORE_EVENT_BUS_TOKEN,
|
|
42
43
|
CORE_HTTP_CLEANUP_TOKEN,
|
|
43
44
|
CORE_POLICY_GATE_TOKEN,
|
|
45
|
+
CORE_PUBLIC_TENANCY_TOKEN,
|
|
44
46
|
CORE_QUEUE_TOKEN,
|
|
45
47
|
CORE_TENANT_RESOLVER_TOKEN,
|
|
46
48
|
CORE_THROTTLE_QUOTA_POLICY_TOKEN,
|
package/dist/entries/context.js
CHANGED
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
CORE_EVENT_BUS_TOKEN,
|
|
62
62
|
CORE_HTTP_CLEANUP_TOKEN,
|
|
63
63
|
CORE_POLICY_GATE_TOKEN,
|
|
64
|
+
CORE_PUBLIC_TENANCY_TOKEN,
|
|
64
65
|
CORE_QUEUE_TOKEN,
|
|
65
66
|
CORE_TENANT_RESOLVER_TOKEN,
|
|
66
67
|
CORE_THROTTLE_QUOTA_POLICY_TOKEN,
|
|
@@ -177,6 +178,7 @@ class HttpKernel {
|
|
|
177
178
|
createAuthMiddleware(auth),
|
|
178
179
|
createMembershipMiddleware(),
|
|
179
180
|
createTenantMiddleware({
|
|
181
|
+
publicTenancy: this.dependencies.container.has(CORE_PUBLIC_TENANCY_TOKEN) ? this.dependencies.container.resolve(CORE_PUBLIC_TENANCY_TOKEN) : undefined,
|
|
180
182
|
resolveTenant: this.dependencies.container.has(CORE_TENANT_RESOLVER_TOKEN) ? this.dependencies.container.resolve(CORE_TENANT_RESOLVER_TOKEN) : undefined
|
|
181
183
|
})
|
|
182
184
|
];
|
|
@@ -251,8 +253,8 @@ class HttpKernel {
|
|
|
251
253
|
return handler(request);
|
|
252
254
|
});
|
|
253
255
|
}
|
|
254
|
-
wrapWebPublicRead(handler) {
|
|
255
|
-
if (isPublicReadsEnabled()) {
|
|
256
|
+
wrapWebPublicRead(handler, options = {}) {
|
|
257
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
256
258
|
return this.wrapWeb(handler);
|
|
257
259
|
}
|
|
258
260
|
return this.wrapWebAuthenticated(handler);
|
|
@@ -298,8 +300,8 @@ class HttpKernel {
|
|
|
298
300
|
const middleware = [...this.group("authenticated"), ...this.verifiedMiddleware()];
|
|
299
301
|
return withMiddleware(...middleware)(handler);
|
|
300
302
|
}
|
|
301
|
-
wrapPublicRead(handler) {
|
|
302
|
-
if (isPublicReadsEnabled()) {
|
|
303
|
+
wrapPublicRead(handler, options = {}) {
|
|
304
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
303
305
|
return handler;
|
|
304
306
|
}
|
|
305
307
|
return this.wrapAuthenticated(handler);
|
package/dist/entries/health.js
CHANGED
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
CORE_EVENT_BUS_TOKEN,
|
|
49
49
|
CORE_HTTP_CLEANUP_TOKEN,
|
|
50
50
|
CORE_POLICY_GATE_TOKEN,
|
|
51
|
+
CORE_PUBLIC_TENANCY_TOKEN,
|
|
51
52
|
CORE_QUEUE_TOKEN,
|
|
52
53
|
CORE_TENANT_RESOLVER_TOKEN,
|
|
53
54
|
CORE_THROTTLE_QUOTA_POLICY_TOKEN,
|
|
@@ -164,6 +165,7 @@ class HttpKernel {
|
|
|
164
165
|
createAuthMiddleware(auth),
|
|
165
166
|
createMembershipMiddleware(),
|
|
166
167
|
createTenantMiddleware({
|
|
168
|
+
publicTenancy: this.dependencies.container.has(CORE_PUBLIC_TENANCY_TOKEN) ? this.dependencies.container.resolve(CORE_PUBLIC_TENANCY_TOKEN) : undefined,
|
|
167
169
|
resolveTenant: this.dependencies.container.has(CORE_TENANT_RESOLVER_TOKEN) ? this.dependencies.container.resolve(CORE_TENANT_RESOLVER_TOKEN) : undefined
|
|
168
170
|
})
|
|
169
171
|
];
|
|
@@ -238,8 +240,8 @@ class HttpKernel {
|
|
|
238
240
|
return handler(request);
|
|
239
241
|
});
|
|
240
242
|
}
|
|
241
|
-
wrapWebPublicRead(handler) {
|
|
242
|
-
if (isPublicReadsEnabled()) {
|
|
243
|
+
wrapWebPublicRead(handler, options = {}) {
|
|
244
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
243
245
|
return this.wrapWeb(handler);
|
|
244
246
|
}
|
|
245
247
|
return this.wrapWebAuthenticated(handler);
|
|
@@ -285,8 +287,8 @@ class HttpKernel {
|
|
|
285
287
|
const middleware = [...this.group("authenticated"), ...this.verifiedMiddleware()];
|
|
286
288
|
return withMiddleware(...middleware)(handler);
|
|
287
289
|
}
|
|
288
|
-
wrapPublicRead(handler) {
|
|
289
|
-
if (isPublicReadsEnabled()) {
|
|
290
|
+
wrapPublicRead(handler, options = {}) {
|
|
291
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
290
292
|
return handler;
|
|
291
293
|
}
|
|
292
294
|
return this.wrapAuthenticated(handler);
|
|
@@ -126,8 +126,8 @@ function assertFeatureProductionSecrets(env) {
|
|
|
126
126
|
throw new Error("Production startup blocked: set explicit CORS_ALLOWED_ORIGINS instead of wildcard.");
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
if (envFlagEnabled(env.
|
|
130
|
-
throw new Error("Production startup blocked: set
|
|
129
|
+
if (envFlagEnabled(env.TENANT_DEV_HEADERS)) {
|
|
130
|
+
throw new Error("Production startup blocked: set TENANT_DEV_HEADERS=false.");
|
|
131
131
|
}
|
|
132
132
|
if (!env.SIEM_EXPORT_URL?.trim() && envFlagEnabled(env.FEATURE_SIEM_EXPORT)) {
|
|
133
133
|
console.warn("[secrets] SIEM_EXPORT_URL is not configured; audit logs remain database-only.");
|
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
CORE_EVENT_BUS_TOKEN,
|
|
59
59
|
CORE_HTTP_CLEANUP_TOKEN,
|
|
60
60
|
CORE_POLICY_GATE_TOKEN,
|
|
61
|
+
CORE_PUBLIC_TENANCY_TOKEN,
|
|
61
62
|
CORE_QUEUE_TOKEN,
|
|
62
63
|
CORE_TENANT_RESOLVER_TOKEN,
|
|
63
64
|
CORE_THROTTLE_QUOTA_POLICY_TOKEN,
|
|
@@ -174,6 +175,7 @@ class HttpKernel {
|
|
|
174
175
|
createAuthMiddleware(auth),
|
|
175
176
|
createMembershipMiddleware(),
|
|
176
177
|
createTenantMiddleware({
|
|
178
|
+
publicTenancy: this.dependencies.container.has(CORE_PUBLIC_TENANCY_TOKEN) ? this.dependencies.container.resolve(CORE_PUBLIC_TENANCY_TOKEN) : undefined,
|
|
177
179
|
resolveTenant: this.dependencies.container.has(CORE_TENANT_RESOLVER_TOKEN) ? this.dependencies.container.resolve(CORE_TENANT_RESOLVER_TOKEN) : undefined
|
|
178
180
|
})
|
|
179
181
|
];
|
|
@@ -248,8 +250,8 @@ class HttpKernel {
|
|
|
248
250
|
return handler(request);
|
|
249
251
|
});
|
|
250
252
|
}
|
|
251
|
-
wrapWebPublicRead(handler) {
|
|
252
|
-
if (isPublicReadsEnabled()) {
|
|
253
|
+
wrapWebPublicRead(handler, options = {}) {
|
|
254
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
253
255
|
return this.wrapWeb(handler);
|
|
254
256
|
}
|
|
255
257
|
return this.wrapWebAuthenticated(handler);
|
|
@@ -295,8 +297,8 @@ class HttpKernel {
|
|
|
295
297
|
const middleware = [...this.group("authenticated"), ...this.verifiedMiddleware()];
|
|
296
298
|
return withMiddleware(...middleware)(handler);
|
|
297
299
|
}
|
|
298
|
-
wrapPublicRead(handler) {
|
|
299
|
-
if (isPublicReadsEnabled()) {
|
|
300
|
+
wrapPublicRead(handler, options = {}) {
|
|
301
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
300
302
|
return handler;
|
|
301
303
|
}
|
|
302
304
|
return this.wrapAuthenticated(handler);
|
|
@@ -19,6 +19,7 @@ function wrapRouteHandler(handler, path, onRequest, track = (work) => work()) {
|
|
|
19
19
|
request,
|
|
20
20
|
routeTemplate: path,
|
|
21
21
|
ipAddress: socketAddress(server, request),
|
|
22
|
+
peerAddress: socketAddress(server, request),
|
|
22
23
|
userAgent: request.headers.get("user-agent")
|
|
23
24
|
}, async () => {
|
|
24
25
|
const intercepted = await onRequest?.(request, server);
|
|
@@ -94,6 +95,7 @@ function createWebServer(options) {
|
|
|
94
95
|
...currentRequestMeta(),
|
|
95
96
|
request,
|
|
96
97
|
ipAddress: socketAddress(server, request),
|
|
98
|
+
peerAddress: socketAddress(server, request),
|
|
97
99
|
userAgent: request.headers.get("user-agent")
|
|
98
100
|
}, async () => {
|
|
99
101
|
const intercepted = await onRequest(request, server);
|
package/dist/index.js
CHANGED
|
@@ -73,6 +73,7 @@ import {
|
|
|
73
73
|
CORE_EVENT_BUS_TOKEN,
|
|
74
74
|
CORE_HTTP_CLEANUP_TOKEN,
|
|
75
75
|
CORE_POLICY_GATE_TOKEN,
|
|
76
|
+
CORE_PUBLIC_TENANCY_TOKEN,
|
|
76
77
|
CORE_QUEUE_TOKEN,
|
|
77
78
|
CORE_TENANT_RESOLVER_TOKEN,
|
|
78
79
|
CORE_THROTTLE_QUOTA_POLICY_TOKEN,
|
|
@@ -188,6 +189,7 @@ class HttpKernel {
|
|
|
188
189
|
createAuthMiddleware(auth),
|
|
189
190
|
createMembershipMiddleware(),
|
|
190
191
|
createTenantMiddleware({
|
|
192
|
+
publicTenancy: this.dependencies.container.has(CORE_PUBLIC_TENANCY_TOKEN) ? this.dependencies.container.resolve(CORE_PUBLIC_TENANCY_TOKEN) : undefined,
|
|
191
193
|
resolveTenant: this.dependencies.container.has(CORE_TENANT_RESOLVER_TOKEN) ? this.dependencies.container.resolve(CORE_TENANT_RESOLVER_TOKEN) : undefined
|
|
192
194
|
})
|
|
193
195
|
];
|
|
@@ -262,8 +264,8 @@ class HttpKernel {
|
|
|
262
264
|
return handler(request);
|
|
263
265
|
});
|
|
264
266
|
}
|
|
265
|
-
wrapWebPublicRead(handler) {
|
|
266
|
-
if (isPublicReadsEnabled()) {
|
|
267
|
+
wrapWebPublicRead(handler, options = {}) {
|
|
268
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
267
269
|
return this.wrapWeb(handler);
|
|
268
270
|
}
|
|
269
271
|
return this.wrapWebAuthenticated(handler);
|
|
@@ -309,8 +311,8 @@ class HttpKernel {
|
|
|
309
311
|
const middleware = [...this.group("authenticated"), ...this.verifiedMiddleware()];
|
|
310
312
|
return withMiddleware(...middleware)(handler);
|
|
311
313
|
}
|
|
312
|
-
wrapPublicRead(handler) {
|
|
313
|
-
if (isPublicReadsEnabled()) {
|
|
314
|
+
wrapPublicRead(handler, options = {}) {
|
|
315
|
+
if (options.allowAnonymous ?? isPublicReadsEnabled()) {
|
|
314
316
|
return handler;
|
|
315
317
|
}
|
|
316
318
|
return this.wrapAuthenticated(handler);
|
|
@@ -1743,8 +1745,8 @@ function assertFeatureProductionSecrets(env) {
|
|
|
1743
1745
|
throw new Error("Production startup blocked: set explicit CORS_ALLOWED_ORIGINS instead of wildcard.");
|
|
1744
1746
|
}
|
|
1745
1747
|
}
|
|
1746
|
-
if (envFlagEnabled3(env.
|
|
1747
|
-
throw new Error("Production startup blocked: set
|
|
1748
|
+
if (envFlagEnabled3(env.TENANT_DEV_HEADERS)) {
|
|
1749
|
+
throw new Error("Production startup blocked: set TENANT_DEV_HEADERS=false.");
|
|
1748
1750
|
}
|
|
1749
1751
|
if (!env.SIEM_EXPORT_URL?.trim() && envFlagEnabled3(env.FEATURE_SIEM_EXPORT)) {
|
|
1750
1752
|
console.warn("[secrets] SIEM_EXPORT_URL is not configured; audit logs remain database-only.");
|
|
@@ -1913,6 +1915,7 @@ function wrapRouteHandler(handler, path, onRequest, track = (work) => work()) {
|
|
|
1913
1915
|
request,
|
|
1914
1916
|
routeTemplate: path,
|
|
1915
1917
|
ipAddress: socketAddress(server, request),
|
|
1918
|
+
peerAddress: socketAddress(server, request),
|
|
1916
1919
|
userAgent: request.headers.get("user-agent")
|
|
1917
1920
|
}, async () => {
|
|
1918
1921
|
const intercepted = await onRequest?.(request, server);
|
|
@@ -1988,6 +1991,7 @@ function createWebServer(options) {
|
|
|
1988
1991
|
...currentRequestMeta2(),
|
|
1989
1992
|
request,
|
|
1990
1993
|
ipAddress: socketAddress(server, request),
|
|
1994
|
+
peerAddress: socketAddress(server, request),
|
|
1991
1995
|
userAgent: request.headers.get("user-agent")
|
|
1992
1996
|
}, async () => {
|
|
1993
1997
|
const intercepted = await onRequest(request, server);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/bootstrap",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Strata application bootstrap: HttpKernel, DI, web session helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -190,7 +190,7 @@
|
|
|
190
190
|
"access": "public"
|
|
191
191
|
},
|
|
192
192
|
"peerDependencies": {
|
|
193
|
-
"@getstrata/core": "^2.2.
|
|
193
|
+
"@getstrata/core": "^2.2.1",
|
|
194
194
|
"typescript": "^5.9.0 || ^6.0.0 || ^7.0.0"
|
|
195
195
|
},
|
|
196
196
|
"engines": {
|