@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 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 calls that from `App.serve()` / `queue:work`. Sibling HTMX apps can call it in production without WorkHub API tokens when feature flags are off — see [SIBLING-HTMX.md](../../docs/SIBLING-HTMX.md).
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. WorkHub’s table is `sessions` (`0031_create_sessions`); its loader is `loadWorkhubSessionUser` (maps `users.role`, decrypts email). WorkHub web login itself stays on HMAC `SessionGuard`.
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 `/organizations` 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 (WorkHub’s `/login` and `/register` do).
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. WorkHub webhook dispatch is `registerWebhookJobs()` in the app webhook provider.
37
+ `registerDefaultJobs()` registers `cache.invalidate-tags` and `audit.export` only. Apps that dispatch model webhooks should call `registerWebhookJobs()` themselves.
38
38
 
39
- These subpaths remain WorkHub-oriented and are not a generic starter API: `@getstrata/bootstrap/createRoutes` (includes SCIM), `@getstrata/bootstrap/schedule`, and `@getstrata/bootstrap/createWebRoutes` (redirects `/` to `/organizations`).
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/rateLimit.ts
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 = "/organizations") {
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. WorkHub and the starter do this from preload.");
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/rateLimit.ts
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 = "/organizations") {
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. WorkHub and the starter do this from preload.");
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. WorkHub and the starter do this from preload.");
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);
@@ -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. WorkHub and the starter do this from preload.");
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() || "WorkHub",
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 = join2(import.meta.dir, "../listeners");
343
+ const listenersDirectory = resolveListenersDirectory();
337
344
  let entries;
338
345
  try {
339
- entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => 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 [index, registerListener] of discoverListeners().entries()) {
416
- registerListenerGroup(`app.listener.${index}`, registerListener);
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() || "WorkHub",
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/rateLimit.ts
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 = "/organizations") {
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. WorkHub and the starter do this from preload.");
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 db2 } from "@getstrata/core/database/repositoryConnection";
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/rateLimit.ts
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 = "/organizations") {
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. WorkHub and the starter do this from preload.");
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. WorkHub and the starter do this from preload.");
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() || "WorkHub",
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 = join2(import.meta.dir, "../listeners");
343
+ const listenersDirectory = resolveListenersDirectory();
337
344
  let entries;
338
345
  try {
339
- entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => 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 [index, registerListener] of discoverListeners().entries()) {
416
- registerListenerGroup(`app.listener.${index}`, registerListener);
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. WorkHub and the starter do this from preload.");
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/rateLimit.ts
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 = "/organizations") {
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. WorkHub and the starter do this from preload.");
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() || "WorkHub",
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 = join(import.meta.dir, "../listeners");
254
+ const listenersDirectory = resolveListenersDirectory();
248
255
  let entries;
249
256
  try {
250
- entries = readdirSync(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => 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. WorkHub and the starter do this from preload.");
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 [index, registerListener] of discoverListeners().entries()) {
406
- registerListenerGroup(`app.listener.${index}`, registerListener);
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 DEFAULT_ADMIN_API_TOKEN = "workhub-admin-test-token";
6
- var DEFAULT_MEMBER_API_TOKEN = "workhub-member-test-token";
7
- var DEFAULT_SCIM_BEARER_TOKEN = "workhub-scim-test-token";
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 DEFAULT_TOKENS = new Set([DEFAULT_ADMIN_API_TOKEN, DEFAULT_MEMBER_API_TOKEN]);
10
- var DEFAULT_SCIM_TOKENS = new Set([DEFAULT_SCIM_BEARER_TOKEN]);
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 assertWorkHubProductionSecrets(env) {
38
- const adminToken = env.ADMIN_API_TOKEN ?? DEFAULT_ADMIN_API_TOKEN;
39
- const memberToken = env.MEMBER_API_TOKEN ?? DEFAULT_MEMBER_API_TOKEN;
40
- const scimToken = env.SCIM_BEARER_TOKEN ?? DEFAULT_SCIM_BEARER_TOKEN;
41
- const encryptionEnabled = isEnabled(env.FEATURE_FIELD_ENCRYPTION, true);
42
- if (DEFAULT_TOKENS.has(adminToken) || DEFAULT_TOKENS.has(memberToken)) {
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
- const corsOrigins = (env.CORS_ALLOWED_ORIGINS ?? "*").split(",").map((origin) => origin.trim());
58
- if (corsOrigins.includes("*")) {
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 assertSiblingProductionSecrets(env) {
60
+ function assertFeatureProductionSecrets(env) {
75
61
  if (isEnabled(env.FEATURE_SCIM, false)) {
76
- const scimToken = env.SCIM_BEARER_TOKEN ?? DEFAULT_SCIM_BEARER_TOKEN;
77
- if (DEFAULT_SCIM_TOKENS.has(scimToken) || !env.SCIM_BEARER_TOKEN?.trim()) {
78
- throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from default WorkHub test values.");
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
- assertWorkHubProductionSecrets(env);
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/rateLimit.ts
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 = "/organizations") {
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/rateLimit.ts
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 = "/organizations") {
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. WorkHub and the starter do this from preload.");
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() || "WorkHub",
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 = join2(import.meta.dir, "../listeners");
748
+ const listenersDirectory = resolveListenersDirectory();
742
749
  let entries;
743
750
  try {
744
- entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => 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 [index, registerListener] of discoverListeners().entries()) {
807
- registerListenerGroup(`app.listener.${index}`, registerListener);
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 DEFAULT_ADMIN_API_TOKEN = "workhub-admin-test-token";
1252
- var DEFAULT_MEMBER_API_TOKEN = "workhub-member-test-token";
1253
- var DEFAULT_SCIM_BEARER_TOKEN = "workhub-scim-test-token";
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 DEFAULT_TOKENS = new Set([DEFAULT_ADMIN_API_TOKEN, DEFAULT_MEMBER_API_TOKEN]);
1256
- var DEFAULT_SCIM_TOKENS = new Set([DEFAULT_SCIM_BEARER_TOKEN]);
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 assertWorkHubProductionSecrets(env) {
1284
- const adminToken = env.ADMIN_API_TOKEN ?? DEFAULT_ADMIN_API_TOKEN;
1285
- const memberToken = env.MEMBER_API_TOKEN ?? DEFAULT_MEMBER_API_TOKEN;
1286
- const scimToken = env.SCIM_BEARER_TOKEN ?? DEFAULT_SCIM_BEARER_TOKEN;
1287
- const encryptionEnabled = isEnabled(env.FEATURE_FIELD_ENCRYPTION, true);
1288
- if (DEFAULT_TOKENS.has(adminToken) || DEFAULT_TOKENS.has(memberToken)) {
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 (isEnabled(env.FEATURE_BILLING, true) && !env.STRIPE_WEBHOOK_SECRET?.trim()) {
1301
- throw new Error("Production startup blocked: set STRIPE_WEBHOOK_SECRET when billing webhooks are enabled.");
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 assertSiblingProductionSecrets(env) {
1310
+ function assertFeatureProductionSecrets(env) {
1321
1311
  if (isEnabled(env.FEATURE_SCIM, false)) {
1322
- const scimToken = env.SCIM_BEARER_TOKEN ?? DEFAULT_SCIM_BEARER_TOKEN;
1323
- if (DEFAULT_SCIM_TOKENS.has(scimToken) || !env.SCIM_BEARER_TOKEN?.trim()) {
1324
- throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from default WorkHub test values.");
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
- assertWorkHubProductionSecrets(env);
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.64",
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/dispatchWebhookJob --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",
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": {