@getstrata/bootstrap 0.2.64 → 0.2.66
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 +10 -0
- package/README.md +5 -5
- package/dist/bootstrap/rateLimit.d.ts +10 -0
- package/dist/entries/buildModuleRoutes.js +29 -29
- package/dist/entries/buildWebModuleRoutes.js +29 -29
- package/dist/entries/cache/modelCacheTags.js +1 -1
- package/dist/entries/context.js +14 -7
- package/dist/entries/createRoutes.js +41 -36
- package/dist/entries/createWebRoutes.js +30 -33
- package/dist/entries/dependencies.js +14 -7
- package/dist/entries/discoverModules.js +1 -1
- package/dist/entries/httpKernel.js +28 -28
- package/dist/entries/listeners/invalidateCacheOnModelWrite.js +1 -1
- package/dist/entries/providers.js +14 -7
- package/dist/entries/secretsGuard.js +25 -40
- package/dist/entries/web/routing.js +28 -28
- package/dist/index.js +67 -78
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @getstrata/bootstrap changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.66
|
|
4
|
+
|
|
5
|
+
- `assertProductionSecrets()` is feature-gated for every app. API tokens no longer imply WorkHub’s encryption/CORS/OAuth/public-read checklist. Published test token strings are still denied. WorkHub’s extra production profile lives in the app (`src/config/productionSecrets.ts`).
|
|
6
|
+
- **Breaking:** `HttpKernel.wrapWebGuest()` defaults `home` to `/` instead of `/organizations`. Apps with an org home should pass that path (WorkHub already does).
|
|
7
|
+
- `createWebRoutes()` no longer seeds a `/` → `/organizations` redirect. The in-repo app owns `/` via its organization module.
|
|
8
|
+
|
|
9
|
+
## 0.2.65
|
|
10
|
+
|
|
11
|
+
- App listener discovery reads `src/listeners` from `process.cwd()` so a built `@getstrata/bootstrap` bundle still finds WorkHub registrars (`import.meta.dir` after `build:bootstrap` is the package dist). Listener boot calls each registrar every time (registrars are idempotent per `eventBus`).
|
|
12
|
+
|
|
3
13
|
## 0.2.64
|
|
4
14
|
|
|
5
15
|
- `registerDefaultJobs()` no longer registers WorkHub `webhook.dispatch`. Apps that dispatch model webhooks should call `registerWebhookJobs()` (WorkHub’s webhook provider and `queue:work` do).
|
package/README.md
CHANGED
|
@@ -28,14 +28,14 @@ import {
|
|
|
28
28
|
import { createHttpKernel, createAppContext, coreProviders } from "@getstrata/bootstrap";
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
`createAppContext()` does not call `assertProductionSecrets`. WorkHub
|
|
31
|
+
`createAppContext()` does not call `assertProductionSecrets`. That helper is feature-gated for every app (tokens, CORS, OAuth, encryption only when those features are on). WorkHub also runs its own production extras from `App.serve()` / `queue:work`. Sibling HTMX apps can call the published helper without API tokens when feature flags are off — see [SIBLING-HTMX.md](../../docs/SIBLING-HTMX.md).
|
|
32
32
|
|
|
33
|
-
Sibling HTMX apps should bind `createCookieSessionAuthManager` from `@getstrata/bootstrap/web/session` instead of HMAC `SessionGuard`. Use `signIn` / `signOut` (or the redirect helpers) instead of calling `CookieSessionStore` from controllers. Pass `mapUser` to map roles in the app. Pass `loadSessionUser` when the default `learn_subscriber` / `is_admin` SELECT does not match your schema.
|
|
33
|
+
Sibling HTMX apps should bind `createCookieSessionAuthManager` from `@getstrata/bootstrap/web/session` instead of HMAC `SessionGuard`. Use `signIn` / `signOut` (or the redirect helpers) instead of calling `CookieSessionStore` from controllers. Pass `mapUser` to map roles in the app. Pass `loadSessionUser` when the default `learn_subscriber` / `is_admin` SELECT does not match your schema.
|
|
34
34
|
|
|
35
|
-
`wrapWeb` applies the web group (CSRF + flash) and `withErrorHandling`, so CSRF `ForbiddenError` becomes an HTML 403 in `FRONTEND_MODE=server-htmx`. `wrapWebGuest` is Laravel `guest` / `RedirectIfAuthenticated` (signed-in users go to
|
|
35
|
+
`wrapWeb` applies the web group (CSRF + flash) and `withErrorHandling`, so CSRF `ForbiddenError` becomes an HTML 403 in `FRONTEND_MODE=server-htmx`. `wrapWebGuest` is Laravel `guest` / `RedirectIfAuthenticated` (signed-in users go to `/` by default; pass a string or `(user) => path` to override). `wrapWebLogin` / `wrapWebRegister` include that web group plus throttle — do not wrap them with `wrapWeb` again. The throttle callback should return an HTML form at 429.
|
|
36
36
|
|
|
37
|
-
`registerDefaultJobs()` registers `cache.invalidate-tags` and `audit.export` only.
|
|
37
|
+
`registerDefaultJobs()` registers `cache.invalidate-tags` and `audit.export` only. Apps that dispatch model webhooks should call `registerWebhookJobs()` themselves.
|
|
38
38
|
|
|
39
|
-
These subpaths
|
|
39
|
+
These subpaths assemble the in-repo dogfood app and are not a generic starter API: `@getstrata/bootstrap/createRoutes` (includes SCIM), `@getstrata/bootstrap/schedule`, and `@getstrata/bootstrap/createWebRoutes` (discovers app `webRoutes`; `/` is owned by the app). Sibling apps should use `buildWebModuleRoutes` / `buildModuleRoutes`.
|
|
40
40
|
|
|
41
41
|
See the [strata](https://github.com/EyK-26/strata) monorepo reference app for full module patterns.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface LoginRateLimitConfig {
|
|
2
|
+
maxAttempts: number;
|
|
3
|
+
decaySeconds: number;
|
|
4
|
+
}
|
|
5
|
+
declare const LOCAL_LOGIN_RATE_LIMIT: LoginRateLimitConfig;
|
|
6
|
+
declare const PRODUCTION_LOGIN_RATE_LIMIT: LoginRateLimitConfig;
|
|
7
|
+
declare function resolveLoginRateLimit(): LoginRateLimitConfig;
|
|
8
|
+
declare function resolveRegisterRateLimit(): LoginRateLimitConfig;
|
|
9
|
+
export type { LoginRateLimitConfig };
|
|
10
|
+
export { LOCAL_LOGIN_RATE_LIMIT, PRODUCTION_LOGIN_RATE_LIMIT, resolveLoginRateLimit, resolveRegisterRateLimit, };
|
|
@@ -39,7 +39,33 @@ import { isPublicReadsEnabled } from "@getstrata/core/security/publicReads";
|
|
|
39
39
|
import { createTenantMiddleware } from "@getstrata/core/tenant/tenantMiddleware";
|
|
40
40
|
import { createTracingMiddleware } from "@getstrata/core/tracing/tracingMiddleware";
|
|
41
41
|
|
|
42
|
-
// ../../src/config
|
|
42
|
+
// ../../src/bootstrap/config.ts
|
|
43
|
+
import {
|
|
44
|
+
CORE_ABILITY_CHECKER_TOKEN,
|
|
45
|
+
CORE_AUTH_TOKEN,
|
|
46
|
+
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
47
|
+
CORE_CACHE_TOKEN,
|
|
48
|
+
CORE_CONFIG_TOKEN,
|
|
49
|
+
CORE_EVENT_BUS_TOKEN,
|
|
50
|
+
CORE_POLICY_GATE_TOKEN,
|
|
51
|
+
CORE_QUEUE_TOKEN,
|
|
52
|
+
CORE_TOKEN_SERVICE_TOKEN
|
|
53
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
54
|
+
var APP_PORT_CONFIG_KEY = "app.port";
|
|
55
|
+
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
56
|
+
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
57
|
+
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
58
|
+
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
59
|
+
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
60
|
+
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
61
|
+
var DEFAULT_APP_PORT = 3000;
|
|
62
|
+
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
63
|
+
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
64
|
+
var DEFAULT_CACHE_DRIVER = "array";
|
|
65
|
+
var DEFAULT_API_TOKEN = "";
|
|
66
|
+
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
67
|
+
|
|
68
|
+
// ../../src/bootstrap/rateLimit.ts
|
|
43
69
|
var LOCAL_LOGIN_RATE_LIMIT = {
|
|
44
70
|
maxAttempts: 100,
|
|
45
71
|
decaySeconds: 60
|
|
@@ -85,32 +111,6 @@ function resolveRegisterRateLimit() {
|
|
|
85
111
|
};
|
|
86
112
|
}
|
|
87
113
|
|
|
88
|
-
// ../../src/bootstrap/config.ts
|
|
89
|
-
import {
|
|
90
|
-
CORE_ABILITY_CHECKER_TOKEN,
|
|
91
|
-
CORE_AUTH_TOKEN,
|
|
92
|
-
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
93
|
-
CORE_CACHE_TOKEN,
|
|
94
|
-
CORE_CONFIG_TOKEN,
|
|
95
|
-
CORE_EVENT_BUS_TOKEN,
|
|
96
|
-
CORE_POLICY_GATE_TOKEN,
|
|
97
|
-
CORE_QUEUE_TOKEN,
|
|
98
|
-
CORE_TOKEN_SERVICE_TOKEN
|
|
99
|
-
} from "@getstrata/core/contracts/serviceTokens";
|
|
100
|
-
var APP_PORT_CONFIG_KEY = "app.port";
|
|
101
|
-
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
102
|
-
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
103
|
-
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
104
|
-
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
105
|
-
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
106
|
-
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
107
|
-
var DEFAULT_APP_PORT = 3000;
|
|
108
|
-
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
109
|
-
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
110
|
-
var DEFAULT_CACHE_DRIVER = "array";
|
|
111
|
-
var DEFAULT_API_TOKEN = "";
|
|
112
|
-
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
113
|
-
|
|
114
114
|
// ../../src/bootstrap/httpKernel.ts
|
|
115
115
|
class HttpKernel {
|
|
116
116
|
dependencies;
|
|
@@ -181,7 +181,7 @@ class HttpKernel {
|
|
|
181
181
|
wrapWeb(handler) {
|
|
182
182
|
return withErrorHandling(this.wrap("web", handler));
|
|
183
183
|
}
|
|
184
|
-
wrapWebGuest(handler, home = "/
|
|
184
|
+
wrapWebGuest(handler, home = "/") {
|
|
185
185
|
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
186
186
|
return this.wrapWeb(async (request) => {
|
|
187
187
|
const user = await auth.resolve(request);
|
|
@@ -351,7 +351,7 @@ function resolveModulesDirectory(options) {
|
|
|
351
351
|
if (state.configuredModulesDir) {
|
|
352
352
|
return state.configuredModulesDir;
|
|
353
353
|
}
|
|
354
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
354
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
355
355
|
}
|
|
356
356
|
async function loadDiscoveredModules(options) {
|
|
357
357
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -42,7 +42,33 @@ import { isPublicReadsEnabled } from "@getstrata/core/security/publicReads";
|
|
|
42
42
|
import { createTenantMiddleware } from "@getstrata/core/tenant/tenantMiddleware";
|
|
43
43
|
import { createTracingMiddleware } from "@getstrata/core/tracing/tracingMiddleware";
|
|
44
44
|
|
|
45
|
-
// ../../src/config
|
|
45
|
+
// ../../src/bootstrap/config.ts
|
|
46
|
+
import {
|
|
47
|
+
CORE_ABILITY_CHECKER_TOKEN,
|
|
48
|
+
CORE_AUTH_TOKEN,
|
|
49
|
+
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
50
|
+
CORE_CACHE_TOKEN,
|
|
51
|
+
CORE_CONFIG_TOKEN,
|
|
52
|
+
CORE_EVENT_BUS_TOKEN,
|
|
53
|
+
CORE_POLICY_GATE_TOKEN,
|
|
54
|
+
CORE_QUEUE_TOKEN,
|
|
55
|
+
CORE_TOKEN_SERVICE_TOKEN
|
|
56
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
57
|
+
var APP_PORT_CONFIG_KEY = "app.port";
|
|
58
|
+
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
59
|
+
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
60
|
+
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
61
|
+
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
62
|
+
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
63
|
+
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
64
|
+
var DEFAULT_APP_PORT = 3000;
|
|
65
|
+
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
66
|
+
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
67
|
+
var DEFAULT_CACHE_DRIVER = "array";
|
|
68
|
+
var DEFAULT_API_TOKEN = "";
|
|
69
|
+
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
70
|
+
|
|
71
|
+
// ../../src/bootstrap/rateLimit.ts
|
|
46
72
|
var LOCAL_LOGIN_RATE_LIMIT = {
|
|
47
73
|
maxAttempts: 100,
|
|
48
74
|
decaySeconds: 60
|
|
@@ -88,32 +114,6 @@ function resolveRegisterRateLimit() {
|
|
|
88
114
|
};
|
|
89
115
|
}
|
|
90
116
|
|
|
91
|
-
// ../../src/bootstrap/config.ts
|
|
92
|
-
import {
|
|
93
|
-
CORE_ABILITY_CHECKER_TOKEN,
|
|
94
|
-
CORE_AUTH_TOKEN,
|
|
95
|
-
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
96
|
-
CORE_CACHE_TOKEN,
|
|
97
|
-
CORE_CONFIG_TOKEN,
|
|
98
|
-
CORE_EVENT_BUS_TOKEN,
|
|
99
|
-
CORE_POLICY_GATE_TOKEN,
|
|
100
|
-
CORE_QUEUE_TOKEN,
|
|
101
|
-
CORE_TOKEN_SERVICE_TOKEN
|
|
102
|
-
} from "@getstrata/core/contracts/serviceTokens";
|
|
103
|
-
var APP_PORT_CONFIG_KEY = "app.port";
|
|
104
|
-
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
105
|
-
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
106
|
-
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
107
|
-
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
108
|
-
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
109
|
-
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
110
|
-
var DEFAULT_APP_PORT = 3000;
|
|
111
|
-
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
112
|
-
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
113
|
-
var DEFAULT_CACHE_DRIVER = "array";
|
|
114
|
-
var DEFAULT_API_TOKEN = "";
|
|
115
|
-
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
116
|
-
|
|
117
117
|
// ../../src/bootstrap/httpKernel.ts
|
|
118
118
|
class HttpKernel {
|
|
119
119
|
dependencies;
|
|
@@ -184,7 +184,7 @@ class HttpKernel {
|
|
|
184
184
|
wrapWeb(handler) {
|
|
185
185
|
return withErrorHandling(this.wrap("web", handler));
|
|
186
186
|
}
|
|
187
|
-
wrapWebGuest(handler, home = "/
|
|
187
|
+
wrapWebGuest(handler, home = "/") {
|
|
188
188
|
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
189
189
|
return this.wrapWeb(async (request) => {
|
|
190
190
|
const user = await auth.resolve(request);
|
|
@@ -354,7 +354,7 @@ function resolveModulesDirectory(options) {
|
|
|
354
354
|
if (state.configuredModulesDir) {
|
|
355
355
|
return state.configuredModulesDir;
|
|
356
356
|
}
|
|
357
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
357
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
358
358
|
}
|
|
359
359
|
async function loadDiscoveredModules(options) {
|
|
360
360
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -26,7 +26,7 @@ function resolveModulesDirectory(options) {
|
|
|
26
26
|
if (state.configuredModulesDir) {
|
|
27
27
|
return state.configuredModulesDir;
|
|
28
28
|
}
|
|
29
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
29
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
30
30
|
}
|
|
31
31
|
async function loadDiscoveredModules(options) {
|
|
32
32
|
const modulesDirectory = resolveModulesDirectory(options);
|
package/dist/entries/context.js
CHANGED
|
@@ -50,7 +50,7 @@ function resolveModulesDirectory(options) {
|
|
|
50
50
|
if (state.configuredModulesDir) {
|
|
51
51
|
return state.configuredModulesDir;
|
|
52
52
|
}
|
|
53
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
53
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
54
54
|
}
|
|
55
55
|
async function loadDiscoveredModules(options) {
|
|
56
56
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -170,7 +170,7 @@ import { validateEnv } from "@getstrata/core/config/envSchema";
|
|
|
170
170
|
|
|
171
171
|
// ../../src/config/app.ts
|
|
172
172
|
var appConfig = {
|
|
173
|
-
name: process.env.APP_NAME?.trim() || "
|
|
173
|
+
name: process.env.APP_NAME?.trim() || "Strata",
|
|
174
174
|
env: process.env.APP_ENV ?? "local",
|
|
175
175
|
debug: (process.env.APP_DEBUG ?? "true") !== "false",
|
|
176
176
|
url: process.env.APP_URL ?? "http://localhost:3000",
|
|
@@ -329,14 +329,21 @@ var eventsProvider = {
|
|
|
329
329
|
var events_default = eventsProvider;
|
|
330
330
|
|
|
331
331
|
// ../../src/bootstrap/discoverListeners.ts
|
|
332
|
-
import { readdirSync as readdirSync2 } from "fs";
|
|
332
|
+
import { existsSync, readdirSync as readdirSync2 } from "fs";
|
|
333
333
|
import { join as join2 } from "path";
|
|
334
334
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
335
|
+
function resolveListenersDirectory() {
|
|
336
|
+
const fromCwd = join2(process.cwd(), "src", "listeners");
|
|
337
|
+
if (existsSync(fromCwd)) {
|
|
338
|
+
return fromCwd;
|
|
339
|
+
}
|
|
340
|
+
return join2(import.meta.dir, "../listeners");
|
|
341
|
+
}
|
|
335
342
|
async function loadDiscoveredListeners() {
|
|
336
|
-
const listenersDirectory =
|
|
343
|
+
const listenersDirectory = resolveListenersDirectory();
|
|
337
344
|
let entries;
|
|
338
345
|
try {
|
|
339
|
-
entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name
|
|
346
|
+
entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && /\.(ts|js)$/.test(entry.name)).map((entry) => entry.name);
|
|
340
347
|
} catch (error) {
|
|
341
348
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
342
349
|
return [];
|
|
@@ -412,8 +419,8 @@ var listenersProvider = {
|
|
|
412
419
|
registerListenerGroup("cache.invalidate-on-model-write", () => {
|
|
413
420
|
registerInvalidateCacheOnModelWriteListeners();
|
|
414
421
|
});
|
|
415
|
-
for (const
|
|
416
|
-
|
|
422
|
+
for (const registerListener of discoverListeners()) {
|
|
423
|
+
registerListener();
|
|
417
424
|
}
|
|
418
425
|
}
|
|
419
426
|
};
|
|
@@ -12,7 +12,7 @@ var strata_default = __jsonParse("{\"index\":\"_.._/_.._/index.html\",\"files\":
|
|
|
12
12
|
|
|
13
13
|
// ../../src/config/app.ts
|
|
14
14
|
var appConfig = {
|
|
15
|
-
name: process.env.APP_NAME?.trim() || "
|
|
15
|
+
name: process.env.APP_NAME?.trim() || "Strata",
|
|
16
16
|
env: process.env.APP_ENV ?? "local",
|
|
17
17
|
debug: (process.env.APP_DEBUG ?? "true") !== "false",
|
|
18
18
|
url: process.env.APP_URL ?? "http://localhost:3000",
|
|
@@ -79,7 +79,33 @@ import { isPublicReadsEnabled } from "@getstrata/core/security/publicReads";
|
|
|
79
79
|
import { createTenantMiddleware } from "@getstrata/core/tenant/tenantMiddleware";
|
|
80
80
|
import { createTracingMiddleware } from "@getstrata/core/tracing/tracingMiddleware";
|
|
81
81
|
|
|
82
|
-
// ../../src/config
|
|
82
|
+
// ../../src/bootstrap/config.ts
|
|
83
|
+
import {
|
|
84
|
+
CORE_ABILITY_CHECKER_TOKEN,
|
|
85
|
+
CORE_AUTH_TOKEN,
|
|
86
|
+
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
87
|
+
CORE_CACHE_TOKEN,
|
|
88
|
+
CORE_CONFIG_TOKEN,
|
|
89
|
+
CORE_EVENT_BUS_TOKEN,
|
|
90
|
+
CORE_POLICY_GATE_TOKEN,
|
|
91
|
+
CORE_QUEUE_TOKEN,
|
|
92
|
+
CORE_TOKEN_SERVICE_TOKEN
|
|
93
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
94
|
+
var APP_PORT_CONFIG_KEY = "app.port";
|
|
95
|
+
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
96
|
+
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
97
|
+
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
98
|
+
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
99
|
+
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
100
|
+
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
101
|
+
var DEFAULT_APP_PORT = 3000;
|
|
102
|
+
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
103
|
+
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
104
|
+
var DEFAULT_CACHE_DRIVER = "array";
|
|
105
|
+
var DEFAULT_API_TOKEN = "";
|
|
106
|
+
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
107
|
+
|
|
108
|
+
// ../../src/bootstrap/rateLimit.ts
|
|
83
109
|
var LOCAL_LOGIN_RATE_LIMIT = {
|
|
84
110
|
maxAttempts: 100,
|
|
85
111
|
decaySeconds: 60
|
|
@@ -125,32 +151,6 @@ function resolveRegisterRateLimit() {
|
|
|
125
151
|
};
|
|
126
152
|
}
|
|
127
153
|
|
|
128
|
-
// ../../src/bootstrap/config.ts
|
|
129
|
-
import {
|
|
130
|
-
CORE_ABILITY_CHECKER_TOKEN,
|
|
131
|
-
CORE_AUTH_TOKEN,
|
|
132
|
-
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
133
|
-
CORE_CACHE_TOKEN,
|
|
134
|
-
CORE_CONFIG_TOKEN,
|
|
135
|
-
CORE_EVENT_BUS_TOKEN,
|
|
136
|
-
CORE_POLICY_GATE_TOKEN,
|
|
137
|
-
CORE_QUEUE_TOKEN,
|
|
138
|
-
CORE_TOKEN_SERVICE_TOKEN
|
|
139
|
-
} from "@getstrata/core/contracts/serviceTokens";
|
|
140
|
-
var APP_PORT_CONFIG_KEY = "app.port";
|
|
141
|
-
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
142
|
-
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
143
|
-
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
144
|
-
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
145
|
-
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
146
|
-
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
147
|
-
var DEFAULT_APP_PORT = 3000;
|
|
148
|
-
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
149
|
-
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
150
|
-
var DEFAULT_CACHE_DRIVER = "array";
|
|
151
|
-
var DEFAULT_API_TOKEN = "";
|
|
152
|
-
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
153
|
-
|
|
154
154
|
// ../../src/bootstrap/httpKernel.ts
|
|
155
155
|
class HttpKernel {
|
|
156
156
|
dependencies;
|
|
@@ -221,7 +221,7 @@ class HttpKernel {
|
|
|
221
221
|
wrapWeb(handler) {
|
|
222
222
|
return withErrorHandling(this.wrap("web", handler));
|
|
223
223
|
}
|
|
224
|
-
wrapWebGuest(handler, home = "/
|
|
224
|
+
wrapWebGuest(handler, home = "/") {
|
|
225
225
|
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
226
226
|
return this.wrapWeb(async (request) => {
|
|
227
227
|
const user = await auth.resolve(request);
|
|
@@ -391,7 +391,7 @@ function resolveModulesDirectory(options) {
|
|
|
391
391
|
if (state.configuredModulesDir) {
|
|
392
392
|
return state.configuredModulesDir;
|
|
393
393
|
}
|
|
394
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
394
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
395
395
|
}
|
|
396
396
|
async function loadDiscoveredModules(options) {
|
|
397
397
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -584,10 +584,7 @@ function registerRoute(method, path, middleware) {
|
|
|
584
584
|
}
|
|
585
585
|
function createWebRoutes(dependencies) {
|
|
586
586
|
const wrappedRoutes = buildWebModuleRoutes(dependencies, {
|
|
587
|
-
clearRegistry: false
|
|
588
|
-
seedRoutes: {
|
|
589
|
-
"/": () => Response.redirect("/organizations", 302)
|
|
590
|
-
}
|
|
587
|
+
clearRegistry: false
|
|
591
588
|
});
|
|
592
589
|
registerRoute("GET", "/", ["global", "web"]);
|
|
593
590
|
wrappedRoutes["/assets/*"] = async (request) => {
|
|
@@ -1122,6 +1119,14 @@ var ADMIN_ABILITIES = [
|
|
|
1122
1119
|
"webhooks:write",
|
|
1123
1120
|
"audit:read"
|
|
1124
1121
|
];
|
|
1122
|
+
// ../../src/modules/user/browserSessions.ts
|
|
1123
|
+
import {
|
|
1124
|
+
createSessionCookieDetails,
|
|
1125
|
+
readSession
|
|
1126
|
+
} from "@getstrata/core/auth/sessionCookie";
|
|
1127
|
+
import { repositoryConnection as db2 } from "@getstrata/core/database/repositoryConnection";
|
|
1128
|
+
import { BadRequestError } from "@getstrata/core/errors/http";
|
|
1129
|
+
|
|
1125
1130
|
// ../../src/modules/user/mfaRequiredError.ts
|
|
1126
1131
|
import { UnauthorizedError } from "@getstrata/core/errors/http";
|
|
1127
1132
|
|
|
@@ -1157,7 +1162,7 @@ var oauthIdentityTable = defineTable4({
|
|
|
1157
1162
|
// ../../src/modules/user/passwordResetService.ts
|
|
1158
1163
|
import { hashPassword as hashPassword2 } from "@getstrata/core/auth/password";
|
|
1159
1164
|
import { hashApiToken } from "@getstrata/core/auth/tokenHash";
|
|
1160
|
-
import { repositoryConnection as
|
|
1165
|
+
import { repositoryConnection as db3 } from "@getstrata/core/database/repositoryConnection";
|
|
1161
1166
|
import { ValidationError as ValidationError2 } from "@getstrata/core/errors/http";
|
|
1162
1167
|
import { absoluteTemporarySignedUrl } from "@getstrata/core/http/signedUrl";
|
|
1163
1168
|
import { mailer } from "@getstrata/core/mail/mailer";
|
|
@@ -1169,7 +1174,7 @@ var RESET_TTL_SECONDS = 60 * 60;
|
|
|
1169
1174
|
var VERIFY_TTL_SECONDS = 60 * 60 * 24;
|
|
1170
1175
|
|
|
1171
1176
|
// ../../src/modules/user/profilePhotoService.ts
|
|
1172
|
-
import { BadRequestError, NotFoundError as NotFoundError5 } from "@getstrata/core/errors/http";
|
|
1177
|
+
import { BadRequestError as BadRequestError2, NotFoundError as NotFoundError5 } from "@getstrata/core/errors/http";
|
|
1173
1178
|
import { isImageMimeType, resizeImageContents } from "@getstrata/core/media/imageTransform";
|
|
1174
1179
|
|
|
1175
1180
|
// ../../src/modules/user/repository.ts
|
|
@@ -47,7 +47,33 @@ import { isPublicReadsEnabled } from "@getstrata/core/security/publicReads";
|
|
|
47
47
|
import { createTenantMiddleware } from "@getstrata/core/tenant/tenantMiddleware";
|
|
48
48
|
import { createTracingMiddleware } from "@getstrata/core/tracing/tracingMiddleware";
|
|
49
49
|
|
|
50
|
-
// ../../src/config
|
|
50
|
+
// ../../src/bootstrap/config.ts
|
|
51
|
+
import {
|
|
52
|
+
CORE_ABILITY_CHECKER_TOKEN,
|
|
53
|
+
CORE_AUTH_TOKEN,
|
|
54
|
+
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
55
|
+
CORE_CACHE_TOKEN,
|
|
56
|
+
CORE_CONFIG_TOKEN,
|
|
57
|
+
CORE_EVENT_BUS_TOKEN,
|
|
58
|
+
CORE_POLICY_GATE_TOKEN,
|
|
59
|
+
CORE_QUEUE_TOKEN,
|
|
60
|
+
CORE_TOKEN_SERVICE_TOKEN
|
|
61
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
62
|
+
var APP_PORT_CONFIG_KEY = "app.port";
|
|
63
|
+
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
64
|
+
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
65
|
+
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
66
|
+
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
67
|
+
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
68
|
+
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
69
|
+
var DEFAULT_APP_PORT = 3000;
|
|
70
|
+
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
71
|
+
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
72
|
+
var DEFAULT_CACHE_DRIVER = "array";
|
|
73
|
+
var DEFAULT_API_TOKEN = "";
|
|
74
|
+
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
75
|
+
|
|
76
|
+
// ../../src/bootstrap/rateLimit.ts
|
|
51
77
|
var LOCAL_LOGIN_RATE_LIMIT = {
|
|
52
78
|
maxAttempts: 100,
|
|
53
79
|
decaySeconds: 60
|
|
@@ -93,32 +119,6 @@ function resolveRegisterRateLimit() {
|
|
|
93
119
|
};
|
|
94
120
|
}
|
|
95
121
|
|
|
96
|
-
// ../../src/bootstrap/config.ts
|
|
97
|
-
import {
|
|
98
|
-
CORE_ABILITY_CHECKER_TOKEN,
|
|
99
|
-
CORE_AUTH_TOKEN,
|
|
100
|
-
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
101
|
-
CORE_CACHE_TOKEN,
|
|
102
|
-
CORE_CONFIG_TOKEN,
|
|
103
|
-
CORE_EVENT_BUS_TOKEN,
|
|
104
|
-
CORE_POLICY_GATE_TOKEN,
|
|
105
|
-
CORE_QUEUE_TOKEN,
|
|
106
|
-
CORE_TOKEN_SERVICE_TOKEN
|
|
107
|
-
} from "@getstrata/core/contracts/serviceTokens";
|
|
108
|
-
var APP_PORT_CONFIG_KEY = "app.port";
|
|
109
|
-
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
110
|
-
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
111
|
-
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
112
|
-
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
113
|
-
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
114
|
-
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
115
|
-
var DEFAULT_APP_PORT = 3000;
|
|
116
|
-
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
117
|
-
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
118
|
-
var DEFAULT_CACHE_DRIVER = "array";
|
|
119
|
-
var DEFAULT_API_TOKEN = "";
|
|
120
|
-
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
121
|
-
|
|
122
122
|
// ../../src/bootstrap/httpKernel.ts
|
|
123
123
|
class HttpKernel {
|
|
124
124
|
dependencies;
|
|
@@ -189,7 +189,7 @@ class HttpKernel {
|
|
|
189
189
|
wrapWeb(handler) {
|
|
190
190
|
return withErrorHandling(this.wrap("web", handler));
|
|
191
191
|
}
|
|
192
|
-
wrapWebGuest(handler, home = "/
|
|
192
|
+
wrapWebGuest(handler, home = "/") {
|
|
193
193
|
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
194
194
|
return this.wrapWeb(async (request) => {
|
|
195
195
|
const user = await auth.resolve(request);
|
|
@@ -359,7 +359,7 @@ function resolveModulesDirectory(options) {
|
|
|
359
359
|
if (state.configuredModulesDir) {
|
|
360
360
|
return state.configuredModulesDir;
|
|
361
361
|
}
|
|
362
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
362
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
363
363
|
}
|
|
364
364
|
async function loadDiscoveredModules(options) {
|
|
365
365
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -508,10 +508,7 @@ function registerRoute(method, path, middleware) {
|
|
|
508
508
|
}
|
|
509
509
|
function createWebRoutes(dependencies) {
|
|
510
510
|
const wrappedRoutes = buildWebModuleRoutes(dependencies, {
|
|
511
|
-
clearRegistry: false
|
|
512
|
-
seedRoutes: {
|
|
513
|
-
"/": () => Response.redirect("/organizations", 302)
|
|
514
|
-
}
|
|
511
|
+
clearRegistry: false
|
|
515
512
|
});
|
|
516
513
|
registerRoute("GET", "/", ["global", "web"]);
|
|
517
514
|
wrappedRoutes["/assets/*"] = async (request) => {
|
|
@@ -50,7 +50,7 @@ function resolveModulesDirectory(options) {
|
|
|
50
50
|
if (state.configuredModulesDir) {
|
|
51
51
|
return state.configuredModulesDir;
|
|
52
52
|
}
|
|
53
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
53
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
54
54
|
}
|
|
55
55
|
async function loadDiscoveredModules(options) {
|
|
56
56
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -170,7 +170,7 @@ import { validateEnv } from "@getstrata/core/config/envSchema";
|
|
|
170
170
|
|
|
171
171
|
// ../../src/config/app.ts
|
|
172
172
|
var appConfig = {
|
|
173
|
-
name: process.env.APP_NAME?.trim() || "
|
|
173
|
+
name: process.env.APP_NAME?.trim() || "Strata",
|
|
174
174
|
env: process.env.APP_ENV ?? "local",
|
|
175
175
|
debug: (process.env.APP_DEBUG ?? "true") !== "false",
|
|
176
176
|
url: process.env.APP_URL ?? "http://localhost:3000",
|
|
@@ -329,14 +329,21 @@ var eventsProvider = {
|
|
|
329
329
|
var events_default = eventsProvider;
|
|
330
330
|
|
|
331
331
|
// ../../src/bootstrap/discoverListeners.ts
|
|
332
|
-
import { readdirSync as readdirSync2 } from "fs";
|
|
332
|
+
import { existsSync, readdirSync as readdirSync2 } from "fs";
|
|
333
333
|
import { join as join2 } from "path";
|
|
334
334
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
335
|
+
function resolveListenersDirectory() {
|
|
336
|
+
const fromCwd = join2(process.cwd(), "src", "listeners");
|
|
337
|
+
if (existsSync(fromCwd)) {
|
|
338
|
+
return fromCwd;
|
|
339
|
+
}
|
|
340
|
+
return join2(import.meta.dir, "../listeners");
|
|
341
|
+
}
|
|
335
342
|
async function loadDiscoveredListeners() {
|
|
336
|
-
const listenersDirectory =
|
|
343
|
+
const listenersDirectory = resolveListenersDirectory();
|
|
337
344
|
let entries;
|
|
338
345
|
try {
|
|
339
|
-
entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name
|
|
346
|
+
entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && /\.(ts|js)$/.test(entry.name)).map((entry) => entry.name);
|
|
340
347
|
} catch (error) {
|
|
341
348
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
342
349
|
return [];
|
|
@@ -412,8 +419,8 @@ var listenersProvider = {
|
|
|
412
419
|
registerListenerGroup("cache.invalidate-on-model-write", () => {
|
|
413
420
|
registerInvalidateCacheOnModelWriteListeners();
|
|
414
421
|
});
|
|
415
|
-
for (const
|
|
416
|
-
|
|
422
|
+
for (const registerListener of discoverListeners()) {
|
|
423
|
+
registerListener();
|
|
417
424
|
}
|
|
418
425
|
}
|
|
419
426
|
};
|
|
@@ -26,7 +26,7 @@ function resolveModulesDirectory(options) {
|
|
|
26
26
|
if (state.configuredModulesDir) {
|
|
27
27
|
return state.configuredModulesDir;
|
|
28
28
|
}
|
|
29
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
29
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
30
30
|
}
|
|
31
31
|
async function loadDiscoveredModules(options) {
|
|
32
32
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -35,7 +35,33 @@ import { isPublicReadsEnabled } from "@getstrata/core/security/publicReads";
|
|
|
35
35
|
import { createTenantMiddleware } from "@getstrata/core/tenant/tenantMiddleware";
|
|
36
36
|
import { createTracingMiddleware } from "@getstrata/core/tracing/tracingMiddleware";
|
|
37
37
|
|
|
38
|
-
// ../../src/config
|
|
38
|
+
// ../../src/bootstrap/config.ts
|
|
39
|
+
import {
|
|
40
|
+
CORE_ABILITY_CHECKER_TOKEN,
|
|
41
|
+
CORE_AUTH_TOKEN,
|
|
42
|
+
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
43
|
+
CORE_CACHE_TOKEN,
|
|
44
|
+
CORE_CONFIG_TOKEN,
|
|
45
|
+
CORE_EVENT_BUS_TOKEN,
|
|
46
|
+
CORE_POLICY_GATE_TOKEN,
|
|
47
|
+
CORE_QUEUE_TOKEN,
|
|
48
|
+
CORE_TOKEN_SERVICE_TOKEN
|
|
49
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
50
|
+
var APP_PORT_CONFIG_KEY = "app.port";
|
|
51
|
+
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
52
|
+
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
53
|
+
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
54
|
+
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
55
|
+
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
56
|
+
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
57
|
+
var DEFAULT_APP_PORT = 3000;
|
|
58
|
+
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
59
|
+
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
60
|
+
var DEFAULT_CACHE_DRIVER = "array";
|
|
61
|
+
var DEFAULT_API_TOKEN = "";
|
|
62
|
+
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
63
|
+
|
|
64
|
+
// ../../src/bootstrap/rateLimit.ts
|
|
39
65
|
var LOCAL_LOGIN_RATE_LIMIT = {
|
|
40
66
|
maxAttempts: 100,
|
|
41
67
|
decaySeconds: 60
|
|
@@ -81,32 +107,6 @@ function resolveRegisterRateLimit() {
|
|
|
81
107
|
};
|
|
82
108
|
}
|
|
83
109
|
|
|
84
|
-
// ../../src/bootstrap/config.ts
|
|
85
|
-
import {
|
|
86
|
-
CORE_ABILITY_CHECKER_TOKEN,
|
|
87
|
-
CORE_AUTH_TOKEN,
|
|
88
|
-
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
89
|
-
CORE_CACHE_TOKEN,
|
|
90
|
-
CORE_CONFIG_TOKEN,
|
|
91
|
-
CORE_EVENT_BUS_TOKEN,
|
|
92
|
-
CORE_POLICY_GATE_TOKEN,
|
|
93
|
-
CORE_QUEUE_TOKEN,
|
|
94
|
-
CORE_TOKEN_SERVICE_TOKEN
|
|
95
|
-
} from "@getstrata/core/contracts/serviceTokens";
|
|
96
|
-
var APP_PORT_CONFIG_KEY = "app.port";
|
|
97
|
-
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
98
|
-
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
99
|
-
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
100
|
-
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
101
|
-
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
102
|
-
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
103
|
-
var DEFAULT_APP_PORT = 3000;
|
|
104
|
-
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
105
|
-
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
106
|
-
var DEFAULT_CACHE_DRIVER = "array";
|
|
107
|
-
var DEFAULT_API_TOKEN = "";
|
|
108
|
-
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
109
|
-
|
|
110
110
|
// ../../src/bootstrap/httpKernel.ts
|
|
111
111
|
class HttpKernel {
|
|
112
112
|
dependencies;
|
|
@@ -177,7 +177,7 @@ class HttpKernel {
|
|
|
177
177
|
wrapWeb(handler) {
|
|
178
178
|
return withErrorHandling(this.wrap("web", handler));
|
|
179
179
|
}
|
|
180
|
-
wrapWebGuest(handler, home = "/
|
|
180
|
+
wrapWebGuest(handler, home = "/") {
|
|
181
181
|
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
182
182
|
return this.wrapWeb(async (request) => {
|
|
183
183
|
const user = await auth.resolve(request);
|
|
@@ -44,7 +44,7 @@ function resolveModulesDirectory(options) {
|
|
|
44
44
|
if (state.configuredModulesDir) {
|
|
45
45
|
return state.configuredModulesDir;
|
|
46
46
|
}
|
|
47
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
47
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
48
48
|
}
|
|
49
49
|
async function loadDiscoveredModules(options) {
|
|
50
50
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -81,7 +81,7 @@ import { validateEnv } from "@getstrata/core/config/envSchema";
|
|
|
81
81
|
|
|
82
82
|
// ../../src/config/app.ts
|
|
83
83
|
var appConfig = {
|
|
84
|
-
name: process.env.APP_NAME?.trim() || "
|
|
84
|
+
name: process.env.APP_NAME?.trim() || "Strata",
|
|
85
85
|
env: process.env.APP_ENV ?? "local",
|
|
86
86
|
debug: (process.env.APP_DEBUG ?? "true") !== "false",
|
|
87
87
|
url: process.env.APP_URL ?? "http://localhost:3000",
|
|
@@ -240,14 +240,21 @@ var eventsProvider = {
|
|
|
240
240
|
var events_default = eventsProvider;
|
|
241
241
|
|
|
242
242
|
// ../../src/bootstrap/discoverListeners.ts
|
|
243
|
-
import { readdirSync } from "fs";
|
|
243
|
+
import { existsSync, readdirSync } from "fs";
|
|
244
244
|
import { join } from "path";
|
|
245
245
|
import { pathToFileURL } from "url";
|
|
246
|
+
function resolveListenersDirectory() {
|
|
247
|
+
const fromCwd = join(process.cwd(), "src", "listeners");
|
|
248
|
+
if (existsSync(fromCwd)) {
|
|
249
|
+
return fromCwd;
|
|
250
|
+
}
|
|
251
|
+
return join(import.meta.dir, "../listeners");
|
|
252
|
+
}
|
|
246
253
|
async function loadDiscoveredListeners() {
|
|
247
|
-
const listenersDirectory =
|
|
254
|
+
const listenersDirectory = resolveListenersDirectory();
|
|
248
255
|
let entries;
|
|
249
256
|
try {
|
|
250
|
-
entries = readdirSync(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name
|
|
257
|
+
entries = readdirSync(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && /\.(ts|js)$/.test(entry.name)).map((entry) => entry.name);
|
|
251
258
|
} catch (error) {
|
|
252
259
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
253
260
|
return [];
|
|
@@ -309,7 +316,7 @@ function resolveModulesDirectory(options) {
|
|
|
309
316
|
if (state.configuredModulesDir) {
|
|
310
317
|
return state.configuredModulesDir;
|
|
311
318
|
}
|
|
312
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
319
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
313
320
|
}
|
|
314
321
|
async function loadDiscoveredModules(options) {
|
|
315
322
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -402,8 +409,8 @@ var listenersProvider = {
|
|
|
402
409
|
registerListenerGroup("cache.invalidate-on-model-write", () => {
|
|
403
410
|
registerInvalidateCacheOnModelWriteListeners();
|
|
404
411
|
});
|
|
405
|
-
for (const
|
|
406
|
-
|
|
412
|
+
for (const registerListener of discoverListeners()) {
|
|
413
|
+
registerListener();
|
|
407
414
|
}
|
|
408
415
|
}
|
|
409
416
|
};
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
var __jsonParse = (a) => JSON.parse(a);
|
|
3
3
|
|
|
4
4
|
// ../../src/bootstrap/secretsGuard.ts
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
5
|
+
var PUBLISHED_TEST_ADMIN_API_TOKEN = "workhub-admin-test-token";
|
|
6
|
+
var PUBLISHED_TEST_MEMBER_API_TOKEN = "workhub-member-test-token";
|
|
7
|
+
var PUBLISHED_TEST_SCIM_BEARER_TOKEN = "workhub-scim-test-token";
|
|
8
8
|
var MIN_SESSION_SECRET_LENGTH = 32;
|
|
9
|
-
var
|
|
10
|
-
|
|
9
|
+
var PUBLISHED_TEST_TOKENS = new Set([
|
|
10
|
+
PUBLISHED_TEST_ADMIN_API_TOKEN,
|
|
11
|
+
PUBLISHED_TEST_MEMBER_API_TOKEN
|
|
12
|
+
]);
|
|
13
|
+
var PUBLISHED_TEST_SCIM_TOKENS = new Set([PUBLISHED_TEST_SCIM_BEARER_TOKEN]);
|
|
11
14
|
function isEnabled(value, defaultEnabled) {
|
|
12
15
|
if (value === undefined) {
|
|
13
16
|
return defaultEnabled;
|
|
@@ -34,36 +37,19 @@ function assertSessionSecret(env) {
|
|
|
34
37
|
throw new Error("Production startup blocked: set SESSION_SECRET when FRONTEND_MODE=server-htmx (32+ characters).");
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
|
-
function
|
|
38
|
-
const adminToken = env.ADMIN_API_TOKEN ??
|
|
39
|
-
const memberToken = env.MEMBER_API_TOKEN ??
|
|
40
|
-
const scimToken = env.SCIM_BEARER_TOKEN ??
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
throw new Error("Production startup blocked: rotate ADMIN_API_TOKEN and MEMBER_API_TOKEN away from default WorkHub test values.");
|
|
44
|
-
}
|
|
45
|
-
if (DEFAULT_SCIM_TOKENS.has(scimToken)) {
|
|
46
|
-
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from default WorkHub test values.");
|
|
47
|
-
}
|
|
48
|
-
if (encryptionEnabled && !env.KMS_ENCRYPTION_KEY?.trim()) {
|
|
49
|
-
throw new Error("Production startup blocked: set KMS_ENCRYPTION_KEY when field encryption is enabled.");
|
|
50
|
-
}
|
|
51
|
-
if (!env.SIEM_EXPORT_URL?.trim() && isEnabled(env.FEATURE_SIEM_EXPORT, true)) {
|
|
52
|
-
console.warn("[secrets] SIEM_EXPORT_URL is not configured; audit logs remain database-only.");
|
|
53
|
-
}
|
|
54
|
-
if (isEnabled(env.FEATURE_BILLING, true) && !env.STRIPE_WEBHOOK_SECRET?.trim()) {
|
|
55
|
-
throw new Error("Production startup blocked: set STRIPE_WEBHOOK_SECRET when billing webhooks are enabled.");
|
|
40
|
+
function assertPublishedTestTokensRotated(env) {
|
|
41
|
+
const adminToken = env.ADMIN_API_TOKEN ?? "";
|
|
42
|
+
const memberToken = env.MEMBER_API_TOKEN ?? "";
|
|
43
|
+
const scimToken = env.SCIM_BEARER_TOKEN ?? "";
|
|
44
|
+
if (PUBLISHED_TEST_TOKENS.has(adminToken) || PUBLISHED_TEST_TOKENS.has(memberToken)) {
|
|
45
|
+
throw new Error("Production startup blocked: rotate ADMIN_API_TOKEN and MEMBER_API_TOKEN away from published test defaults.");
|
|
56
46
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
throw new Error("Production startup blocked: set explicit CORS_ALLOWED_ORIGINS instead of wildcard.");
|
|
60
|
-
}
|
|
61
|
-
if (isEnabled(env.FEATURE_PUBLIC_READS, true)) {
|
|
62
|
-
throw new Error("Production startup blocked: set FEATURE_PUBLIC_READS=false for authenticated-only reads.");
|
|
63
|
-
}
|
|
64
|
-
if (!env.OAUTH_STATE_SECRET?.trim()) {
|
|
65
|
-
throw new Error("Production startup blocked: set OAUTH_STATE_SECRET for OAuth CSRF protection.");
|
|
47
|
+
if (scimToken && PUBLISHED_TEST_SCIM_TOKENS.has(scimToken)) {
|
|
48
|
+
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from published test defaults.");
|
|
66
49
|
}
|
|
50
|
+
}
|
|
51
|
+
function assertTokenAuthProductionSecrets(env) {
|
|
52
|
+
assertPublishedTestTokensRotated(env);
|
|
67
53
|
if (!env.TOKEN_HASH_PEPPER?.trim()) {
|
|
68
54
|
throw new Error("Production startup blocked: set TOKEN_HASH_PEPPER for API token hashing.");
|
|
69
55
|
}
|
|
@@ -71,11 +57,11 @@ function assertWorkHubProductionSecrets(env) {
|
|
|
71
57
|
throw new Error("Production startup blocked: set API_TOKEN_DEFAULT_EXPIRY_DAYS to enforce token rotation.");
|
|
72
58
|
}
|
|
73
59
|
}
|
|
74
|
-
function
|
|
60
|
+
function assertFeatureProductionSecrets(env) {
|
|
75
61
|
if (isEnabled(env.FEATURE_SCIM, false)) {
|
|
76
|
-
const scimToken = env.SCIM_BEARER_TOKEN ??
|
|
77
|
-
if (
|
|
78
|
-
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from
|
|
62
|
+
const scimToken = env.SCIM_BEARER_TOKEN ?? PUBLISHED_TEST_SCIM_BEARER_TOKEN;
|
|
63
|
+
if (PUBLISHED_TEST_SCIM_TOKENS.has(scimToken) || !env.SCIM_BEARER_TOKEN?.trim()) {
|
|
64
|
+
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from published test defaults.");
|
|
79
65
|
}
|
|
80
66
|
}
|
|
81
67
|
if (isEnabled(env.FEATURE_FIELD_ENCRYPTION, false) && !env.KMS_ENCRYPTION_KEY?.trim()) {
|
|
@@ -107,10 +93,9 @@ function assertProductionSecrets(env = process.env) {
|
|
|
107
93
|
}
|
|
108
94
|
assertAuthDevHeadersDisabled(env);
|
|
109
95
|
if (isTokenAuthEnabled(env)) {
|
|
110
|
-
|
|
111
|
-
} else {
|
|
112
|
-
assertSiblingProductionSecrets(env);
|
|
96
|
+
assertTokenAuthProductionSecrets(env);
|
|
113
97
|
}
|
|
98
|
+
assertFeatureProductionSecrets(env);
|
|
114
99
|
const frontendMode = (env.FRONTEND_MODE ?? "api").trim();
|
|
115
100
|
if (frontendMode === "server-htmx") {
|
|
116
101
|
assertSessionSecret(env);
|
|
@@ -44,7 +44,33 @@ import { isPublicReadsEnabled } from "@getstrata/core/security/publicReads";
|
|
|
44
44
|
import { createTenantMiddleware } from "@getstrata/core/tenant/tenantMiddleware";
|
|
45
45
|
import { createTracingMiddleware } from "@getstrata/core/tracing/tracingMiddleware";
|
|
46
46
|
|
|
47
|
-
// ../../src/config
|
|
47
|
+
// ../../src/bootstrap/config.ts
|
|
48
|
+
import {
|
|
49
|
+
CORE_ABILITY_CHECKER_TOKEN,
|
|
50
|
+
CORE_AUTH_TOKEN,
|
|
51
|
+
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
52
|
+
CORE_CACHE_TOKEN,
|
|
53
|
+
CORE_CONFIG_TOKEN,
|
|
54
|
+
CORE_EVENT_BUS_TOKEN,
|
|
55
|
+
CORE_POLICY_GATE_TOKEN,
|
|
56
|
+
CORE_QUEUE_TOKEN,
|
|
57
|
+
CORE_TOKEN_SERVICE_TOKEN
|
|
58
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
59
|
+
var APP_PORT_CONFIG_KEY = "app.port";
|
|
60
|
+
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
61
|
+
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
62
|
+
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
63
|
+
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
64
|
+
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
65
|
+
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
66
|
+
var DEFAULT_APP_PORT = 3000;
|
|
67
|
+
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
68
|
+
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
69
|
+
var DEFAULT_CACHE_DRIVER = "array";
|
|
70
|
+
var DEFAULT_API_TOKEN = "";
|
|
71
|
+
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
72
|
+
|
|
73
|
+
// ../../src/bootstrap/rateLimit.ts
|
|
48
74
|
var LOCAL_LOGIN_RATE_LIMIT = {
|
|
49
75
|
maxAttempts: 100,
|
|
50
76
|
decaySeconds: 60
|
|
@@ -90,32 +116,6 @@ function resolveRegisterRateLimit() {
|
|
|
90
116
|
};
|
|
91
117
|
}
|
|
92
118
|
|
|
93
|
-
// ../../src/bootstrap/config.ts
|
|
94
|
-
import {
|
|
95
|
-
CORE_ABILITY_CHECKER_TOKEN,
|
|
96
|
-
CORE_AUTH_TOKEN,
|
|
97
|
-
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
98
|
-
CORE_CACHE_TOKEN,
|
|
99
|
-
CORE_CONFIG_TOKEN,
|
|
100
|
-
CORE_EVENT_BUS_TOKEN,
|
|
101
|
-
CORE_POLICY_GATE_TOKEN,
|
|
102
|
-
CORE_QUEUE_TOKEN,
|
|
103
|
-
CORE_TOKEN_SERVICE_TOKEN
|
|
104
|
-
} from "@getstrata/core/contracts/serviceTokens";
|
|
105
|
-
var APP_PORT_CONFIG_KEY = "app.port";
|
|
106
|
-
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
107
|
-
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
108
|
-
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
109
|
-
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
110
|
-
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
111
|
-
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
112
|
-
var DEFAULT_APP_PORT = 3000;
|
|
113
|
-
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
114
|
-
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
115
|
-
var DEFAULT_CACHE_DRIVER = "array";
|
|
116
|
-
var DEFAULT_API_TOKEN = "";
|
|
117
|
-
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
118
|
-
|
|
119
119
|
// ../../src/bootstrap/httpKernel.ts
|
|
120
120
|
class HttpKernel {
|
|
121
121
|
dependencies;
|
|
@@ -186,7 +186,7 @@ class HttpKernel {
|
|
|
186
186
|
wrapWeb(handler) {
|
|
187
187
|
return withErrorHandling(this.wrap("web", handler));
|
|
188
188
|
}
|
|
189
|
-
wrapWebGuest(handler, home = "/
|
|
189
|
+
wrapWebGuest(handler, home = "/") {
|
|
190
190
|
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
191
191
|
return this.wrapWeb(async (request) => {
|
|
192
192
|
const user = await auth.resolve(request);
|
package/dist/index.js
CHANGED
|
@@ -52,7 +52,32 @@ import { isPublicReadsEnabled } from "@getstrata/core/security/publicReads";
|
|
|
52
52
|
import { createTenantMiddleware } from "@getstrata/core/tenant/tenantMiddleware";
|
|
53
53
|
import { createTracingMiddleware } from "@getstrata/core/tracing/tracingMiddleware";
|
|
54
54
|
|
|
55
|
-
// ../../src/config
|
|
55
|
+
// ../../src/bootstrap/config.ts
|
|
56
|
+
import {
|
|
57
|
+
CORE_ABILITY_CHECKER_TOKEN,
|
|
58
|
+
CORE_AUTH_TOKEN,
|
|
59
|
+
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
60
|
+
CORE_CACHE_TOKEN,
|
|
61
|
+
CORE_CONFIG_TOKEN,
|
|
62
|
+
CORE_EVENT_BUS_TOKEN,
|
|
63
|
+
CORE_POLICY_GATE_TOKEN,
|
|
64
|
+
CORE_QUEUE_TOKEN,
|
|
65
|
+
CORE_TOKEN_SERVICE_TOKEN
|
|
66
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
67
|
+
var APP_PORT_CONFIG_KEY = "app.port";
|
|
68
|
+
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
69
|
+
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
70
|
+
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
71
|
+
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
72
|
+
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
73
|
+
var DEFAULT_APP_PORT = 3000;
|
|
74
|
+
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
75
|
+
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
76
|
+
var DEFAULT_CACHE_DRIVER = "array";
|
|
77
|
+
var DEFAULT_API_TOKEN = "";
|
|
78
|
+
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
79
|
+
|
|
80
|
+
// ../../src/bootstrap/rateLimit.ts
|
|
56
81
|
var LOCAL_LOGIN_RATE_LIMIT = {
|
|
57
82
|
maxAttempts: 100,
|
|
58
83
|
decaySeconds: 60
|
|
@@ -98,31 +123,6 @@ function resolveRegisterRateLimit() {
|
|
|
98
123
|
};
|
|
99
124
|
}
|
|
100
125
|
|
|
101
|
-
// ../../src/bootstrap/config.ts
|
|
102
|
-
import {
|
|
103
|
-
CORE_ABILITY_CHECKER_TOKEN,
|
|
104
|
-
CORE_AUTH_TOKEN,
|
|
105
|
-
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
106
|
-
CORE_CACHE_TOKEN,
|
|
107
|
-
CORE_CONFIG_TOKEN,
|
|
108
|
-
CORE_EVENT_BUS_TOKEN,
|
|
109
|
-
CORE_POLICY_GATE_TOKEN,
|
|
110
|
-
CORE_QUEUE_TOKEN,
|
|
111
|
-
CORE_TOKEN_SERVICE_TOKEN
|
|
112
|
-
} from "@getstrata/core/contracts/serviceTokens";
|
|
113
|
-
var APP_PORT_CONFIG_KEY = "app.port";
|
|
114
|
-
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
115
|
-
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
116
|
-
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
117
|
-
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
118
|
-
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
119
|
-
var DEFAULT_APP_PORT = 3000;
|
|
120
|
-
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
121
|
-
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
122
|
-
var DEFAULT_CACHE_DRIVER = "array";
|
|
123
|
-
var DEFAULT_API_TOKEN = "";
|
|
124
|
-
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
125
|
-
|
|
126
126
|
// ../../src/bootstrap/httpKernel.ts
|
|
127
127
|
class HttpKernel {
|
|
128
128
|
dependencies;
|
|
@@ -193,7 +193,7 @@ class HttpKernel {
|
|
|
193
193
|
wrapWeb(handler) {
|
|
194
194
|
return withErrorHandling(this.wrap("web", handler));
|
|
195
195
|
}
|
|
196
|
-
wrapWebGuest(handler, home = "/
|
|
196
|
+
wrapWebGuest(handler, home = "/") {
|
|
197
197
|
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
198
198
|
return this.wrapWeb(async (request) => {
|
|
199
199
|
const user = await auth.resolve(request);
|
|
@@ -363,7 +363,7 @@ function resolveModulesDirectory(options) {
|
|
|
363
363
|
if (state.configuredModulesDir) {
|
|
364
364
|
return state.configuredModulesDir;
|
|
365
365
|
}
|
|
366
|
-
throw new Error("configureModulesDirectory() must be called before discovering modules.
|
|
366
|
+
throw new Error("configureModulesDirectory() must be called before discovering modules. The app preload (or starter) should call it.");
|
|
367
367
|
}
|
|
368
368
|
async function loadDiscoveredModules(options) {
|
|
369
369
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -575,7 +575,7 @@ import { validateEnv } from "@getstrata/core/config/envSchema";
|
|
|
575
575
|
|
|
576
576
|
// ../../src/config/app.ts
|
|
577
577
|
var appConfig = {
|
|
578
|
-
name: process.env.APP_NAME?.trim() || "
|
|
578
|
+
name: process.env.APP_NAME?.trim() || "Strata",
|
|
579
579
|
env: process.env.APP_ENV ?? "local",
|
|
580
580
|
debug: (process.env.APP_DEBUG ?? "true") !== "false",
|
|
581
581
|
url: process.env.APP_URL ?? "http://localhost:3000",
|
|
@@ -734,14 +734,21 @@ var eventsProvider = {
|
|
|
734
734
|
var events_default = eventsProvider;
|
|
735
735
|
|
|
736
736
|
// ../../src/bootstrap/discoverListeners.ts
|
|
737
|
-
import { readdirSync as readdirSync2 } from "fs";
|
|
737
|
+
import { existsSync, readdirSync as readdirSync2 } from "fs";
|
|
738
738
|
import { join as join2 } from "path";
|
|
739
739
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
740
|
+
function resolveListenersDirectory() {
|
|
741
|
+
const fromCwd = join2(process.cwd(), "src", "listeners");
|
|
742
|
+
if (existsSync(fromCwd)) {
|
|
743
|
+
return fromCwd;
|
|
744
|
+
}
|
|
745
|
+
return join2(import.meta.dir, "../listeners");
|
|
746
|
+
}
|
|
740
747
|
async function loadDiscoveredListeners() {
|
|
741
|
-
const listenersDirectory =
|
|
748
|
+
const listenersDirectory = resolveListenersDirectory();
|
|
742
749
|
let entries;
|
|
743
750
|
try {
|
|
744
|
-
entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name
|
|
751
|
+
entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && /\.(ts|js)$/.test(entry.name)).map((entry) => entry.name);
|
|
745
752
|
} catch (error) {
|
|
746
753
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
747
754
|
return [];
|
|
@@ -803,8 +810,8 @@ var listenersProvider = {
|
|
|
803
810
|
registerListenerGroup("cache.invalidate-on-model-write", () => {
|
|
804
811
|
registerInvalidateCacheOnModelWriteListeners();
|
|
805
812
|
});
|
|
806
|
-
for (const
|
|
807
|
-
|
|
813
|
+
for (const registerListener of discoverListeners()) {
|
|
814
|
+
registerListener();
|
|
808
815
|
}
|
|
809
816
|
}
|
|
810
817
|
};
|
|
@@ -1113,10 +1120,7 @@ function registerRoute(method, path, middleware) {
|
|
|
1113
1120
|
}
|
|
1114
1121
|
function createWebRoutes(dependencies) {
|
|
1115
1122
|
const wrappedRoutes = buildWebModuleRoutes(dependencies, {
|
|
1116
|
-
clearRegistry: false
|
|
1117
|
-
seedRoutes: {
|
|
1118
|
-
"/": () => Response.redirect("/organizations", 302)
|
|
1119
|
-
}
|
|
1123
|
+
clearRegistry: false
|
|
1120
1124
|
});
|
|
1121
1125
|
registerRoute("GET", "/", ["global", "web"]);
|
|
1122
1126
|
wrappedRoutes["/assets/*"] = async (request) => {
|
|
@@ -1248,12 +1252,15 @@ import {
|
|
|
1248
1252
|
// ../../src/bootstrap/membershipService.ts
|
|
1249
1253
|
import { resolveMembershipService } from "@getstrata/core/auth/membershipService";
|
|
1250
1254
|
// ../../src/bootstrap/secretsGuard.ts
|
|
1251
|
-
var
|
|
1252
|
-
var
|
|
1253
|
-
var
|
|
1255
|
+
var PUBLISHED_TEST_ADMIN_API_TOKEN = "workhub-admin-test-token";
|
|
1256
|
+
var PUBLISHED_TEST_MEMBER_API_TOKEN = "workhub-member-test-token";
|
|
1257
|
+
var PUBLISHED_TEST_SCIM_BEARER_TOKEN = "workhub-scim-test-token";
|
|
1254
1258
|
var MIN_SESSION_SECRET_LENGTH = 32;
|
|
1255
|
-
var
|
|
1256
|
-
|
|
1259
|
+
var PUBLISHED_TEST_TOKENS = new Set([
|
|
1260
|
+
PUBLISHED_TEST_ADMIN_API_TOKEN,
|
|
1261
|
+
PUBLISHED_TEST_MEMBER_API_TOKEN
|
|
1262
|
+
]);
|
|
1263
|
+
var PUBLISHED_TEST_SCIM_TOKENS = new Set([PUBLISHED_TEST_SCIM_BEARER_TOKEN]);
|
|
1257
1264
|
function isEnabled(value, defaultEnabled) {
|
|
1258
1265
|
if (value === undefined) {
|
|
1259
1266
|
return defaultEnabled;
|
|
@@ -1280,36 +1287,19 @@ function assertSessionSecret(env) {
|
|
|
1280
1287
|
throw new Error("Production startup blocked: set SESSION_SECRET when FRONTEND_MODE=server-htmx (32+ characters).");
|
|
1281
1288
|
}
|
|
1282
1289
|
}
|
|
1283
|
-
function
|
|
1284
|
-
const adminToken = env.ADMIN_API_TOKEN ??
|
|
1285
|
-
const memberToken = env.MEMBER_API_TOKEN ??
|
|
1286
|
-
const scimToken = env.SCIM_BEARER_TOKEN ??
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
throw new Error("Production startup blocked: rotate ADMIN_API_TOKEN and MEMBER_API_TOKEN away from default WorkHub test values.");
|
|
1290
|
-
}
|
|
1291
|
-
if (DEFAULT_SCIM_TOKENS.has(scimToken)) {
|
|
1292
|
-
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from default WorkHub test values.");
|
|
1293
|
-
}
|
|
1294
|
-
if (encryptionEnabled && !env.KMS_ENCRYPTION_KEY?.trim()) {
|
|
1295
|
-
throw new Error("Production startup blocked: set KMS_ENCRYPTION_KEY when field encryption is enabled.");
|
|
1296
|
-
}
|
|
1297
|
-
if (!env.SIEM_EXPORT_URL?.trim() && isEnabled(env.FEATURE_SIEM_EXPORT, true)) {
|
|
1298
|
-
console.warn("[secrets] SIEM_EXPORT_URL is not configured; audit logs remain database-only.");
|
|
1290
|
+
function assertPublishedTestTokensRotated(env) {
|
|
1291
|
+
const adminToken = env.ADMIN_API_TOKEN ?? "";
|
|
1292
|
+
const memberToken = env.MEMBER_API_TOKEN ?? "";
|
|
1293
|
+
const scimToken = env.SCIM_BEARER_TOKEN ?? "";
|
|
1294
|
+
if (PUBLISHED_TEST_TOKENS.has(adminToken) || PUBLISHED_TEST_TOKENS.has(memberToken)) {
|
|
1295
|
+
throw new Error("Production startup blocked: rotate ADMIN_API_TOKEN and MEMBER_API_TOKEN away from published test defaults.");
|
|
1299
1296
|
}
|
|
1300
|
-
if (
|
|
1301
|
-
throw new Error("Production startup blocked:
|
|
1302
|
-
}
|
|
1303
|
-
const corsOrigins = (env.CORS_ALLOWED_ORIGINS ?? "*").split(",").map((origin) => origin.trim());
|
|
1304
|
-
if (corsOrigins.includes("*")) {
|
|
1305
|
-
throw new Error("Production startup blocked: set explicit CORS_ALLOWED_ORIGINS instead of wildcard.");
|
|
1306
|
-
}
|
|
1307
|
-
if (isEnabled(env.FEATURE_PUBLIC_READS, true)) {
|
|
1308
|
-
throw new Error("Production startup blocked: set FEATURE_PUBLIC_READS=false for authenticated-only reads.");
|
|
1309
|
-
}
|
|
1310
|
-
if (!env.OAUTH_STATE_SECRET?.trim()) {
|
|
1311
|
-
throw new Error("Production startup blocked: set OAUTH_STATE_SECRET for OAuth CSRF protection.");
|
|
1297
|
+
if (scimToken && PUBLISHED_TEST_SCIM_TOKENS.has(scimToken)) {
|
|
1298
|
+
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from published test defaults.");
|
|
1312
1299
|
}
|
|
1300
|
+
}
|
|
1301
|
+
function assertTokenAuthProductionSecrets(env) {
|
|
1302
|
+
assertPublishedTestTokensRotated(env);
|
|
1313
1303
|
if (!env.TOKEN_HASH_PEPPER?.trim()) {
|
|
1314
1304
|
throw new Error("Production startup blocked: set TOKEN_HASH_PEPPER for API token hashing.");
|
|
1315
1305
|
}
|
|
@@ -1317,11 +1307,11 @@ function assertWorkHubProductionSecrets(env) {
|
|
|
1317
1307
|
throw new Error("Production startup blocked: set API_TOKEN_DEFAULT_EXPIRY_DAYS to enforce token rotation.");
|
|
1318
1308
|
}
|
|
1319
1309
|
}
|
|
1320
|
-
function
|
|
1310
|
+
function assertFeatureProductionSecrets(env) {
|
|
1321
1311
|
if (isEnabled(env.FEATURE_SCIM, false)) {
|
|
1322
|
-
const scimToken = env.SCIM_BEARER_TOKEN ??
|
|
1323
|
-
if (
|
|
1324
|
-
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from
|
|
1312
|
+
const scimToken = env.SCIM_BEARER_TOKEN ?? PUBLISHED_TEST_SCIM_BEARER_TOKEN;
|
|
1313
|
+
if (PUBLISHED_TEST_SCIM_TOKENS.has(scimToken) || !env.SCIM_BEARER_TOKEN?.trim()) {
|
|
1314
|
+
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from published test defaults.");
|
|
1325
1315
|
}
|
|
1326
1316
|
}
|
|
1327
1317
|
if (isEnabled(env.FEATURE_FIELD_ENCRYPTION, false) && !env.KMS_ENCRYPTION_KEY?.trim()) {
|
|
@@ -1353,10 +1343,9 @@ function assertProductionSecrets(env = process.env) {
|
|
|
1353
1343
|
}
|
|
1354
1344
|
assertAuthDevHeadersDisabled(env);
|
|
1355
1345
|
if (isTokenAuthEnabled(env)) {
|
|
1356
|
-
|
|
1357
|
-
} else {
|
|
1358
|
-
assertSiblingProductionSecrets(env);
|
|
1346
|
+
assertTokenAuthProductionSecrets(env);
|
|
1359
1347
|
}
|
|
1348
|
+
assertFeatureProductionSecrets(env);
|
|
1360
1349
|
const frontendMode = (env.FRONTEND_MODE ?? "api").trim();
|
|
1361
1350
|
if (frontendMode === "server-htmx") {
|
|
1362
1351
|
assertSessionSecret(env);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/bootstrap",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.66",
|
|
4
4
|
"description": "Strata application bootstrap — HttpKernel, DI, web session helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
"build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta --external @getstrata/core",
|
|
174
174
|
"build:types": "tsc -p tsconfig.types.json && bun ../../scripts/prune-bootstrap-dist-types.ts",
|
|
175
175
|
"prepublishOnly": "bun run build",
|
|
176
|
-
"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/createRoutes.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 @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/createRoutes --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/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/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/defaultConnection --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/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/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/
|
|
176
|
+
"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/createRoutes.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 @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/createRoutes --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/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/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/defaultConnection --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/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/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/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",
|
|
177
177
|
"build:shims": "true"
|
|
178
178
|
},
|
|
179
179
|
"publishConfig": {
|