create-kumiko-app 0.4.128 → 0.4.130

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.
@@ -2240,12 +2240,13 @@
2240
2240
  },
2241
2241
  {
2242
2242
  "name": "user-profile",
2243
- "description": "Self-service account page building blocks: a `change-email` write handler (re-auth via current password, uniqueness check, resets emailVerified and expects the app to trigger the verification flow) plus the ProfileScreen web component that composes change-password (auth-email-password), change-email and account deletion (user-data-rights request/cancel with grace period) into one screen. Apps register the screen as `type: \"custom\"` with `__component: \"UserProfileScreen\"`. Requires `user`, `auth-email-password`, and `user-data-rights`.",
2243
+ "description": "Self-service account page building blocks: a `change-email` write handler (re-auth via current password, uniqueness check, resets emailVerified and expects the app to trigger the verification flow) plus the ProfileScreen web component that composes change-password (auth-email-password), change-email and account deletion (user-data-rights request/cancel with grace period) into one screen. Apps register the screen as `type: \"custom\"` with `__component: \"UserProfileScreen\"`. Requires `user`, `auth-email-password`, `user-data-rights`, and `user-data-rights-defaults` (so the GDPR boot-validator finds export/delete hooks for `user`'s PII fields once user-data-rights is mounted).",
2244
2244
  "toggleableDefault": null,
2245
2245
  "requires": [
2246
2246
  "user",
2247
2247
  "auth-email-password",
2248
- "user-data-rights"
2248
+ "user-data-rights",
2249
+ "user-data-rights-defaults"
2249
2250
  ],
2250
2251
  "optionalRequires": [],
2251
2252
  "configReads": [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kumiko-app",
3
- "version": "0.4.128",
3
+ "version": "0.4.130",
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>",
@@ -30,8 +30,9 @@
30
30
  "vendor:manifest": "bun run scripts/vendor-manifest.ts"
31
31
  },
32
32
  "dependencies": {
33
- "@cosmicdrift/kumiko-dev-server": "0.156.0",
34
- "@cosmicdrift/kumiko-framework": "0.156.0",
33
+ "@cosmicdrift/kumiko-dev-server": "0.156.2",
34
+ "@cosmicdrift/kumiko-framework": "0.156.2",
35
+ "@cosmicdrift/kumiko-server-runtime": "0.156.2",
35
36
  "@inquirer/core": "^10.0.0",
36
37
  "@inquirer/prompts": "^7.4.0"
37
38
  },
@@ -44,6 +44,11 @@ describe("create-kumiko-app CLI", () => {
44
44
  expect(cfg).toContain("createDeliveryFeature");
45
45
  // mail-transport-smtp is opt-in (not recommended, no transitive require) — should NOT auto-mount.
46
46
  expect(cfg).not.toContain("mailTransportSmtpFeature");
47
+ // issue-1174: user-profile (recommended) requires user-data-rights
48
+ // transitively, which trips the GDPR boot-validator unless
49
+ // user-data-rights-defaults (the PII export/delete hooks for `user`)
50
+ // is auto-included too.
51
+ expect(cfg).toContain("createUserDataRightsDefaultsFeature");
47
52
 
48
53
  // UX-polish: Next-steps points at `bun dev` (the primary dev path since
49
54
  // PR #583 introduced bin/dev.ts), not the CI-only `bun run boot` smoke.
@@ -0,0 +1,60 @@
1
+ // issue-1174: `bun create kumiko-app <name> --yes` resolves the recommended
2
+ // feature set through the manifest's `requires` graph (dep-resolver.ts), not
3
+ // through hand-written app composition. That graph can pull in a feature
4
+ // (here: user-data-rights, transitively via user-profile) whose boot-time
5
+ // obligations (an EXT_USER_DATA hook per PII entity) no OTHER auto-included
6
+ // feature satisfies — cli.test.ts's file-existence checks can't catch that,
7
+ // only actually booting the resolved set through validateBoot can.
8
+
9
+ import { describe, expect, test } from "bun:test";
10
+ import {
11
+ createRegistry,
12
+ type FeatureDefinition,
13
+ validateBoot as validateBootRaw,
14
+ } from "@cosmicdrift/kumiko-framework/engine";
15
+ import { withBootValidatorFixture } from "@cosmicdrift/kumiko-framework/testing";
16
+ import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";
17
+ import { resolveDeps } from "../dep-resolver";
18
+ import { FEATURE_CONSTRUCTORS } from "../feature-constructors";
19
+ import { loadManifest } from "../manifest";
20
+ import { buildChoices } from "../picker";
21
+
22
+ function validateBoot(features: readonly FeatureDefinition[]): void {
23
+ validateBootRaw(withBootValidatorFixture(features));
24
+ }
25
+
26
+ async function instantiateResolved(names: readonly string[]): Promise<FeatureDefinition[]> {
27
+ const instances: FeatureDefinition[] = [];
28
+ for (const name of names) {
29
+ const entry = FEATURE_CONSTRUCTORS[name];
30
+ if (!entry) continue; // mirrors index.ts:47-49 — auto-mounted core deps have no entry
31
+ const mod = (await import(entry.importPath)) as Record<string, unknown>;
32
+ const exp = mod[entry.exportName];
33
+ instances.push(
34
+ entry.callExpression.endsWith("()")
35
+ ? (exp as () => FeatureDefinition)()
36
+ : (exp as FeatureDefinition),
37
+ );
38
+ }
39
+ return instances;
40
+ }
41
+
42
+ describe("--yes resolved set boots (issue-1174 regression)", () => {
43
+ const manifest = loadManifest();
44
+ const recommended = buildChoices(manifest)
45
+ .filter((c) => c.recommended)
46
+ .map((c) => c.name);
47
+ const resolved = resolveDeps(recommended, manifest);
48
+
49
+ test("resolves user-data-rights-defaults alongside the transitively-pulled user-data-rights", () => {
50
+ expect(resolved.featureNames).toContain("user-data-rights");
51
+ expect(resolved.featureNames).toContain("user-data-rights-defaults");
52
+ });
53
+
54
+ test("the resolved --yes feature set boots without the GDPR PII-hook-coverage error", async () => {
55
+ const instances = await instantiateResolved(resolved.featureNames);
56
+ const composed = composeFeatures(instances, { includeBundled: true });
57
+ expect(() => validateBoot(composed)).not.toThrow();
58
+ expect(() => createRegistry(composed)).not.toThrow();
59
+ });
60
+ });
@@ -177,6 +177,12 @@ export const FEATURE_CONSTRUCTORS: Readonly<Record<string, ScaffoldFeatureEntry>
177
177
  exportName: "createUserDataRightsFeature",
178
178
  callExpression: "createUserDataRightsFeature()",
179
179
  },
180
+ "user-data-rights-defaults": {
181
+ name: "user-data-rights-defaults",
182
+ importPath: "@cosmicdrift/kumiko-bundled-features/user-data-rights-defaults",
183
+ exportName: "createUserDataRightsDefaultsFeature",
184
+ callExpression: "createUserDataRightsDefaultsFeature()",
185
+ },
180
186
 
181
187
  // --- Operations ---
182
188
  "feature-toggles": {