@cosmicdrift/kumiko-dev-server 0.51.0 → 0.53.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-dev-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.0",
|
|
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>",
|
|
@@ -706,3 +706,44 @@ describe("runProdApp: lokaler Event-Dispatcher (MSP-Anwendung im Single-Containe
|
|
|
706
706
|
expect(handle.entrypoint.eventDispatcher).toBeUndefined();
|
|
707
707
|
});
|
|
708
708
|
});
|
|
709
|
+
|
|
710
|
+
// Origin-guard config (framework #340) flows from runProdApp's auth options
|
|
711
|
+
// through to buildServer. Before the forwarding fix, RunProdAppAuthOptions had
|
|
712
|
+
// no `allowedOrigins`, so a cookieDomain app could not satisfy the fail-closed
|
|
713
|
+
// guard — it could only CrashLoop.
|
|
714
|
+
describe("runProdApp — auth allowedOrigins forwarding", () => {
|
|
715
|
+
const ADMIN = {
|
|
716
|
+
email: "origin-guard@example.eu",
|
|
717
|
+
password: "test-pw-strong-1234",
|
|
718
|
+
displayName: "Admin",
|
|
719
|
+
memberships: [],
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
test("cookieDomain without allowedOrigins fails closed — guard is wired through runProdApp", async () => {
|
|
723
|
+
await expect(
|
|
724
|
+
boot(undefined, { auth: { admin: ADMIN, cookieDomain: "example.eu" } }),
|
|
725
|
+
).rejects.toThrow(/allowedOrigins is empty/);
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
test("cookieDomain + allowedOrigins clears the guard — allowlist reaches buildServer", async () => {
|
|
729
|
+
// Without the forwarding fix this would ALSO throw /allowedOrigins is empty/.
|
|
730
|
+
// It may still fail later on the minimal harness (no auth tables migrated),
|
|
731
|
+
// but never on the origin guard — that is the forwarding proof.
|
|
732
|
+
let bootError: unknown;
|
|
733
|
+
try {
|
|
734
|
+
const handle = await boot(undefined, {
|
|
735
|
+
auth: {
|
|
736
|
+
admin: ADMIN,
|
|
737
|
+
cookieDomain: "example.eu",
|
|
738
|
+
allowedOrigins: ["https://app.example.eu"],
|
|
739
|
+
},
|
|
740
|
+
});
|
|
741
|
+
expect(handle).toBeDefined();
|
|
742
|
+
} catch (error) {
|
|
743
|
+
bootError = error;
|
|
744
|
+
}
|
|
745
|
+
if (bootError !== undefined) {
|
|
746
|
+
expect(String(bootError)).not.toMatch(/allowedOrigins is empty/);
|
|
747
|
+
}
|
|
748
|
+
});
|
|
749
|
+
});
|
package/src/run-dev-app.ts
CHANGED
|
@@ -99,6 +99,12 @@ export type RunDevAppAuthOptions = {
|
|
|
99
99
|
/** Domain attribute for both auth cookies (see
|
|
100
100
|
* AuthRoutesConfig.cookieDomain). Symmetric zu RunProdAppAuthOptions. */
|
|
101
101
|
readonly cookieDomain?: string;
|
|
102
|
+
/** Server-side Origin allowlist for the CSRF guard (see
|
|
103
|
+
* AuthRoutesConfig.allowedOrigins). Symmetric zu RunProdAppAuthOptions —
|
|
104
|
+
* required once `cookieDomain` is set. */
|
|
105
|
+
readonly allowedOrigins?: readonly string[];
|
|
106
|
+
/** Opt out of the Origin guard. Symmetric zu RunProdAppAuthOptions. */
|
|
107
|
+
readonly unsafeSkipOriginCheck?: boolean;
|
|
102
108
|
};
|
|
103
109
|
|
|
104
110
|
/** Hook for app-specific seeding (demo data, fixtures). Runs after the
|
|
@@ -300,6 +306,12 @@ export async function runDevApp(options: RunDevAppOptions): Promise<KumikoServer
|
|
|
300
306
|
...(options.auth.cookieDomain !== undefined && {
|
|
301
307
|
cookieDomain: options.auth.cookieDomain,
|
|
302
308
|
}),
|
|
309
|
+
...(options.auth.allowedOrigins !== undefined && {
|
|
310
|
+
allowedOrigins: options.auth.allowedOrigins,
|
|
311
|
+
}),
|
|
312
|
+
...(options.auth.unsafeSkipOriginCheck !== undefined && {
|
|
313
|
+
unsafeSkipOriginCheck: options.auth.unsafeSkipOriginCheck,
|
|
314
|
+
}),
|
|
303
315
|
...sessionAuthFragment,
|
|
304
316
|
...(options.auth.passwordReset && {
|
|
305
317
|
passwordReset: {
|
package/src/run-prod-app.ts
CHANGED
|
@@ -280,6 +280,15 @@ export type RunProdAppAuthOptions = {
|
|
|
280
280
|
* AuthRoutesConfig.cookieDomain). Set to the registrable parent
|
|
281
281
|
* domain when login and app live on different subdomains. */
|
|
282
282
|
readonly cookieDomain?: string;
|
|
283
|
+
/** Server-side Origin allowlist for the CSRF guard (see
|
|
284
|
+
* AuthRoutesConfig.allowedOrigins). REQUIRED once `cookieDomain` is set —
|
|
285
|
+
* buildServer fails closed otherwise. Apex + admin host, never tenant
|
|
286
|
+
* subdomains. */
|
|
287
|
+
readonly allowedOrigins?: readonly string[];
|
|
288
|
+
/** Opt out of the Origin guard (see AuthRoutesConfig.unsafeSkipOriginCheck)
|
|
289
|
+
* — accept the wide-cookie CSRF risk explicitly instead of setting
|
|
290
|
+
* `allowedOrigins`. */
|
|
291
|
+
readonly unsafeSkipOriginCheck?: boolean;
|
|
283
292
|
};
|
|
284
293
|
|
|
285
294
|
/** Hook for app-specific seeding — runs after the admin (when auth is
|
|
@@ -725,6 +734,12 @@ export async function runProdApp(options: RunProdAppOptions): Promise<ProdAppHan
|
|
|
725
734
|
...(options.auth.cookieDomain !== undefined && {
|
|
726
735
|
cookieDomain: options.auth.cookieDomain,
|
|
727
736
|
}),
|
|
737
|
+
...(options.auth.allowedOrigins !== undefined && {
|
|
738
|
+
allowedOrigins: options.auth.allowedOrigins,
|
|
739
|
+
}),
|
|
740
|
+
...(options.auth.unsafeSkipOriginCheck !== undefined && {
|
|
741
|
+
unsafeSkipOriginCheck: options.auth.unsafeSkipOriginCheck,
|
|
742
|
+
}),
|
|
728
743
|
...sessionAuthFragment,
|
|
729
744
|
...(options.auth.passwordReset && {
|
|
730
745
|
passwordReset: {
|