@cosmicdrift/kumiko-dev-server 0.152.0 → 0.153.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.
Files changed (48) hide show
  1. package/package.json +5 -8
  2. package/src/__tests__/build-prod-bundle.integration.test.ts +1 -1
  3. package/src/__tests__/compose-stacks.test.ts +1 -1
  4. package/src/__tests__/discover-format.test.ts +1 -1
  5. package/src/__tests__/env-schema.integration.test.ts +1 -1
  6. package/src/__tests__/walkthrough.integration.test.ts +1 -1
  7. package/src/build.ts +1 -1
  8. package/src/create-kumiko-server.ts +12 -6
  9. package/src/index.ts +4 -12
  10. package/src/run-dev-app.ts +12 -8
  11. package/src/scaffold-app.ts +9 -4
  12. package/src/schema-apply.ts +4 -1
  13. package/src/schema-check-core.ts +1 -1
  14. package/src/setup-test-stack-from-features.ts +4 -1
  15. package/src/__tests__/boot-extra-context.test.ts +0 -140
  16. package/src/__tests__/build-prod-bundle.test.ts +0 -278
  17. package/src/__tests__/cache-headers.test.ts +0 -83
  18. package/src/__tests__/compose-features-mfa-wiring.integration.test.ts +0 -308
  19. package/src/__tests__/compose-features-wiring.integration.test.ts +0 -382
  20. package/src/__tests__/compose-features.test.ts +0 -128
  21. package/src/__tests__/config-seed-boot.integration.test.ts +0 -158
  22. package/src/__tests__/inject-schema.test.ts +0 -62
  23. package/src/__tests__/pii-boot-gate.test.ts +0 -68
  24. package/src/__tests__/renderer-web-css-relocation.integration.test.ts +0 -85
  25. package/src/__tests__/renderer-web-shell-sentinel.test.ts +0 -35
  26. package/src/__tests__/require-env.test.ts +0 -29
  27. package/src/__tests__/resolve-auth-mail.test.ts +0 -69
  28. package/src/__tests__/resolve-tailwind-cli.test.ts +0 -81
  29. package/src/__tests__/run-prod-app-env-source.test.ts +0 -157
  30. package/src/__tests__/run-prod-app-spec.test.ts +0 -57
  31. package/src/__tests__/run-prod-app.integration.test.ts +0 -915
  32. package/src/__tests__/session-wiring.test.ts +0 -51
  33. package/src/__tests__/try-hono-first.test.ts +0 -63
  34. package/src/boot/__tests__/job-run-logger.test.ts +0 -26
  35. package/src/boot/apply-boot-seeds.ts +0 -19
  36. package/src/boot/boot-crypto.ts +0 -82
  37. package/src/boot/job-run-logger.ts +0 -51
  38. package/src/build-prod-bundle.ts +0 -692
  39. package/src/compose-features.ts +0 -164
  40. package/src/extra-routes-deps.ts +0 -47
  41. package/src/inject-schema.ts +0 -30
  42. package/src/pii-boot-gate.ts +0 -62
  43. package/src/resolve-tailwind-cli.ts +0 -45
  44. package/src/run-prod-app-boot-context.ts +0 -241
  45. package/src/run-prod-app-static-files.ts +0 -273
  46. package/src/run-prod-app.ts +0 -1158
  47. package/src/session-wiring.ts +0 -29
  48. package/src/try-hono-first.ts +0 -46
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-dev-server",
3
- "version": "0.152.0",
4
- "description": "Development server bootstrap for Kumiko apps. Bundles the client, mints dev-JWTs, injects the resolved AppSchema, and seeds an admin. Not for production.",
3
+ "version": "0.153.0",
4
+ "description": "Dev-tooling for Kumiko apps: local dev-server bootstrap (runDevApp), scaffolding, codegen. Not shipped into production node_modules see @cosmicdrift/kumiko-server-runtime for the prod boot path.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
7
7
  "repository": {
@@ -26,10 +26,6 @@
26
26
  "types": "./src/build.ts",
27
27
  "default": "./src/build.ts"
28
28
  },
29
- "./compose-features": {
30
- "types": "./src/compose-features.ts",
31
- "default": "./src/compose-features.ts"
32
- },
33
29
  "./compose-stacks": {
34
30
  "types": "./src/compose-stacks.ts",
35
31
  "default": "./src/compose-stacks.ts"
@@ -58,8 +54,9 @@
58
54
  "kumiko-schema-check": "./bin/kumiko-schema-check.ts"
59
55
  },
60
56
  "dependencies": {
61
- "@cosmicdrift/kumiko-bundled-features": "0.152.0",
62
- "@cosmicdrift/kumiko-framework": "0.152.0",
57
+ "@cosmicdrift/kumiko-bundled-features": "0.153.0",
58
+ "@cosmicdrift/kumiko-framework": "0.153.0",
59
+ "@cosmicdrift/kumiko-server-runtime": "0.153.0",
63
60
  "ts-morph": "^28.0.0"
64
61
  },
65
62
  "publishConfig": {
@@ -19,7 +19,7 @@ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
19
19
  import { tmpdir } from "node:os";
20
20
  import { dirname, join, resolve } from "node:path";
21
21
  import { fileURLToPath } from "node:url";
22
- import { buildProdBundle } from "../build-prod-bundle";
22
+ import { buildProdBundle } from "@cosmicdrift/kumiko-server-runtime/build-prod-bundle";
23
23
 
24
24
  const __filename = fileURLToPath(import.meta.url);
25
25
  const __dirname = dirname(__filename);
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import { validateBoot } from "@cosmicdrift/kumiko-framework/engine";
3
- import { composeFeatures } from "../compose-features";
3
+ import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";
4
4
  import {
5
5
  composeFileStack,
6
6
  composeGdprStack,
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
2
2
  import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { formatBuildResult } from "../build-prod-bundle";
5
+ import { formatBuildResult } from "@cosmicdrift/kumiko-server-runtime/build-prod-bundle";
6
6
  import { discoverServerEntry } from "../build-server-bundle";
7
7
 
8
8
  describe("discoverServerEntry", () => {
@@ -7,10 +7,10 @@
7
7
  import { describe, expect, it } from "bun:test";
8
8
  import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
9
9
  import { composeEnvSchema, KumikoBootError } from "@cosmicdrift/kumiko-framework/env";
10
+ import { runProdApp } from "@cosmicdrift/kumiko-server-runtime/run-prod-app";
10
11
  import { z } from "zod";
11
12
  import { frameworkCoreEnvSchema } from "../env-schema";
12
13
  import * as devServerPublicApi from "../index";
13
- import { runProdApp } from "../run-prod-app";
14
14
 
15
15
  const secretsFeature = defineFeature("secrets", (r) => {
16
16
  r.envSchema(
@@ -16,7 +16,7 @@ import { join } from "node:path";
16
16
  import { createSecretsFeature } from "@cosmicdrift/kumiko-bundled-features/secrets";
17
17
  import { createSessionsFeature } from "@cosmicdrift/kumiko-bundled-features/sessions";
18
18
  import { createRegistry, defineFeature, validateBoot } from "@cosmicdrift/kumiko-framework/engine";
19
- import { composeFeatures } from "../compose-features";
19
+ import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";
20
20
  import { scaffoldApp } from "../scaffold-app";
21
21
  import { scaffoldAppFeature } from "../scaffold-app-feature";
22
22
 
package/src/build.ts CHANGED
@@ -13,7 +13,7 @@ export {
13
13
  discoverHtmlTemplate,
14
14
  formatBuildResult,
15
15
  injectAssetTags,
16
- } from "./build-prod-bundle";
16
+ } from "@cosmicdrift/kumiko-server-runtime/build-prod-bundle";
17
17
 
18
18
  export {
19
19
  type BuildServerBundleEntry,
@@ -29,12 +29,18 @@ import {
29
29
  type TestStackOptions,
30
30
  TestUsers,
31
31
  } from "@cosmicdrift/kumiko-framework/stack";
32
- import { startDevJobRunners } from "./boot/job-run-logger";
33
- import { type ExtraRoutesSystemDeps, makeDispatchSystemWrite } from "./extra-routes-deps";
34
- import { injectSchema } from "./inject-schema";
35
- import { canResolveTailwindStylesheet, resolveTailwindCli } from "./resolve-tailwind-cli";
36
- import { buildBunServeOptions } from "./run-prod-app";
37
- import { tryHonoFirst } from "./try-hono-first";
32
+ import { startDevJobRunners } from "@cosmicdrift/kumiko-server-runtime/boot/job-run-logger";
33
+ import { buildBunServeOptions } from "@cosmicdrift/kumiko-server-runtime/bun-serve-options";
34
+ import {
35
+ type ExtraRoutesSystemDeps,
36
+ makeDispatchSystemWrite,
37
+ } from "@cosmicdrift/kumiko-server-runtime/extra-routes-deps";
38
+ import { injectSchema } from "@cosmicdrift/kumiko-server-runtime/inject-schema";
39
+ import {
40
+ canResolveTailwindStylesheet,
41
+ resolveTailwindCli,
42
+ } from "@cosmicdrift/kumiko-server-runtime/resolve-tailwind-cli";
43
+ import { tryHonoFirst } from "@cosmicdrift/kumiko-server-runtime/try-hono-first";
38
44
 
39
45
  // Runtime-detection. The dev-server is meant to run under Bun (Kumiko's
40
46
  // target runtime), but the test-suite runs under vitest on Node — we
package/src/index.ts CHANGED
@@ -13,6 +13,10 @@
13
13
  // Login-Routes + Error-Map, ruft seedAdmin im onAfterSetup. Default
14
14
  // für Sample-Apps und Showcases — 5-10 Zeilen Bootstrap statt 50.
15
15
 
16
+ export {
17
+ type ComposeFeaturesOptions,
18
+ composeFeatures,
19
+ } from "@cosmicdrift/kumiko-server-runtime/compose-features";
16
20
  // Build-Toolchain (buildProdBundle, Bun.build, Tailwind-Pipeline, ts-morph) lebt
17
21
  // im Sub-Path-Export `@cosmicdrift/kumiko-dev-server/build`. Damit zieht der Main-Barrel
18
22
  // kein Bun-Toolchain-Bundle mehr in Production-Reads (z.B. wenn drizzle-kit
@@ -25,7 +29,6 @@ export {
25
29
  type ScanWarning,
26
30
  scanEvents,
27
31
  } from "./codegen";
28
- export { type ComposeFeaturesOptions, composeFeatures } from "./compose-features";
29
32
  export {
30
33
  composeFileStack,
31
34
  composeGdprStack,
@@ -62,17 +65,6 @@ export type {
62
65
  export { buildFewShotCorpus, pathToId } from "./few-shot-corpus";
63
66
  export type { RunDevAppAuthOptions, RunDevAppOptions, SeedFn } from "./run-dev-app";
64
67
  export { runDevApp } from "./run-dev-app";
65
- export type {
66
- EmailVerificationSetup,
67
- InviteSetup,
68
- PasswordResetSetup,
69
- ProdAppHandle,
70
- ProdSeedFn,
71
- RunProdAppAuthOptions,
72
- RunProdAppOptions,
73
- SignupSetup,
74
- } from "./run-prod-app";
75
- export { runProdApp } from "./run-prod-app";
76
68
  export type {
77
69
  ScaffoldAppOptions,
78
70
  ScaffoldAppResult,
@@ -69,28 +69,32 @@ import {
69
69
  import type { EnvelopeCipher, MasterKeyProvider } from "@cosmicdrift/kumiko-framework/secrets";
70
70
  import type { TestStack } from "@cosmicdrift/kumiko-framework/stack";
71
71
  import { warnIfNonUtcServerTimeZone } from "@cosmicdrift/kumiko-framework/time";
72
- import { applyBootSeeds } from "./boot/apply-boot-seeds";
73
- import { resolveBootCrypto } from "./boot/boot-crypto";
72
+ import { applyBootSeeds } from "@cosmicdrift/kumiko-server-runtime/boot/apply-boot-seeds";
73
+ import { resolveBootCrypto } from "@cosmicdrift/kumiko-server-runtime/boot/boot-crypto";
74
+ import {
75
+ buildComposeAuthOptions,
76
+ composeFeatures,
77
+ } from "@cosmicdrift/kumiko-server-runtime/compose-features";
78
+ import { assertPiiBootInvariants } from "@cosmicdrift/kumiko-server-runtime/pii-boot-gate";
74
79
  import { watchAndRegenerate } from "./codegen";
75
- import { buildComposeAuthOptions, composeFeatures } from "./compose-features";
76
80
  import {
77
81
  type CreateKumikoServerOptions,
78
82
  createKumikoServer,
79
83
  type KumikoServerHandle,
80
84
  } from "./create-kumiko-server";
81
- import { assertPiiBootInvariants } from "./pii-boot-gate";
82
85
  import { renderWelcomeBanner } from "./welcome-banner";
83
86
 
84
87
  // Re-export der shared Auth-Setup-Types damit Apps nur einen Import-Pfad
85
88
  // brauchen. PasswordResetSetup / EmailVerificationSetup leben in
86
- // run-prod-app.ts (single source of truth) — hier nur durchgereicht.
89
+ // @cosmicdrift/kumiko-server-runtime (single source of truth) — hier nur
90
+ // durchgereicht.
87
91
  export type {
88
92
  AuthMailOptions,
89
93
  EmailVerificationSetup,
90
94
  InviteSetup,
91
95
  PasswordResetSetup,
92
96
  SignupSetup,
93
- } from "./run-prod-app";
97
+ } from "@cosmicdrift/kumiko-server-runtime/run-prod-app";
94
98
 
95
99
  import type {
96
100
  AuthMailOptions,
@@ -98,13 +102,13 @@ import type {
98
102
  InviteSetup,
99
103
  PasswordResetSetup,
100
104
  SignupSetup,
101
- } from "./run-prod-app";
105
+ } from "@cosmicdrift/kumiko-server-runtime/run-prod-app";
102
106
  import {
103
107
  addConfigAccessorFactory,
104
108
  buildBootExtraContext,
105
109
  requireEnv,
106
110
  resolveAuthMail,
107
- } from "./run-prod-app";
111
+ } from "@cosmicdrift/kumiko-server-runtime/run-prod-app";
108
112
 
109
113
  export type RunDevAppAuthOptions = {
110
114
  /** Admin user to seed at boot. Idempotent — re-runs in persistent-DB
@@ -19,8 +19,8 @@ import {
19
19
  writeSnapshotJson,
20
20
  } from "@cosmicdrift/kumiko-framework/db";
21
21
  import type { FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
22
+ import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";
22
23
  import { IndentationText, Project, VariableDeclarationKind } from "ts-morph";
23
- import { composeFeatures } from "./compose-features";
24
24
  import { isKebabSegment } from "./kebab";
25
25
  import {
26
26
  createDemoTasksFeature,
@@ -177,6 +177,7 @@ function renderPackageJson(name: string, version: string): string {
177
177
  "@cosmicdrift/kumiko-dev-server": version,
178
178
  "@cosmicdrift/kumiko-framework": version,
179
179
  "@cosmicdrift/kumiko-renderer-web": version,
180
+ "@cosmicdrift/kumiko-server-runtime": version,
180
181
  react: "^19.2.6",
181
182
  "react-dom": "^19.2.6",
182
183
  zod: "^4.4.3",
@@ -410,7 +411,11 @@ function renderMain(appName: string): string {
410
411
 
411
412
  sf.addImportDeclaration({
412
413
  moduleSpecifier: "@cosmicdrift/kumiko-dev-server",
413
- namedImports: ["composeFeatures", "frameworkCoreEnvSchema", "runProdApp"],
414
+ namedImports: ["frameworkCoreEnvSchema"],
415
+ });
416
+ sf.addImportDeclaration({
417
+ moduleSpecifier: "@cosmicdrift/kumiko-server-runtime",
418
+ namedImports: ["composeFeatures", "runProdApp"],
414
419
  });
415
420
  sf.addImportDeclaration({
416
421
  moduleSpecifier: "@cosmicdrift/kumiko-framework/engine",
@@ -773,7 +778,7 @@ function renderKumikoSchema(): string {
773
778
  "// Computes table-metas from the SAME composeFeatures(APP_FEATURES) the",
774
779
  "// runtime sees (runProdApp/runDevApp) — migration and runtime cannot drift.",
775
780
  "",
776
- 'import { composeFeatures } from "@cosmicdrift/kumiko-dev-server/compose-features";',
781
+ 'import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";',
777
782
  'import { collectTableMetas, type EntityTableMeta } from "@cosmicdrift/kumiko-framework/db";',
778
783
  'import type { FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";',
779
784
  'import { APP_FEATURES, HAS_AUTH } from "../src/run-config";',
@@ -795,7 +800,7 @@ function renderBinKumiko(): string {
795
800
  "// migrate-step runs `bun /app/kumiko.js schema apply`; kumiko-build bundles",
796
801
  "// this file to dist-server/kumiko.js.",
797
802
  "",
798
- 'import { composeFeatures } from "@cosmicdrift/kumiko-dev-server/compose-features";',
803
+ 'import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";',
799
804
  'import { runSchemaCli } from "@cosmicdrift/kumiko-framework/schema-cli";',
800
805
  'import { APP_FEATURES, HAS_AUTH } from "../src/run-config";',
801
806
  "",
@@ -22,7 +22,10 @@ import {
22
22
  createProjectionStateTable,
23
23
  rebuildProjection,
24
24
  } from "@cosmicdrift/kumiko-framework/pipeline";
25
- import { type ComposeFeaturesOptions, composeFeatures } from "./compose-features";
25
+ import {
26
+ type ComposeFeaturesOptions,
27
+ composeFeatures,
28
+ } from "@cosmicdrift/kumiko-server-runtime/compose-features";
26
29
 
27
30
  export type SchemaApplyOptions = ComposeFeaturesOptions & {
28
31
  /** App-Features (z.B. APP_FEATURES aus run-config) — composed mit den
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { existsSync } from "node:fs";
6
6
  import { resolve } from "node:path";
7
- import { composeFeatures } from "./compose-features";
7
+ import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";
8
8
 
9
9
  // The generate-script lives under different roots across apps: publicstatus
10
10
  // uses `drizzle/generate.ts`, the framework's own sample-apps use
@@ -9,7 +9,10 @@ import {
9
9
  type TestStack,
10
10
  type TestStackOptions,
11
11
  } from "@cosmicdrift/kumiko-framework/stack";
12
- import { type ComposeFeaturesOptions, composeFeatures } from "./compose-features";
12
+ import {
13
+ type ComposeFeaturesOptions,
14
+ composeFeatures,
15
+ } from "@cosmicdrift/kumiko-server-runtime/compose-features";
13
16
 
14
17
  export type TestStackPreset = "config" | "text-content";
15
18
 
@@ -1,140 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import { createDeliveryFeature } from "@cosmicdrift/kumiko-bundled-features/delivery";
3
- import { createSecretsFeature } from "@cosmicdrift/kumiko-bundled-features/secrets";
4
- import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
5
- import { createRegistry, defineFeature } from "@cosmicdrift/kumiko-framework/engine";
6
- import type { MasterKeyProvider } from "@cosmicdrift/kumiko-framework/secrets";
7
- import { buildBootExtraContext } from "../run-prod-app";
8
-
9
- // Pins runProdApp's framework-default-provider autowire (buildBootExtraContext):
10
- // textContent unconditional, secrets feature-gated, KEK-env trap avoided, the
11
- // money-horse regression (no secrets feature → no forced KEK → no throw), and
12
- // the delivery _notifyFactory wiring that makes ctx.notify work in prod (only
13
- // test-wired before — runProdApp/runDevApp call THIS, not createDeliveryTestContext).
14
-
15
- // db is never touched at construction time — createTextContentApi /
16
- // createSecretsContext only store the handle and query lazily. A bare stub
17
- // keeps this a fast unit test (no Postgres) instead of a full boot.
18
- const fakeDb = {} as unknown as DbConnection;
19
- const registry = createRegistry([]);
20
- const KEK = Buffer.alloc(32, 7).toString("base64");
21
-
22
- const otherFeature = defineFeature("widgets", () => {});
23
-
24
- describe("buildBootExtraContext — framework-default provider autowire", () => {
25
- test("textContent is wired unconditionally (no secrets feature, no auth)", () => {
26
- const ctx = buildBootExtraContext({
27
- db: fakeDb,
28
- features: [otherFeature],
29
- envSource: {},
30
- registry,
31
- hasAuth: false,
32
- });
33
- expect(typeof (ctx["textContent"] as { getBlock?: unknown }).getBlock).toBe("function");
34
- expect(ctx["secrets"]).toBeUndefined();
35
- expect(ctx["configResolver"]).toBeUndefined();
36
- expect(ctx["_notifyFactory"]).toBeUndefined();
37
- });
38
-
39
- test("delivery feature mounted → _notifyFactory wired (ctx.notify works in prod)", () => {
40
- const ctx = buildBootExtraContext({
41
- db: fakeDb,
42
- features: [createDeliveryFeature()],
43
- envSource: {},
44
- registry,
45
- hasAuth: false,
46
- });
47
- expect(typeof ctx["_notifyFactory"]).toBe("function");
48
- });
49
-
50
- test("no delivery feature → _notifyFactory not wired", () => {
51
- const ctx = buildBootExtraContext({
52
- db: fakeDb,
53
- features: [otherFeature],
54
- envSource: {},
55
- registry,
56
- hasAuth: false,
57
- });
58
- expect(ctx["_notifyFactory"]).toBeUndefined();
59
- });
60
-
61
- test("secrets feature mounted + valid KEK env → ctx.secrets wired", () => {
62
- const ctx = buildBootExtraContext({
63
- db: fakeDb,
64
- features: [createSecretsFeature()],
65
- envSource: {
66
- KUMIKO_SECRETS_MASTER_KEY_V1: KEK,
67
- KUMIKO_SECRETS_MASTER_KEY_CURRENT_VERSION: "1",
68
- },
69
- registry,
70
- hasAuth: false,
71
- });
72
- const secrets = ctx["secrets"] as {
73
- get?: unknown;
74
- set?: unknown;
75
- has?: unknown;
76
- delete?: unknown;
77
- };
78
- expect(typeof secrets.get).toBe("function");
79
- expect(typeof secrets.set).toBe("function");
80
- });
81
-
82
- test("secrets feature mounted, only V1 set (no CURRENT_VERSION) → wired (default '1')", () => {
83
- const ctx = buildBootExtraContext({
84
- db: fakeDb,
85
- features: [createSecretsFeature()],
86
- envSource: { KUMIKO_SECRETS_MASTER_KEY_V1: KEK },
87
- registry,
88
- hasAuth: false,
89
- });
90
- expect(ctx["secrets"]).toBeDefined();
91
- });
92
-
93
- test("secrets feature mounted but NO KEK + no override → skipped, no throw (dev DEV_KEY path)", () => {
94
- // dev wires its own DEV_KEY secrets explicitly; the auto-wire must not
95
- // eagerly construct an env-provider and crash the boot when no env KEK
96
- // exists. ctx.secrets stays unset so the app's explicit wiring wins.
97
- let ctx: Record<string, unknown> | undefined;
98
- expect(() => {
99
- ctx = buildBootExtraContext({
100
- db: fakeDb,
101
- features: [createSecretsFeature()],
102
- envSource: {},
103
- registry,
104
- hasAuth: false,
105
- });
106
- }).not.toThrow();
107
- expect(ctx?.["secrets"]).toBeUndefined();
108
- });
109
-
110
- test("no secrets feature → no KEK ever read, boots green (money-horse regression)", () => {
111
- const ctx = buildBootExtraContext({
112
- db: fakeDb,
113
- features: [otherFeature],
114
- envSource: {}, // no KEK — must NOT matter when secrets isn't mounted
115
- registry,
116
- hasAuth: false,
117
- });
118
- expect(ctx["secrets"]).toBeUndefined();
119
- });
120
-
121
- test("masterKey override is used verbatim — no env-provider built", () => {
122
- const override: MasterKeyProvider = {
123
- wrapDek: async () => ({ encryptedDek: Buffer.alloc(0), kekVersion: 1 }),
124
- unwrapDek: async () => Buffer.alloc(0),
125
- currentVersion: () => 1,
126
- isAvailable: async () => true,
127
- };
128
- // envSource is empty: if the override weren't honoured, createEnvMasterKeyProvider
129
- // would throw "no KEK". It doesn't → the override path is taken.
130
- const ctx = buildBootExtraContext({
131
- db: fakeDb,
132
- features: [createSecretsFeature()],
133
- envSource: {},
134
- registry,
135
- hasAuth: false,
136
- masterKey: override,
137
- });
138
- expect(ctx["secrets"]).toBeDefined();
139
- });
140
- });