@cosmicdrift/kumiko-dev-server 0.389.0 → 0.390.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/bin/kumiko-upgrade.ts +3 -1
- package/dist/build-server-bundle.js +4 -2
- package/dist/create-kumiko-server-stack.js +4 -3
- package/dist/create-kumiko-server.d.ts +4 -1
- package/dist/create-kumiko-server.js +2 -0
- package/dist/few-shot-corpus.d.ts +1 -1
- package/dist/few-shot-corpus.js +1 -1
- package/dist/managed-files/registry.js +1 -1
- package/dist/run-dev-app-server-options.js +1 -0
- package/dist/run-dev-app.d.ts +5 -2
- package/dist/scaffold-app.js +10 -7
- package/dist/scaffold-feature.js +1 -1
- package/dist/schema-apply.d.ts +3 -0
- package/dist/schema-apply.js +6 -2
- package/package.json +11 -10
- package/src/changes.json +26 -0
- package/templates/deploy/Dockerfile.template +1 -1
- package/templates/managed/kumiko-schema.ts.template +3 -0
package/bin/kumiko-upgrade.ts
CHANGED
|
@@ -17,6 +17,8 @@ import { runUpgradeCli } from "@cosmicdrift/kumiko-framework/upgrade-cli";
|
|
|
17
17
|
// biome-ignore lint/suspicious/noConsole: CLI output is the feature.
|
|
18
18
|
const out = { log: (l: string) => console.log(l), err: (l: string) => console.error(l) };
|
|
19
19
|
const appCwd = process.env["INIT_CWD"] ?? process.cwd();
|
|
20
|
-
const code = await runUpgradeCli(process.argv.slice(2), appCwd, out
|
|
20
|
+
const code = await runUpgradeCli(process.argv.slice(2), appCwd, out, {
|
|
21
|
+
codemodResolveFrom: import.meta.dir,
|
|
22
|
+
});
|
|
21
23
|
// Let the event loop drain stdout (piped by guard-upgrade-state) before exit.
|
|
22
24
|
process.exitCode = code;
|
|
@@ -59,7 +59,8 @@ const hasBun = typeof Bun !== "undefined";
|
|
|
59
59
|
// reference the package at runtime (no native binding, plain HTTP client,
|
|
60
60
|
// but a real runtime import). A production crash in money-horse,
|
|
61
61
|
// "Cannot find package 'meilisearch'", occurred because it used to be in
|
|
62
|
-
// BUILD_ONLY_EXTERNALS instead.
|
|
62
|
+
// BUILD_ONLY_EXTERNALS instead. Its version comes from the framework's
|
|
63
|
+
// peerDependencies range.
|
|
63
64
|
const RUNTIME_EXTERNALS = [
|
|
64
65
|
"@node-rs/argon2",
|
|
65
66
|
"sharp",
|
|
@@ -296,7 +297,8 @@ async function resolveRuntimeDepsVersions(cwd, repoRoot, packages) {
|
|
|
296
297
|
continue;
|
|
297
298
|
const raw = await readFile(path, "utf-8");
|
|
298
299
|
const parsed = parseJsonOrThrow(raw, path);
|
|
299
|
-
|
|
300
|
+
// Peers first: a real dependency of the same source overrides a peer range.
|
|
301
|
+
Object.assign(allDeps, parsed.peerDependencies ?? {}, parsed.dependencies ?? {}, parsed.optionalDependencies ?? {});
|
|
300
302
|
}
|
|
301
303
|
// App package.json fills gaps only — pins extraRuntimeExternals without
|
|
302
304
|
// overriding framework-native pins the app may also list.
|
|
@@ -39,6 +39,7 @@ function buildDevStackOptions(options, dbMode) {
|
|
|
39
39
|
...(options.extraRoutes !== undefined && { extraRoutes: options.extraRoutes }),
|
|
40
40
|
...(options.trustedProxyHops !== undefined && { trustedProxyHops: options.trustedProxyHops }),
|
|
41
41
|
...(options.errorDocs && { errorDocs: options.errorDocs }),
|
|
42
|
+
...(options.rowLevelSecurity !== undefined && { rowLevelSecurity: options.rowLevelSecurity }),
|
|
42
43
|
// jobs.consumerLane unset = enqueuer-only; startDevJobRunners is the sole
|
|
43
44
|
// consumer/cron-scheduler per lane, so runOnBoot/cron jobs don't
|
|
44
45
|
// double-fire.
|
|
@@ -48,7 +49,7 @@ function buildDevStackOptions(options, dbMode) {
|
|
|
48
49
|
export async function bootDevStack(options, dbMode) {
|
|
49
50
|
logInfo(`[kumiko-server] booting Kumiko stack${dbMode.persistentDb ? ` — persistent DB "${dbMode.devDbName}"` : " — ephemeral test DB"}…`);
|
|
50
51
|
const stack = await setupTestStack(buildDevStackOptions(options, dbMode));
|
|
51
|
-
await createEventsTable(stack.
|
|
52
|
+
await createEventsTable(stack.unscopedDb);
|
|
52
53
|
await pushEntityProjectionTables(stack, stack.registry);
|
|
53
54
|
// `extraRoutes` is already mounted by setupTestStack's buildServer();
|
|
54
55
|
// `wire` is for co-running components that need the system-write
|
|
@@ -86,13 +87,13 @@ export async function startDevBackgroundRunners(stack, jobQueueNamePrefix) {
|
|
|
86
87
|
registry: stack.registry,
|
|
87
88
|
db: stack.db,
|
|
88
89
|
// The stack's own AppContext, not a `{ db, registry }` literal: these
|
|
89
|
-
// runners consume the lanes, and a job reaching for ctx.files /
|
|
90
|
+
// runners consume the lanes, and a job reaching for ctx.services.files /
|
|
90
91
|
// ctx.notify / ctx.config would otherwise die here while the very same
|
|
91
92
|
// handler works on the request path.
|
|
92
93
|
context: stack.context,
|
|
93
94
|
redisUrl,
|
|
94
95
|
// Same dispatcher the request path writes through — without this,
|
|
95
|
-
// ctx.write/ctx.writeAs/ctx.queryAs inside a dev-run job throw on their
|
|
96
|
+
// ctx.dispatch.write/ctx.dispatch.writeAs/ctx.dispatch.queryAs inside a dev-run job throw on their
|
|
96
97
|
// first call.
|
|
97
98
|
dispatcher: stack.dispatcher,
|
|
98
99
|
// Must match setupTestStack's jobs.queueNamePrefix so enqueuer and
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="bun-types" preserve="true" />
|
|
2
2
|
import type { AuthRoutesConfig, ExtraRouteDefinition } from "@cosmicdrift/kumiko-framework/api";
|
|
3
|
+
import { type RowLevelSecurityMode } from "@cosmicdrift/kumiko-framework/db";
|
|
3
4
|
import { type FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
5
|
import type { ErrorDocsConfig } from "@cosmicdrift/kumiko-framework/errors";
|
|
5
6
|
import type { PageHeadResolver, PageHeadSystemQuery } from "@cosmicdrift/kumiko-renderer/headless/apex";
|
|
@@ -64,6 +65,8 @@ export type DevHostDispatch = (req: Request, deps: {
|
|
|
64
65
|
readonly cspScriptHashes: readonly string[];
|
|
65
66
|
}) => DevHostDispatchResult | Promise<DevHostDispatchResult>;
|
|
66
67
|
export type CreateKumikoServerOptions = {
|
|
68
|
+
/** Row level security of the dev stack, as in prod. Default "on", so tenant-isolation bugs show up in development. */
|
|
69
|
+
readonly rowLevelSecurity?: RowLevelSecurityMode;
|
|
67
70
|
/** Features whose entities, handlers, and screens get wired into the
|
|
68
71
|
* dev stack. Pass every feature the app is supposed to run. */
|
|
69
72
|
readonly features: readonly FeatureDefinition[];
|
|
@@ -141,7 +144,7 @@ export type CreateKumikoServerOptions = {
|
|
|
141
144
|
readonly anonymousAccess?: TestStackOptions["anonymousAccess"];
|
|
142
145
|
/** File-storage provider forwarded to `setupTestStack`. When set, the
|
|
143
146
|
* stack mounts the upload routes (POST/GET/DELETE /api/files), exposes
|
|
144
|
-
* `ctx.files`, and creates the `file_refs` table. Example:
|
|
147
|
+
* `ctx.services.files`, and creates the `file_refs` table. Example:
|
|
145
148
|
* `{ storageProvider: createInMemoryFileProvider() }`. */
|
|
146
149
|
readonly files?: TestStackOptions["files"];
|
|
147
150
|
/** Feature-toggle resolver forwarded to `setupTestStack`. When set, the
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
//
|
|
15
15
|
// The companion prod entry will land at `@cosmicdrift/kumiko-framework/server`
|
|
16
16
|
// with a different options shape (clientDist, auth config, db url).
|
|
17
|
+
import { assertNoActiveRowLevelSecurityScope, } from "@cosmicdrift/kumiko-framework/db";
|
|
17
18
|
import { buildAppSchema } from "@cosmicdrift/kumiko-framework/engine";
|
|
18
19
|
import { buildBunServeOptions, resolveDerivedMaxRequestBodySize, } from "@cosmicdrift/kumiko-server-runtime/bun-serve-options";
|
|
19
20
|
import { stripNoRouteMatchHeader } from "@cosmicdrift/kumiko-server-runtime/try-hono-first";
|
|
@@ -33,6 +34,7 @@ import { hasBun, logInfo } from "./dev-server-runtime.js";
|
|
|
33
34
|
function startDevHttpServer(port, handleFetch, stack) {
|
|
34
35
|
if (!hasBun)
|
|
35
36
|
return undefined;
|
|
37
|
+
assertNoActiveRowLevelSecurityScope("dev server");
|
|
36
38
|
return Bun.serve(buildBunServeOptions(port, handleFetch, resolveDerivedMaxRequestBodySize(stack.registry), {
|
|
37
39
|
upgradeFetch: async (req, env) => stripNoRouteMatchHeader(await stack.app.fetch(req, env)),
|
|
38
40
|
}));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FeaturePattern, type ParseError } from "@cosmicdrift/kumiko-
|
|
1
|
+
import { type FeaturePattern, type ParseError } from "@cosmicdrift/kumiko-feature-ast";
|
|
2
2
|
export type AuthoringStyle = "canonical" | "legacy";
|
|
3
3
|
export type CorpusWarning = {
|
|
4
4
|
/** Repo-relative path to the file that triggered the warning. */
|
package/dist/few-shot-corpus.js
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// builder is permissive, and the Designer filters at read-time.
|
|
32
32
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
33
33
|
import { dirname, join, relative, resolve } from "node:path";
|
|
34
|
-
import { PATTERN_LIBRARY, parseFeatureFile, } from "@cosmicdrift/kumiko-
|
|
34
|
+
import { PATTERN_LIBRARY, parseFeatureFile, } from "@cosmicdrift/kumiko-feature-ast";
|
|
35
35
|
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
36
36
|
// =============================================================================
|
|
37
37
|
// Builder
|
|
@@ -101,7 +101,7 @@ export function renderManagedTemplates(facts) {
|
|
|
101
101
|
});
|
|
102
102
|
return [
|
|
103
103
|
...deploy.files
|
|
104
|
-
// Managed apps migrate through the
|
|
104
|
+
// Managed apps migrate through the migrate-db initContainer of the infra _app-deploy.yml; migrate-step.sh is compose-only.
|
|
105
105
|
.filter((file) => file.output !== COMPOSE_ONLY_DEPLOY_FILE)
|
|
106
106
|
.map((file) => marked(`deploy/${file.output}`, file.content, "#", file.output.endsWith(".sh"))),
|
|
107
107
|
marked(".husky/pre-push", readTemplate("husky-pre-push.template"), "#", true),
|
|
@@ -3,6 +3,7 @@ function pickDevClientOptions(options) {
|
|
|
3
3
|
return {
|
|
4
4
|
...(options.clientEntry !== undefined && { clientEntry: options.clientEntry }),
|
|
5
5
|
...(options.errorDocs && { errorDocs: options.errorDocs }),
|
|
6
|
+
...(options.rowLevelSecurity !== undefined && { rowLevelSecurity: options.rowLevelSecurity }),
|
|
6
7
|
...(options.clientEntries !== undefined && { clientEntries: options.clientEntries }),
|
|
7
8
|
...(options.hostDispatch !== undefined && { hostDispatch: options.hostDispatch }),
|
|
8
9
|
...(options.resolvePageHead !== undefined && { resolvePageHead: options.resolvePageHead }),
|
package/dist/run-dev-app.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SeedAdminOptions } from "@cosmicdrift/kumiko-bundled-features/auth-email-password/seeding";
|
|
2
2
|
import type { PostAuthLandingResolver } from "@cosmicdrift/kumiko-framework/api";
|
|
3
3
|
import type { KmsAdapter } from "@cosmicdrift/kumiko-framework/crypto";
|
|
4
|
+
import type { RowLevelSecurityMode } from "@cosmicdrift/kumiko-framework/db";
|
|
4
5
|
import { type BundledListsOptions, type FeatureDefinition, type Registry, type ValidateBootOptions } from "@cosmicdrift/kumiko-framework/engine";
|
|
5
6
|
import type { ComposedEnvSchema } from "@cosmicdrift/kumiko-framework/env";
|
|
6
7
|
import type { ErrorDocsConfig } from "@cosmicdrift/kumiko-framework/errors";
|
|
@@ -128,7 +129,7 @@ export type RunDevAppOptions = {
|
|
|
128
129
|
readonly extraContext?: CreateKumikoServerOptions["extraContext"];
|
|
129
130
|
/** App-level config values, same semantics and merge as RunProdAppOptions["appOverrides"]. */
|
|
130
131
|
readonly appOverrides?: ConfigOverridesInput;
|
|
131
|
-
/** MasterKeyProvider for the automatically wired `ctx.secrets`. Defaults to
|
|
132
|
+
/** MasterKeyProvider for the automatically wired `ctx.services.secrets`. Defaults to
|
|
132
133
|
* `createEnvMasterKeyProvider`; override it for KMS backends. Only relevant
|
|
133
134
|
* when the secrets feature is mounted. Symmetric with runProdApp. */
|
|
134
135
|
readonly masterKey?: MasterKeyProvider;
|
|
@@ -153,7 +154,7 @@ export type RunDevAppOptions = {
|
|
|
153
154
|
* role in `access.roles`. */
|
|
154
155
|
readonly anonymousAccess?: CreateKumikoServerOptions["anonymousAccess"];
|
|
155
156
|
/** File-Storage-Provider — aktiviert die Upload-Routes (/api/files) +
|
|
156
|
-
* `ctx.files`. Demos: `{ storageProvider: createInMemoryFileProvider() }`. */
|
|
157
|
+
* `ctx.services.files`. Demos: `{ storageProvider: createInMemoryFileProvider() }`. */
|
|
157
158
|
readonly files?: CreateKumikoServerOptions["files"];
|
|
158
159
|
/** App-defined HTTP routes, such as /feed.xml and /sitemap.xml. They are
|
|
159
160
|
* attached to the Hono app before the static-asset path. Symmetric with the
|
|
@@ -202,6 +203,8 @@ export type RunDevAppOptions = {
|
|
|
202
203
|
readonly trustedProxyHops?: number;
|
|
203
204
|
/** Links the app's own error reasons to its own docs (`docsUrl` in error responses); framework reasons keep the framework docs link. */
|
|
204
205
|
readonly errorDocs?: ErrorDocsConfig;
|
|
206
|
+
/** Row level security of the dev stack, as in prod. Default "on", so tenant-isolation bugs show up in development. */
|
|
207
|
+
readonly rowLevelSecurity?: RowLevelSecurityMode;
|
|
205
208
|
};
|
|
206
209
|
export declare function runDevApp(options: RunDevAppOptions): Promise<KumikoServerHandle>;
|
|
207
210
|
export declare function mergeConfigResolverDefault(ctx: CreateKumikoServerOptions["extraContext"], registry: Registry, envSource: Record<string, string | undefined>, cipher?: EnvelopeCipher, appOverrides?: ConfigOverridesInput): CreateKumikoServerOptions["extraContext"];
|
package/dist/scaffold-app.js
CHANGED
|
@@ -21,6 +21,7 @@ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
|
21
21
|
import { dirname, join, resolve } from "node:path";
|
|
22
22
|
import { APP_CONFIG_FILE } from "@cosmicdrift/kumiko-framework/config";
|
|
23
23
|
import { collectTableMetas, generateMigration, writeSnapshotJson, } from "@cosmicdrift/kumiko-framework/db";
|
|
24
|
+
import { DEFAULT_ROW_LEVEL_SECURITY_MODE } from "@cosmicdrift/kumiko-framework/internal/row-level-security";
|
|
24
25
|
import { escapeHtml } from "@cosmicdrift/kumiko-renderer/headless";
|
|
25
26
|
import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";
|
|
26
27
|
import { resolveFrameworkVersion } from "./framework-version.js";
|
|
@@ -161,7 +162,7 @@ function renderPackageJson(name, version, testSetup, infraRef) {
|
|
|
161
162
|
"@cosmicdrift/kumiko-server-runtime": version,
|
|
162
163
|
react: "^19.2.6",
|
|
163
164
|
"react-dom": "^19.2.6",
|
|
164
|
-
zod: "^4.
|
|
165
|
+
zod: "^4.6.7",
|
|
165
166
|
},
|
|
166
167
|
devDependencies: sortedByName({
|
|
167
168
|
"@biomejs/biome": SCAFFOLD_BIOME_VERSION,
|
|
@@ -396,6 +397,7 @@ const kmsWiring =
|
|
|
396
397
|
await runProdApp({
|
|
397
398
|
features: APP_FEATURES,
|
|
398
399
|
...(appConfig.validateBootOptions && { validateBootOptions: appConfig.validateBootOptions }),
|
|
400
|
+
...(appConfig.rowLevelSecurity && { rowLevelSecurity: appConfig.rowLevelSecurity }),
|
|
399
401
|
envSchema,
|
|
400
402
|
staticDir: "./dist",
|
|
401
403
|
...kmsWiring,
|
|
@@ -412,12 +414,9 @@ function renderServer(appName) {
|
|
|
412
414
|
{ specifier: "../kumiko.config", names: [], defaultName: "appConfig" },
|
|
413
415
|
{ specifier: "../src/seed", names: ["seedDemoTasks"] },
|
|
414
416
|
]);
|
|
415
|
-
// Dev-only emailVerified skips the login verify gate for the seeded admin;
|
|
416
|
-
// prod's bin/main.ts leaves it unset because the verify flow must run there.
|
|
417
417
|
const authBlock = renderAdminAuthBlock(appName, [
|
|
418
418
|
'password: "changeme",',
|
|
419
419
|
'displayName: "Admin",',
|
|
420
|
-
"emailVerified: true,",
|
|
421
420
|
]);
|
|
422
421
|
return `// Dev bootstrap. \`bun --watch bin/server.ts\` (see package.json scripts.dev)
|
|
423
422
|
// starts a full-featured dev server with auto-reload on code changes.
|
|
@@ -715,10 +714,10 @@ function renderBinKumiko() {
|
|
|
715
714
|
"// consumer status|restart <name>` to recover a dead event consumer without",
|
|
716
715
|
"// ad-hoc SQL. kumiko-build bundles this file to dist-server/kumiko.js.",
|
|
717
716
|
"",
|
|
718
|
-
'import { allAppFeatures } from "@cosmicdrift/kumiko-framework/config";',
|
|
719
717
|
'import { runConsumerCli } from "@cosmicdrift/kumiko-framework/consumer-cli";',
|
|
720
718
|
'import { kmsSlotsOf } from "@cosmicdrift/kumiko-framework/env";',
|
|
721
719
|
'import { runSchemaCli } from "@cosmicdrift/kumiko-framework/schema-cli";',
|
|
720
|
+
'import { FEATURES } from "../kumiko/schema";',
|
|
722
721
|
'import appConfig from "../kumiko.config";',
|
|
723
722
|
'import { envSchema } from "./env-schema";',
|
|
724
723
|
"",
|
|
@@ -726,10 +725,13 @@ function renderBinKumiko() {
|
|
|
726
725
|
"const out = { log: (l: string) => console.log(l), err: (l: string) => console.error(l) };",
|
|
727
726
|
"",
|
|
728
727
|
'if (cmd === "schema") {',
|
|
729
|
-
" const features = allAppFeatures(appConfig);",
|
|
730
728
|
" const kmsSlots = kmsSlotsOf(envSchema.schema);",
|
|
731
729
|
" process.exit(",
|
|
732
|
-
" await runSchemaCli(rest, process.env.INIT_CWD ?? process.cwd(), out, {
|
|
730
|
+
" await runSchemaCli(rest, process.env.INIT_CWD ?? process.cwd(), out, {",
|
|
731
|
+
" features: FEATURES,",
|
|
732
|
+
" kmsSlots,",
|
|
733
|
+
" ...(appConfig.rowLevelSecurity && { rowLevelSecurity: appConfig.rowLevelSecurity }),",
|
|
734
|
+
" }),",
|
|
733
735
|
" );",
|
|
734
736
|
"}",
|
|
735
737
|
"",
|
|
@@ -774,6 +776,7 @@ async function writeInitMigration(destination, features) {
|
|
|
774
776
|
const metas = collectTableMetas(composed);
|
|
775
777
|
const result = generateMigration({
|
|
776
778
|
metas,
|
|
779
|
+
rowLevelSecurity: DEFAULT_ROW_LEVEL_SECURITY_MODE,
|
|
777
780
|
prevSnapshot: null,
|
|
778
781
|
name: "init",
|
|
779
782
|
sequenceNumber: 1,
|
package/dist/scaffold-feature.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// scaffolding).
|
|
13
13
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
14
14
|
import { join, resolve } from "node:path";
|
|
15
|
-
import { renderFeatureFile, } from "@cosmicdrift/kumiko-
|
|
15
|
+
import { renderFeatureFile, } from "@cosmicdrift/kumiko-feature-ast";
|
|
16
16
|
/**
|
|
17
17
|
* Generate a starter feature workspace at `destination`. Throws when
|
|
18
18
|
* the destination already exists — refuses to overwrite. The caller is
|
package/dist/schema-apply.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type RowLevelSecurityMode } from "@cosmicdrift/kumiko-framework/db";
|
|
1
2
|
import { type FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
3
|
import { type ComposeFeaturesOptions } from "@cosmicdrift/kumiko-server-runtime/compose-features";
|
|
3
4
|
export type SchemaApplyOptions = ComposeFeaturesOptions & {
|
|
@@ -6,6 +7,8 @@ export type SchemaApplyOptions = ComposeFeaturesOptions & {
|
|
|
6
7
|
readonly features: readonly FeatureDefinition[];
|
|
7
8
|
/** Default INIT_CWD ?? process.cwd(); migrations live under <appCwd>/kumiko/migrations. */
|
|
8
9
|
readonly appCwd?: string;
|
|
10
|
+
/** Pass appConfig.rowLevelSecurity: on a role the policies bind, migrations and rebuilds only see rows through an "on" connection. Default "on". */
|
|
11
|
+
readonly rowLevelSecurity?: RowLevelSecurityMode;
|
|
9
12
|
};
|
|
10
13
|
export declare function runSchemaApply(opts: SchemaApplyOptions): Promise<number>;
|
|
11
14
|
export declare function runStandaloneSchemaCli(opts: SchemaApplyOptions): Promise<never>;
|
package/dist/schema-apply.js
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
// kumiko-build discovers the app bin via findRepoRoot() and bundles it.
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
9
|
import { join } from "node:path";
|
|
10
|
-
import { createDbConnection, runMigrationsFromDir } from "@cosmicdrift/kumiko-framework/db";
|
|
10
|
+
import { createDbConnection, runMigrationsFromDir, } from "@cosmicdrift/kumiko-framework/db";
|
|
11
11
|
import { createRegistry } from "@cosmicdrift/kumiko-framework/engine";
|
|
12
12
|
import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
13
|
+
import { DEFAULT_ROW_LEVEL_SECURITY_MODE } from "@cosmicdrift/kumiko-framework/internal/row-level-security";
|
|
13
14
|
import { queueRebuildsFromMarkers, reportPendingRebuildRun, runPendingRebuilds, } from "@cosmicdrift/kumiko-framework/migrations";
|
|
14
15
|
import { createEventConsumerStateTable, createProjectionStateTable, } from "@cosmicdrift/kumiko-framework/pipeline";
|
|
15
16
|
import { composeFeatures, } from "@cosmicdrift/kumiko-server-runtime/compose-features";
|
|
@@ -25,7 +26,10 @@ export async function runSchemaApply(opts) {
|
|
|
25
26
|
console.error(`\n ${migrationsDir} is missing — kumiko/migrations/ must be part of the image.\n`);
|
|
26
27
|
return 1;
|
|
27
28
|
}
|
|
28
|
-
const { db, close } = createDbConnection({
|
|
29
|
+
const { db, close } = createDbConnection({
|
|
30
|
+
url: dbUrl,
|
|
31
|
+
rowLevelSecurity: opts.rowLevelSecurity ?? DEFAULT_ROW_LEVEL_SECURITY_MODE,
|
|
32
|
+
});
|
|
29
33
|
try {
|
|
30
34
|
// Create infrastructure tables (event store + pipeline state) first; all are
|
|
31
35
|
// tableExists-gated and idempotent: on an existing DB this is a no-op, while
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-dev-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.390.1",
|
|
4
4
|
"description": "Dev-tooling for Kumiko apps: local dev-server bootstrap (runDevApp), scaffolding. Its compose-stacks/env-schema subpaths are consumed at prod boot too — see @cosmicdrift/kumiko-server-runtime for the prod runner itself.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -77,16 +77,17 @@
|
|
|
77
77
|
"kumiko-upgrade": "./bin/kumiko-upgrade.ts"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
81
|
-
"@cosmicdrift/kumiko-
|
|
82
|
-
"@cosmicdrift/kumiko-
|
|
83
|
-
"@cosmicdrift/kumiko-renderer
|
|
84
|
-
"@cosmicdrift/kumiko-
|
|
85
|
-
"@cosmicdrift/kumiko-
|
|
86
|
-
"@cosmicdrift/kumiko-
|
|
87
|
-
"@cosmicdrift/kumiko-
|
|
80
|
+
"@cosmicdrift/kumiko-bundled-features": "0.390.1",
|
|
81
|
+
"@cosmicdrift/kumiko-feature-ast": "0.390.1",
|
|
82
|
+
"@cosmicdrift/kumiko-framework": "0.390.1",
|
|
83
|
+
"@cosmicdrift/kumiko-renderer": "0.390.1",
|
|
84
|
+
"@cosmicdrift/kumiko-renderer-mail-html": "0.390.1",
|
|
85
|
+
"@cosmicdrift/kumiko-guards": "0.390.1",
|
|
86
|
+
"@cosmicdrift/kumiko-server-runtime": "0.390.1",
|
|
87
|
+
"@cosmicdrift/kumiko-testing": "0.390.1",
|
|
88
|
+
"@cosmicdrift/kumiko-types": "0.390.1",
|
|
88
89
|
"ts-morph": "^28.0.0",
|
|
89
|
-
"zod": "^4.
|
|
90
|
+
"zod": "^4.6.7"
|
|
90
91
|
},
|
|
91
92
|
"peerDependencies": {
|
|
92
93
|
"bun-types": "^1.4.4"
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,30 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.390.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "The managed Dockerfile names the real k3s migration step",
|
|
6
|
+
"detail": "The comment above the migrations COPY in the managed Dockerfile pointed at a release.yml InitContainer that does not exist. It now names the migrate-db initContainer of the infra _app-deploy.yml, and migrate-step.sh for compose hosts. Only the comment changes; the next kumiko-upgrade shows it as a managed-file diff."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.390.0",
|
|
10
|
+
"type": "fix",
|
|
11
|
+
"title": "Scaffolded bin/kumiko.ts passes FEATURES from kumiko/schema",
|
|
12
|
+
"detail": "The scaffolded standalone CLI handed allAppFeatures(appConfig) to runSchemaCli, a raw list without the bundled foundation. It now imports FEATURES from kumiko/schema, which the Schema CLI Features guard requires. Existing apps are not touched."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"version": "0.390.0",
|
|
16
|
+
"type": "breaking",
|
|
17
|
+
"title": "The dev server runs with row level security on",
|
|
18
|
+
"detail": "runDevApp and createKumikoServer default to rowLevelSecurity \"on\" and run the dev stack as kumiko_app. On boot against a persistent dev database, the stack creates the role and transfers ownership of the database and of the public schema's tables, views and sequences to kumiko_app. The database user in DATABASE_URL needs the right to create roles, which the superuser of a local Postgres has. Code that reads tenant tables through a raw connection without a scope sees no rows in development; the boot does not detect this. runSchemaApply takes rowLevelSecurity, and the managed kumiko/schema.ts exports ROW_LEVEL_SECURITY from appConfig; the managed file updates on the next sync.",
|
|
19
|
+
"migration": "Pass rowLevelSecurity: \"off\" to runDevApp while fixing code paths without tenant context; the dev database keeps kumiko_app as owner. A server entry written by an older scaffold passes appConfig.rowLevelSecurity to runProdApp by hand once the app turns row level security on. Manual migration, there is no codemod."
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"version": "0.390.0",
|
|
23
|
+
"type": "improvement",
|
|
24
|
+
"title": "Scaffolded dev admin leaves emailVerified to the boot seed",
|
|
25
|
+
"detail": "The boot seed marks the operator-created admin and the seed shortcut accounts as email-verified, so the scaffolded `bin/server.ts` no longer sets `emailVerified: true` on its own. Self-registered users still go through the verify flow.",
|
|
26
|
+
"migration": "Optional. Existing apps can drop `emailVerified: true` from `auth.admin` in `bin/server.ts` and `bin/main.ts`; an explicit value still wins over the default."
|
|
27
|
+
},
|
|
2
28
|
{
|
|
3
29
|
"version": "0.389.0",
|
|
4
30
|
"type": "improvement",
|
|
@@ -70,7 +70,7 @@ RUN bun install --production --frozen-lockfile
|
|
|
70
70
|
COPY --from=build --chown=app:app /app/dist ./dist
|
|
71
71
|
|
|
72
72
|
# Checked-in SQL migrations for the pre-deploy `kumiko schema apply` step
|
|
73
|
-
# (
|
|
73
|
+
# (migrate-db initContainer of the infra _app-deploy.yml on k3s, or migrate-step.sh on compose hosts).
|
|
74
74
|
# The shipped `kumiko-schema` bin reads `${INIT_CWD}/kumiko/migrations/*.sql`
|
|
75
75
|
# (see ENV INIT_CWD=/app below). kumiko/schema.ts is NOT needed at runtime
|
|
76
76
|
# (only generate reads it; apply is checksum-tracked SQL only).
|
|
@@ -28,4 +28,7 @@ export const FEATURES: readonly FeatureDefinition[] = composeFeatures([...CONFIG
|
|
|
28
28
|
// `kumiko check` validates the boot with the options kumiko.config.ts declares.
|
|
29
29
|
export const VALIDATE_BOOT_OPTIONS = appConfig.validateBootOptions;
|
|
30
30
|
|
|
31
|
+
// Decides whether `generate` emits row-level-security policies and `apply` runs as a policy-enforced connection.
|
|
32
|
+
export const ROW_LEVEL_SECURITY = appConfig.rowLevelSecurity;
|
|
33
|
+
|
|
31
34
|
export const ENTITY_METAS: readonly EntityTableMeta[] = collectTableMetas(FEATURES);
|