@getstrata/bootstrap 0.2.65 → 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 +6 -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 +2 -2
- package/dist/entries/createRoutes.js +41 -36
- package/dist/entries/createWebRoutes.js +30 -33
- package/dist/entries/dependencies.js +2 -2
- 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 +2 -2
- package/dist/entries/secretsGuard.js +25 -40
- package/dist/entries/web/routing.js +28 -28
- package/dist/index.js +55 -73
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
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
|
+
|
|
3
9
|
## 0.2.65
|
|
4
10
|
|
|
5
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`).
|
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",
|
|
@@ -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",
|
|
@@ -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",
|
|
@@ -316,7 +316,7 @@ function resolveModulesDirectory(options) {
|
|
|
316
316
|
if (state.configuredModulesDir) {
|
|
317
317
|
return state.configuredModulesDir;
|
|
318
318
|
}
|
|
319
|
-
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.");
|
|
320
320
|
}
|
|
321
321
|
async function loadDiscoveredModules(options) {
|
|
322
322
|
const modulesDirectory = resolveModulesDirectory(options);
|
|
@@ -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",
|
|
@@ -1120,10 +1120,7 @@ function registerRoute(method, path, middleware) {
|
|
|
1120
1120
|
}
|
|
1121
1121
|
function createWebRoutes(dependencies) {
|
|
1122
1122
|
const wrappedRoutes = buildWebModuleRoutes(dependencies, {
|
|
1123
|
-
clearRegistry: false
|
|
1124
|
-
seedRoutes: {
|
|
1125
|
-
"/": () => Response.redirect("/organizations", 302)
|
|
1126
|
-
}
|
|
1123
|
+
clearRegistry: false
|
|
1127
1124
|
});
|
|
1128
1125
|
registerRoute("GET", "/", ["global", "web"]);
|
|
1129
1126
|
wrappedRoutes["/assets/*"] = async (request) => {
|
|
@@ -1255,12 +1252,15 @@ import {
|
|
|
1255
1252
|
// ../../src/bootstrap/membershipService.ts
|
|
1256
1253
|
import { resolveMembershipService } from "@getstrata/core/auth/membershipService";
|
|
1257
1254
|
// ../../src/bootstrap/secretsGuard.ts
|
|
1258
|
-
var
|
|
1259
|
-
var
|
|
1260
|
-
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";
|
|
1261
1258
|
var MIN_SESSION_SECRET_LENGTH = 32;
|
|
1262
|
-
var
|
|
1263
|
-
|
|
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]);
|
|
1264
1264
|
function isEnabled(value, defaultEnabled) {
|
|
1265
1265
|
if (value === undefined) {
|
|
1266
1266
|
return defaultEnabled;
|
|
@@ -1287,36 +1287,19 @@ function assertSessionSecret(env) {
|
|
|
1287
1287
|
throw new Error("Production startup blocked: set SESSION_SECRET when FRONTEND_MODE=server-htmx (32+ characters).");
|
|
1288
1288
|
}
|
|
1289
1289
|
}
|
|
1290
|
-
function
|
|
1291
|
-
const adminToken = env.ADMIN_API_TOKEN ??
|
|
1292
|
-
const memberToken = env.MEMBER_API_TOKEN ??
|
|
1293
|
-
const scimToken = env.SCIM_BEARER_TOKEN ??
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
throw new Error("Production startup blocked: rotate ADMIN_API_TOKEN and MEMBER_API_TOKEN away from default WorkHub test values.");
|
|
1297
|
-
}
|
|
1298
|
-
if (DEFAULT_SCIM_TOKENS.has(scimToken)) {
|
|
1299
|
-
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from default WorkHub test values.");
|
|
1300
|
-
}
|
|
1301
|
-
if (encryptionEnabled && !env.KMS_ENCRYPTION_KEY?.trim()) {
|
|
1302
|
-
throw new Error("Production startup blocked: set KMS_ENCRYPTION_KEY when field encryption is enabled.");
|
|
1303
|
-
}
|
|
1304
|
-
if (!env.SIEM_EXPORT_URL?.trim() && isEnabled(env.FEATURE_SIEM_EXPORT, true)) {
|
|
1305
|
-
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.");
|
|
1306
1296
|
}
|
|
1307
|
-
if (
|
|
1308
|
-
throw new Error("Production startup blocked:
|
|
1309
|
-
}
|
|
1310
|
-
const corsOrigins = (env.CORS_ALLOWED_ORIGINS ?? "*").split(",").map((origin) => origin.trim());
|
|
1311
|
-
if (corsOrigins.includes("*")) {
|
|
1312
|
-
throw new Error("Production startup blocked: set explicit CORS_ALLOWED_ORIGINS instead of wildcard.");
|
|
1313
|
-
}
|
|
1314
|
-
if (isEnabled(env.FEATURE_PUBLIC_READS, true)) {
|
|
1315
|
-
throw new Error("Production startup blocked: set FEATURE_PUBLIC_READS=false for authenticated-only reads.");
|
|
1316
|
-
}
|
|
1317
|
-
if (!env.OAUTH_STATE_SECRET?.trim()) {
|
|
1318
|
-
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.");
|
|
1319
1299
|
}
|
|
1300
|
+
}
|
|
1301
|
+
function assertTokenAuthProductionSecrets(env) {
|
|
1302
|
+
assertPublishedTestTokensRotated(env);
|
|
1320
1303
|
if (!env.TOKEN_HASH_PEPPER?.trim()) {
|
|
1321
1304
|
throw new Error("Production startup blocked: set TOKEN_HASH_PEPPER for API token hashing.");
|
|
1322
1305
|
}
|
|
@@ -1324,11 +1307,11 @@ function assertWorkHubProductionSecrets(env) {
|
|
|
1324
1307
|
throw new Error("Production startup blocked: set API_TOKEN_DEFAULT_EXPIRY_DAYS to enforce token rotation.");
|
|
1325
1308
|
}
|
|
1326
1309
|
}
|
|
1327
|
-
function
|
|
1310
|
+
function assertFeatureProductionSecrets(env) {
|
|
1328
1311
|
if (isEnabled(env.FEATURE_SCIM, false)) {
|
|
1329
|
-
const scimToken = env.SCIM_BEARER_TOKEN ??
|
|
1330
|
-
if (
|
|
1331
|
-
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.");
|
|
1332
1315
|
}
|
|
1333
1316
|
}
|
|
1334
1317
|
if (isEnabled(env.FEATURE_FIELD_ENCRYPTION, false) && !env.KMS_ENCRYPTION_KEY?.trim()) {
|
|
@@ -1360,10 +1343,9 @@ function assertProductionSecrets(env = process.env) {
|
|
|
1360
1343
|
}
|
|
1361
1344
|
assertAuthDevHeadersDisabled(env);
|
|
1362
1345
|
if (isTokenAuthEnabled(env)) {
|
|
1363
|
-
|
|
1364
|
-
} else {
|
|
1365
|
-
assertSiblingProductionSecrets(env);
|
|
1346
|
+
assertTokenAuthProductionSecrets(env);
|
|
1366
1347
|
}
|
|
1348
|
+
assertFeatureProductionSecrets(env);
|
|
1367
1349
|
const frontendMode = (env.FRONTEND_MODE ?? "api").trim();
|
|
1368
1350
|
if (frontendMode === "server-htmx") {
|
|
1369
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": {
|