create-kumiko-app 0.4.229 → 0.4.230
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-kumiko-app",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.230",
|
|
4
4
|
"description": "`bun create kumiko-app <name>` — scaffold a new Kumiko app with an interactive feature picker.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@cosmicdrift/kumiko-dev-server": "0.
|
|
31
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
32
|
-
"@cosmicdrift/kumiko-server-runtime": "0.
|
|
30
|
+
"@cosmicdrift/kumiko-dev-server": "0.215.0",
|
|
31
|
+
"@cosmicdrift/kumiko-framework": "0.215.0",
|
|
32
|
+
"@cosmicdrift/kumiko-server-runtime": "0.215.0",
|
|
33
33
|
"@inquirer/core": "^10.0.0",
|
|
34
34
|
"@inquirer/prompts": "^7.4.0"
|
|
35
35
|
},
|
|
@@ -7,12 +7,17 @@
|
|
|
7
7
|
// only actually booting the resolved set through validateBoot can.
|
|
8
8
|
|
|
9
9
|
import { describe, expect, test } from "bun:test";
|
|
10
|
+
import { frameworkCoreEnvSchema } from "@cosmicdrift/kumiko-dev-server";
|
|
11
|
+
import { resolveKmsWiring } from "@cosmicdrift/kumiko-framework/crypto";
|
|
10
12
|
import {
|
|
11
13
|
createRegistry,
|
|
12
14
|
type FeatureDefinition,
|
|
15
|
+
type TenantId,
|
|
13
16
|
validateBoot as validateBootRaw,
|
|
14
17
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
18
|
+
import { composeEnvSchema } from "@cosmicdrift/kumiko-framework/env";
|
|
15
19
|
import { withBootValidatorFixture } from "@cosmicdrift/kumiko-framework/testing";
|
|
20
|
+
import { runProdApp } from "@cosmicdrift/kumiko-server-runtime";
|
|
16
21
|
import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";
|
|
17
22
|
import { resolveDeps } from "../dep-resolver";
|
|
18
23
|
import { FEATURE_CONSTRUCTORS } from "../feature-constructors";
|
|
@@ -61,3 +66,94 @@ describe("--yes resolved set boots (issue-1174 regression)", () => {
|
|
|
61
66
|
expect(() => createRegistry(composed)).not.toThrow();
|
|
62
67
|
});
|
|
63
68
|
});
|
|
69
|
+
|
|
70
|
+
// kumiko-framework#2330: validateBoot/createRegistry above never reach
|
|
71
|
+
// runProdApp's PII boot gate (assertPiiBootInvariants) — it's not part of
|
|
72
|
+
// validateBoot, it runs a step later. The --yes set mounts PII-annotated
|
|
73
|
+
// entities (user, tenant-invitation, fileRef via user-data-rights), so the
|
|
74
|
+
// generated bin/main.ts must wire kms/allowPlaintextPii or the first
|
|
75
|
+
// `bun run boot` throws BOOT ABORTED. This drives the SAME resolved feature
|
|
76
|
+
// set through the actual runProdApp (KUMIKO_DRY_RUN_ENV=boot — no DB/Redis
|
|
77
|
+
// connect) to pin both halves of the fix.
|
|
78
|
+
describe("--yes resolved set through runProdApp's PII boot gate (issue-2330 regression)", () => {
|
|
79
|
+
const manifest = loadManifest();
|
|
80
|
+
const recommended = buildChoices(manifest)
|
|
81
|
+
.filter((c) => c.recommended)
|
|
82
|
+
.map((c) => c.name);
|
|
83
|
+
const resolved = resolveDeps(recommended, manifest);
|
|
84
|
+
|
|
85
|
+
const auth = {
|
|
86
|
+
admin: {
|
|
87
|
+
email: "admin@test.local",
|
|
88
|
+
password: "change-me-on-first-deploy",
|
|
89
|
+
displayName: "Admin",
|
|
90
|
+
memberships: [
|
|
91
|
+
{
|
|
92
|
+
tenantId: "93238e36-e2e5-4e2e-8be4-00004739a98c" as TenantId,
|
|
93
|
+
tenantKey: "test",
|
|
94
|
+
tenantName: "test",
|
|
95
|
+
roles: ["TenantAdmin" as const],
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
async function bootWithWiring(wiring: Record<string, unknown>) {
|
|
102
|
+
const instances = await instantiateResolved(resolved.featureNames);
|
|
103
|
+
const bootFeatures = composeFeatures(instances, { includeBundled: true });
|
|
104
|
+
const envSchema = composeEnvSchema({ core: frameworkCoreEnvSchema, features: bootFeatures });
|
|
105
|
+
return runProdApp({
|
|
106
|
+
features: instances,
|
|
107
|
+
envSchema,
|
|
108
|
+
autoListen: false,
|
|
109
|
+
migrations: false,
|
|
110
|
+
auth,
|
|
111
|
+
envSource: {
|
|
112
|
+
KUMIKO_DRY_RUN_ENV: "boot",
|
|
113
|
+
JWT_SECRET: "a".repeat(32),
|
|
114
|
+
KUMIKO_SECRETS_MASTER_KEY_V1: Buffer.alloc(32, 7).toString("base64"),
|
|
115
|
+
DATABASE_URL: "postgres://dummy:dummy@127.0.0.1:1/dummy",
|
|
116
|
+
REDIS_URL: "redis://127.0.0.1:1",
|
|
117
|
+
},
|
|
118
|
+
...wiring,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
test("without kms/allowPlaintextPii wiring, boot aborts (pins the bug this issue reports)", async () => {
|
|
123
|
+
await expect(bootWithWiring({})).rejects.toThrow(
|
|
124
|
+
/BOOT ABORTED.*user.*tenant-invitation.*fileRef/s,
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("with resolveKmsWiring's fallback (what the generated bin/main.ts now does), boot succeeds", async () => {
|
|
129
|
+
// Empty object, not process.env: a dev machine with the real trio set
|
|
130
|
+
// would otherwise flip this into the ActiveKmsWiring branch and the test
|
|
131
|
+
// would stop exercising the plaintext fallback it's meant to pin.
|
|
132
|
+
const kmsWiring = resolveKmsWiring(
|
|
133
|
+
{},
|
|
134
|
+
{
|
|
135
|
+
logPrefix: "[test]",
|
|
136
|
+
plaintextReason: "no PLATFORM_KEK / SUBJECT_KEYS_DATABASE_URL / KUMIKO_BLIND_INDEX_KEY set",
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
expect(kmsWiring).toHaveProperty("allowPlaintextPii");
|
|
140
|
+
const handle = await bootWithWiring(kmsWiring);
|
|
141
|
+
expect(handle).toBeDefined();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("generated .env.example's unset trio (empty string, not absent) still resolves to the plaintext fallback", async () => {
|
|
145
|
+
// dotenv turns `PLATFORM_KEK=` into process.env.PLATFORM_KEK === "" — the
|
|
146
|
+
// actual value a user gets from `cp .env.example .env` without filling it
|
|
147
|
+
// in. resolveKmsWiring reads raw env (not the zod-validated envSchema),
|
|
148
|
+
// and Boolean("") === Boolean(undefined), so this must behave identically
|
|
149
|
+
// to the {} case above.
|
|
150
|
+
const kmsWiring = resolveKmsWiring({
|
|
151
|
+
PLATFORM_KEK: "",
|
|
152
|
+
SUBJECT_KEYS_DATABASE_URL: "",
|
|
153
|
+
KUMIKO_BLIND_INDEX_KEY: "",
|
|
154
|
+
});
|
|
155
|
+
expect(kmsWiring).toHaveProperty("allowPlaintextPii");
|
|
156
|
+
const handle = await bootWithWiring(kmsWiring);
|
|
157
|
+
expect(handle).toBeDefined();
|
|
158
|
+
});
|
|
159
|
+
});
|