@getstrata/bootstrap 1.0.0 → 1.0.2
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 +27 -12
- package/README.md +32 -12
- package/dist/bootstrap/web/server.d.ts +3 -3
- package/dist/entries/secretsGuard.js +39 -7
- package/dist/entries/web/server.js +8 -2
- package/dist/entries/web/session.js +10 -4
- package/dist/index.js +57 -13
- package/package.json +7 -9
- package/dist/_.._/_.._/index.html +0 -174
- package/dist/bootstrap/createRoutes.d.ts +0 -3
- package/dist/bootstrap/dogfoodApp.d.ts +0 -7
- package/dist/bootstrap/preloadModules.d.ts +0 -1
- package/dist/bootstrap/routes.d.ts +0 -3
- package/dist/entries/createRoutes.js +0 -801
- package/dist/index-a3tzxvag.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @getstrata/bootstrap changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.2
|
|
4
|
+
|
|
5
|
+
- Lockstep with `create-strata` 1.0.2. No runtime changes.
|
|
6
|
+
|
|
7
|
+
## 1.0.1
|
|
8
|
+
|
|
9
|
+
- `assertProductionSecrets()` rejects secrets still holding a generated `change-me` placeholder. The shipped `SESSION_SECRET` placeholder was 38 characters, so it passed the length check and booted in production unchanged.
|
|
10
|
+
- Cookie sessions write timestamps through the active dialect, so `CookieSessionStore.create()` works on MySQL.
|
|
11
|
+
- Removed the `createRoutes` subpath. It was in-repo fixture HTTP, documented as not an app API, and it packed a stray `dist/_.._/_.._/index.html` asset and dogfood helpers into the tarball.
|
|
12
|
+
- Removed leftover third-party product token strings from the production blocklist.
|
|
13
|
+
- `assertProductionSecrets()` requires `APP_URL` to be a public `http(s)` origin (localhost rejected, plain http warns). Signed links and redirects are built from it.
|
|
14
|
+
- `createWebServer()` records the socket address (IPv4-mapped addresses normalized) in the request context, so throttles, request logs, and session rows see the real client.
|
|
15
|
+
- `CookieSessionAuthManager.signIn()` fills `ip_address` and `user_agent` from the request context when the caller passes no meta. The `Secure` cookie flag now keys on `APP_ENV=production` (or `NODE_ENV`), matching the rest of the framework; generated apps never set `NODE_ENV`, so production cookies were not marked `Secure`.
|
|
16
|
+
- `engines.bun` is declared.
|
|
17
|
+
|
|
3
18
|
## 1.0.0
|
|
4
19
|
|
|
5
20
|
- First stable release of `@getstrata/bootstrap`.
|
|
@@ -23,7 +38,7 @@
|
|
|
23
38
|
|
|
24
39
|
- Peer `@getstrata/core` `^0.7.0`.
|
|
25
40
|
- Production `SESSION_SECRET` is required whenever views are on (`FRONTEND_MODE=server-htmx` or `hybrid`).
|
|
26
|
-
- Hybrid SPA routes stay under `/app/*`. They do not redirect `/`, so
|
|
41
|
+
- Hybrid SPA routes stay under `/app/*`. They do not redirect `/`, so HTML at `/` keeps the home path.
|
|
27
42
|
- `appEnvSchema` validates `FRONTEND_MODE` with the core pattern, including `hybrid`.
|
|
28
43
|
- `HttpKernel.wrapApi` maps thrown HTTP errors to JSON the same way `wrapWeb` maps them to HTML.
|
|
29
44
|
|
|
@@ -31,7 +46,7 @@
|
|
|
31
46
|
|
|
32
47
|
- Peer `@getstrata/core` `^0.6.0`.
|
|
33
48
|
- Cookie session SQL uses the current SQL dialect for placeholders, `NOW()`, and `NULLS LAST`.
|
|
34
|
-
- Kernel
|
|
49
|
+
- Kernel helpers cover guest, verified-email, and password-confirm gates.
|
|
35
50
|
|
|
36
51
|
## 0.2.68
|
|
37
52
|
|
|
@@ -46,17 +61,17 @@
|
|
|
46
61
|
|
|
47
62
|
## 0.2.66
|
|
48
63
|
|
|
49
|
-
- `assertProductionSecrets()` is feature-gated for every app. API tokens no longer imply
|
|
50
|
-
- **Breaking:** `HttpKernel.wrapWebGuest()` defaults `home` to `/` instead of `/organizations`. Apps with an org home should pass that path (
|
|
64
|
+
- `assertProductionSecrets()` is feature-gated for every app. API tokens no longer imply HiroApp's encryption/CORS/OAuth/public-read checklist. Published test token strings are still denied. HiroApp's extra production profile lives in the app (`src/config/productionSecrets.ts`).
|
|
65
|
+
- **Breaking:** `HttpKernel.wrapWebGuest()` defaults `home` to `/` instead of `/organizations`. Apps with an org home should pass that path (HiroApp already does).
|
|
51
66
|
- `createWebRoutes()` no longer seeds a `/` → `/organizations` redirect. The in-repo app owns `/` via its organization module.
|
|
52
67
|
|
|
53
68
|
## 0.2.65
|
|
54
69
|
|
|
55
|
-
- App listener discovery reads `src/listeners` from `process.cwd()` so a built `@getstrata/bootstrap` bundle still finds
|
|
70
|
+
- App listener discovery reads `src/listeners` from `process.cwd()` so a built `@getstrata/bootstrap` bundle still finds HiroApp registrars (`import.meta.dir` after `build:bootstrap` is the package dist). Listener boot calls each registrar every time (registrars are idempotent per `eventBus`).
|
|
56
71
|
|
|
57
72
|
## 0.2.64
|
|
58
73
|
|
|
59
|
-
- `registerDefaultJobs()` no longer registers
|
|
74
|
+
- `registerDefaultJobs()` no longer registers HiroApp `webhook.dispatch`. Apps that dispatch model webhooks should call `registerWebhookJobs()` (HiroApp's webhook provider and `queue:work` do).
|
|
60
75
|
|
|
61
76
|
## 0.2.63
|
|
62
77
|
|
|
@@ -64,7 +79,7 @@
|
|
|
64
79
|
|
|
65
80
|
## 0.2.62
|
|
66
81
|
|
|
67
|
-
- `HttpKernel.wrapWebPasswordConfirm()` is the
|
|
82
|
+
- `HttpKernel.wrapWebPasswordConfirm()` is the HTML password-confirm gate. Peer `@getstrata/core` `^0.5.75`.
|
|
68
83
|
|
|
69
84
|
## 0.2.61
|
|
70
85
|
|
|
@@ -76,7 +91,7 @@
|
|
|
76
91
|
|
|
77
92
|
## 0.2.59
|
|
78
93
|
|
|
79
|
-
- `HttpKernel.wrapWebGuest()`
|
|
94
|
+
- `HttpKernel.wrapWebGuest()` sends signed-in HTML users to `/organizations` (override the home path). Peer `@getstrata/core` `^0.5.72`.
|
|
80
95
|
|
|
81
96
|
## 0.2.58
|
|
82
97
|
|
|
@@ -92,7 +107,7 @@
|
|
|
92
107
|
|
|
93
108
|
## 0.2.55
|
|
94
109
|
|
|
95
|
-
- HttpKernel and route builders read `isViewsEnabled` / `isSpaEnabled` from `@getstrata/core/runtime/frontendMode` instead of
|
|
110
|
+
- HttpKernel and route builders read `isViewsEnabled` / `isSpaEnabled` from `@getstrata/core/runtime/frontendMode` instead of HiroApp `src/config/frontend`.
|
|
96
111
|
|
|
97
112
|
## 0.2.54
|
|
98
113
|
|
|
@@ -116,7 +131,7 @@
|
|
|
116
131
|
|
|
117
132
|
## 0.2.50
|
|
118
133
|
|
|
119
|
-
- `createCookieSessionAuthManager` / `CookieSessionGuard` turn `CookieSessionStore` into an `AuthGuard` / `AuthManager` for `CORE_AUTH_TOKEN`. Supply a `mapUser` mapper;
|
|
120
|
-
- `checkDatabase()` / `createHealthRoutes()` ping the bound database client, not
|
|
121
|
-
- `assertProductionSecrets()` is feature-gated. A production HTMX app with `SESSION_SECRET` (32+), `AUTH_DEV_HEADERS=false`, and feature flags off does not need
|
|
134
|
+
- `createCookieSessionAuthManager` / `CookieSessionGuard` turn `CookieSessionStore` into an `AuthGuard` / `AuthManager` for `CORE_AUTH_TOKEN`. Supply a `mapUser` mapper; HiroApp abilities are not baked in. Omit `sql` to read the client from `bindDatabaseConnection()` on every call.
|
|
135
|
+
- `checkDatabase()` / `createHealthRoutes()` ping the bound database client, not HiroApp's private connection holder. `/health` stays `{ status: "ok" }` unless `{ pingOnHealth: true }`. Extra JSON fields are optional.
|
|
136
|
+
- `assertProductionSecrets()` is feature-gated. A production HTMX app with `SESSION_SECRET` (32+), `AUTH_DEV_HEADERS=false`, and feature flags off does not need HiroApp API tokens. HiroApp's current production env (rotated tokens, CORS, pepper, expiry) still passes.
|
|
122
137
|
- Re-exports `CORE_ABILITY_CHECKER_TOKEN` and `CORE_AUTH_USER_DIRECTORY_TOKEN`.
|
package/README.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# @getstrata/bootstrap
|
|
2
2
|
|
|
3
|
-
Application bootstrap for Strata apps: HttpKernel, service container, and web
|
|
3
|
+
Application bootstrap for [Strata](https://github.com/EyK-26/strata) apps: HttpKernel, service container, and web session helpers. Requires Bun (tested on 1.4.x).
|
|
4
|
+
|
|
5
|
+
Generate an app rather than wiring this by hand:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bunx create-strata my-app
|
|
9
|
+
```
|
|
4
10
|
|
|
5
11
|
## Install
|
|
6
12
|
|
|
@@ -8,6 +14,16 @@ Application bootstrap for Strata apps: HttpKernel, service container, and web ut
|
|
|
8
14
|
bun add @getstrata/bootstrap @getstrata/core
|
|
9
15
|
```
|
|
10
16
|
|
|
17
|
+
## HttpKernel and providers
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { coreProviders, createAppContext, createHttpKernel } from "@getstrata/bootstrap";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`createAppContext()` does not call `assertProductionSecrets`. Call that yourself when `APP_ENV=production`; it is feature-gated, so an HTML app with API tokens off is not asked for token secrets. It rejects empty secrets, short `SESSION_SECRET` values, wildcard `CORS_ALLOWED_ORIGINS`, `AUTH_DEV_HEADERS=true`, `FEATURE_PUBLIC_READS=true`, and any secret still holding a generated `change-me` placeholder.
|
|
24
|
+
|
|
25
|
+
Build routes with `buildWebModuleRoutes` and `buildModuleRoutes`.
|
|
26
|
+
|
|
11
27
|
## Web utilities
|
|
12
28
|
|
|
13
29
|
```typescript
|
|
@@ -20,22 +36,26 @@ import {
|
|
|
20
36
|
} from "@getstrata/bootstrap";
|
|
21
37
|
```
|
|
22
38
|
|
|
23
|
-
`CookieSessionStore`
|
|
39
|
+
`CookieSessionStore` reads `is_admin` from the user row for `wrapWebGlobalAdmin`. Pass `loadSessionUser` when your `users` table does not match the default `SELECT u.*`.
|
|
24
40
|
|
|
25
|
-
|
|
41
|
+
HTML apps should bind `createCookieSessionAuthManager` from `@getstrata/bootstrap/web/session` rather than the HMAC `SessionGuard`, then use `signIn` / `signOut` or the redirect helpers. Pass `mapUser` to map roles.
|
|
26
42
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
43
|
+
`wrapWeb` applies the web group (CSRF plus flash) and `withErrorHandling`, so a CSRF `ForbiddenError` becomes an HTML 403 when views are on (`FRONTEND_MODE=server-htmx` or `hybrid`). `wrapWebGuest` sends signed-in users to `/` by default; pass a string or `(user) => path` to override. `wrapWebLogin` and `wrapWebRegister` already include the web group plus throttle, so do not wrap them with `wrapWeb` again. The throttle callback should return an HTML form at 429.
|
|
44
|
+
|
|
45
|
+
## SPA routes
|
|
46
|
+
|
|
47
|
+
`createSpaRoutes` and `mergeSpaRoutes` serve `SPA_PREFIX` (default `/app`) as `prefix`, `prefix/`, and `prefix/*`. Hybrid keeps HTML at `/`. Pass `distDirectory` and `wrap` when the app is not the process cwd. Until the SPA is built, the prefix answers 503 telling you to run `bun run frontend:build`; generated apps ship that script.
|
|
30
48
|
|
|
31
|
-
|
|
49
|
+
## Queue
|
|
32
50
|
|
|
33
|
-
|
|
51
|
+
`registerDefaultJobs()` registers `cache.invalidate-tags` and `audit.export` only. Apps that dispatch model webhooks call `registerWebhookJobs()` themselves.
|
|
34
52
|
|
|
35
|
-
|
|
53
|
+
## Not a starter API
|
|
36
54
|
|
|
37
|
-
|
|
55
|
+
`@getstrata/bootstrap/createWebRoutes` and `@getstrata/bootstrap/schedule` assemble in-repo fixture HTTP for framework tests. They are not a general app API. New apps use `buildWebModuleRoutes` and `buildModuleRoutes`.
|
|
38
56
|
|
|
39
|
-
|
|
57
|
+
## Docs
|
|
40
58
|
|
|
41
|
-
|
|
59
|
+
- [Building apps](https://github.com/EyK-26/strata/blob/main/docs/BUILDING-APPS.md)
|
|
60
|
+
- [Production](https://github.com/EyK-26/strata/blob/main/docs/PRODUCTION.md)
|
|
61
|
+
- [Auth choices](https://github.com/EyK-26/strata/blob/main/docs/AUTH.md)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BunRequest } from "bun";
|
|
1
|
+
import type { BunRequest, Server } from "bun";
|
|
2
2
|
import type { AppRouteMap } from "../contracts.ts";
|
|
3
3
|
export interface WebServerOptions {
|
|
4
4
|
port: number;
|
|
@@ -7,7 +7,7 @@ export interface WebServerOptions {
|
|
|
7
7
|
publicDir?: string;
|
|
8
8
|
onRequest?: (request: Request) => Promise<void> | void;
|
|
9
9
|
}
|
|
10
|
-
type BunRouteHandler = (request: BunRequest) => Response | Promise<Response>;
|
|
10
|
+
type BunRouteHandler = (request: BunRequest, server: Server<unknown>) => Response | Promise<Response>;
|
|
11
11
|
declare function convertAppRoutesToBunRoutes(routes: AppRouteMap): Record<string, Record<string, BunRouteHandler>>;
|
|
12
|
-
export declare function createWebServer(options: WebServerOptions):
|
|
12
|
+
export declare function createWebServer(options: WebServerOptions): Server<undefined>;
|
|
13
13
|
export { convertAppRoutesToBunRoutes };
|
|
@@ -7,14 +7,28 @@ var PUBLISHED_TEST_SCIM_BEARER_TOKEN = "strata-scim-test-token";
|
|
|
7
7
|
var MIN_SESSION_SECRET_LENGTH = 32;
|
|
8
8
|
var PUBLISHED_TEST_TOKENS = new Set([
|
|
9
9
|
PUBLISHED_TEST_ADMIN_API_TOKEN,
|
|
10
|
-
PUBLISHED_TEST_MEMBER_API_TOKEN
|
|
11
|
-
"workhub-admin-test-token",
|
|
12
|
-
"workhub-member-test-token"
|
|
13
|
-
]);
|
|
14
|
-
var PUBLISHED_TEST_SCIM_TOKENS = new Set([
|
|
15
|
-
PUBLISHED_TEST_SCIM_BEARER_TOKEN,
|
|
16
|
-
"workhub-scim-test-token"
|
|
10
|
+
PUBLISHED_TEST_MEMBER_API_TOKEN
|
|
17
11
|
]);
|
|
12
|
+
var PUBLISHED_TEST_SCIM_TOKENS = new Set([PUBLISHED_TEST_SCIM_BEARER_TOKEN]);
|
|
13
|
+
var PLACEHOLDER_SECRET_PATTERN = /change-me/i;
|
|
14
|
+
var SECRETS_TO_ROTATE = [
|
|
15
|
+
"SESSION_SECRET",
|
|
16
|
+
"TOKEN_HASH_PEPPER",
|
|
17
|
+
"METRICS_TOKEN",
|
|
18
|
+
"SCIM_BEARER_TOKEN",
|
|
19
|
+
"JWT_SECRET",
|
|
20
|
+
"OAUTH_STATE_SECRET",
|
|
21
|
+
"KMS_ENCRYPTION_KEY",
|
|
22
|
+
"STRIPE_WEBHOOK_SECRET",
|
|
23
|
+
"ADMIN_API_TOKEN",
|
|
24
|
+
"MEMBER_API_TOKEN"
|
|
25
|
+
];
|
|
26
|
+
function assertNoPlaceholderSecrets(env) {
|
|
27
|
+
const unrotated = SECRETS_TO_ROTATE.filter((name) => PLACEHOLDER_SECRET_PATTERN.test(env[name]?.trim() ?? ""));
|
|
28
|
+
if (unrotated.length > 0) {
|
|
29
|
+
throw new Error(`Production startup blocked: replace the generated placeholder values for ${unrotated.join(", ")}.`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
18
32
|
function isEnabled(value, defaultEnabled) {
|
|
19
33
|
if (value === undefined) {
|
|
20
34
|
return defaultEnabled;
|
|
@@ -90,12 +104,30 @@ function assertFeatureProductionSecrets(env) {
|
|
|
90
104
|
console.warn("[secrets] SIEM_EXPORT_URL is not configured; audit logs remain database-only.");
|
|
91
105
|
}
|
|
92
106
|
}
|
|
107
|
+
var LOCAL_HOSTS = new Set(["localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"]);
|
|
108
|
+
function assertPublicAppUrl(env) {
|
|
109
|
+
const raw = env.APP_URL?.trim() ?? "";
|
|
110
|
+
let url = null;
|
|
111
|
+
try {
|
|
112
|
+
url = raw ? new URL(raw) : null;
|
|
113
|
+
} catch {
|
|
114
|
+
url = null;
|
|
115
|
+
}
|
|
116
|
+
if (!url || !/^https?:$/.test(url.protocol) || LOCAL_HOSTS.has(url.hostname)) {
|
|
117
|
+
throw new Error("Production startup blocked: set APP_URL to the public origin of this app (for example https://app.example.com). Signed links and redirects are built from it.");
|
|
118
|
+
}
|
|
119
|
+
if (url.protocol === "http:") {
|
|
120
|
+
console.warn(`[secrets] APP_URL uses http; session cookies are marked Secure in production and will not be sent over ${raw}.`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
93
123
|
function assertProductionSecrets(env = process.env) {
|
|
94
124
|
const appEnv = env.APP_ENV ?? "local";
|
|
95
125
|
if (appEnv !== "production") {
|
|
96
126
|
return;
|
|
97
127
|
}
|
|
128
|
+
assertNoPlaceholderSecrets(env);
|
|
98
129
|
assertAuthDevHeadersDisabled(env);
|
|
130
|
+
assertPublicAppUrl(env);
|
|
99
131
|
if (isTokenAuthEnabled(env)) {
|
|
100
132
|
assertTokenAuthProductionSecrets(env);
|
|
101
133
|
}
|
|
@@ -2,14 +2,19 @@
|
|
|
2
2
|
// ../../src/bootstrap/web/server.ts
|
|
3
3
|
import { currentRequestMeta, runWithRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
4
4
|
import { notFoundHtmlResponse } from "@getstrata/core/view";
|
|
5
|
+
function socketAddress(server, request) {
|
|
6
|
+
const address = server?.requestIP(request)?.address;
|
|
7
|
+
return address ? address.replace(/^::ffff:/i, "") : null;
|
|
8
|
+
}
|
|
5
9
|
async function missingHtmlResponse() {
|
|
6
10
|
return notFoundHtmlResponse();
|
|
7
11
|
}
|
|
8
12
|
function wrapRouteHandler(handler) {
|
|
9
|
-
return async (request) => {
|
|
13
|
+
return async (request, server) => {
|
|
10
14
|
return await runWithRequestMeta({
|
|
11
15
|
...currentRequestMeta(),
|
|
12
16
|
request,
|
|
17
|
+
ipAddress: socketAddress(server, request),
|
|
13
18
|
userAgent: request.headers.get("user-agent")
|
|
14
19
|
}, async () => {
|
|
15
20
|
const response = await handler(request);
|
|
@@ -45,10 +50,11 @@ function createWebServer(options) {
|
|
|
45
50
|
return Bun.serve({
|
|
46
51
|
port: options.port,
|
|
47
52
|
...bunRoutes ? { routes: bunRoutes } : {},
|
|
48
|
-
async fetch(request) {
|
|
53
|
+
async fetch(request, server) {
|
|
49
54
|
return await runWithRequestMeta({
|
|
50
55
|
...currentRequestMeta(),
|
|
51
56
|
request,
|
|
57
|
+
ipAddress: socketAddress(server, request),
|
|
52
58
|
userAgent: request.headers.get("user-agent")
|
|
53
59
|
}, async () => {
|
|
54
60
|
await options.onRequest?.(request);
|
|
@@ -4,8 +4,10 @@ import { createHmac, randomBytes } from "crypto";
|
|
|
4
4
|
import { AuthManager } from "@getstrata/core/auth/guard";
|
|
5
5
|
import { getBoundDatabaseConnection } from "@getstrata/core/database/boundConnection";
|
|
6
6
|
import { getDefaultDatabasePool } from "@getstrata/core/database/defaultConnection";
|
|
7
|
-
import { currentSqlDialect } from "@getstrata/core/database/dialect";
|
|
7
|
+
import { currentSqlDialect, sqlTimestamp } from "@getstrata/core/database/dialect";
|
|
8
8
|
import { readRequestCookie } from "@getstrata/core/http/cookies";
|
|
9
|
+
import { currentRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
10
|
+
import { isProductionEnv } from "@getstrata/core/runtime/appEnv";
|
|
9
11
|
import { timingSafeCompareString } from "@getstrata/core/security/timingSafeCompare";
|
|
10
12
|
function sqlPlaceholder(index) {
|
|
11
13
|
return currentSqlDialect().placeholder(index);
|
|
@@ -108,7 +110,7 @@ class CookieSessionStore {
|
|
|
108
110
|
return sessionId;
|
|
109
111
|
}
|
|
110
112
|
withSecureFlag(header) {
|
|
111
|
-
if (
|
|
113
|
+
if (!isProductionEnv()) {
|
|
112
114
|
return header;
|
|
113
115
|
}
|
|
114
116
|
return header.includes("Secure") ? header : `${header}; Secure`;
|
|
@@ -120,7 +122,7 @@ class CookieSessionStore {
|
|
|
120
122
|
const id = randomBytes(32).toString("hex");
|
|
121
123
|
const expires = new Date(Date.now() + this.maxAgeSeconds * 1000);
|
|
122
124
|
await this.sql().unsafe(`INSERT INTO sessions (id, user_id, expires_at, user_agent, ip_address, last_active_at)
|
|
123
|
-
VALUES (${sqlPlaceholder(1)}, ${sqlPlaceholder(2)}, ${sqlPlaceholder(3)}, ${sqlPlaceholder(4)}, ${sqlPlaceholder(5)}, ${sqlNow()})`, [id, user.id, expires
|
|
125
|
+
VALUES (${sqlPlaceholder(1)}, ${sqlPlaceholder(2)}, ${sqlPlaceholder(3)}, ${sqlPlaceholder(4)}, ${sqlPlaceholder(5)}, ${sqlNow()})`, [id, user.id, sqlTimestamp(expires), meta.userAgent ?? null, meta.ipAddress ?? null]);
|
|
124
126
|
return id;
|
|
125
127
|
}
|
|
126
128
|
async destroy(sessionId) {
|
|
@@ -176,7 +178,11 @@ class CookieSessionAuthManager extends AuthManager {
|
|
|
176
178
|
this.registerGuard("session", guard);
|
|
177
179
|
}
|
|
178
180
|
async signIn(user, meta = {}) {
|
|
179
|
-
const
|
|
181
|
+
const current = currentRequestMeta();
|
|
182
|
+
const sessionId = await this.store.create(user, {
|
|
183
|
+
userAgent: meta.userAgent ?? current.userAgent ?? null,
|
|
184
|
+
ipAddress: meta.ipAddress ?? current.ipAddress ?? null
|
|
185
|
+
});
|
|
180
186
|
return { sessionId, setCookie: this.store.cookieHeader(user, sessionId) };
|
|
181
187
|
}
|
|
182
188
|
async signOut(request) {
|
package/dist/index.js
CHANGED
|
@@ -1146,14 +1146,28 @@ var PUBLISHED_TEST_SCIM_BEARER_TOKEN = "strata-scim-test-token";
|
|
|
1146
1146
|
var MIN_SESSION_SECRET_LENGTH = 32;
|
|
1147
1147
|
var PUBLISHED_TEST_TOKENS = new Set([
|
|
1148
1148
|
PUBLISHED_TEST_ADMIN_API_TOKEN,
|
|
1149
|
-
PUBLISHED_TEST_MEMBER_API_TOKEN
|
|
1150
|
-
"workhub-admin-test-token",
|
|
1151
|
-
"workhub-member-test-token"
|
|
1152
|
-
]);
|
|
1153
|
-
var PUBLISHED_TEST_SCIM_TOKENS = new Set([
|
|
1154
|
-
PUBLISHED_TEST_SCIM_BEARER_TOKEN,
|
|
1155
|
-
"workhub-scim-test-token"
|
|
1149
|
+
PUBLISHED_TEST_MEMBER_API_TOKEN
|
|
1156
1150
|
]);
|
|
1151
|
+
var PUBLISHED_TEST_SCIM_TOKENS = new Set([PUBLISHED_TEST_SCIM_BEARER_TOKEN]);
|
|
1152
|
+
var PLACEHOLDER_SECRET_PATTERN = /change-me/i;
|
|
1153
|
+
var SECRETS_TO_ROTATE = [
|
|
1154
|
+
"SESSION_SECRET",
|
|
1155
|
+
"TOKEN_HASH_PEPPER",
|
|
1156
|
+
"METRICS_TOKEN",
|
|
1157
|
+
"SCIM_BEARER_TOKEN",
|
|
1158
|
+
"JWT_SECRET",
|
|
1159
|
+
"OAUTH_STATE_SECRET",
|
|
1160
|
+
"KMS_ENCRYPTION_KEY",
|
|
1161
|
+
"STRIPE_WEBHOOK_SECRET",
|
|
1162
|
+
"ADMIN_API_TOKEN",
|
|
1163
|
+
"MEMBER_API_TOKEN"
|
|
1164
|
+
];
|
|
1165
|
+
function assertNoPlaceholderSecrets(env) {
|
|
1166
|
+
const unrotated = SECRETS_TO_ROTATE.filter((name) => PLACEHOLDER_SECRET_PATTERN.test(env[name]?.trim() ?? ""));
|
|
1167
|
+
if (unrotated.length > 0) {
|
|
1168
|
+
throw new Error(`Production startup blocked: replace the generated placeholder values for ${unrotated.join(", ")}.`);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1157
1171
|
function isEnabled(value, defaultEnabled) {
|
|
1158
1172
|
if (value === undefined) {
|
|
1159
1173
|
return defaultEnabled;
|
|
@@ -1229,12 +1243,30 @@ function assertFeatureProductionSecrets(env) {
|
|
|
1229
1243
|
console.warn("[secrets] SIEM_EXPORT_URL is not configured; audit logs remain database-only.");
|
|
1230
1244
|
}
|
|
1231
1245
|
}
|
|
1246
|
+
var LOCAL_HOSTS = new Set(["localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"]);
|
|
1247
|
+
function assertPublicAppUrl(env) {
|
|
1248
|
+
const raw = env.APP_URL?.trim() ?? "";
|
|
1249
|
+
let url = null;
|
|
1250
|
+
try {
|
|
1251
|
+
url = raw ? new URL(raw) : null;
|
|
1252
|
+
} catch {
|
|
1253
|
+
url = null;
|
|
1254
|
+
}
|
|
1255
|
+
if (!url || !/^https?:$/.test(url.protocol) || LOCAL_HOSTS.has(url.hostname)) {
|
|
1256
|
+
throw new Error("Production startup blocked: set APP_URL to the public origin of this app (for example https://app.example.com). Signed links and redirects are built from it.");
|
|
1257
|
+
}
|
|
1258
|
+
if (url.protocol === "http:") {
|
|
1259
|
+
console.warn(`[secrets] APP_URL uses http; session cookies are marked Secure in production and will not be sent over ${raw}.`);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1232
1262
|
function assertProductionSecrets(env = process.env) {
|
|
1233
1263
|
const appEnv = env.APP_ENV ?? "local";
|
|
1234
1264
|
if (appEnv !== "production") {
|
|
1235
1265
|
return;
|
|
1236
1266
|
}
|
|
1267
|
+
assertNoPlaceholderSecrets(env);
|
|
1237
1268
|
assertAuthDevHeadersDisabled(env);
|
|
1269
|
+
assertPublicAppUrl(env);
|
|
1238
1270
|
if (isTokenAuthEnabled(env)) {
|
|
1239
1271
|
assertTokenAuthProductionSecrets(env);
|
|
1240
1272
|
}
|
|
@@ -1324,14 +1356,19 @@ function createRouteKernel(dependencies) {
|
|
|
1324
1356
|
// ../../src/bootstrap/web/server.ts
|
|
1325
1357
|
import { currentRequestMeta as currentRequestMeta2, runWithRequestMeta } from "@getstrata/core/http/requestMetaContext";
|
|
1326
1358
|
import { notFoundHtmlResponse as notFoundHtmlResponse2 } from "@getstrata/core/view";
|
|
1359
|
+
function socketAddress(server, request) {
|
|
1360
|
+
const address = server?.requestIP(request)?.address;
|
|
1361
|
+
return address ? address.replace(/^::ffff:/i, "") : null;
|
|
1362
|
+
}
|
|
1327
1363
|
async function missingHtmlResponse() {
|
|
1328
1364
|
return notFoundHtmlResponse2();
|
|
1329
1365
|
}
|
|
1330
1366
|
function wrapRouteHandler(handler) {
|
|
1331
|
-
return async (request) => {
|
|
1367
|
+
return async (request, server) => {
|
|
1332
1368
|
return await runWithRequestMeta({
|
|
1333
1369
|
...currentRequestMeta2(),
|
|
1334
1370
|
request,
|
|
1371
|
+
ipAddress: socketAddress(server, request),
|
|
1335
1372
|
userAgent: request.headers.get("user-agent")
|
|
1336
1373
|
}, async () => {
|
|
1337
1374
|
const response = await handler(request);
|
|
@@ -1367,10 +1404,11 @@ function createWebServer(options) {
|
|
|
1367
1404
|
return Bun.serve({
|
|
1368
1405
|
port: options.port,
|
|
1369
1406
|
...bunRoutes ? { routes: bunRoutes } : {},
|
|
1370
|
-
async fetch(request) {
|
|
1407
|
+
async fetch(request, server) {
|
|
1371
1408
|
return await runWithRequestMeta({
|
|
1372
1409
|
...currentRequestMeta2(),
|
|
1373
1410
|
request,
|
|
1411
|
+
ipAddress: socketAddress(server, request),
|
|
1374
1412
|
userAgent: request.headers.get("user-agent")
|
|
1375
1413
|
}, async () => {
|
|
1376
1414
|
await options.onRequest?.(request);
|
|
@@ -1395,8 +1433,10 @@ import { createHmac, randomBytes } from "crypto";
|
|
|
1395
1433
|
import { AuthManager as AuthManager2 } from "@getstrata/core/auth/guard";
|
|
1396
1434
|
import { getBoundDatabaseConnection as getBoundDatabaseConnection2 } from "@getstrata/core/database/boundConnection";
|
|
1397
1435
|
import { getDefaultDatabasePool as getDefaultDatabasePool2 } from "@getstrata/core/database/defaultConnection";
|
|
1398
|
-
import { currentSqlDialect } from "@getstrata/core/database/dialect";
|
|
1436
|
+
import { currentSqlDialect, sqlTimestamp } from "@getstrata/core/database/dialect";
|
|
1399
1437
|
import { readRequestCookie } from "@getstrata/core/http/cookies";
|
|
1438
|
+
import { currentRequestMeta as currentRequestMeta3 } from "@getstrata/core/http/requestMetaContext";
|
|
1439
|
+
import { isProductionEnv } from "@getstrata/core/runtime/appEnv";
|
|
1400
1440
|
import { timingSafeCompareString } from "@getstrata/core/security/timingSafeCompare";
|
|
1401
1441
|
function sqlPlaceholder(index) {
|
|
1402
1442
|
return currentSqlDialect().placeholder(index);
|
|
@@ -1499,7 +1539,7 @@ class CookieSessionStore {
|
|
|
1499
1539
|
return sessionId;
|
|
1500
1540
|
}
|
|
1501
1541
|
withSecureFlag(header) {
|
|
1502
|
-
if (
|
|
1542
|
+
if (!isProductionEnv()) {
|
|
1503
1543
|
return header;
|
|
1504
1544
|
}
|
|
1505
1545
|
return header.includes("Secure") ? header : `${header}; Secure`;
|
|
@@ -1511,7 +1551,7 @@ class CookieSessionStore {
|
|
|
1511
1551
|
const id = randomBytes(32).toString("hex");
|
|
1512
1552
|
const expires = new Date(Date.now() + this.maxAgeSeconds * 1000);
|
|
1513
1553
|
await this.sql().unsafe(`INSERT INTO sessions (id, user_id, expires_at, user_agent, ip_address, last_active_at)
|
|
1514
|
-
VALUES (${sqlPlaceholder(1)}, ${sqlPlaceholder(2)}, ${sqlPlaceholder(3)}, ${sqlPlaceholder(4)}, ${sqlPlaceholder(5)}, ${sqlNow()})`, [id, user.id, expires
|
|
1554
|
+
VALUES (${sqlPlaceholder(1)}, ${sqlPlaceholder(2)}, ${sqlPlaceholder(3)}, ${sqlPlaceholder(4)}, ${sqlPlaceholder(5)}, ${sqlNow()})`, [id, user.id, sqlTimestamp(expires), meta.userAgent ?? null, meta.ipAddress ?? null]);
|
|
1515
1555
|
return id;
|
|
1516
1556
|
}
|
|
1517
1557
|
async destroy(sessionId) {
|
|
@@ -1567,7 +1607,11 @@ class CookieSessionAuthManager extends AuthManager2 {
|
|
|
1567
1607
|
this.registerGuard("session", guard);
|
|
1568
1608
|
}
|
|
1569
1609
|
async signIn(user, meta = {}) {
|
|
1570
|
-
const
|
|
1610
|
+
const current = currentRequestMeta3();
|
|
1611
|
+
const sessionId = await this.store.create(user, {
|
|
1612
|
+
userAgent: meta.userAgent ?? current.userAgent ?? null,
|
|
1613
|
+
ipAddress: meta.ipAddress ?? current.ipAddress ?? null
|
|
1614
|
+
});
|
|
1571
1615
|
return { sessionId, setCookie: this.store.cookieHeader(user, sessionId) };
|
|
1572
1616
|
}
|
|
1573
1617
|
async signOut(request) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/bootstrap",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Strata application bootstrap: HttpKernel, DI, web session helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,11 +55,6 @@
|
|
|
55
55
|
"import": "./dist/entries/createWebRoutes.js",
|
|
56
56
|
"default": "./dist/entries/createWebRoutes.js"
|
|
57
57
|
},
|
|
58
|
-
"./createRoutes": {
|
|
59
|
-
"types": "./dist/bootstrap/createRoutes.d.ts",
|
|
60
|
-
"import": "./dist/entries/createRoutes.js",
|
|
61
|
-
"default": "./dist/entries/createRoutes.js"
|
|
62
|
-
},
|
|
63
58
|
"./createSpaRoutes": {
|
|
64
59
|
"types": "./dist/bootstrap/createSpaRoutes.d.ts",
|
|
65
60
|
"import": "./dist/entries/createSpaRoutes.js",
|
|
@@ -169,18 +164,21 @@
|
|
|
169
164
|
"CHANGELOG.md"
|
|
170
165
|
],
|
|
171
166
|
"scripts": {
|
|
172
|
-
"build": "bun run build:bundle && bun run build:shims && bun run build:subpaths && bun run build:types",
|
|
167
|
+
"build": "rm -rf dist && bun run build:bundle && bun run build:shims && bun run build:subpaths && bun run build:types",
|
|
173
168
|
"build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta --external mysql2 --external @getstrata/core",
|
|
174
169
|
"build:types": "tsc -p tsconfig.types.json && bun ../../scripts/prune-bootstrap-dist-types.ts",
|
|
175
170
|
"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 mysql2 --external @getstrata/core --external @getstrata/bootstrap --external @getstrata/bootstrap/applicationRegistry --external @getstrata/bootstrap/buildModuleRoutes --external @getstrata/bootstrap/buildWebModuleRoutes --external @getstrata/bootstrap/cache/modelCacheTags --external @getstrata/bootstrap/config --external @getstrata/bootstrap/context --external @getstrata/bootstrap/contracts --external @getstrata/bootstrap/createWebRoutes --external @getstrata/bootstrap/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/jwt --external @getstrata/core/auth/jwtGuard --external @getstrata/core/auth/basicAuthGuard --external @getstrata/core/auth/tokenAbilityChecker --external @getstrata/core/auth/membershipContext --external @getstrata/core/auth/membershipMiddleware --external @getstrata/core/auth/membershipScope --external @getstrata/core/auth/membershipService --external @getstrata/core/auth/oauth/oidcProvider --external @getstrata/core/auth/oauth/providers --external @getstrata/core/auth/oauth/samlProvider --external @getstrata/core/auth/oauth/types --external @getstrata/core/auth/password --external @getstrata/core/auth/intendedUrlCookie --external @getstrata/core/auth/passwordConfirmCookie --external @getstrata/core/auth/policy --external @getstrata/core/auth/scimAuthMiddleware --external @getstrata/core/auth/sessionCookie --external @getstrata/core/auth/sessionGuard --external @getstrata/core/auth/tokenHash --external @getstrata/core/audit/exportAuditLogs --external @getstrata/core/audit/siemFormatter --external @getstrata/core/admin/formatValue --external @getstrata/core/admin/registry --external @getstrata/core/admin/types --external @getstrata/core/cache/tags --external @getstrata/core/cache/createCacheStore --external @getstrata/core/cache/repository --external @getstrata/core/cache/simpleCache --external @getstrata/core/cache/simpleCacheStore --external @getstrata/core/config/envSchema --external @getstrata/core/contracts/serviceTokens --external @getstrata/core/contracts/container --external @getstrata/core/contracts/di --external @getstrata/core/crypto/fieldEncryption --external @getstrata/core/crypto/mfaSecret --external @getstrata/core/database --external @getstrata/core/database/baseRepository --external @getstrata/core/database/bindConnection --external @getstrata/core/database/boundConnection --external @getstrata/core/database/bunSql --external @getstrata/core/database/connection --external @getstrata/core/database/connectionContext --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/dialect --external @getstrata/core/database/mysqlConnection --external @getstrata/core/database/namedConnections --external @getstrata/core/database/errors --external @getstrata/core/database/factory --external @getstrata/core/database/migrations --external @getstrata/core/database/migrations/types --external @getstrata/core/database/model --external @getstrata/core/database/query --external @getstrata/core/database/relationships --external @getstrata/core/database/repositoryConnection --external @getstrata/core/database/repositoryQuery --external @getstrata/core/database/seeders --external @getstrata/core/database/seeders/types --external @getstrata/core/database/schema --external @getstrata/core/database/sqliteConnection --external @getstrata/core/database/table --external @getstrata/core/database/transaction --external @getstrata/core/database/types --external @getstrata/core/database/whereBuilder --external @getstrata/core/errors/http --external @getstrata/core/events --external @getstrata/core/facades --external @getstrata/core/http --external @getstrata/core/http/authMiddleware --external @getstrata/core/http/authorizeMiddleware --external @getstrata/core/http/bodySizeLimitMiddleware --external @getstrata/core/http/clientIp --external @getstrata/core/http/cookies --external @getstrata/core/http/contentNegotiation --external @getstrata/core/http/contentSecurityPolicy --external @getstrata/core/http/conditionalResponse --external @getstrata/core/http/corsMiddleware --external @getstrata/core/http/csrfMiddleware --external @getstrata/core/http/csrfProtection --external @getstrata/core/http/csrfToken --external @getstrata/core/http/etag --external @getstrata/core/http/flashSession --external @getstrata/core/http/flashMiddleware --external @getstrata/core/http/formRequest --external @getstrata/core/http/middleware --external @getstrata/core/http/metricsMiddleware --external @getstrata/core/http/loginThrottleMiddleware --external @getstrata/core/http/memoryThrottleMiddleware --external @getstrata/core/http/pagination --external @getstrata/core/http/parseFormBody --external @getstrata/core/http/parseMultipartUpload --external @getstrata/core/http/requireAbilityMiddleware --external @getstrata/core/http/requireAuthMiddleware --external @getstrata/core/http/requireGlobalAdminMiddleware --external @getstrata/core/http/requireWebAuthMiddleware --external @getstrata/core/http/requireVerifiedMiddleware --external @getstrata/core/http/requirePasswordConfirmMiddleware --external @getstrata/core/http/resources --external @getstrata/core/http/response --external @getstrata/core/http/route --external @getstrata/core/http/routeMiddleware --external @getstrata/core/http/routeModelBinding --external @getstrata/core/http/safeInternalPath --external @getstrata/core/http/signedUrl --external @getstrata/core/http/statelessAuth --external @getstrata/core/http/scimThrottleMiddleware --external @getstrata/core/http/securityHeadersMiddleware --external @getstrata/core/http/securedRouteModelBinding --external @getstrata/core/http/requestMetaContext --external @getstrata/core/http/webErrorResponse --external @getstrata/core/http/webFormRequest --external @getstrata/core/http/throttleMiddleware --external @getstrata/core/http/validation --external @getstrata/core/jobs/exportAuditLogsJob --external @getstrata/core/jobs/invalidateCacheTagsJob --external @getstrata/core/lifecycle/gracefulShutdown --external @getstrata/core/logging/logger --external @getstrata/core/logging/requestLoggingMiddleware --external @getstrata/core/mail/mailer --external @getstrata/core/mail/markdownMail --external @getstrata/core/mail/markdownMailable --external @getstrata/core/mail/sanitizeMailHtml --external @getstrata/core/media/imageTransform --external @getstrata/core/metrics/prometheus --external @getstrata/core/notifications --external @getstrata/core/openapi/generator --external @getstrata/core/openapi/registeredRoute --external @getstrata/core/openapi/validate --external @getstrata/core/pagination --external @getstrata/core/queue --external @getstrata/core/queue/createAppQueue --external @getstrata/core/queue/failedJobRepository --external @getstrata/core/queue/failedJobService --external @getstrata/core/queue/jobRegistry --external @getstrata/core/queue/jobRunner --external @getstrata/core/queue/queueMetrics --external @getstrata/core/queue/publicQueue --external @getstrata/core/queue/redisQueue --external @getstrata/core/queue/types --external @getstrata/core/runtime/appKeyPrefix --external @getstrata/core/runtime/frontendMode --external @getstrata/core/runtime/applicationRegistry --external @getstrata/core/runtime/asyncContextStore --external @getstrata/core/scheduler/schedule --external @getstrata/core/scheduler/osCron --external @getstrata/core/security/oauthState --external @getstrata/core/security/publicReads --external @getstrata/core/security/recoveryCodes --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safeUrl --external @getstrata/core/security/scimTenantTokens --external @getstrata/core/security/securityEvents --external @getstrata/core/security/stripeWebhook --external @getstrata/core/security/timingSafeCompare --external @getstrata/core/security/tokenExpiry --external @getstrata/core/security/totp --external @getstrata/core/storage/storage --external @getstrata/core/tenant/tenancyConfig --external @getstrata/core/tenant/tenantContext --external @getstrata/core/tenant/tenantDatabaseScope --external @getstrata/core/tenant/databaseTenantContext --external @getstrata/core/tenant/tenantMiddleware --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
|
|
171
|
+
"build:subpaths": "bun build entries/applicationRegistry.ts entries/buildModuleRoutes.ts entries/buildWebModuleRoutes.ts entries/cache/modelCacheTags.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/createSpaRoutes.ts entries/dependencies.ts entries/discoverModules.ts entries/health.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/listeners/invalidateCacheOnModelWrite.ts entries/membershipService.ts entries/metricsRoutes.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts entries/routeRegistry.ts entries/schedule.ts entries/secretsGuard.ts entries/web/forms.ts entries/web/routing.ts entries/web/server.ts entries/web/session.ts entries/web/slug.ts --outdir dist --root . --target bun --external bun --external eta --external mysql2 --external @getstrata/core --external @getstrata/bootstrap --external @getstrata/bootstrap/applicationRegistry --external @getstrata/bootstrap/buildModuleRoutes --external @getstrata/bootstrap/buildWebModuleRoutes --external @getstrata/bootstrap/cache/modelCacheTags --external @getstrata/bootstrap/config --external @getstrata/bootstrap/context --external @getstrata/bootstrap/contracts --external @getstrata/bootstrap/createWebRoutes --external @getstrata/bootstrap/createSpaRoutes --external @getstrata/bootstrap/dependencies --external @getstrata/bootstrap/discoverModules --external @getstrata/bootstrap/health --external @getstrata/bootstrap/http/securedRouteModelBinding --external @getstrata/bootstrap/httpKernel --external @getstrata/bootstrap/listeners/invalidateCacheOnModelWrite --external @getstrata/bootstrap/membershipService --external @getstrata/bootstrap/metricsRoutes --external @getstrata/bootstrap/queue/defaultJobs --external @getstrata/bootstrap/providers --external @getstrata/bootstrap/providers/view --external @getstrata/bootstrap/routeRegistry --external @getstrata/bootstrap/schedule --external @getstrata/bootstrap/secretsGuard --external @getstrata/bootstrap/web/forms --external @getstrata/bootstrap/web/routing --external @getstrata/bootstrap/web/server --external @getstrata/bootstrap/web/session --external @getstrata/bootstrap/web/slug --external @getstrata/core/auth/accessControl --external @getstrata/core/auth/abilityChecker --external @getstrata/core/auth/authContext --external @getstrata/core/auth/emailVerification --external @getstrata/core/auth/guard --external @getstrata/core/auth/jwt --external @getstrata/core/auth/jwtGuard --external @getstrata/core/auth/basicAuthGuard --external @getstrata/core/auth/tokenAbilityChecker --external @getstrata/core/auth/membershipContext --external @getstrata/core/auth/membershipMiddleware --external @getstrata/core/auth/membershipScope --external @getstrata/core/auth/membershipService --external @getstrata/core/auth/oauth/oidcProvider --external @getstrata/core/auth/oauth/providers --external @getstrata/core/auth/oauth/samlProvider --external @getstrata/core/auth/oauth/types --external @getstrata/core/auth/password --external @getstrata/core/auth/intendedUrlCookie --external @getstrata/core/auth/passwordConfirmCookie --external @getstrata/core/auth/policy --external @getstrata/core/auth/scimAuthMiddleware --external @getstrata/core/auth/sessionCookie --external @getstrata/core/auth/sessionGuard --external @getstrata/core/auth/tokenHash --external @getstrata/core/audit/exportAuditLogs --external @getstrata/core/audit/siemFormatter --external @getstrata/core/admin/formatValue --external @getstrata/core/admin/registry --external @getstrata/core/admin/types --external @getstrata/core/cache/tags --external @getstrata/core/cache/createCacheStore --external @getstrata/core/cache/repository --external @getstrata/core/cache/simpleCache --external @getstrata/core/cache/simpleCacheStore --external @getstrata/core/config/envSchema --external @getstrata/core/contracts/serviceTokens --external @getstrata/core/contracts/authUserDirectory --external @getstrata/core/contracts/container --external @getstrata/core/contracts/di --external @getstrata/core/crypto/fieldEncryption --external @getstrata/core/crypto/mfaSecret --external @getstrata/core/database --external @getstrata/core/database/baseRepository --external @getstrata/core/database/bindConnection --external @getstrata/core/database/boundConnection --external @getstrata/core/database/bunSql --external @getstrata/core/database/connection --external @getstrata/core/database/connectionContext --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/dialect --external @getstrata/core/database/mysqlConnection --external @getstrata/core/database/namedConnections --external @getstrata/core/database/errors --external @getstrata/core/database/factory --external @getstrata/core/database/migrations --external @getstrata/core/database/migrations/types --external @getstrata/core/database/model --external @getstrata/core/database/query --external @getstrata/core/database/relationships --external @getstrata/core/database/repositoryConnection --external @getstrata/core/database/repositoryQuery --external @getstrata/core/database/seeders --external @getstrata/core/database/seeders/types --external @getstrata/core/database/schema --external @getstrata/core/database/sqliteConnection --external @getstrata/core/database/table --external @getstrata/core/database/transaction --external @getstrata/core/database/types --external @getstrata/core/database/whereBuilder --external @getstrata/core/errors/http --external @getstrata/core/events --external @getstrata/core/facades --external @getstrata/core/http --external @getstrata/core/http/authMiddleware --external @getstrata/core/http/authorizeMiddleware --external @getstrata/core/http/bodySizeLimitMiddleware --external @getstrata/core/http/clientIp --external @getstrata/core/http/cookies --external @getstrata/core/http/contentNegotiation --external @getstrata/core/http/contentSecurityPolicy --external @getstrata/core/http/conditionalResponse --external @getstrata/core/http/corsMiddleware --external @getstrata/core/http/csrfMiddleware --external @getstrata/core/http/csrfProtection --external @getstrata/core/http/csrfToken --external @getstrata/core/http/etag --external @getstrata/core/http/flashSession --external @getstrata/core/http/flashMiddleware --external @getstrata/core/http/formRequest --external @getstrata/core/http/middleware --external @getstrata/core/http/metricsMiddleware --external @getstrata/core/http/loginThrottleMiddleware --external @getstrata/core/http/memoryThrottleMiddleware --external @getstrata/core/http/pagination --external @getstrata/core/http/parseFormBody --external @getstrata/core/http/parseMultipartUpload --external @getstrata/core/http/requireAbilityMiddleware --external @getstrata/core/http/requireAuthMiddleware --external @getstrata/core/http/requireGlobalAdminMiddleware --external @getstrata/core/http/requireWebAuthMiddleware --external @getstrata/core/http/requireVerifiedMiddleware --external @getstrata/core/http/requirePasswordConfirmMiddleware --external @getstrata/core/http/resources --external @getstrata/core/http/response --external @getstrata/core/http/route --external @getstrata/core/http/routeMiddleware --external @getstrata/core/http/routeModelBinding --external @getstrata/core/http/safeInternalPath --external @getstrata/core/http/signedUrl --external @getstrata/core/http/statelessAuth --external @getstrata/core/http/scimThrottleMiddleware --external @getstrata/core/http/securityHeadersMiddleware --external @getstrata/core/http/securedRouteModelBinding --external @getstrata/core/http/requestMetaContext --external @getstrata/core/http/webErrorResponse --external @getstrata/core/http/webFormRequest --external @getstrata/core/http/throttleMiddleware --external @getstrata/core/http/validation --external @getstrata/core/jobs/exportAuditLogsJob --external @getstrata/core/jobs/invalidateCacheTagsJob --external @getstrata/core/lifecycle/gracefulShutdown --external @getstrata/core/logging/logger --external @getstrata/core/logging/requestLoggingMiddleware --external @getstrata/core/mail/mailer --external @getstrata/core/mail/markdownMail --external @getstrata/core/mail/markdownMailable --external @getstrata/core/mail/sanitizeMailHtml --external @getstrata/core/media/imageTransform --external @getstrata/core/metrics/prometheus --external @getstrata/core/notifications --external @getstrata/core/openapi/generator --external @getstrata/core/openapi/registeredRoute --external @getstrata/core/openapi/validate --external @getstrata/core/pagination --external @getstrata/core/queue --external @getstrata/core/queue/createAppQueue --external @getstrata/core/queue/failedJobRepository --external @getstrata/core/queue/failedJobService --external @getstrata/core/queue/jobRegistry --external @getstrata/core/queue/jobRunner --external @getstrata/core/queue/queueMetrics --external @getstrata/core/queue/publicQueue --external @getstrata/core/queue/redisQueue --external @getstrata/core/queue/types --external @getstrata/core/runtime/appEnv --external @getstrata/core/runtime/appKeyPrefix --external @getstrata/core/runtime/frontendMode --external @getstrata/core/runtime/applicationRegistry --external @getstrata/core/runtime/asyncContextStore --external @getstrata/core/scheduler/schedule --external @getstrata/core/scheduler/osCron --external @getstrata/core/security/oauthState --external @getstrata/core/security/publicReads --external @getstrata/core/security/recoveryCodes --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safeUrl --external @getstrata/core/security/scimTenantTokens --external @getstrata/core/security/securityEvents --external @getstrata/core/security/stripeWebhook --external @getstrata/core/security/timingSafeCompare --external @getstrata/core/security/tokenExpiry --external @getstrata/core/security/totp --external @getstrata/core/storage/storage --external @getstrata/core/tenant/tenancyConfig --external @getstrata/core/tenant/tenantContext --external @getstrata/core/tenant/tenantDatabaseScope --external @getstrata/core/tenant/databaseTenantContext --external @getstrata/core/tenant/tenantMiddleware --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
|
|
177
172
|
"build:shims": "true"
|
|
178
173
|
},
|
|
179
174
|
"publishConfig": {
|
|
180
175
|
"access": "public"
|
|
181
176
|
},
|
|
182
177
|
"peerDependencies": {
|
|
183
|
-
"@getstrata/core": "^1.0.
|
|
178
|
+
"@getstrata/core": "^1.0.2",
|
|
184
179
|
"typescript": "^5.9.0"
|
|
180
|
+
},
|
|
181
|
+
"engines": {
|
|
182
|
+
"bun": ">=1.4.0"
|
|
185
183
|
}
|
|
186
184
|
}
|