@cosmicdrift/kumiko-dev-server 0.59.1 → 0.60.1

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": "@cosmicdrift/kumiko-dev-server",
3
- "version": "0.59.1",
3
+ "version": "0.60.1",
4
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.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -0,0 +1,59 @@
1
+ // The origin-guard config (allowedOrigins / unsafeSkipOriginCheck) is forwarded
2
+ // from runDevApp's auth options through to the server exactly like runProdApp
3
+ // (#399/1). The guard fires during server build — AFTER the ephemeral test DB is
4
+ // up — so this is an integration test (needs TEST_DATABASE_URL), mirroring the
5
+ // run-prod-app forwarding pair. Without it a typo or wrong spread-key on the dev
6
+ // path would silently drop the fail-closed guard and dev/prod would diverge.
7
+
8
+ import { afterEach, describe, expect, test } from "bun:test";
9
+ import { createEntity, createTextField, defineFeature } from "@cosmicdrift/kumiko-framework/engine";
10
+ import type { KumikoServerHandle } from "../create-kumiko-server";
11
+ import { runDevApp } from "../run-dev-app";
12
+
13
+ function validFeature() {
14
+ return defineFeature("shop", (r) => {
15
+ r.entity("product", createEntity({ fields: { name: createTextField() } }));
16
+ });
17
+ }
18
+
19
+ const ADMIN = {
20
+ email: "origin-guard@example.eu",
21
+ password: "test-pw-strong-1234",
22
+ displayName: "Admin",
23
+ memberships: [],
24
+ };
25
+
26
+ let handle: KumikoServerHandle | undefined;
27
+
28
+ afterEach(async () => {
29
+ await handle?.stop();
30
+ handle = undefined;
31
+ });
32
+
33
+ describe("runDevApp — auth allowedOrigins forwarding (#399/1)", () => {
34
+ test("cookieDomain without allowedOrigins fails closed — guard is wired through runDevApp", async () => {
35
+ await expect(
36
+ runDevApp({
37
+ features: [validFeature()],
38
+ auth: { admin: ADMIN, cookieDomain: "example.eu" },
39
+ }),
40
+ ).rejects.toThrow(/allowedOrigins is empty/);
41
+ });
42
+
43
+ test("cookieDomain + allowedOrigins clears the guard — allowlist reaches the server", async () => {
44
+ // Without the forwarding fix this would ALSO throw /allowedOrigins is empty/.
45
+ handle = await runDevApp({
46
+ features: [validFeature()],
47
+ // Port 0 → OS-assigned ephemeral port, no fixed-port collision in CI.
48
+ port: 0,
49
+ auth: {
50
+ admin: ADMIN,
51
+ cookieDomain: "example.eu",
52
+ allowedOrigins: ["https://app.example.eu"],
53
+ },
54
+ });
55
+ // A booted handle that did not throw on the origin guard IS the forwarding
56
+ // proof — the allowlist reached the server build.
57
+ expect(handle).toBeDefined();
58
+ });
59
+ });