@getstrata/bootstrap 1.0.8 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/bootstrap/secretsGuard.d.ts +13 -1
- package/dist/bootstrap/web/session.d.ts +1 -0
- package/dist/entries/buildModuleRoutes.js +34 -38
- package/dist/entries/buildWebModuleRoutes.js +34 -38
- package/dist/entries/context.js +3 -3
- package/dist/entries/createSpaRoutes.js +10 -3
- package/dist/entries/createWebRoutes.js +43 -42
- package/dist/entries/dependencies.js +3 -3
- package/dist/entries/health.js +3 -2
- package/dist/entries/httpKernel.js +28 -37
- package/dist/entries/metricsRoutes.js +2 -1
- package/dist/entries/providers.js +3 -3
- package/dist/entries/schedule.js +2 -2
- package/dist/entries/secretsGuard.js +100 -5
- package/dist/entries/web/routing.js +28 -37
- package/dist/entries/web/server.js +9 -3
- package/dist/entries/web/session.js +68 -18
- package/dist/index.js +205 -79
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
// ../../src/bootstrap/buildModuleRoutes.ts
|
|
18
18
|
import { conditionalJsonResponse } from "@getstrata/core/http/conditionalResponse";
|
|
19
19
|
import { applyMiddlewareToRoutes } from "@getstrata/core/http/middleware";
|
|
20
|
+
import { createJsonErrorMiddleware } from "@getstrata/core/http/response";
|
|
20
21
|
|
|
21
22
|
// ../../src/bootstrap/httpKernel.ts
|
|
22
23
|
import {
|
|
@@ -152,8 +153,9 @@ class HttpKernel {
|
|
|
152
153
|
case "web":
|
|
153
154
|
return isViewsEnabled() ? [createFlashMiddleware(), createCsrfMiddleware()] : [];
|
|
154
155
|
case "api": {
|
|
156
|
+
const csrf = createCsrfMiddleware();
|
|
155
157
|
if (!this.dependencies.container.has(CORE_CONFIG_TOKEN)) {
|
|
156
|
-
return [];
|
|
158
|
+
return [csrf];
|
|
157
159
|
}
|
|
158
160
|
const config = this.dependencies.container.resolve(CORE_CONFIG_TOKEN);
|
|
159
161
|
const redisUrl = config.get(REDIS_URL_CONFIG_KEY)?.trim() ?? "";
|
|
@@ -163,7 +165,8 @@ class HttpKernel {
|
|
|
163
165
|
createMemoryThrottleMiddleware({
|
|
164
166
|
maxAttempts: Number.isFinite(maxAttempts) ? maxAttempts : 120,
|
|
165
167
|
decaySeconds: 60
|
|
166
|
-
})
|
|
168
|
+
}),
|
|
169
|
+
csrf
|
|
167
170
|
];
|
|
168
171
|
}
|
|
169
172
|
const maxAttempts = Number(process.env.RATE_LIMIT_PER_MINUTE ?? "120");
|
|
@@ -172,7 +175,8 @@ class HttpKernel {
|
|
|
172
175
|
redisUrl,
|
|
173
176
|
maxAttempts: Number.isFinite(maxAttempts) ? maxAttempts : 120,
|
|
174
177
|
decaySeconds: 60
|
|
175
|
-
})
|
|
178
|
+
}),
|
|
179
|
+
csrf
|
|
176
180
|
];
|
|
177
181
|
}
|
|
178
182
|
default:
|
|
@@ -182,13 +186,14 @@ class HttpKernel {
|
|
|
182
186
|
wrap(groups, handler) {
|
|
183
187
|
const names = Array.isArray(groups) ? groups : [groups];
|
|
184
188
|
const middleware = names.flatMap((name) => this.group(name));
|
|
185
|
-
|
|
186
|
-
|
|
189
|
+
const wrapped = middleware.length === 0 ? handler : withMiddleware(...middleware)(handler);
|
|
190
|
+
if (names.includes("api")) {
|
|
191
|
+
return withJsonErrorHandling(wrapped);
|
|
187
192
|
}
|
|
188
|
-
return
|
|
193
|
+
return wrapped;
|
|
189
194
|
}
|
|
190
195
|
wrapApi(handler) {
|
|
191
|
-
return
|
|
196
|
+
return this.wrap(["api", "authenticated"], handler);
|
|
192
197
|
}
|
|
193
198
|
wrapWeb(handler) {
|
|
194
199
|
return withErrorHandling(this.wrap("web", handler));
|
|
@@ -297,41 +302,28 @@ class HttpKernel {
|
|
|
297
302
|
return [createRequireVerifiedMiddleware(auth)];
|
|
298
303
|
}
|
|
299
304
|
wrapThrottle(scope, rateLimit, handler) {
|
|
300
|
-
const middleware = [];
|
|
301
305
|
const memoryKeyPrefix = scope === "login" ? "login-throttle:" : "register-throttle:";
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
decaySeconds: rateLimit.decaySeconds,
|
|
314
|
-
keyPrefix: memoryKeyPrefix
|
|
315
|
-
});
|
|
316
|
-
middleware.push(throttle);
|
|
317
|
-
} else {
|
|
318
|
-
middleware.push(createMemoryThrottleMiddleware({
|
|
319
|
-
maxAttempts: rateLimit.maxAttempts,
|
|
320
|
-
decaySeconds: rateLimit.decaySeconds,
|
|
321
|
-
keyPrefix: memoryKeyPrefix
|
|
322
|
-
}));
|
|
323
|
-
}
|
|
324
|
-
} else {
|
|
325
|
-
middleware.push(createMemoryThrottleMiddleware({
|
|
306
|
+
const redisUrl = this.dependencies.container.has(CORE_CONFIG_TOKEN) ? this.dependencies.container.resolve(CORE_CONFIG_TOKEN).get(REDIS_URL_CONFIG_KEY)?.trim() ?? "" : "";
|
|
307
|
+
if (scope === "login") {
|
|
308
|
+
return withMiddleware(createLoginThrottleMiddleware({
|
|
309
|
+
...redisUrl ? { redisUrl } : {},
|
|
310
|
+
maxAttempts: rateLimit.maxAttempts,
|
|
311
|
+
decaySeconds: rateLimit.decaySeconds
|
|
312
|
+
}))(handler);
|
|
313
|
+
}
|
|
314
|
+
if (redisUrl) {
|
|
315
|
+
return withMiddleware(createThrottleMiddleware({
|
|
316
|
+
redisUrl,
|
|
326
317
|
maxAttempts: rateLimit.maxAttempts,
|
|
327
318
|
decaySeconds: rateLimit.decaySeconds,
|
|
328
319
|
keyPrefix: memoryKeyPrefix
|
|
329
|
-
}));
|
|
330
|
-
}
|
|
331
|
-
if (middleware.length === 0) {
|
|
332
|
-
return handler;
|
|
320
|
+
}))(handler);
|
|
333
321
|
}
|
|
334
|
-
return withMiddleware(
|
|
322
|
+
return withMiddleware(createMemoryThrottleMiddleware({
|
|
323
|
+
maxAttempts: rateLimit.maxAttempts,
|
|
324
|
+
decaySeconds: rateLimit.decaySeconds,
|
|
325
|
+
keyPrefix: memoryKeyPrefix
|
|
326
|
+
}))(handler);
|
|
335
327
|
}
|
|
336
328
|
}
|
|
337
329
|
function createHttpKernel(dependencies) {
|
|
@@ -470,7 +462,11 @@ function buildModuleRoutes(dependencies, options = {}) {
|
|
|
470
462
|
routeRegistry.clear();
|
|
471
463
|
}
|
|
472
464
|
const kernel = createHttpKernel(dependencies);
|
|
473
|
-
const middleware = [
|
|
465
|
+
const middleware = [
|
|
466
|
+
...kernel.globalMiddleware(),
|
|
467
|
+
createJsonErrorMiddleware(),
|
|
468
|
+
...kernel.group("api")
|
|
469
|
+
];
|
|
474
470
|
const cachedJson = createCachedJson(dependencies);
|
|
475
471
|
const moduleRoutes = {};
|
|
476
472
|
for (const module of modules) {
|
|
@@ -541,7 +537,7 @@ import { SessionGuard } from "@getstrata/core/auth/sessionGuard";
|
|
|
541
537
|
import { envFlagEnabled } from "@getstrata/core/runtime/appEnv";
|
|
542
538
|
var authConfig = {
|
|
543
539
|
allowDevHeaders: envFlagEnabled(process.env.AUTH_DEV_HEADERS),
|
|
544
|
-
tokenDefaultAbilities: [
|
|
540
|
+
tokenDefaultAbilities: []
|
|
545
541
|
};
|
|
546
542
|
|
|
547
543
|
// ../../src/bootstrap/providers/auth.ts
|
|
@@ -551,7 +547,7 @@ var authProvider = {
|
|
|
551
547
|
config.set("auth.allowDevHeaders", authConfig.allowDevHeaders);
|
|
552
548
|
const apiGuard = new DatabaseTokenGuard(container);
|
|
553
549
|
const sessionGuard = new SessionGuard(container);
|
|
554
|
-
const jwtGuard = new JwtGuard;
|
|
550
|
+
const jwtGuard = new JwtGuard(container);
|
|
555
551
|
const basicGuard = new BasicAuthGuard(container);
|
|
556
552
|
const guards = [apiGuard, jwtGuard, basicGuard, sessionGuard];
|
|
557
553
|
if (authConfig.allowDevHeaders) {
|
|
@@ -596,7 +592,7 @@ import { validateEnv } from "@getstrata/core/config/envSchema";
|
|
|
596
592
|
var appConfig = {
|
|
597
593
|
name: process.env.APP_NAME?.trim() || "Strata",
|
|
598
594
|
env: process.env.APP_ENV ?? "local",
|
|
599
|
-
debug: (process.env.APP_DEBUG ?? "
|
|
595
|
+
debug: (process.env.APP_DEBUG ?? "false") === "true",
|
|
600
596
|
url: process.env.APP_URL ?? "http://localhost:3000",
|
|
601
597
|
apiPrefix: process.env.API_PREFIX ?? "/api/v1"
|
|
602
598
|
};
|
|
@@ -1001,6 +997,7 @@ function createAppContext() {
|
|
|
1001
997
|
// ../../src/bootstrap/createWebRoutes.ts
|
|
1002
998
|
import { join as join3 } from "path";
|
|
1003
999
|
import { isViewsEnabled as isViewsEnabled3 } from "@getstrata/core/runtime/frontendMode";
|
|
1000
|
+
import { assertUrlPathUnderRoot } from "@getstrata/core/security/safePath";
|
|
1004
1001
|
import { notFoundHtmlResponse } from "@getstrata/core/view";
|
|
1005
1002
|
function registerRoute(method, path, middleware) {
|
|
1006
1003
|
routeRegistry.register({ method, path, middleware });
|
|
@@ -1014,12 +1011,16 @@ function createWebRoutes(dependencies, options = {}) {
|
|
|
1014
1011
|
wrappedRoutes["/assets/*"] = async (request) => {
|
|
1015
1012
|
registerRoute("GET", "/assets/*", ["global", "web"]);
|
|
1016
1013
|
const pathname = new URL(request.url).pathname;
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1014
|
+
try {
|
|
1015
|
+
const filePath = assertUrlPathUnderRoot(join3(process.cwd(), "public"), pathname);
|
|
1016
|
+
const file = Bun.file(filePath);
|
|
1017
|
+
if (!await file.exists()) {
|
|
1018
|
+
return notFoundHtmlResponse();
|
|
1019
|
+
}
|
|
1020
|
+
return new Response(file);
|
|
1021
|
+
} catch {
|
|
1020
1022
|
return notFoundHtmlResponse();
|
|
1021
1023
|
}
|
|
1022
|
-
return new Response(file);
|
|
1023
1024
|
};
|
|
1024
1025
|
registerRoute("GET", "/assets/*", ["global", "web"]);
|
|
1025
1026
|
return wrappedRoutes;
|
|
@@ -1041,6 +1042,7 @@ function createAppDependencies() {
|
|
|
1041
1042
|
import { getBoundDatabaseConnection } from "@getstrata/core/database/boundConnection";
|
|
1042
1043
|
import { getDefaultDatabasePool } from "@getstrata/core/database/defaultConnection";
|
|
1043
1044
|
import { jsonResponse } from "@getstrata/core/http/response";
|
|
1045
|
+
import { envFlagEnabled as envFlagEnabled2 } from "@getstrata/core/runtime/appEnv";
|
|
1044
1046
|
var {RedisClient } = globalThis.Bun;
|
|
1045
1047
|
function resolveRedisUrl(dependencies) {
|
|
1046
1048
|
if (!dependencies.container.has(CORE_CONFIG_TOKEN)) {
|
|
@@ -1124,10 +1126,10 @@ function createHealthRoutes(dependencies, options = {}) {
|
|
|
1124
1126
|
"/ready": async () => {
|
|
1125
1127
|
const extra = await resolveExtraFields(options.extra);
|
|
1126
1128
|
const { checks, ready } = await collectDependencyChecks(dependencies);
|
|
1129
|
+
const debug = envFlagEnabled2(process.env.APP_DEBUG);
|
|
1127
1130
|
return jsonResponse({
|
|
1128
1131
|
status: ready ? "ready" : "not_ready",
|
|
1129
|
-
checks,
|
|
1130
|
-
...extra
|
|
1132
|
+
...debug ? { checks, ...extra } : {}
|
|
1131
1133
|
}, { status: ready ? 200 : 503 });
|
|
1132
1134
|
}
|
|
1133
1135
|
};
|
|
@@ -1140,8 +1142,16 @@ import {
|
|
|
1140
1142
|
// ../../src/bootstrap/membershipService.ts
|
|
1141
1143
|
import { resolveMembershipService } from "@getstrata/core/auth/membershipService";
|
|
1142
1144
|
// ../../src/bootstrap/secretsGuard.ts
|
|
1143
|
-
import {
|
|
1145
|
+
import { getDefaultDatabasePool as getDefaultDatabasePool2 } from "@getstrata/core/database/defaultConnection";
|
|
1146
|
+
import { envFlagEnabled as envFlagEnabled3, isProductionEnv } from "@getstrata/core/runtime/appEnv";
|
|
1144
1147
|
import { isViewsMode, parseFrontendMode } from "@getstrata/core/runtime/frontendMode";
|
|
1148
|
+
import {
|
|
1149
|
+
assertPostgresRoleCannotBypassRls,
|
|
1150
|
+
inspectCurrentPostgresRole,
|
|
1151
|
+
isPostgresUrl,
|
|
1152
|
+
postgresUrlUsername
|
|
1153
|
+
} from "@getstrata/core/tenant/enableTenantRls";
|
|
1154
|
+
import { isRlsTenancy } from "@getstrata/core/tenant/tenancyConfig";
|
|
1145
1155
|
var PUBLISHED_TEST_ADMIN_API_TOKEN = "strata-admin-test-token";
|
|
1146
1156
|
var PUBLISHED_TEST_MEMBER_API_TOKEN = "strata-member-test-token";
|
|
1147
1157
|
var PUBLISHED_TEST_SCIM_BEARER_TOKEN = "strata-scim-test-token";
|
|
@@ -1162,8 +1172,11 @@ var SECRETS_TO_ROTATE = [
|
|
|
1162
1172
|
"KMS_ENCRYPTION_KEY",
|
|
1163
1173
|
"STRIPE_WEBHOOK_SECRET",
|
|
1164
1174
|
"ADMIN_API_TOKEN",
|
|
1165
|
-
"MEMBER_API_TOKEN"
|
|
1175
|
+
"MEMBER_API_TOKEN",
|
|
1176
|
+
"DATABASE_URL",
|
|
1177
|
+
"APP_DATABASE_URL"
|
|
1166
1178
|
];
|
|
1179
|
+
var RLS_BYPASS_DATABASE_USERS = new Set(["postgres", "root"]);
|
|
1167
1180
|
function assertNoPlaceholderSecrets(env) {
|
|
1168
1181
|
const unrotated = SECRETS_TO_ROTATE.filter((name) => PLACEHOLDER_SECRET_PATTERN.test(env[name]?.trim() ?? ""));
|
|
1169
1182
|
if (unrotated.length > 0) {
|
|
@@ -1171,10 +1184,14 @@ function assertNoPlaceholderSecrets(env) {
|
|
|
1171
1184
|
}
|
|
1172
1185
|
}
|
|
1173
1186
|
function isTokenAuthEnabled(env) {
|
|
1174
|
-
return Boolean(env.ADMIN_API_TOKEN?.trim()) || Boolean(env.MEMBER_API_TOKEN?.trim()) ||
|
|
1187
|
+
return Boolean(env.ADMIN_API_TOKEN?.trim()) || Boolean(env.MEMBER_API_TOKEN?.trim()) || envFlagEnabled3(env.FEATURE_API_TOKENS);
|
|
1175
1188
|
}
|
|
1176
1189
|
function isOAuthEnabled(env) {
|
|
1177
|
-
return
|
|
1190
|
+
return envFlagEnabled3(env.FEATURE_OAUTH) || envFlagEnabled3(env.FEATURE_SAML) || Boolean(env.GITHUB_CLIENT_ID?.trim()) || Boolean(env.OIDC_ISSUER?.trim()) || Boolean(env.SAML_IDP_SSO_URL?.trim()) || Boolean(env.SAML_LOGIN_URL?.trim());
|
|
1191
|
+
}
|
|
1192
|
+
function isHeaderOnlyAuth(env) {
|
|
1193
|
+
const frontend = env.FRONTEND_MODE?.trim() ?? "";
|
|
1194
|
+
return env.AUTH_MODE === "headers" || frontend === "api" && env.AUTH_DEV_HEADERS === "true";
|
|
1178
1195
|
}
|
|
1179
1196
|
function isCorsConfigured(env) {
|
|
1180
1197
|
return env.CORS_ALLOWED_ORIGINS !== undefined;
|
|
@@ -1211,16 +1228,35 @@ function assertTokenAuthProductionSecrets(env) {
|
|
|
1211
1228
|
}
|
|
1212
1229
|
}
|
|
1213
1230
|
function assertFeatureProductionSecrets(env) {
|
|
1214
|
-
if (
|
|
1231
|
+
if (envFlagEnabled3(env.FEATURE_SCIM)) {
|
|
1215
1232
|
const scimToken = env.SCIM_BEARER_TOKEN ?? PUBLISHED_TEST_SCIM_BEARER_TOKEN;
|
|
1216
1233
|
if (PUBLISHED_TEST_SCIM_TOKENS.has(scimToken) || !env.SCIM_BEARER_TOKEN?.trim()) {
|
|
1217
1234
|
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from published test defaults.");
|
|
1218
1235
|
}
|
|
1219
1236
|
}
|
|
1220
|
-
if (
|
|
1221
|
-
throw new Error("Production startup blocked: set KMS_ENCRYPTION_KEY when field encryption is enabled.");
|
|
1237
|
+
if ((envFlagEnabled3(env.FEATURE_FIELD_ENCRYPTION) || envFlagEnabled3(env.FEATURE_MFA)) && !env.KMS_ENCRYPTION_KEY?.trim()) {
|
|
1238
|
+
throw new Error("Production startup blocked: set KMS_ENCRYPTION_KEY when field encryption or MFA is enabled.");
|
|
1222
1239
|
}
|
|
1223
|
-
if (
|
|
1240
|
+
if (envFlagEnabled3(env.FEATURE_SAML)) {
|
|
1241
|
+
const required = [
|
|
1242
|
+
"SAML_IDP_CERT",
|
|
1243
|
+
"SAML_IDP_SSO_URL",
|
|
1244
|
+
"SAML_SP_ENTITY_ID",
|
|
1245
|
+
"SAML_ACS_URL",
|
|
1246
|
+
"SAML_IDP_ISSUER"
|
|
1247
|
+
];
|
|
1248
|
+
const missing = required.filter((name) => !env[name]?.trim());
|
|
1249
|
+
if (missing.length > 0) {
|
|
1250
|
+
throw new Error(`Production startup blocked: set ${missing.join(", ")} when FEATURE_SAML=true.`);
|
|
1251
|
+
}
|
|
1252
|
+
if (env.SAML_WANT_RESPONSE_SIGNED === "false") {
|
|
1253
|
+
throw new Error("Production startup blocked: signed SAML responses are required (do not set SAML_WANT_RESPONSE_SIGNED=false).");
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
if (envFlagEnabled3(env.UPLOAD_ALLOW_UNKNOWN_MIME)) {
|
|
1257
|
+
throw new Error("Production startup blocked: set UPLOAD_ALLOW_UNKNOWN_MIME=false (unknown MIME types are not allowed).");
|
|
1258
|
+
}
|
|
1259
|
+
if (envFlagEnabled3(env.FEATURE_BILLING) && !env.STRIPE_WEBHOOK_SECRET?.trim()) {
|
|
1224
1260
|
throw new Error("Production startup blocked: set STRIPE_WEBHOOK_SECRET when billing webhooks are enabled.");
|
|
1225
1261
|
}
|
|
1226
1262
|
if (isOAuthEnabled(env) && !env.OAUTH_STATE_SECRET?.trim()) {
|
|
@@ -1232,14 +1268,44 @@ function assertFeatureProductionSecrets(env) {
|
|
|
1232
1268
|
throw new Error("Production startup blocked: set explicit CORS_ALLOWED_ORIGINS instead of wildcard.");
|
|
1233
1269
|
}
|
|
1234
1270
|
}
|
|
1235
|
-
if (
|
|
1271
|
+
if (envFlagEnabled3(env.FEATURE_PUBLIC_READS)) {
|
|
1236
1272
|
throw new Error("Production startup blocked: set FEATURE_PUBLIC_READS=false for authenticated-only reads.");
|
|
1237
1273
|
}
|
|
1238
|
-
if (!env.SIEM_EXPORT_URL?.trim() &&
|
|
1274
|
+
if (!env.SIEM_EXPORT_URL?.trim() && envFlagEnabled3(env.FEATURE_SIEM_EXPORT)) {
|
|
1239
1275
|
console.warn("[secrets] SIEM_EXPORT_URL is not configured; audit logs remain database-only.");
|
|
1240
1276
|
}
|
|
1241
1277
|
}
|
|
1242
1278
|
var LOCAL_HOSTS = new Set(["localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"]);
|
|
1279
|
+
function rlsRuntimeDatabaseUrl(env) {
|
|
1280
|
+
const app = env.APP_DATABASE_URL?.trim();
|
|
1281
|
+
if (app) {
|
|
1282
|
+
return { name: "APP_DATABASE_URL", raw: app };
|
|
1283
|
+
}
|
|
1284
|
+
const database = env.DATABASE_URL?.trim();
|
|
1285
|
+
if (database) {
|
|
1286
|
+
return { name: "DATABASE_URL", raw: database };
|
|
1287
|
+
}
|
|
1288
|
+
return null;
|
|
1289
|
+
}
|
|
1290
|
+
function assertRlsUsesAppDatabaseRole(env) {
|
|
1291
|
+
if (!isRlsTenancy(env)) {
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
const runtime = rlsRuntimeDatabaseUrl(env);
|
|
1295
|
+
if (!runtime) {
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
const user = postgresUrlUsername(runtime.raw);
|
|
1299
|
+
if (user === null) {
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
if (user === "") {
|
|
1303
|
+
throw new Error(`TENANCY_DRIVER=rls startup blocked: ${runtime.name} must include a NOBYPASSRLS role username.`);
|
|
1304
|
+
}
|
|
1305
|
+
if (RLS_BYPASS_DATABASE_USERS.has(user.toLowerCase())) {
|
|
1306
|
+
throw new Error(`TENANCY_DRIVER=rls startup blocked: ${runtime.name} for TENANCY_DRIVER=rls must use a NOBYPASSRLS role, not ${user}. FORCE RLS does not apply to PostgreSQL superusers.`);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1243
1309
|
function assertPublicAppUrl(env) {
|
|
1244
1310
|
const raw = env.APP_URL?.trim() ?? "";
|
|
1245
1311
|
let url = null;
|
|
@@ -1262,6 +1328,9 @@ function assertProductionSecrets(env = process.env) {
|
|
|
1262
1328
|
assertNoPlaceholderSecrets(env);
|
|
1263
1329
|
assertAuthDevHeadersDisabled(env);
|
|
1264
1330
|
assertPublicAppUrl(env);
|
|
1331
|
+
if (isHeaderOnlyAuth(env)) {
|
|
1332
|
+
throw new Error("Production startup blocked: header-only authentication is not allowed. Configure cookie, token, or JWT auth.");
|
|
1333
|
+
}
|
|
1265
1334
|
if (isTokenAuthEnabled(env)) {
|
|
1266
1335
|
assertTokenAuthProductionSecrets(env);
|
|
1267
1336
|
}
|
|
@@ -1269,6 +1338,7 @@ function assertProductionSecrets(env = process.env) {
|
|
|
1269
1338
|
if (isViewsMode(parseFrontendMode(env.FRONTEND_MODE))) {
|
|
1270
1339
|
assertSessionSecret(env);
|
|
1271
1340
|
}
|
|
1341
|
+
assertRlsUsesAppDatabaseRole(env);
|
|
1272
1342
|
}
|
|
1273
1343
|
// ../../src/bootstrap/web/forms.ts
|
|
1274
1344
|
import {
|
|
@@ -1350,6 +1420,7 @@ function createRouteKernel(dependencies) {
|
|
|
1350
1420
|
}
|
|
1351
1421
|
// ../../src/bootstrap/web/server.ts
|
|
1352
1422
|
import { currentRequestMeta as currentRequestMeta2, runWithRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
1423
|
+
import { assertUrlPathUnderRoot as assertUrlPathUnderRoot2 } from "@getstrata/core/security/safePath";
|
|
1353
1424
|
import { notFoundHtmlResponse as notFoundHtmlResponse2 } from "@getstrata/core/view";
|
|
1354
1425
|
function socketAddress(server, request) {
|
|
1355
1426
|
const address = server?.requestIP(request)?.address;
|
|
@@ -1409,9 +1480,14 @@ function createWebServer(options) {
|
|
|
1409
1480
|
await options.onRequest?.(request);
|
|
1410
1481
|
const url = new URL(request.url);
|
|
1411
1482
|
if (url.pathname.startsWith("/assets/")) {
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1483
|
+
try {
|
|
1484
|
+
const filePath = assertUrlPathUnderRoot2(publicDir, url.pathname);
|
|
1485
|
+
const file = Bun.file(filePath);
|
|
1486
|
+
if (await file.exists()) {
|
|
1487
|
+
return new Response(file);
|
|
1488
|
+
}
|
|
1489
|
+
} catch {
|
|
1490
|
+
return await missingHtmlResponse();
|
|
1415
1491
|
}
|
|
1416
1492
|
}
|
|
1417
1493
|
if (options.handle) {
|
|
@@ -1426,13 +1502,22 @@ function createWebServer(options) {
|
|
|
1426
1502
|
// ../../src/bootstrap/web/session.ts
|
|
1427
1503
|
import { createHmac, randomBytes } from "crypto";
|
|
1428
1504
|
import { AuthManager as AuthManager2 } from "@getstrata/core/auth/guard";
|
|
1505
|
+
import { isSessionInvalidated } from "@getstrata/core/auth/sessionCookie";
|
|
1429
1506
|
import { getBoundDatabaseConnection as getBoundDatabaseConnection2 } from "@getstrata/core/database/boundConnection";
|
|
1430
|
-
import {
|
|
1507
|
+
import {
|
|
1508
|
+
getActiveDatabaseConnection,
|
|
1509
|
+
hasActiveDatabaseConnection
|
|
1510
|
+
} from "@getstrata/core/database/connectionContext";
|
|
1511
|
+
import {
|
|
1512
|
+
getDefaultDatabasePool as getDefaultDatabasePool3,
|
|
1513
|
+
getDefaultDatabaseQuery
|
|
1514
|
+
} from "@getstrata/core/database/defaultConnection";
|
|
1431
1515
|
import { currentSqlDialect, sqlTimestamp } from "@getstrata/core/database/dialect";
|
|
1432
1516
|
import { readRequestCookie } from "@getstrata/core/http/cookies";
|
|
1433
1517
|
import { currentRequestMeta as currentRequestMeta3 } from "@getstrata/core/http/requestMetaContext";
|
|
1434
1518
|
import { isProductionEnv as isProductionEnv2 } from "@getstrata/core/runtime/appEnv";
|
|
1435
1519
|
import { timingSafeCompareString } from "@getstrata/core/security/timingSafeCompare";
|
|
1520
|
+
import { runWithMigrationBypassForIdentifier } from "@getstrata/core/tenant/databaseTenantContext";
|
|
1436
1521
|
function sqlPlaceholder(index) {
|
|
1437
1522
|
return currentSqlDialect().placeholder(index);
|
|
1438
1523
|
}
|
|
@@ -1443,17 +1528,25 @@ function isSqlClient(value) {
|
|
|
1443
1528
|
return typeof value.unsafe === "function";
|
|
1444
1529
|
}
|
|
1445
1530
|
function resolveSql(source) {
|
|
1446
|
-
|
|
1447
|
-
|
|
1531
|
+
const client = isSqlClient(source) ? source : source();
|
|
1532
|
+
if (!hasActiveDatabaseConnection()) {
|
|
1533
|
+
return client;
|
|
1534
|
+
}
|
|
1535
|
+
try {
|
|
1536
|
+
if (client === getDefaultDatabasePool3() || client === getDefaultDatabaseQuery()) {
|
|
1537
|
+
return getActiveDatabaseConnection(client);
|
|
1538
|
+
}
|
|
1539
|
+
} catch {
|
|
1540
|
+
return client;
|
|
1448
1541
|
}
|
|
1449
|
-
return
|
|
1542
|
+
return client;
|
|
1450
1543
|
}
|
|
1451
1544
|
function defaultSessionSql() {
|
|
1452
1545
|
const bound = getBoundDatabaseConnection2();
|
|
1453
1546
|
if (bound) {
|
|
1454
1547
|
return bound;
|
|
1455
1548
|
}
|
|
1456
|
-
return
|
|
1549
|
+
return getDefaultDatabasePool3();
|
|
1457
1550
|
}
|
|
1458
1551
|
function defaultMapSessionUser(user) {
|
|
1459
1552
|
return {
|
|
@@ -1483,14 +1576,32 @@ function mapSessionUserRow(row) {
|
|
|
1483
1576
|
};
|
|
1484
1577
|
}
|
|
1485
1578
|
async function defaultLoadSessionUser(sql, sessionId) {
|
|
1486
|
-
const
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
WHERE
|
|
1490
|
-
|
|
1491
|
-
|
|
1579
|
+
const sessionRows = await runWithMigrationBypassForIdentifier(sessionId, async () => {
|
|
1580
|
+
return await sql.unsafe(`SELECT user_id, expires_at, created_at AS session_created_at
|
|
1581
|
+
FROM sessions
|
|
1582
|
+
WHERE id = ${sqlPlaceholder(1)} AND expires_at > ${sqlNow()}`, [sessionId]);
|
|
1583
|
+
});
|
|
1584
|
+
const session = sessionRows[0];
|
|
1585
|
+
if (!session)
|
|
1586
|
+
return null;
|
|
1587
|
+
const userId = Number(session.user_id);
|
|
1588
|
+
if (!Number.isInteger(userId) || userId <= 0) {
|
|
1492
1589
|
return null;
|
|
1493
|
-
|
|
1590
|
+
}
|
|
1591
|
+
return await runWithMigrationBypassForIdentifier(userId, async () => {
|
|
1592
|
+
const rows = await sql.unsafe(`SELECT * FROM users WHERE id = ${sqlPlaceholder(1)}`, [
|
|
1593
|
+
userId
|
|
1594
|
+
]);
|
|
1595
|
+
const row = rows[0];
|
|
1596
|
+
if (!row)
|
|
1597
|
+
return null;
|
|
1598
|
+
const createdSource = session.session_created_at;
|
|
1599
|
+
const createdAt = createdSource instanceof Date ? createdSource.getTime() : createdSource ? Date.parse(String(createdSource)) : Number.NaN;
|
|
1600
|
+
if (!Number.isFinite(createdAt) || isSessionInvalidated(createdAt, row.session_valid_after)) {
|
|
1601
|
+
return null;
|
|
1602
|
+
}
|
|
1603
|
+
return mapSessionUserRow({ ...row, user_id: userId, session_created_at: createdSource });
|
|
1604
|
+
});
|
|
1494
1605
|
}
|
|
1495
1606
|
function redirectWithCookie(location, setCookie, status) {
|
|
1496
1607
|
return new Response(null, {
|
|
@@ -1545,25 +1656,40 @@ class CookieSessionStore {
|
|
|
1545
1656
|
async create(user, meta = {}) {
|
|
1546
1657
|
const id = randomBytes(32).toString("hex");
|
|
1547
1658
|
const expires = new Date(Date.now() + this.maxAgeSeconds * 1000);
|
|
1548
|
-
await
|
|
1549
|
-
|
|
1659
|
+
await runWithMigrationBypassForIdentifier(user.id, async () => {
|
|
1660
|
+
await this.sql().unsafe(`INSERT INTO sessions (id, user_id, expires_at, user_agent, ip_address, last_active_at, created_at)
|
|
1661
|
+
VALUES (${sqlPlaceholder(1)}, ${sqlPlaceholder(2)}, ${sqlPlaceholder(3)}, ${sqlPlaceholder(4)}, ${sqlPlaceholder(5)}, ${sqlNow()}, ${sqlNow()})`, [id, user.id, sqlTimestamp(expires), meta.userAgent ?? null, meta.ipAddress ?? null]);
|
|
1662
|
+
});
|
|
1550
1663
|
return id;
|
|
1551
1664
|
}
|
|
1552
1665
|
async destroy(sessionId) {
|
|
1553
|
-
await
|
|
1666
|
+
await runWithMigrationBypassForIdentifier(sessionId, async () => {
|
|
1667
|
+
await this.sql().unsafe(`DELETE FROM sessions WHERE id = ${sqlPlaceholder(1)}`, [sessionId]);
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1670
|
+
async destroyAllSessions(userId) {
|
|
1671
|
+
await runWithMigrationBypassForIdentifier(userId, async () => {
|
|
1672
|
+
await this.sql().unsafe(`DELETE FROM sessions WHERE user_id = ${sqlPlaceholder(1)}`, [
|
|
1673
|
+
userId
|
|
1674
|
+
]);
|
|
1675
|
+
});
|
|
1554
1676
|
}
|
|
1555
1677
|
async destroyOtherSessions(userId, keepSessionId) {
|
|
1556
|
-
await
|
|
1678
|
+
await runWithMigrationBypassForIdentifier(userId, async () => {
|
|
1679
|
+
await this.sql().unsafe(`DELETE FROM sessions WHERE user_id = ${sqlPlaceholder(1)} AND id <> ${sqlPlaceholder(2)}`, [userId, keepSessionId]);
|
|
1680
|
+
});
|
|
1557
1681
|
}
|
|
1558
1682
|
async listForUser(userId) {
|
|
1559
1683
|
const dialect = currentSqlDialect();
|
|
1560
|
-
return this.sql().unsafe(`SELECT id, user_id, user_agent, ip_address, last_active_at, expires_at
|
|
1684
|
+
return await runWithMigrationBypassForIdentifier(userId, () => this.sql().unsafe(`SELECT id, user_id, user_agent, ip_address, last_active_at, expires_at
|
|
1561
1685
|
FROM sessions
|
|
1562
1686
|
WHERE user_id = ${dialect.placeholder(1)} AND expires_at > ${dialect.nowExpression()}
|
|
1563
|
-
ORDER BY last_active_at DESC${dialect.nullsLastSuffix()}, expires_at DESC`, [userId]);
|
|
1687
|
+
ORDER BY last_active_at DESC${dialect.nullsLastSuffix()}, expires_at DESC`, [userId]));
|
|
1564
1688
|
}
|
|
1565
1689
|
async touch(sessionId) {
|
|
1566
|
-
await
|
|
1690
|
+
await runWithMigrationBypassForIdentifier(sessionId, async () => {
|
|
1691
|
+
await this.sql().unsafe(`UPDATE sessions SET last_active_at = ${sqlNow()} WHERE id = ${sqlPlaceholder(1)}`, [sessionId]);
|
|
1692
|
+
});
|
|
1567
1693
|
}
|
|
1568
1694
|
async read(request) {
|
|
1569
1695
|
const sessionId = this.sessionIdFromRequest(request);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/bootstrap",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Strata application bootstrap: HttpKernel, DI, web session helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -168,14 +168,14 @@
|
|
|
168
168
|
"build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta --external mysql2 --external @getstrata/core",
|
|
169
169
|
"build:types": "tsc -p tsconfig.types.json && bun ../../scripts/prune-bootstrap-dist-types.ts",
|
|
170
170
|
"prepublishOnly": "bun run build",
|
|
171
|
-
"build:subpaths": "bun build entries/applicationRegistry.ts entries/buildModuleRoutes.ts entries/buildWebModuleRoutes.ts entries/cache/modelCacheTags.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/createSpaRoutes.ts entries/dependencies.ts entries/discoverModules.ts entries/health.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/listeners/invalidateCacheOnModelWrite.ts entries/membershipService.ts entries/metricsRoutes.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts entries/routeRegistry.ts entries/schedule.ts entries/secretsGuard.ts entries/web/forms.ts entries/web/routing.ts entries/web/server.ts entries/web/session.ts entries/web/slug.ts --outdir dist --root . --target bun --external bun --external eta --external mysql2 --external @getstrata/core --external @getstrata/bootstrap --external @getstrata/bootstrap/applicationRegistry --external @getstrata/bootstrap/buildModuleRoutes --external @getstrata/bootstrap/buildWebModuleRoutes --external @getstrata/bootstrap/cache/modelCacheTags --external @getstrata/bootstrap/config --external @getstrata/bootstrap/context --external @getstrata/bootstrap/contracts --external @getstrata/bootstrap/createWebRoutes --external @getstrata/bootstrap/createSpaRoutes --external @getstrata/bootstrap/dependencies --external @getstrata/bootstrap/discoverModules --external @getstrata/bootstrap/health --external @getstrata/bootstrap/http/securedRouteModelBinding --external @getstrata/bootstrap/httpKernel --external @getstrata/bootstrap/listeners/invalidateCacheOnModelWrite --external @getstrata/bootstrap/membershipService --external @getstrata/bootstrap/metricsRoutes --external @getstrata/bootstrap/queue/defaultJobs --external @getstrata/bootstrap/providers --external @getstrata/bootstrap/providers/view --external @getstrata/bootstrap/routeRegistry --external @getstrata/bootstrap/schedule --external @getstrata/bootstrap/secretsGuard --external @getstrata/bootstrap/web/forms --external @getstrata/bootstrap/web/routing --external @getstrata/bootstrap/web/server --external @getstrata/bootstrap/web/session --external @getstrata/bootstrap/web/slug --external @getstrata/core/auth/accessControl --external @getstrata/core/auth/abilityChecker --external @getstrata/core/auth/authContext --external @getstrata/core/auth/emailVerification --external @getstrata/core/auth/guard --external @getstrata/core/auth/jwt --external @getstrata/core/auth/jwtGuard --external @getstrata/core/auth/basicAuthGuard --external @getstrata/core/auth/tokenAbilityChecker --external @getstrata/core/auth/membershipContext --external @getstrata/core/auth/membershipMiddleware --external @getstrata/core/auth/membershipScope --external @getstrata/core/auth/membershipService --external @getstrata/core/auth/oauth/oidcProvider --external @getstrata/core/auth/oauth/providers --external @getstrata/core/auth/oauth/samlProvider --external @getstrata/core/auth/oauth/types --external @getstrata/core/auth/password --external @getstrata/core/auth/intendedUrlCookie --external @getstrata/core/auth/passwordConfirmCookie --external @getstrata/core/auth/policy --external @getstrata/core/auth/scimAuthMiddleware --external @getstrata/core/auth/sessionCookie --external @getstrata/core/auth/sessionGuard --external @getstrata/core/auth/tokenHash --external @getstrata/core/audit/exportAuditLogs --external @getstrata/core/audit/siemFormatter --external @getstrata/core/admin/formatValue --external @getstrata/core/admin/registry --external @getstrata/core/admin/types --external @getstrata/core/cache/tags --external @getstrata/core/cache/createCacheStore --external @getstrata/core/cache/repository --external @getstrata/core/cache/simpleCache --external @getstrata/core/cache/simpleCacheStore --external @getstrata/core/config/envSchema --external @getstrata/core/contracts/serviceTokens --external @getstrata/core/contracts/authUserDirectory --external @getstrata/core/contracts/container --external @getstrata/core/contracts/di --external @getstrata/core/crypto/fieldEncryption --external @getstrata/core/crypto/mfaSecret --external @getstrata/core/database --external @getstrata/core/database/baseRepository --external @getstrata/core/database/bindConnection --external @getstrata/core/database/boundConnection --external @getstrata/core/database/bunSql --external @getstrata/core/database/connection --external @getstrata/core/database/connectionContext --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/dialect --external @getstrata/core/database/mysqlConnection --external @getstrata/core/database/namedConnections --external @getstrata/core/database/errors --external @getstrata/core/database/factory --external @getstrata/core/database/migrations --external @getstrata/core/database/migrations/types --external @getstrata/core/database/model --external @getstrata/core/database/query --external @getstrata/core/database/relationships --external @getstrata/core/database/repositoryConnection --external @getstrata/core/database/repositoryQuery --external @getstrata/core/database/seeders --external @getstrata/core/database/seeders/types --external @getstrata/core/database/schema --external @getstrata/core/database/sqliteConnection --external @getstrata/core/database/table --external @getstrata/core/database/transaction --external @getstrata/core/database/types --external @getstrata/core/database/whereBuilder --external @getstrata/core/errors/http --external @getstrata/core/events --external @getstrata/core/facades --external @getstrata/core/http --external @getstrata/core/http/authMiddleware --external @getstrata/core/http/authorizeMiddleware --external @getstrata/core/http/bodySizeLimitMiddleware --external @getstrata/core/http/clientIp --external @getstrata/core/http/cookies --external @getstrata/core/http/contentNegotiation --external @getstrata/core/http/contentSecurityPolicy --external @getstrata/core/http/conditionalResponse --external @getstrata/core/http/corsMiddleware --external @getstrata/core/http/csrfMiddleware --external @getstrata/core/http/csrfProtection --external @getstrata/core/http/csrfToken --external @getstrata/core/http/etag --external @getstrata/core/http/flashSession --external @getstrata/core/http/flashMiddleware --external @getstrata/core/http/formRequest --external @getstrata/core/http/middleware --external @getstrata/core/http/metricsMiddleware --external @getstrata/core/http/loginThrottleMiddleware --external @getstrata/core/http/memoryThrottleMiddleware --external @getstrata/core/http/pagination --external @getstrata/core/http/parseFormBody --external @getstrata/core/http/parseMultipartUpload --external @getstrata/core/http/requireAbilityMiddleware --external @getstrata/core/http/requireAuthMiddleware --external @getstrata/core/http/requireGlobalAdminMiddleware --external @getstrata/core/http/requireWebAuthMiddleware --external @getstrata/core/http/requireVerifiedMiddleware --external @getstrata/core/http/requirePasswordConfirmMiddleware --external @getstrata/core/http/resources --external @getstrata/core/http/response --external @getstrata/core/http/route --external @getstrata/core/http/routeMiddleware --external @getstrata/core/http/routeModelBinding --external @getstrata/core/http/safeInternalPath --external @getstrata/core/http/signedUrl --external @getstrata/core/http/statelessAuth --external @getstrata/core/http/scimThrottleMiddleware --external @getstrata/core/http/securityHeadersMiddleware --external @getstrata/core/http/securedRouteModelBinding --external @getstrata/core/http/requestMetaContext --external @getstrata/core/http/webErrorResponse --external @getstrata/core/http/webFormRequest --external @getstrata/core/http/throttleMiddleware --external @getstrata/core/http/validation --external @getstrata/core/jobs/exportAuditLogsJob --external @getstrata/core/jobs/invalidateCacheTagsJob --external @getstrata/core/lifecycle/gracefulShutdown --external @getstrata/core/logging/logger --external @getstrata/core/logging/requestLoggingMiddleware --external @getstrata/core/mail/mailer --external @getstrata/core/mail/markdownMail --external @getstrata/core/mail/markdownMailable --external @getstrata/core/mail/sanitizeMailHtml --external @getstrata/core/media/imageTransform --external @getstrata/core/metrics/prometheus --external @getstrata/core/notifications --external @getstrata/core/openapi/generator --external @getstrata/core/openapi/registeredRoute --external @getstrata/core/openapi/validate --external @getstrata/core/pagination --external @getstrata/core/queue --external @getstrata/core/queue/createAppQueue --external @getstrata/core/queue/failedJobRepository --external @getstrata/core/queue/failedJobService --external @getstrata/core/queue/jobRegistry --external @getstrata/core/queue/jobRunner --external @getstrata/core/queue/queueMetrics --external @getstrata/core/queue/publicQueue --external @getstrata/core/queue/redisQueue --external @getstrata/core/queue/types --external @getstrata/core/runtime/appEnv --external @getstrata/core/runtime/appKeyPrefix --external @getstrata/core/runtime/frontendMode --external @getstrata/core/runtime/applicationRegistry --external @getstrata/core/runtime/asyncContextStore --external @getstrata/core/scheduler/schedule --external @getstrata/core/scheduler/osCron --external @getstrata/core/security/oauthState --external @getstrata/core/security/publicReads --external @getstrata/core/security/recoveryCodes --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safeUrl --external @getstrata/core/security/scimTenantTokens --external @getstrata/core/security/securityEvents --external @getstrata/core/security/stripeWebhook --external @getstrata/core/security/timingSafeCompare --external @getstrata/core/security/tokenExpiry --external @getstrata/core/security/totp --external @getstrata/core/storage/storage --external @getstrata/core/tenant/tenancyConfig --external @getstrata/core/tenant/tenantContext --external @getstrata/core/tenant/tenantDatabaseScope --external @getstrata/core/tenant/databaseTenantContext --external @getstrata/core/tenant/tenantMiddleware --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
|
|
171
|
+
"build:subpaths": "bun build entries/applicationRegistry.ts entries/buildModuleRoutes.ts entries/buildWebModuleRoutes.ts entries/cache/modelCacheTags.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/createSpaRoutes.ts entries/dependencies.ts entries/discoverModules.ts entries/health.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/listeners/invalidateCacheOnModelWrite.ts entries/membershipService.ts entries/metricsRoutes.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts entries/routeRegistry.ts entries/schedule.ts entries/secretsGuard.ts entries/web/forms.ts entries/web/routing.ts entries/web/server.ts entries/web/session.ts entries/web/slug.ts --outdir dist --root . --target bun --external bun --external eta --external mysql2 --external @getstrata/core --external @getstrata/bootstrap --external @getstrata/bootstrap/applicationRegistry --external @getstrata/bootstrap/buildModuleRoutes --external @getstrata/bootstrap/buildWebModuleRoutes --external @getstrata/bootstrap/cache/modelCacheTags --external @getstrata/bootstrap/config --external @getstrata/bootstrap/context --external @getstrata/bootstrap/contracts --external @getstrata/bootstrap/createWebRoutes --external @getstrata/bootstrap/createSpaRoutes --external @getstrata/bootstrap/dependencies --external @getstrata/bootstrap/discoverModules --external @getstrata/bootstrap/health --external @getstrata/bootstrap/http/securedRouteModelBinding --external @getstrata/bootstrap/httpKernel --external @getstrata/bootstrap/listeners/invalidateCacheOnModelWrite --external @getstrata/bootstrap/membershipService --external @getstrata/bootstrap/metricsRoutes --external @getstrata/bootstrap/queue/defaultJobs --external @getstrata/bootstrap/providers --external @getstrata/bootstrap/providers/view --external @getstrata/bootstrap/routeRegistry --external @getstrata/bootstrap/schedule --external @getstrata/bootstrap/secretsGuard --external @getstrata/bootstrap/web/forms --external @getstrata/bootstrap/web/routing --external @getstrata/bootstrap/web/server --external @getstrata/bootstrap/web/session --external @getstrata/bootstrap/web/slug --external @getstrata/core/auth/accessControl --external @getstrata/core/auth/abilityChecker --external @getstrata/core/auth/authContext --external @getstrata/core/auth/emailVerification --external @getstrata/core/auth/guard --external @getstrata/core/auth/jwt --external @getstrata/core/auth/jwtGuard --external @getstrata/core/auth/basicAuthGuard --external @getstrata/core/auth/tokenAbilityChecker --external @getstrata/core/auth/membershipContext --external @getstrata/core/auth/membershipMiddleware --external @getstrata/core/auth/membershipScope --external @getstrata/core/auth/membershipService --external @getstrata/core/auth/oauth/oidcProvider --external @getstrata/core/auth/oauth/providers --external @getstrata/core/auth/oauth/samlProvider --external @getstrata/core/auth/oauth/types --external @getstrata/core/auth/saml/samlServiceProvider --external @getstrata/core/auth/password --external @getstrata/core/auth/passwordLogin --external @getstrata/core/auth/oneTimeToken --external @getstrata/core/auth/intendedUrlCookie --external @getstrata/core/auth/passwordConfirmCookie --external @getstrata/core/auth/policy --external @getstrata/core/auth/scimAuthMiddleware --external @getstrata/core/auth/sessionCookie --external @getstrata/core/auth/sessionGuard --external @getstrata/core/auth/tokenHash --external @getstrata/core/audit/exportAuditLogs --external @getstrata/core/audit/siemFormatter --external @getstrata/core/admin/formatValue --external @getstrata/core/admin/registry --external @getstrata/core/admin/types --external @getstrata/core/cache/tags --external @getstrata/core/cache/createCacheStore --external @getstrata/core/cache/repository --external @getstrata/core/cache/simpleCache --external @getstrata/core/cache/simpleCacheStore --external @getstrata/core/config/envSchema --external @getstrata/core/contracts/serviceTokens --external @getstrata/core/contracts/authUserDirectory --external @getstrata/core/contracts/container --external @getstrata/core/contracts/di --external @getstrata/core/crypto/fieldEncryption --external @getstrata/core/crypto/mfaSecret --external @getstrata/core/database --external @getstrata/core/database/baseRepository --external @getstrata/core/database/bindConnection --external @getstrata/core/database/boundConnection --external @getstrata/core/database/bunSql --external @getstrata/core/database/connection --external @getstrata/core/database/connectionContext --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/dialect --external @getstrata/core/database/mysqlConnection --external @getstrata/core/database/namedConnections --external @getstrata/core/database/errors --external @getstrata/core/database/factory --external @getstrata/core/database/migrations --external @getstrata/core/database/migrations/types --external @getstrata/core/database/model --external @getstrata/core/database/query --external @getstrata/core/database/relationships --external @getstrata/core/database/repositoryConnection --external @getstrata/core/database/repositoryQuery --external @getstrata/core/database/seeders --external @getstrata/core/database/seeders/types --external @getstrata/core/database/schema --external @getstrata/core/database/sqliteConnection --external @getstrata/core/database/table --external @getstrata/core/database/transaction --external @getstrata/core/database/types --external @getstrata/core/database/whereBuilder --external @getstrata/core/errors/http --external @getstrata/core/events --external @getstrata/core/facades --external @getstrata/core/http --external @getstrata/core/http/authMiddleware --external @getstrata/core/http/authorizeMiddleware --external @getstrata/core/http/bodySizeLimitMiddleware --external @getstrata/core/http/clientIp --external @getstrata/core/http/cookies --external @getstrata/core/http/contentNegotiation --external @getstrata/core/http/contentSecurityPolicy --external @getstrata/core/http/conditionalResponse --external @getstrata/core/http/corsMiddleware --external @getstrata/core/http/csrfMiddleware --external @getstrata/core/http/csrfProtection --external @getstrata/core/http/csrfToken --external @getstrata/core/http/etag --external @getstrata/core/http/flashSession --external @getstrata/core/http/flashMiddleware --external @getstrata/core/http/formRequest --external @getstrata/core/http/middleware --external @getstrata/core/http/metricsMiddleware --external @getstrata/core/http/loginThrottleMiddleware --external @getstrata/core/http/memoryThrottleMiddleware --external @getstrata/core/http/pagination --external @getstrata/core/http/parseFormBody --external @getstrata/core/http/parseMultipartUpload --external @getstrata/core/http/requireAbilityMiddleware --external @getstrata/core/http/requireAuthMiddleware --external @getstrata/core/http/requireGlobalAdminMiddleware --external @getstrata/core/http/requireWebAuthMiddleware --external @getstrata/core/http/requireVerifiedMiddleware --external @getstrata/core/http/requirePasswordConfirmMiddleware --external @getstrata/core/http/resources --external @getstrata/core/http/response --external @getstrata/core/http/route --external @getstrata/core/http/routeMiddleware --external @getstrata/core/http/routeModelBinding --external @getstrata/core/http/safeInternalPath --external @getstrata/core/http/signedUrl --external @getstrata/core/http/statelessAuth --external @getstrata/core/http/scimThrottleMiddleware --external @getstrata/core/http/securityHeadersMiddleware --external @getstrata/core/http/securedRouteModelBinding --external @getstrata/core/http/requestMetaContext --external @getstrata/core/http/webErrorResponse --external @getstrata/core/http/webFormRequest --external @getstrata/core/http/throttleMiddleware --external @getstrata/core/http/validation --external @getstrata/core/jobs/exportAuditLogsJob --external @getstrata/core/jobs/invalidateCacheTagsJob --external @getstrata/core/lifecycle/gracefulShutdown --external @getstrata/core/logging/logger --external @getstrata/core/logging/requestLoggingMiddleware --external @getstrata/core/mail/mailer --external @getstrata/core/mail/markdownMail --external @getstrata/core/mail/markdownMailable --external @getstrata/core/mail/sanitizeMailHtml --external @getstrata/core/media/imageTransform --external @getstrata/core/metrics/prometheus --external @getstrata/core/notifications --external @getstrata/core/openapi/generator --external @getstrata/core/openapi/registeredRoute --external @getstrata/core/openapi/validate --external @getstrata/core/pagination --external @getstrata/core/queue --external @getstrata/core/queue/createAppQueue --external @getstrata/core/queue/failedJobRepository --external @getstrata/core/queue/failedJobService --external @getstrata/core/queue/jobRegistry --external @getstrata/core/queue/jobRunner --external @getstrata/core/queue/queueMetrics --external @getstrata/core/queue/publicQueue --external @getstrata/core/queue/redisQueue --external @getstrata/core/queue/types --external @getstrata/core/runtime/appEnv --external @getstrata/core/runtime/appKeyPrefix --external @getstrata/core/runtime/frontendMode --external @getstrata/core/runtime/applicationRegistry --external @getstrata/core/runtime/asyncContextStore --external @getstrata/core/scheduler/schedule --external @getstrata/core/scheduler/osCron --external @getstrata/core/security/oauthState --external @getstrata/core/security/publicReads --external @getstrata/core/security/recoveryCodes --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safePath --external @getstrata/core/security/safeUrl --external @getstrata/core/security/scimTenantTokens --external @getstrata/core/security/securityEvents --external @getstrata/core/security/stripeWebhook --external @getstrata/core/security/timingSafeCompare --external @getstrata/core/security/tokenExpiry --external @getstrata/core/security/totp --external @getstrata/core/storage/storage --external @getstrata/core/tenant/tenancyConfig --external @getstrata/core/tenant/tenantContext --external @getstrata/core/tenant/tenantDatabaseScope --external @getstrata/core/tenant/databaseTenantContext --external @getstrata/core/tenant/tenantMiddleware --external @getstrata/core/tenant/enableTenantRls --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
|
|
172
172
|
"build:shims": "true"
|
|
173
173
|
},
|
|
174
174
|
"publishConfig": {
|
|
175
175
|
"access": "public"
|
|
176
176
|
},
|
|
177
177
|
"peerDependencies": {
|
|
178
|
-
"@getstrata/core": "^1.0
|
|
178
|
+
"@getstrata/core": "^1.1.0",
|
|
179
179
|
"typescript": "^5.9.0"
|
|
180
180
|
},
|
|
181
181
|
"engines": {
|