@cosmicdrift/kumiko-server-runtime 0.368.0 → 0.370.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/boot-crypto.js +17 -11
- package/dist/boot/worker-boot-core.d.ts +1 -1
- package/dist/boot-options/billing-option.d.ts +34 -0
- package/dist/boot-options/billing-option.js +35 -0
- package/dist/boot-options/demo-mode.d.ts +51 -0
- package/dist/boot-options/demo-mode.js +64 -0
- package/dist/boot-options/file-storage-option.d.ts +30 -0
- package/dist/boot-options/file-storage-option.js +52 -0
- package/dist/boot-options/kms-mode.d.ts +27 -0
- package/dist/boot-options/kms-mode.js +40 -0
- package/dist/boot-options/mail-option.d.ts +30 -0
- package/dist/boot-options/mail-option.js +44 -0
- package/dist/boot-options/option-env-schema.d.ts +7 -0
- package/dist/boot-options/option-env-schema.js +113 -0
- package/dist/boot-options/process-signals.d.ts +23 -0
- package/dist/boot-options/process-signals.js +58 -0
- package/dist/boot-options/resolve-boot-options.d.ts +44 -0
- package/dist/boot-options/resolve-boot-options.js +88 -0
- package/dist/boot-options/seed-shortcuts.d.ts +49 -0
- package/dist/boot-options/seed-shortcuts.js +92 -0
- package/dist/boot-options/stack-boot-requirements.d.ts +6 -0
- package/dist/boot-options/stack-boot-requirements.js +63 -0
- package/dist/build-prod-bundle.d.ts +4 -0
- package/dist/build-prod-bundle.js +41 -2
- package/dist/csp-hashes.d.ts +15 -0
- package/dist/csp-hashes.js +46 -0
- package/dist/index.d.ts +18 -9
- package/dist/index.js +1 -0
- package/dist/rate-limit-defaults.d.ts +19 -0
- package/dist/rate-limit-defaults.js +13 -0
- package/dist/resolve-unsubscribe-wiring.d.ts +17 -0
- package/dist/resolve-unsubscribe-wiring.js +24 -0
- package/dist/run-bootstrap.d.ts +2 -2
- package/dist/run-prod-app-boot-context.d.ts +5 -3
- package/dist/run-prod-app-boot-context.js +4 -2
- package/dist/run-prod-app-static-files.d.ts +6 -2
- package/dist/run-prod-app-static-files.js +22 -1
- package/dist/run-prod-app.d.ts +77 -32
- package/dist/run-prod-app.js +172 -120
- package/dist/run-worker-app.d.ts +2 -2
- package/dist/security-headers.d.ts +16 -5
- package/dist/security-headers.js +56 -5
- package/package.json +18 -9
- package/src/changes.json +43 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createUnsubscribeRoutes, } from "@cosmicdrift/kumiko-bundled-features/delivery";
|
|
2
|
+
import { publicOriginOf } from "@cosmicdrift/kumiko-framework/api";
|
|
3
|
+
import { APP_BASE_URL_ENV } from "./resolve-auth-public-origin.js";
|
|
4
|
+
export function resolveUnsubscribeWiring(opts) {
|
|
5
|
+
const { unsubscribe } = opts;
|
|
6
|
+
if (unsubscribe === undefined)
|
|
7
|
+
return { unsubscribeLinks: undefined, unsubscribeRoutes: [] };
|
|
8
|
+
const baseUrl = publicOriginOf(opts.publicOrigin ?? opts.mailBaseUrl ?? opts.envSource[APP_BASE_URL_ENV] ?? "");
|
|
9
|
+
if (baseUrl === undefined) {
|
|
10
|
+
opts.warn(`unsubscribe is enabled but no valid public app URL is known (auth.publicOrigin, auth.mail.baseUrl or ${APP_BASE_URL_ENV}), so mails get no unsubscribe link.`);
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
unsubscribeLinks: baseUrl === undefined
|
|
14
|
+
? undefined
|
|
15
|
+
: {
|
|
16
|
+
secret: unsubscribe.secret,
|
|
17
|
+
baseUrl,
|
|
18
|
+
...(unsubscribe.tenantOrigin !== undefined && {
|
|
19
|
+
tenantOrigin: unsubscribe.tenantOrigin,
|
|
20
|
+
}),
|
|
21
|
+
},
|
|
22
|
+
unsubscribeRoutes: createUnsubscribeRoutes({ secret: unsubscribe.secret }),
|
|
23
|
+
};
|
|
24
|
+
}
|
package/dist/run-bootstrap.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type BootstrapPlan, type BootstrapReport } from "@cosmicdrift/kumiko-bundled-features/auth-email-password";
|
|
2
|
-
import { type RunProdAppAuthOptions } from "./run-prod-app.
|
|
3
|
-
import type { RunWorkerAppOptions } from "./run-worker-app.
|
|
2
|
+
import { type RunProdAppAuthOptions } from "./run-prod-app.ts";
|
|
3
|
+
import type { RunWorkerAppOptions } from "./run-worker-app.ts";
|
|
4
4
|
export type RunBootstrapOptions = Omit<RunWorkerAppOptions, "wireComponents" | "includeBundled" | "jobs" | "eventDispatcher" | "metrics"> & BootstrapPlan & {
|
|
5
5
|
/** The same auth block the app passes to runProdApp (`admin` is ignored).
|
|
6
6
|
* Needs a mounted invite flow: `auth.invite`, or `auth.mail` with
|
|
@@ -8,8 +8,8 @@ import { type ConfigResolver, type FeatureDefinition, type Registry } from "@cos
|
|
|
8
8
|
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
|
-
import { type BootCrypto } from "./boot/boot-crypto.
|
|
12
|
-
import type { AuthMailOptions, EmailVerificationSetup, InviteSetup, PasswordResetSetup, SignupSetup } from "./run-prod-app.
|
|
11
|
+
import { type BootCrypto } from "./boot/boot-crypto.ts";
|
|
12
|
+
import type { 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;
|
|
@@ -43,7 +43,9 @@ type AuthMailNormalizable = {
|
|
|
43
43
|
readonly signup?: SignupSetup;
|
|
44
44
|
readonly invite?: InviteSetup;
|
|
45
45
|
};
|
|
46
|
-
export declare function resolveAuthMail<T extends AuthMailNormalizable>(auth: T, hmacSecret: string, envSource: Record<string, string | undefined
|
|
46
|
+
export declare function resolveAuthMail<T extends AuthMailNormalizable>(auth: T, hmacSecret: string, envSource: Record<string, string | undefined>, mailWiring?: {
|
|
47
|
+
readonly mailConfigured?: boolean;
|
|
48
|
+
}): T & {
|
|
47
49
|
readonly passwordReset?: PasswordResetOptions;
|
|
48
50
|
readonly emailVerification?: EmailVerificationOptions;
|
|
49
51
|
};
|
|
@@ -185,7 +185,7 @@ function backfillTokenSecrets(auth, tokenSecret) {
|
|
|
185
185
|
}),
|
|
186
186
|
};
|
|
187
187
|
}
|
|
188
|
-
export function resolveAuthMail(auth, hmacSecret, envSource) {
|
|
188
|
+
export function resolveAuthMail(auth, hmacSecret, envSource, mailWiring = {}) {
|
|
189
189
|
// Runs before the mail/SMTP guards below so an app-supplied block without
|
|
190
190
|
// hmacSecret is backfilled even without a `mail` block; an explicit secret still wins.
|
|
191
191
|
const tokenSecret = auth.mail?.hmacSecret ?? hmacSecret;
|
|
@@ -196,7 +196,9 @@ export function resolveAuthMail(auth, hmacSecret, envSource) {
|
|
|
196
196
|
// blieben sonst 500). Der eigentliche Mail-Versand läuft über delivery
|
|
197
197
|
// (channel-email), nicht über diesen Transport — er ist nur der Detektor
|
|
198
198
|
// "ist Mail konfiguriert?".
|
|
199
|
-
|
|
199
|
+
// An app transport from runProdApp's `mail` option replaces the probe.
|
|
200
|
+
if (mailWiring.mailConfigured !== true &&
|
|
201
|
+
!createSmtpTransportFromEnv(envSource, { fallbackFrom: auth.mail.from ?? "noreply@localhost" })) {
|
|
200
202
|
return withResolvedSecrets;
|
|
201
203
|
}
|
|
202
204
|
const paths = makeAuthPaths(auth.mail.paths);
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { type CachePolicy } from "@cosmicdrift/kumiko-framework/api";
|
|
2
|
-
import { type QueryDispatcher } from "./request-bound-system-query.
|
|
3
|
-
import type { HostDispatchFn, PageHeadResolver } from "./run-prod-app.
|
|
2
|
+
import { type QueryDispatcher } from "./request-bound-system-query.ts";
|
|
3
|
+
import type { HostDispatchFn, PageHeadResolver } from "./run-prod-app.ts";
|
|
4
|
+
import type { SecurityHeadersOption } from "./security-headers.ts";
|
|
4
5
|
export declare function readStaticFile(filePath: string): Promise<{
|
|
5
6
|
readonly bytes: Uint8Array;
|
|
6
7
|
readonly mime: string;
|
|
7
8
|
readonly mtimeMs: number;
|
|
8
9
|
} | undefined>;
|
|
10
|
+
/** Hashes for the default CSP. Only an app that keeps the default CSP and serves a
|
|
11
|
+
* staticDir needs them; a missing or broken file leaves inline scripts blocked, so boot says so. */
|
|
12
|
+
export declare function resolveCspScriptHashes(staticDir: string | undefined, securityHeaders: SecurityHeadersOption | undefined): Promise<readonly string[]>;
|
|
9
13
|
export declare function serveDiskFile(req: Request, pathname: string, file: {
|
|
10
14
|
readonly bytes: Uint8Array;
|
|
11
15
|
readonly mime: string;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { resolve, sep } from "node:path";
|
|
1
|
+
import { join, resolve, sep } from "node:path";
|
|
2
2
|
import { cachedResponse, computeStrongEtag, computeWeakEtag, createClientIpResolver, } from "@cosmicdrift/kumiko-framework/api";
|
|
3
3
|
import { resolveAndInjectPageHead } from "@cosmicdrift/kumiko-headless/apex";
|
|
4
4
|
import { errorCodeOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
5
5
|
import { ASSETS_DIR } from "./build-prod-bundle.js";
|
|
6
6
|
import { BUNDLED_ASSETS_DIST_DIR } from "./bundled-assets.js";
|
|
7
|
+
import { CSP_HASHES_FILE, parseCspHashes } from "./csp-hashes.js";
|
|
7
8
|
import { buildRequestBoundSystemQuery, } from "./request-bound-system-query.js";
|
|
8
9
|
import { stripNoRouteMatchHeader, tryHonoFirst } from "./try-hono-first.js";
|
|
9
10
|
// Static-asset + SPA-fallback serving for runProdApp's HTTP handler. Split
|
|
@@ -48,6 +49,26 @@ export async function readStaticFile(filePath) {
|
|
|
48
49
|
throw err;
|
|
49
50
|
}
|
|
50
51
|
}
|
|
52
|
+
/** Hashes for the default CSP. Only an app that keeps the default CSP and serves a
|
|
53
|
+
* staticDir needs them; a missing or broken file leaves inline scripts blocked, so boot says so. */
|
|
54
|
+
export async function resolveCspScriptHashes(staticDir, securityHeaders) {
|
|
55
|
+
if (staticDir === undefined || securityHeaders === false)
|
|
56
|
+
return [];
|
|
57
|
+
const csp = securityHeaders?.csp;
|
|
58
|
+
if (csp === false || typeof csp === "string")
|
|
59
|
+
return [];
|
|
60
|
+
const file = await readStaticFile(join(staticDir, CSP_HASHES_FILE));
|
|
61
|
+
const result = file ? parseCspHashes(new TextDecoder().decode(file.bytes)) : undefined;
|
|
62
|
+
if (result?.kind === "found")
|
|
63
|
+
return result.scriptSrc;
|
|
64
|
+
const problem = result === undefined
|
|
65
|
+
? `${CSP_HASHES_FILE} not found in ${staticDir} (written by kumiko build)`
|
|
66
|
+
: `${CSP_HASHES_FILE} is invalid: ${result.kind === "invalid" ? result.problem : ""}`;
|
|
67
|
+
// biome-ignore lint/suspicious/noConsole: boot-time warn, no logger configured this early
|
|
68
|
+
console.warn(`[runProdApp] ${problem}; the default CSP carries no inline-script hashes, so inline scripts in the served HTML are blocked. ` +
|
|
69
|
+
"Rebuild with kumiko build, or set securityHeaders.csp.");
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
51
72
|
// Bundled assets are server-side inputs (readBundledAsset), never public URLs.
|
|
52
73
|
// Compared on the resolved path, not the URL prefix: "//kumiko-bundled-assets/x"
|
|
53
74
|
// or a case variant on a case-insensitive disk would slip past a prefix check.
|
package/dist/run-prod-app.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/// <reference types="bun-types" preserve="true" />
|
|
2
2
|
import { type AccountLockoutOptions, type AccountUnlockOptions, type AuthMailLocale, type AuthPaths, type EmailVerificationOptions, type InviteOptions, type PasswordResetOptions, type SignupOptions } from "@cosmicdrift/kumiko-bundled-features/auth-email-password";
|
|
3
3
|
import { type SeedAdminOptions } from "@cosmicdrift/kumiko-bundled-features/auth-email-password/seeding";
|
|
4
|
-
import { type UnsubscribeLinkConfig } from "@cosmicdrift/kumiko-bundled-features/delivery";
|
|
5
4
|
import { type ExtraRouteDefinition, type KumikoServeEnv, type PostAuthLandingResolver, type SseBroker } from "@cosmicdrift/kumiko-framework/api";
|
|
6
5
|
import { type KmsAdapter } from "@cosmicdrift/kumiko-framework/crypto";
|
|
7
6
|
import { type EffectiveFeaturesResolver, type FeatureDefinition, type ValidateBootOptions } from "@cosmicdrift/kumiko-framework/engine";
|
|
@@ -13,12 +12,22 @@ import { type ObservabilityOptions, type ObservabilityProvider } from "@cosmicdr
|
|
|
13
12
|
import type { MasterKeyProvider } from "@cosmicdrift/kumiko-framework/secrets";
|
|
14
13
|
import type { PageHeadMeta, PageHeadResolver, PageHeadSystemQuery } from "@cosmicdrift/kumiko-headless/apex";
|
|
15
14
|
import { Redis } from "ioredis";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
import type { BillingBootOption } from "./boot-options/billing-option.ts";
|
|
16
|
+
import type { DemoModeOption } from "./boot-options/demo-mode.ts";
|
|
17
|
+
import type { FileStorageBootOption } from "./boot-options/file-storage-option.ts";
|
|
18
|
+
import type { KmsMode } from "./boot-options/kms-mode.ts";
|
|
19
|
+
import type { MailBootOption } from "./boot-options/mail-option.ts";
|
|
20
|
+
import { type SignalsOption } from "./boot-options/process-signals.ts";
|
|
21
|
+
import type { ProdSeedsConfig } from "./boot-options/seed-shortcuts.ts";
|
|
22
|
+
import { type SystemWireDeps } from "./extra-routes-deps.ts";
|
|
23
|
+
import { type RateLimitOption } from "./rate-limit-defaults.ts";
|
|
24
|
+
import { type UnsubscribeOption } from "./resolve-unsubscribe-wiring.ts";
|
|
25
|
+
import { type SecurityHeadersOption } from "./security-headers.ts";
|
|
26
|
+
import { type SeedCreateFileRef } from "./seed-dispatcher.ts";
|
|
27
|
+
export { buildBunServeOptions } from "./bun-serve-options.ts";
|
|
28
|
+
export { resolveUnsubscribeWiring, type UnsubscribeOption, } from "./resolve-unsubscribe-wiring.ts";
|
|
29
|
+
export { addConfigAccessorFactory, buildBootExtraContext, loggerFromExtraContext, resolveAuthMail, } from "./run-prod-app-boot-context.ts";
|
|
30
|
+
export { staticCachePolicy } from "./run-prod-app-static-files.ts";
|
|
22
31
|
export declare function requireEnv(name: string, src?: Record<string, string | undefined>, context?: string): string;
|
|
23
32
|
/** Wrapper API for the password-reset flow.
|
|
24
33
|
*
|
|
@@ -257,8 +266,13 @@ export type RunProdAppOptions = {
|
|
|
257
266
|
readonly maxRequestBodySize?: number;
|
|
258
267
|
/** Auth-mode: standard features + routes wired, admin seeded. */
|
|
259
268
|
readonly auth?: RunProdAppAuthOptions;
|
|
260
|
-
/** Custom seed functions, run after the admin seed (when auth-mode).
|
|
261
|
-
|
|
269
|
+
/** Custom seed functions, run after the admin seed (when auth-mode). The
|
|
270
|
+
* object form adds the declarative demo-tenant / demo-admin / sysadmin
|
|
271
|
+
* seeds from the env and takes the functions under `run`; see
|
|
272
|
+
* `ProdSeedsConfig`.
|
|
273
|
+
* @example
|
|
274
|
+
* seeds: { demoTenant: { key: "demo", name: "Demo" }, sysadminFromEnv: true, run: [seedDemoData] } */
|
|
275
|
+
readonly seeds?: readonly ProdSeedFn[] | ProdSeedsConfig;
|
|
262
276
|
/** Pfad zum seeds-Directory für ES-Operations / Seed-Migrations
|
|
263
277
|
* (file-basiert wie drizzle-migrate). Wenn gesetzt + KUMIKO_SKIP_ES_OPS
|
|
264
278
|
* != "1": runProdApp scannt das Verzeichnis nach `<id>.ts` Files,
|
|
@@ -353,6 +367,39 @@ export type RunProdAppOptions = {
|
|
|
353
367
|
* ist eine Begründung für den Audit-Trail (z.B. "kms rollout pending,
|
|
354
368
|
* infra#188"). Ohne Flag und ohne `kms` bricht der Boot ab. */
|
|
355
369
|
readonly allowPlaintextPii?: string;
|
|
370
|
+
/** Short form over `kms` / `blindIndexKey` / `allowPlaintextPii` that wires
|
|
371
|
+
* the subject-key KMS from the env; not combinable with them. Unset keeps
|
|
372
|
+
* today's behavior: no KMS unless `kms` is passed, and the PII boot gate
|
|
373
|
+
* aborts when PII fields exist without one. See `KmsMode`.
|
|
374
|
+
* @example
|
|
375
|
+
* kmsMode: "required" */
|
|
376
|
+
readonly kmsMode?: KmsMode;
|
|
377
|
+
/** App-wide mail transport: mounts `channel-email` and wires the `auth.mail`
|
|
378
|
+
* flows without an `SMTP_HOST` probe. See `MailBootOption`.
|
|
379
|
+
* @example
|
|
380
|
+
* mail: { transport: "smtp-env", from: "Acme <noreply@acme.example>" } */
|
|
381
|
+
readonly mail?: MailBootOption;
|
|
382
|
+
/** File provider for `file-foundation` plus the `FILE_STORAGE_PROVIDER`
|
|
383
|
+
* default. See `FileStorageBootOption`.
|
|
384
|
+
* @example
|
|
385
|
+
* fileStorage: { provider: "auto" } */
|
|
386
|
+
readonly fileStorage?: FileStorageBootOption;
|
|
387
|
+
/** Stripe billing: `subscription-stripe` plus the tier-syncing webhook
|
|
388
|
+
* route. Needs `billing-foundation` and `tier-engine`. See `BillingBootOption`.
|
|
389
|
+
* @example
|
|
390
|
+
* billing: { stripe: { priceToTier: { [env.STRIPE_PRICE_PRO]: "pro" } }, defaultTier: "free" } */
|
|
391
|
+
readonly billing?: BillingBootOption;
|
|
392
|
+
/** Live-demo mode: read-only gate in the fetch chain plus the anonymous
|
|
393
|
+
* `GET /demo-mode` route. See `DemoModeOption`.
|
|
394
|
+
* @example
|
|
395
|
+
* demoMode: { readOnly: env.DEMO_READ_ONLY === "true", notice: { text: { en: "Read-only demo" } } } */
|
|
396
|
+
readonly demoMode?: DemoModeOption;
|
|
397
|
+
/** SIGTERM/SIGINT handling of `listen()`: drains via `stop()` (default
|
|
398
|
+
* timeout 25 s), exits 0, or 1 when the drain fails or times out. `false`
|
|
399
|
+
* leaves the signals to the app.
|
|
400
|
+
* @example
|
|
401
|
+
* signals: { drainTimeoutMs: 10_000 } */
|
|
402
|
+
readonly signals?: SignalsOption;
|
|
356
403
|
/** Deploy topology. Default `true` (single container): this process runs
|
|
357
404
|
* HTTP, both job lanes (api + worker) and the event dispatcher (MSP apply)
|
|
358
405
|
* inline via `createAllInOneEntrypoint`. Worker-lane crons (e.g. the data
|
|
@@ -409,10 +456,7 @@ export type RunProdAppOptions = {
|
|
|
409
456
|
* a throw or a non-https value fall back to the app origin. The link carries the mail's
|
|
410
457
|
* locale, so the confirmation pages speak the mail's language. An app reacts to an address
|
|
411
458
|
* opt-out with an `r.job` triggered on `DeliveryHandlers.unsubscribeAddress`. */
|
|
412
|
-
readonly unsubscribe?:
|
|
413
|
-
readonly secret: string;
|
|
414
|
-
readonly tenantOrigin?: UnsubscribeLinkConfig["tenantOrigin"];
|
|
415
|
-
};
|
|
459
|
+
readonly unsubscribe?: UnsubscribeOption;
|
|
416
460
|
/** Hook for app-wired co-running components that need the system-write
|
|
417
461
|
* dispatcher (e.g. wiring a webhook plugin's system-scoped secrets, or
|
|
418
462
|
* starting a co-running supervisor) — runs after buildServer, before
|
|
@@ -425,23 +469,22 @@ export type RunProdAppOptions = {
|
|
|
425
469
|
* the fetch-handler directly (Bun.serve isn't available under vitest +
|
|
426
470
|
* node), then call handle.listen() manually if needed. */
|
|
427
471
|
readonly autoListen?: boolean;
|
|
428
|
-
/**
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
* seed-fn (db ist erst nach migrations + features ready). */
|
|
472
|
+
/** Per-tenant feature resolver, passed to the dispatcher.
|
|
473
|
+
* @deprecated Removed in the next release. `createTierEngineFeature({ tierMap })`
|
|
474
|
+
* (or `composeSaasStack`) builds the resolver at boot, and prod-only features
|
|
475
|
+
* come from the `mail`, `fileStorage` and `billing` options. */
|
|
433
476
|
readonly effectiveFeatures?: EffectiveFeaturesResolver;
|
|
434
477
|
/** Composed Zod-schema for env-validation (from `composeEnvSchema({
|
|
435
|
-
* features, extend })` in @cosmicdrift/kumiko-framework/env)
|
|
478
|
+
* core, features, extend })` in @cosmicdrift/kumiko-framework/env):
|
|
436
479
|
* - `process.env` is parsed against it BEFORE any boot work; missing
|
|
437
480
|
* or invalid vars throw a `KumikoBootError` listing ALL problems
|
|
438
481
|
* at once (not first-fail).
|
|
439
482
|
* - `KUMIKO_DRY_RUN_ENV=human|json|pulumi|k8s` introspects the schema
|
|
440
483
|
* and prints the env-var inventory, then exits without booting.
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
readonly envSchema
|
|
484
|
+
* - `KUMIKO_DRY_RUN_ENV=boot` prints a per-variable table. With required
|
|
485
|
+
* values missing it exits 0 without validating the feature wiring; an
|
|
486
|
+
* invalid value exits 1; a complete env runs the boot validators. */
|
|
487
|
+
readonly envSchema: ComposedEnvSchema;
|
|
445
488
|
/** Prefix for `pulumi config set <prefix><CamelCase(VAR)>` in dry-run
|
|
446
489
|
* output and boot-error suggestions. Without this, suggestions use
|
|
447
490
|
* bare `camelCase(VAR)` and ops has to guess the app prefix. */
|
|
@@ -468,16 +511,18 @@ export type RunProdAppOptions = {
|
|
|
468
511
|
* PrometheusMeter-basierten `observability`-Provider antwortet `/metrics`
|
|
469
512
|
* mit 503 + Misconfiguration-Hinweis statt echter Metriken. */
|
|
470
513
|
readonly metrics?: import("@cosmicdrift/kumiko-framework/api").ServerOptions["metrics"];
|
|
471
|
-
/** L1 (
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
|
|
514
|
+
/** L1 (global per-IP limit) + L2 (auth endpoints) rate-limit middleware, passed
|
|
515
|
+
* to `buildServer`'s `ServerOptions.rateLimit`. Without a value L1 allows 600/60 s
|
|
516
|
+
* and L2 30/60 s; a partial value overrides only the fields it names, `false`
|
|
517
|
+
* (whole option or one layer) switches it off. Behind a reverse proxy the
|
|
518
|
+
* client-IP key needs `trustedProxyHops`, otherwise all clients share one bucket. */
|
|
519
|
+
readonly rateLimit?: RateLimitOption;
|
|
476
520
|
/** Default security headers on every response (HSTS, X-Frame-Options,
|
|
477
|
-
* X-Content-Type-Options, Referrer-Policy
|
|
478
|
-
*
|
|
479
|
-
*
|
|
480
|
-
* via the object form —
|
|
521
|
+
* X-Content-Type-Options, Referrer-Policy, Content-Security-Policy with
|
|
522
|
+
* the build's inline-script hashes). Headers already set by a response
|
|
523
|
+
* (e.g. hostDispatch's per-host CSP) are never overridden. `false`
|
|
524
|
+
* disables the whole block; per-header overrides via the object form —
|
|
525
|
+
* see SecurityHeadersOption. */
|
|
481
526
|
readonly securityHeaders?: SecurityHeadersOption;
|
|
482
527
|
/** Number of trusted reverse-proxy hops for client-IP resolution — 1:1
|
|
483
528
|
* durchgereicht an `buildServer`s
|