@cosmicdrift/kumiko-dev-server 0.163.3 → 0.165.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.165.0",
|
|
4
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>",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"kumiko-schema-check": "./bin/kumiko-schema-check.ts"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
58
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
59
|
-
"@cosmicdrift/kumiko-server-runtime": "0.
|
|
57
|
+
"@cosmicdrift/kumiko-bundled-features": "0.165.0",
|
|
58
|
+
"@cosmicdrift/kumiko-framework": "0.165.0",
|
|
59
|
+
"@cosmicdrift/kumiko-server-runtime": "0.165.0",
|
|
60
60
|
"ts-morph": "^28.0.0"
|
|
61
61
|
},
|
|
62
62
|
"publishConfig": {
|
|
@@ -144,6 +144,31 @@ describe("composeStacks boots for real", () => {
|
|
|
144
144
|
expect(() => validateBoot(features)).not.toThrow();
|
|
145
145
|
});
|
|
146
146
|
|
|
147
|
+
test("money-horse-shaped composeGdprStack({sessions:true}) without a tokenVerifier provider fails boot", () => {
|
|
148
|
+
// Regression pin for the open design question this stack shape raised:
|
|
149
|
+
// composeGdprStack({sessions:true}) mounts auth-foundation, which
|
|
150
|
+
// hard-requires at least one tokenVerifier provider. Without composing
|
|
151
|
+
// one in (money-horse/solon's real run-config passes none), boot must
|
|
152
|
+
// fail loudly instead of silently shipping an unauthenticatable app.
|
|
153
|
+
const features = composeFeatures([...composeGdprStack({ sessions: true })], {
|
|
154
|
+
includeBundled: true,
|
|
155
|
+
});
|
|
156
|
+
expect(() => validateBoot(features)).toThrow(/no tokenVerifier providers registered/i);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("composeGdprStack({sessions:true, providers:[...]}) passes boot with a tokenVerifier mounted", () => {
|
|
160
|
+
const features = composeFeatures(
|
|
161
|
+
[
|
|
162
|
+
...composeGdprStack({
|
|
163
|
+
sessions: true,
|
|
164
|
+
providers: [createPersonalAccessTokensFeature({ scopes: {} })],
|
|
165
|
+
}),
|
|
166
|
+
],
|
|
167
|
+
{ includeBundled: true },
|
|
168
|
+
);
|
|
169
|
+
expect(() => validateBoot(features)).not.toThrow();
|
|
170
|
+
});
|
|
171
|
+
|
|
147
172
|
// auth-mfa's encrypted fields need a runtime KEK (env or configureEntityFieldEncryption
|
|
148
173
|
// + secrets). Name-list + saas-identity-wire.integration.test.ts cover identity boot.
|
|
149
174
|
test("identity stack names compose with ops + renderer under includeBundled", () => {
|
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
// createKumikoServer error / graceful-degradation paths — boot rejects,
|
|
2
2
|
// stylesheet pipeline failures, missing CSS route.
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { describe, expect, test } from "bun:test";
|
|
5
5
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
|
|
9
|
-
import { createKumikoServer
|
|
9
|
+
import { createKumikoServer } from "../create-kumiko-server";
|
|
10
10
|
|
|
11
11
|
const emptyFeature = defineFeature("dev-server-errors-probe", () => {});
|
|
12
12
|
|
|
13
|
-
let handle: KumikoServerHandle | undefined;
|
|
14
|
-
|
|
15
|
-
afterEach(async () => {
|
|
16
|
-
if (handle) {
|
|
17
|
-
await handle.stop();
|
|
18
|
-
handle = undefined;
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
13
|
describe("createKumikoServer — client bundle failure", () => {
|
|
23
14
|
test("broken clientEntry rejects at boot with client bundle failed", async () => {
|
|
24
15
|
const tmpDir = mkdtempSync(join(tmpdir(), "kumiko-bundle-fail-"));
|
package/src/compose-stacks.ts
CHANGED
|
@@ -59,6 +59,11 @@ export type GdprStackOptions = {
|
|
|
59
59
|
readonly order?: GdprStackOrder;
|
|
60
60
|
readonly sessions?: boolean;
|
|
61
61
|
readonly tenantLifecycle?: boolean;
|
|
62
|
+
/** tokenVerifier provider(s) for auth-foundation when `sessions` is on.
|
|
63
|
+
* Without at least one, auth-foundation's boot check throws ("no
|
|
64
|
+
* tokenVerifier providers registered"). Omit only if the app mounts a
|
|
65
|
+
* provider itself elsewhere. */
|
|
66
|
+
readonly providers?: readonly FeatureDefinition[];
|
|
62
67
|
};
|
|
63
68
|
|
|
64
69
|
export type UserDataRightsStackOptions = {
|
|
@@ -79,15 +84,14 @@ export type OpsStackOptions = {
|
|
|
79
84
|
/** sessions (+ optional auth-mfa). config/user/tenant/auth-email-password stay
|
|
80
85
|
* on composeFeatures(includeBundled). Pass `mfa` options to mount TOTP.
|
|
81
86
|
* When `sessions` is on (the default), auth-foundation is mounted alongside it —
|
|
82
|
-
* the framework's registry now hard-requires it (sessions.requires("auth-foundation"))
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
+
* the framework's registry now hard-requires it (sessions.requires("auth-foundation")),
|
|
88
|
+
* which in turn needs at least one tokenVerifier provider mounted by the caller
|
|
89
|
+
* (e.g. createPersonalAccessTokensFeature({ scopes })) — PAT scopes are app-specific
|
|
90
|
+
* (which write-handlers an API token may call), so they stay caller-owned instead of
|
|
91
|
+
* a framework default. */
|
|
87
92
|
export type IdentityStackOptions = {
|
|
88
93
|
readonly sessions?: boolean;
|
|
89
94
|
readonly mfa?: AuthMfaFeatureOptions;
|
|
90
|
-
readonly providers?: readonly FeatureDefinition[];
|
|
91
95
|
};
|
|
92
96
|
|
|
93
97
|
export function stackFeatureNames(features: readonly FeatureDefinition[]): string[] {
|
|
@@ -139,7 +143,10 @@ export function composeGdprStack(options: GdprStackOptions = {}): FeatureDefinit
|
|
|
139
143
|
const out: FeatureDefinition[] =
|
|
140
144
|
order === "compliance-first" ? [compliance, retention] : [retention, compliance];
|
|
141
145
|
if (options.tenantLifecycle) out.push(createTenantLifecycleFeature());
|
|
142
|
-
if (options.sessions)
|
|
146
|
+
if (options.sessions) {
|
|
147
|
+
out.push(authFoundationFeature, createSessionsFeature());
|
|
148
|
+
if (options.providers) out.push(...options.providers);
|
|
149
|
+
}
|
|
143
150
|
return out;
|
|
144
151
|
}
|
|
145
152
|
|
|
@@ -172,7 +179,6 @@ export function composeIdentityStack(options: IdentityStackOptions = {}): Featur
|
|
|
172
179
|
const out: FeatureDefinition[] = [];
|
|
173
180
|
if (sessions) {
|
|
174
181
|
out.push(authFoundationFeature, createSessionsFeature());
|
|
175
|
-
if (options.providers) out.push(...options.providers);
|
|
176
182
|
}
|
|
177
183
|
if (options.mfa !== undefined) out.push(createAuthMfaFeature(options.mfa));
|
|
178
184
|
return out;
|