@cosmicdrift/kumiko-server-runtime 0.383.1 → 0.385.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/boot/wait-for-database.js +0 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/run-prod-app-boot-context.d.ts +4 -2
- package/dist/run-prod-app-boot-context.js +12 -5
- package/dist/run-prod-app-static-files.d.ts +7 -1
- package/dist/run-prod-app-static-files.js +18 -5
- package/dist/run-prod-app.d.ts +21 -22
- package/dist/run-prod-app.js +5 -2
- package/package.json +7 -7
- package/src/changes.json +12 -0
|
@@ -10,10 +10,6 @@ const TRANSIENT_CODES = new Set([
|
|
|
10
10
|
"CONNECTION_CLOSED",
|
|
11
11
|
"CONNECT_TIMEOUT",
|
|
12
12
|
"CONNECTION_DESTROYED",
|
|
13
|
-
"ERR_POSTGRES_CONNECTION_REFUSED", // Bun.SQL
|
|
14
|
-
"ERR_POSTGRES_CONNECTION_CLOSED", // Bun.SQL
|
|
15
|
-
"ERR_POSTGRES_CONNECTION_TIMEOUT", // Bun.SQL
|
|
16
|
-
"ERR_POSTGRES_CONNECTION_FAILED", // Bun.SQL
|
|
17
13
|
]);
|
|
18
14
|
const CONNECTION_EXCEPTION_CLASS = "08";
|
|
19
15
|
export function isTransientConnectionError(error) {
|
package/dist/index.d.ts
CHANGED
|
@@ -22,4 +22,5 @@ export { parseRunMode, requireEnv, runProdApp } from "./run-prod-app.ts";
|
|
|
22
22
|
export type { RunWorkerAppOptions, WorkerAppHandle, WorkerWireDeps, } from "./run-worker-app.ts";
|
|
23
23
|
export { runWorkerApp } from "./run-worker-app.ts";
|
|
24
24
|
export type { CspExtension, CspOption, SecurityHeadersOption } from "./security-headers.ts";
|
|
25
|
+
export { buildDefaultCsp } from "./security-headers.ts";
|
|
25
26
|
export { makeSeedCreateFileRef, type SeedCreateFileRef } from "./seed-dispatcher.ts";
|
package/dist/index.js
CHANGED
|
@@ -16,4 +16,5 @@ export { installFatalErrorHandlers, } from "./fatal-error-handlers.js";
|
|
|
16
16
|
export { runBootstrap } from "./run-bootstrap.js";
|
|
17
17
|
export { parseRunMode, requireEnv, runProdApp } from "./run-prod-app.js";
|
|
18
18
|
export { runWorkerApp } from "./run-worker-app.js";
|
|
19
|
+
export { buildDefaultCsp } from "./security-headers.js";
|
|
19
20
|
export { makeSeedCreateFileRef } from "./seed-dispatcher.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EmailVerificationOptions, type PasswordResetOptions } from "@cosmicdrift/kumiko-bundled-features/auth-email-password";
|
|
1
|
+
import { type AccountUnlockOptions, type EmailVerificationOptions, type PasswordResetOptions } from "@cosmicdrift/kumiko-bundled-features/auth-email-password";
|
|
2
2
|
import { resolveSessionStore } from "@cosmicdrift/kumiko-bundled-features/auth-foundation";
|
|
3
3
|
import { type UnsubscribeLinkConfig } from "@cosmicdrift/kumiko-bundled-features/delivery";
|
|
4
4
|
import type { SseBroker } from "@cosmicdrift/kumiko-framework/api";
|
|
@@ -9,7 +9,7 @@ import { type Logger } from "@cosmicdrift/kumiko-framework/logging";
|
|
|
9
9
|
import type { MasterKeyProvider } from "@cosmicdrift/kumiko-framework/secrets";
|
|
10
10
|
import type { Redis } from "ioredis";
|
|
11
11
|
import { type BootCrypto } from "./boot/boot-crypto.ts";
|
|
12
|
-
import type { AuthMailOptions, EmailVerificationSetup, InviteSetup, PasswordResetSetup, SignupSetup } from "./run-prod-app.ts";
|
|
12
|
+
import type { AccountUnlockSetup, AuthMailOptions, EmailVerificationSetup, InviteSetup, PasswordResetSetup, SignupSetup } from "./run-prod-app.ts";
|
|
13
13
|
export declare function addConfigAccessorFactory<T extends {
|
|
14
14
|
readonly configResolver?: ConfigResolver;
|
|
15
15
|
}>(resolved: T, registry: Registry): T;
|
|
@@ -47,12 +47,14 @@ type AuthMailNormalizable = {
|
|
|
47
47
|
readonly emailVerification?: EmailVerificationSetup;
|
|
48
48
|
readonly signup?: SignupSetup;
|
|
49
49
|
readonly invite?: InviteSetup;
|
|
50
|
+
readonly accountUnlock?: AccountUnlockSetup;
|
|
50
51
|
};
|
|
51
52
|
export declare function resolveAuthMail<T extends AuthMailNormalizable>(auth: T, hmacSecret: string, envSource: Record<string, string | undefined>, mailWiring?: {
|
|
52
53
|
readonly mailConfigured?: boolean;
|
|
53
54
|
}): T & {
|
|
54
55
|
readonly passwordReset?: PasswordResetOptions;
|
|
55
56
|
readonly emailVerification?: EmailVerificationOptions;
|
|
57
|
+
readonly accountUnlock?: AccountUnlockOptions;
|
|
56
58
|
};
|
|
57
59
|
export declare function buildProdSessionAuth(db: DbConnection, registry: Registry, sessionsFeature: FeatureDefinition | undefined, mfaFeature: FeatureDefinition | undefined, patFeature: FeatureDefinition | undefined): Promise<{
|
|
58
60
|
readonly sessionCreator: Awaited<ReturnType<typeof resolveSessionStore>>["creator"];
|
|
@@ -189,11 +189,6 @@ function buildAuthPathAppUrl(baseUrl, path) {
|
|
|
189
189
|
? (locale) => `${baseUrl}${path(locale)}`
|
|
190
190
|
: `${baseUrl}${path}`;
|
|
191
191
|
}
|
|
192
|
-
// accountUnlock (#1266) deliberately does NOT join this convenience block —
|
|
193
|
-
// unlike reset/verify/signup/invite it's only meaningful paired with
|
|
194
|
-
// `accountLockout` (kumiko-framework#1627), and apps set both explicitly
|
|
195
|
-
// alongside each other (same shape as `passwordReset`), so `mail` alone
|
|
196
|
-
// can't silently expose a new public endpoint an app didn't ask for.
|
|
197
192
|
function backfillTokenSecrets(auth, tokenSecret) {
|
|
198
193
|
return {
|
|
199
194
|
...auth,
|
|
@@ -209,6 +204,12 @@ function backfillTokenSecrets(auth, tokenSecret) {
|
|
|
209
204
|
hmacSecret: auth.emailVerification.hmacSecret ?? tokenSecret,
|
|
210
205
|
},
|
|
211
206
|
}),
|
|
207
|
+
...(auth.accountUnlock && {
|
|
208
|
+
accountUnlock: {
|
|
209
|
+
...auth.accountUnlock,
|
|
210
|
+
hmacSecret: auth.accountUnlock.hmacSecret ?? tokenSecret,
|
|
211
|
+
},
|
|
212
|
+
}),
|
|
212
213
|
};
|
|
213
214
|
}
|
|
214
215
|
export function resolveAuthMail(auth, hmacSecret, envSource, mailWiring = {}) {
|
|
@@ -256,6 +257,12 @@ export function resolveAuthMail(auth, hmacSecret, envSource, mailWiring = {}) {
|
|
|
256
257
|
appUrl: buildAuthPathAppUrl(auth.mail.baseUrl, paths.inviteAccept),
|
|
257
258
|
...mailPresentation,
|
|
258
259
|
},
|
|
260
|
+
// The login lockout is always on, so its escape hatch ships with the mail flows.
|
|
261
|
+
accountUnlock: withResolvedSecrets.accountUnlock ?? {
|
|
262
|
+
hmacSecret: tokenSecret,
|
|
263
|
+
appUrl: buildAuthPathAppUrl(auth.mail.baseUrl, paths.unlockAccount),
|
|
264
|
+
...mailPresentation,
|
|
265
|
+
},
|
|
259
266
|
};
|
|
260
267
|
}
|
|
261
268
|
export async function buildProdSessionAuth(db, registry, sessionsFeature, mfaFeature, patFeature) {
|
|
@@ -10,6 +10,10 @@ export declare function readStaticFile(filePath: string): Promise<{
|
|
|
10
10
|
/** Hashes for the default CSP. Only an app that keeps the default CSP and serves a
|
|
11
11
|
* staticDir needs them; a missing or broken file leaves inline scripts blocked, so boot says so. */
|
|
12
12
|
export declare function resolveCspScriptHashes(staticDir: string | undefined, securityHeaders: SecurityHeadersOption | undefined): Promise<readonly string[]>;
|
|
13
|
+
/** Hashes handed to hostDispatch: read from disk only when the default-CSP
|
|
14
|
+
* path above has not already done so. */
|
|
15
|
+
export declare function resolveHostDispatchScriptHashes(staticDir: string, securityHeaders: SecurityHeadersOption | undefined, defaultCspHashes: readonly string[]): Promise<readonly string[]>;
|
|
16
|
+
export declare function readBuildScriptHashes(staticDir: string): Promise<readonly string[]>;
|
|
13
17
|
export declare function serveDiskFile(req: Request, pathname: string, file: {
|
|
14
18
|
readonly bytes: Uint8Array;
|
|
15
19
|
readonly mime: string;
|
|
@@ -28,5 +32,7 @@ export declare function buildStaticFallback(apiHandler: (req: Request, socketAdd
|
|
|
28
32
|
hostDispatchDispatcher?: QueryDispatcher,
|
|
29
33
|
/** trustedProxyHops for the systemQuery request-context builds below —
|
|
30
34
|
* 1:1 with runProdApp's effective value. */
|
|
31
|
-
trustedProxyHops?: number
|
|
35
|
+
trustedProxyHops?: number,
|
|
36
|
+
/** Build inline-script hashes, passed through to hostDispatch's deps. */
|
|
37
|
+
hostDispatchScriptHashes?: readonly string[]): (req: Request, socketAddress?: string) => Promise<Response>;
|
|
32
38
|
export declare function staticCachePolicy(pathname: string): CachePolicy;
|
|
@@ -53,11 +53,22 @@ export async function readStaticFile(filePath) {
|
|
|
53
53
|
/** Hashes for the default CSP. Only an app that keeps the default CSP and serves a
|
|
54
54
|
* staticDir needs them; a missing or broken file leaves inline scripts blocked, so boot says so. */
|
|
55
55
|
export async function resolveCspScriptHashes(staticDir, securityHeaders) {
|
|
56
|
-
if (staticDir === undefined || securityHeaders
|
|
56
|
+
if (staticDir === undefined || !usesDefaultCsp(securityHeaders))
|
|
57
57
|
return [];
|
|
58
|
+
return readBuildScriptHashes(staticDir);
|
|
59
|
+
}
|
|
60
|
+
function usesDefaultCsp(securityHeaders) {
|
|
61
|
+
if (securityHeaders === false)
|
|
62
|
+
return false;
|
|
58
63
|
const csp = securityHeaders?.csp;
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
return csp !== false && typeof csp !== "string";
|
|
65
|
+
}
|
|
66
|
+
/** Hashes handed to hostDispatch: read from disk only when the default-CSP
|
|
67
|
+
* path above has not already done so. */
|
|
68
|
+
export async function resolveHostDispatchScriptHashes(staticDir, securityHeaders, defaultCspHashes) {
|
|
69
|
+
return usesDefaultCsp(securityHeaders) ? defaultCspHashes : readBuildScriptHashes(staticDir);
|
|
70
|
+
}
|
|
71
|
+
export async function readBuildScriptHashes(staticDir) {
|
|
61
72
|
const file = await readStaticFile(join(staticDir, CSP_HASHES_FILE));
|
|
62
73
|
const result = file ? parseCspHashes(new TextDecoder().decode(file.bytes)) : undefined;
|
|
63
74
|
if (result?.kind === "found")
|
|
@@ -133,7 +144,9 @@ export function buildStaticFallback(apiHandler, staticDir, hostDispatch, pageHea
|
|
|
133
144
|
hostDispatchDispatcher,
|
|
134
145
|
/** trustedProxyHops for the systemQuery request-context builds below —
|
|
135
146
|
* 1:1 with runProdApp's effective value. */
|
|
136
|
-
trustedProxyHops = 0
|
|
147
|
+
trustedProxyHops = 0,
|
|
148
|
+
/** Build inline-script hashes, passed through to hostDispatch's deps. */
|
|
149
|
+
hostDispatchScriptHashes = []) {
|
|
137
150
|
const indexHtml = `${staticDir}/index.html`;
|
|
138
151
|
const clientIpResolver = createClientIpResolver(trustedProxyHops, "buildStaticFallback");
|
|
139
152
|
// Reads an HTML file from disk. No schema injection — createKumikoApp
|
|
@@ -231,7 +244,7 @@ trustedProxyHops = 0) {
|
|
|
231
244
|
socketAddress,
|
|
232
245
|
})(type, payload, tenantId);
|
|
233
246
|
};
|
|
234
|
-
const result = await hostDispatch({ host, path: url.pathname, search: url.search }, { systemQuery });
|
|
247
|
+
const result = await hostDispatch({ host, path: url.pathname, search: url.search }, { systemQuery, cspScriptHashes: hostDispatchScriptHashes });
|
|
235
248
|
if (result.kind === "redirect") {
|
|
236
249
|
return new Response(null, {
|
|
237
250
|
status: result.status ?? 302,
|
package/dist/run-prod-app.d.ts
CHANGED
|
@@ -60,10 +60,11 @@ export type SignupSetup = SignupOptions;
|
|
|
60
60
|
export type InviteSetup = InviteOptions;
|
|
61
61
|
/** Wrapper API for the account-unlock flow (#1266). = AccountUnlockOptions
|
|
62
62
|
* (appUrl via delivery, symmetric to PasswordResetSetup). Self-service
|
|
63
|
-
* escape hatch for accountLockout's
|
|
64
|
-
*
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
* escape hatch for accountLockout's failure counter; the lockout is always
|
|
64
|
+
* on, so `auth.mail` mounts this flow by default. */
|
|
65
|
+
export type AccountUnlockSetup = Omit<AccountUnlockOptions, "hmacSecret"> & {
|
|
66
|
+
readonly hmacSecret?: string;
|
|
67
|
+
};
|
|
67
68
|
/** Wrapper API for the account-lockout brute-force guard on the login
|
|
68
69
|
* handler. = AccountLockoutOptions (maxFailedAttempts, lockoutDurationMinutes
|
|
69
70
|
* — no mail/appUrl fields, it doesn't mount any routes). Symmetric to
|
|
@@ -72,7 +73,7 @@ export type AccountUnlockSetup = AccountUnlockOptions;
|
|
|
72
73
|
* lockout it's meant to escape. */
|
|
73
74
|
export type AccountLockoutSetup = AccountLockoutOptions;
|
|
74
75
|
/** Auth-Mail-Convenience-Optionen — shared zwischen runProdApp + runDevApp.
|
|
75
|
-
* Verdrahtet alle
|
|
76
|
+
* Verdrahtet alle 5 Mail-Flows aus einem env-SMTP-Transport + Standard-
|
|
76
77
|
* Templates (siehe `auth.mail` + resolveAuthMail). */
|
|
77
78
|
export type AuthMailOptions = {
|
|
78
79
|
/** App-Basis-URL inkl. Schema (z.B. "https://app.example.com"). */
|
|
@@ -85,7 +86,7 @@ export type AuthMailOptions = {
|
|
|
85
86
|
readonly emailVerificationMode?: "strict" | "off";
|
|
86
87
|
/** Fallback-From-Adresse wenn `SMTP_FROM`-env fehlt (env gewinnt). */
|
|
87
88
|
readonly from?: string;
|
|
88
|
-
/**
|
|
89
|
+
/** Overrides single auth paths (default DEFAULT_AUTH_PATHS). */
|
|
89
90
|
readonly paths?: Partial<AuthPaths>;
|
|
90
91
|
/** Reset/verify token secret, decoupled from JWT_SECRET rotation.
|
|
91
92
|
* Falls back to resolveAuthMail's call-site secret when unset. */
|
|
@@ -99,26 +100,22 @@ export type RunProdAppAuthOptions = {
|
|
|
99
100
|
readonly admin?: SeedAdminOptions;
|
|
100
101
|
/** Optional override of the login error → HTTP status map. */
|
|
101
102
|
readonly loginErrorStatusMap?: Readonly<Record<string, number>>;
|
|
102
|
-
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* hand-gerollte `send*Email`-Callback-Wiring.
|
|
103
|
+
/** Wires all five mail flows (passwordReset, emailVerification, signup,
|
|
104
|
+
* invite, accountUnlock) from `auth.mail.baseUrl` plus the default paths,
|
|
105
|
+
* mailing via delivery (ctx.notify).
|
|
106
106
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* der explizite Block gewinnt über den mail-Default.
|
|
107
|
+
* Without `SMTP_HOST` no flow is wired, since the routes would otherwise
|
|
108
|
+
* answer 500. An explicit `passwordReset`/`signup`/… block wins over the
|
|
109
|
+
* mail default for that flow.
|
|
111
110
|
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* Self-Signup. */
|
|
111
|
+
* Deliberately mounts signup and invite too (self-registration on); apps
|
|
112
|
+
* that want only reset and verify leave `mail` unset and wire those flows
|
|
113
|
+
* explicitly, so there is no implicit self-signup. */
|
|
116
114
|
readonly mail?: AuthMailOptions;
|
|
117
115
|
/** Password-reset flow. When set, /api/auth/request-password-reset +
|
|
118
|
-
* /api/auth/reset-password are mounted as public routes
|
|
119
|
-
* request/confirm
|
|
120
|
-
*
|
|
121
|
-
* Überschreibt den `mail`-Default für genau diesen Flow. */
|
|
116
|
+
* /api/auth/reset-password are mounted as public routes and the
|
|
117
|
+
* request/confirm handlers are registered (otherwise the routes answer
|
|
118
|
+
* 500). Overrides the `mail` default for this flow. */
|
|
122
119
|
readonly passwordReset?: PasswordResetSetup;
|
|
123
120
|
/** Email-verification flow. Symmetric to passwordReset. */
|
|
124
121
|
readonly emailVerification?: EmailVerificationSetup;
|
|
@@ -258,6 +255,8 @@ export type HostDispatchFn = (req: {
|
|
|
258
255
|
* tenant for a subdomain instead of needing its own db handle. */
|
|
259
256
|
deps: {
|
|
260
257
|
readonly systemQuery: PageHeadSystemQuery;
|
|
258
|
+
/** Raw `sha256-…` hashes of the build's inline scripts (csp-hashes.json), for a per-host CSP without 'unsafe-inline'. */
|
|
259
|
+
readonly cspScriptHashes: readonly string[];
|
|
261
260
|
}) => HostDispatchResult | Promise<HostDispatchResult>;
|
|
262
261
|
export type { PageHeadMeta, PageHeadResolver, PageHeadSystemQuery };
|
|
263
262
|
export type RunProdAppOptions = {
|
package/dist/run-prod-app.js
CHANGED
|
@@ -81,7 +81,7 @@ import { resolveRateLimit } from "./rate-limit-defaults.js";
|
|
|
81
81
|
import { resolveAuthPublicOrigin } from "./resolve-auth-public-origin.js";
|
|
82
82
|
import { resolveUnsubscribeWiring } from "./resolve-unsubscribe-wiring.js";
|
|
83
83
|
import { addConfigAccessorFactory, buildBootExtraContext, buildProdSessionAuth, loggerFromExtraContext, resolveAuthMail, wireProdPatAutoRevoke, } from "./run-prod-app-boot-context.js";
|
|
84
|
-
import { buildStaticFallback, resolveCspScriptHashes } from "./run-prod-app-static-files.js";
|
|
84
|
+
import { buildStaticFallback, resolveCspScriptHashes, resolveHostDispatchScriptHashes, } from "./run-prod-app-static-files.js";
|
|
85
85
|
import { withSecurityHeaders } from "./security-headers.js";
|
|
86
86
|
import { makeSeedCreateFileRef, withSeedErrorContext, } from "./seed-dispatcher.js";
|
|
87
87
|
import { assertSessionBootInvariants } from "./session-boot-gate.js";
|
|
@@ -775,10 +775,13 @@ export async function runProdApp(options) {
|
|
|
775
775
|
// owns the rest. Tests use this directly; listen() wraps it in
|
|
776
776
|
// Bun.serve.
|
|
777
777
|
const cspScriptHashes = await resolveCspScriptHashes(options.staticDir, options.securityHeaders);
|
|
778
|
+
const hostDispatchScriptHashes = options.hostDispatch !== undefined && options.staticDir !== undefined
|
|
779
|
+
? await resolveHostDispatchScriptHashes(options.staticDir, options.securityHeaders, cspScriptHashes)
|
|
780
|
+
: [];
|
|
778
781
|
const fetchHandler = withSecurityHeaders(bootOptionWiring.wrapFetch(options.staticDir
|
|
779
782
|
? buildStaticFallback(entrypoint.app.fetch.bind(entrypoint.app), options.staticDir, options.hostDispatch, options.resolvePageHead
|
|
780
783
|
? { resolvePageHead: options.resolvePageHead, dispatcher: entrypoint.dispatcher }
|
|
781
|
-
: undefined, entrypoint.dispatcher, trustedProxyHops ?? 0)
|
|
784
|
+
: undefined, entrypoint.dispatcher, trustedProxyHops ?? 0, hostDispatchScriptHashes)
|
|
782
785
|
: // No staticDir (split-deploy / API-only container) → app.fetch's
|
|
783
786
|
// response goes straight to the client, bypassing buildStaticFallback
|
|
784
787
|
// (and with it tryHonoFirst) entirely. Must strip the router-miss
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-server-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.385.0",
|
|
4
4
|
"description": "Production server-boot runtime for Kumiko apps: connections, schema-drift-gate, seeds, lifecycle, graceful shutdown. Symmetric to kumiko-dev-server's runDevApp, without dev/scaffold tooling.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -88,18 +88,18 @@
|
|
|
88
88
|
}
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
92
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
93
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
94
|
-
"@cosmicdrift/kumiko-renderer-mail-html": "0.
|
|
95
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
91
|
+
"@cosmicdrift/kumiko-bundled-features": "0.385.0",
|
|
92
|
+
"@cosmicdrift/kumiko-framework": "0.385.0",
|
|
93
|
+
"@cosmicdrift/kumiko-renderer": "0.385.0",
|
|
94
|
+
"@cosmicdrift/kumiko-renderer-mail-html": "0.385.0",
|
|
95
|
+
"@cosmicdrift/kumiko-types": "0.385.0",
|
|
96
96
|
"bun-types": "^1.3.13",
|
|
97
97
|
"ioredis": "^5.10.1",
|
|
98
98
|
"temporal-polyfill": "^0.3.2",
|
|
99
99
|
"zod": "^4.4.3"
|
|
100
100
|
},
|
|
101
101
|
"devDependencies": {
|
|
102
|
-
"@cosmicdrift/kumiko-testing": "0.
|
|
102
|
+
"@cosmicdrift/kumiko-testing": "0.385.0"
|
|
103
103
|
},
|
|
104
104
|
"publishConfig": {
|
|
105
105
|
"registry": "https://registry.npmjs.org",
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.385.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "Database wait ignores Bun.SQL error codes",
|
|
6
|
+
"detail": "The transient connection error list no longer contains the ERR_POSTGRES_* codes of the removed Bun.SQL driver; postgres-js never raises them."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.384.0",
|
|
10
|
+
"type": "improvement",
|
|
11
|
+
"title": "hostDispatch pages get the build's CSP script hashes",
|
|
12
|
+
"detail": "The deps passed to hostDispatch now carry cspScriptHashes (the inline-script hashes from csp-hashes.json). Build the page CSP with buildDefaultCsp(deps.cspScriptHashes), now exported, so per-host pages keep script-src without unsafe-inline. runDevApp passes an empty list because dev serves no per-host CSP."
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"version": "0.383.0",
|
|
4
16
|
"type": "improvement",
|