kozou 0.1.0 → 0.1.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/README.md CHANGED
@@ -50,17 +50,20 @@ DATABASE_URL=postgres://kozou:kozou@localhost:5432/kozou \
50
50
 
51
51
  The `${DATABASE_URL}` placeholder inside the bundled
52
52
  `kozou.config.yaml` template is what consumes that env var; the
53
- CLI does not honor `KOZOU_DATABASE_URL` directly (an alias is on
54
- the v0.1.1 roadmap). HTTP transport (`--http`) is also reserved
55
- for v0.1.1.
53
+ `kozou` CLI does not honor `KOZOU_DATABASE_URL` directly (an alias
54
+ is on the roadmap). HTTP transport is available via
55
+ `kozou mcp --http` (`--port` / `--host` configure the listener;
56
+ stdio stays the default).
56
57
 
57
58
  ### `kozou dev`
58
59
 
59
- Reserved for v0.1.1. In v0.1.0 the command prints a hand-off
60
- message listing the subcommands available today
61
- (`kozou mcp --stdio`, `kozou inspect`) and exits. In v0.1.1 it
62
- will spawn the bundled `@kozou/svelte-ui` Admin UI + an MCP HTTP
63
- server.
60
+ Runs the bundled `@kozou/svelte-ui` Admin UI (adapter-node)
61
+ alongside an MCP HTTP server, both wired up from
62
+ `kozou.config.yaml`. The Admin UI listens on port 3333 and the MCP
63
+ HTTP server on 3334 by default (override via `server.ui` /
64
+ `server.mcp.http` in the config); `Ctrl-C` (SIGINT / SIGTERM)
65
+ tears both down. This is the command behind the `kozou` service in
66
+ the scaffolded `docker-compose.yml`.
64
67
 
65
68
  ### `create-kozou <dir>`
66
69
 
@@ -74,11 +77,9 @@ cp .env.example .env
74
77
  docker compose up
75
78
  ```
76
79
 
77
- The generated `docker-compose.yml` brings up PostgreSQL + PostgREST.
78
- The `kozou` service block (which would host the Admin UI + MCP HTTP
79
- server) is commented out in v0.1.0; it gets reactivated in v0.1.1
80
- once `kozou dev` ships as a real implementation rather than a
81
- hand-off placeholder.
80
+ The generated `docker-compose.yml` brings up PostgreSQL, PostgREST,
81
+ and a `kozou` service that runs `kozou dev` to host the Admin UI +
82
+ MCP HTTP server.
82
83
 
83
84
  ## Configuration
84
85
 
package/dist/cli.js CHANGED
@@ -25,22 +25,24 @@ program
25
25
  });
26
26
  program
27
27
  .command('mcp')
28
- .description('Run the MCP server (stdio in v0.1; HTTP in v0.1.1).')
28
+ .description('Run the MCP server (--stdio default, or --http).')
29
29
  .option('--stdio', 'use stdio transport (default)')
30
- .option('--http', 'use HTTP transport (scheduled for v0.1.1)')
31
- .option('--port <n>', 'HTTP port', (raw) => parseInt(raw, 10))
30
+ .option('--http', 'use Streamable HTTP transport')
31
+ .option('--port <n>', 'HTTP port (default 3334)', (raw) => parseInt(raw, 10))
32
+ .option('--host <host>', 'HTTP bind host (default 127.0.0.1)')
32
33
  .option('--config <path>', 'path to kozou.config.yaml')
33
34
  .action(async (flags) => {
34
35
  await mcpCommand({
35
36
  stdio: flags.stdio,
36
37
  http: flags.http,
37
38
  port: flags.port,
39
+ host: flags.host,
38
40
  config: flags.config,
39
41
  });
40
42
  });
41
43
  program
42
44
  .command('dev')
43
- .description('Run the bundled Admin UI + MCP HTTP dev server (v0.1.1).')
45
+ .description('Run the bundled Admin UI + MCP HTTP dev server.')
44
46
  .option('--config <path>', 'path to kozou.config.yaml')
45
47
  .action(async (flags) => {
46
48
  await devCommand({ config: flags.config });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,gEAAgE;AAChE,6CAA6C;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAmB7C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;KAC1B,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CACV,mFAAmF,CACpF;KACA,OAAO,CAAC,eAAe,CAAC,CAAC;AAE5B,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,CAAC;KAC9D,MAAM,CAAC,iBAAiB,EAAE,4BAA4B,EAAE,GAAG,CAAC;KAC5D,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,CAAC;KACtD,MAAM,CAAC,KAAK,EAAE,KAAmB,EAAE,EAAE;IACpC,MAAM,cAAc,CAAC;QACnB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,qDAAqD,CAAC;KAClE,MAAM,CAAC,SAAS,EAAE,+BAA+B,CAAC;KAClD,MAAM,CAAC,QAAQ,EAAE,2CAA2C,CAAC;KAC7D,MAAM,CAAC,YAAY,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;KAC7D,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,CAAC;KACtD,MAAM,CAAC,KAAK,EAAE,KAAe,EAAE,EAAE;IAChC,MAAM,UAAU,CAAC;QACf,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,CAAC;KACtD,MAAM,CAAC,KAAK,EAAE,KAAe,EAAE,EAAE;IAChC,MAAM,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,gEAAgE;AAChE,6CAA6C;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAoB7C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;KAC1B,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CACV,mFAAmF,CACpF;KACA,OAAO,CAAC,eAAe,CAAC,CAAC;AAE5B,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,CAAC;KAC9D,MAAM,CAAC,iBAAiB,EAAE,4BAA4B,EAAE,GAAG,CAAC;KAC5D,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,CAAC;KACtD,MAAM,CAAC,KAAK,EAAE,KAAmB,EAAE,EAAE;IACpC,MAAM,cAAc,CAAC;QACnB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,kDAAkD,CAAC;KAC/D,MAAM,CAAC,SAAS,EAAE,+BAA+B,CAAC;KAClD,MAAM,CAAC,QAAQ,EAAE,+BAA+B,CAAC;KACjD,MAAM,CAAC,YAAY,EAAE,0BAA0B,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;KAC5E,MAAM,CAAC,eAAe,EAAE,oCAAoC,CAAC;KAC7D,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,CAAC;KACtD,MAAM,CAAC,KAAK,EAAE,KAAe,EAAE,EAAE;IAChC,MAAM,UAAU,CAAC;QACf,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,iDAAiD,CAAC;KAC9D,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,CAAC;KACtD,MAAM,CAAC,KAAK,EAAE,KAAe,EAAE,EAAE;IAChC,MAAM,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { KozouConfig } from '../config.js';
2
+ export declare function resolveAdminUiEntry(): string;
3
+ export declare function resolveOrigin(config: KozouConfig, env: NodeJS.ProcessEnv): string;
4
+ export declare function buildAdminUiEnv(config: KozouConfig, origin: string, baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
5
+ //# sourceMappingURL=dev-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-runtime.d.ts","sourceRoot":"","sources":["../../src/commands/dev-runtime.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAOhD,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAMD,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAEjF;AAID,wBAAgB,eAAe,CAC7B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,UAAU,GACzB,MAAM,CAAC,UAAU,CAUnB"}
@@ -0,0 +1,38 @@
1
+ // Pure wiring helpers for `kozou dev` (see commands/dev.ts).
2
+ //
3
+ // Kept separate from the spawn / lifecycle shell in dev.ts so the
4
+ // config -> child-process-env / origin / entry-path mapping can be unit
5
+ // tested without launching any servers.
6
+ import { createRequire } from 'node:module';
7
+ import { dirname, join } from 'node:path';
8
+ // Resolve the Admin UI's adapter-node standalone server entry. The
9
+ // `build/` directory ships in @kozou/svelte-ui's published `files`, and
10
+ // resolving the package's own package.json works whether kozou runs from
11
+ // a flat node_modules tree (Docker / npm install) or a workspace symlink
12
+ // (local dev).
13
+ export function resolveAdminUiEntry() {
14
+ const require = createRequire(import.meta.url);
15
+ const pkgJsonPath = require.resolve('@kozou/svelte-ui/package.json');
16
+ return join(dirname(pkgJsonPath), 'build', 'index.js');
17
+ }
18
+ // The browser-facing origin the Admin UI must accept form posts from.
19
+ // An explicit ORIGIN / KOZOU_ORIGIN wins; otherwise default to localhost
20
+ // on the UI port (host stays 0.0.0.0 for binding, but browsers reach it
21
+ // as localhost in the common single-host case).
22
+ export function resolveOrigin(config, env) {
23
+ return env.ORIGIN ?? env.KOZOU_ORIGIN ?? `http://localhost:${config.server.ui.port}`;
24
+ }
25
+ // Build the child-process environment for the Admin UI server. Keeping
26
+ // it pure makes the wiring unit-testable without spawning anything.
27
+ export function buildAdminUiEnv(config, origin, baseEnv) {
28
+ return {
29
+ ...baseEnv,
30
+ DATABASE_URL: config.database.url,
31
+ KOZOU_ADAPTER_URL: config.adapter.url,
32
+ PORT: String(config.server.ui.port),
33
+ HOST: config.server.ui.host,
34
+ ORIGIN: origin,
35
+ NODE_ENV: 'production',
36
+ };
37
+ }
38
+ //# sourceMappingURL=dev-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-runtime.js","sourceRoot":"","sources":["../../src/commands/dev-runtime.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,kEAAkE;AAClE,wEAAwE;AACxE,wCAAwC;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAI1C,mEAAmE;AACnE,wEAAwE;AACxE,yEAAyE;AACzE,yEAAyE;AACzE,eAAe;AACf,MAAM,UAAU,mBAAmB;IACjC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC;IACrE,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AACzD,CAAC;AAED,sEAAsE;AACtE,yEAAyE;AACzE,wEAAwE;AACxE,gDAAgD;AAChD,MAAM,UAAU,aAAa,CAAC,MAAmB,EAAE,GAAsB;IACvE,OAAO,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,YAAY,IAAI,oBAAoB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;AACvF,CAAC;AAED,uEAAuE;AACvE,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAC7B,MAAmB,EACnB,MAAc,EACd,OAA0B;IAE1B,OAAO;QACL,GAAG,OAAO;QACV,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG;QACjC,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG;QACrC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC;QACnC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI;QAC3B,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,YAAY;KACvB,CAAC;AACJ,CAAC"}
@@ -1,5 +1,5 @@
1
1
  export type DevOptions = {
2
2
  config?: string;
3
3
  };
4
- export declare function devCommand(_opts?: DevOptions): Promise<void>;
4
+ export declare function devCommand(opts?: DevOptions): Promise<void>;
5
5
  //# sourceMappingURL=dev.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAeF,wBAAsB,UAAU,CAAC,KAAK,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAcF,wBAAsB,UAAU,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ErE"}
@@ -1,21 +1,96 @@
1
1
  // `kozou dev` command implementation.
2
2
  //
3
- // In v0.1 this is a deliberate stub: the Admin UI (`@kozou/svelte-ui`) is
4
- // scheduled for v0.1.1 per the Kozou v0.1 design spec §16.1.1 B, so there is nothing for the
5
- // dev server to host yet. Until the UI lands, we print a hand-off message
6
- // pointing adopters at `kozou mcp --stdio` for AI agent access.
7
- const DEV_HANDOFF_MESSAGE = 'kozou dev: the bundled Admin UI is scheduled for v0.1.1.\n' +
8
- ' See Kozou v0.1 design spec §16.1.1 B for the roadmap and §8 for the\n' +
9
- ' @kozou/svelte-ui specification.\n' +
10
- '\n' +
11
- ' Available today:\n' +
12
- ' kozou mcp --stdio Run the MCP server for AI agent access.\n' +
13
- ' kozou inspect Dump the Schema Context as JSON or YAML.\n';
14
- // The leading underscore on `_opts` flags this as a deliberately ignored
15
- // parameter (eslint argsIgnorePattern: ^_). The full DevOptions shape is
16
- // kept in the signature so it matches the v0.1.1 implementation that
17
- // will actually consume the config.
18
- export async function devCommand(_opts = {}) {
19
- process.stderr.write(DEV_HANDOFF_MESSAGE);
3
+ // Brings up the full local runtime described in Kozou v0.1 spec §9.1:
4
+ // - the bundled @kozou/svelte-ui Admin UI, spawned as a child process
5
+ // (`node <svelte-ui>/build/index.js` the adapter-node standalone
6
+ // server, the same entry the svelte-ui E2E suite exercises);
7
+ // - the MCP Streamable HTTP server, run in-process via @kozou/mcp's
8
+ // startHttpServer (spec §7.1).
9
+ //
10
+ // Both default to 0.0.0.0 (spec §9.1, so `docker compose` port mapping
11
+ // works); a loud warning fires on a non-loopback bind because neither
12
+ // surface authenticates in v0.1 (spec §18.5).
13
+ //
14
+ // The Admin UI is an adapter-node (SvelteKit) server: without ORIGIN it
15
+ // assumes https and rejects every form POST over plain http with a 403.
16
+ // We default ORIGIN to http://localhost:<ui-port>; override via the
17
+ // ORIGIN / KOZOU_ORIGIN env when serving on a different public URL.
18
+ import { spawn } from 'node:child_process';
19
+ import { existsSync } from 'node:fs';
20
+ import { SchemaCache, startHttpServer, isLoopbackHost } from '@kozou/mcp';
21
+ import { loadConfig } from '../config.js';
22
+ import { buildAdminUiEnv, resolveAdminUiEntry, resolveOrigin, } from './dev-runtime.js';
23
+ const PREFIX = '[kozou dev]';
24
+ function warnIfPublic(label, host) {
25
+ if (isLoopbackHost(host))
26
+ return;
27
+ process.stderr.write(`${PREFIX} WARNING: ${label} bound to non-loopback host "${host}".\n` +
28
+ `${PREFIX} v0.1 has NO authentication (spec §18.5). Anyone who can reach\n` +
29
+ `${PREFIX} ${host} can use it. This is expected inside docker compose;\n` +
30
+ `${PREFIX} avoid it on an untrusted network or put an auth proxy in front.\n`);
31
+ }
32
+ export async function devCommand(opts = {}) {
33
+ const config = await loadConfig({ path: opts.config });
34
+ const adminUiEntry = resolveAdminUiEntry();
35
+ if (!existsSync(adminUiEntry)) {
36
+ throw new Error(`${PREFIX} Admin UI build not found at ${adminUiEntry}. ` +
37
+ 'Reinstall @kozou/svelte-ui (its `build/` output ships in the package), ' +
38
+ 'or in a workspace checkout run `pnpm --filter @kozou/svelte-ui run build`.');
39
+ }
40
+ const cache = new SchemaCache({
41
+ connection: config.database.url,
42
+ schemas: config.database.schemas,
43
+ ttlMs: config.cache.ttlMs,
44
+ });
45
+ // 1. MCP HTTP, in-process. startHttpServer already warns on a
46
+ // non-loopback bind, so we do not double-warn for it.
47
+ const mcp = await startHttpServer(cache, {
48
+ port: config.server.mcp.http.port,
49
+ host: config.server.mcp.http.host,
50
+ logPrefix: `${PREFIX} mcp`,
51
+ });
52
+ // 2. Admin UI, as a child process.
53
+ warnIfPublic('Admin UI', config.server.ui.host);
54
+ const origin = resolveOrigin(config, process.env);
55
+ const child = spawn('node', [adminUiEntry], {
56
+ env: buildAdminUiEnv(config, origin, process.env),
57
+ stdio: ['ignore', 'pipe', 'pipe'],
58
+ });
59
+ child.stdout?.on('data', (b) => process.stdout.write(`${PREFIX} ui | ${b}`));
60
+ child.stderr?.on('data', (b) => process.stderr.write(`${PREFIX} ui | ${b}`));
61
+ process.stderr.write(`${PREFIX} Admin UI on http://${config.server.ui.host}:${config.server.ui.port}` +
62
+ ` (origin ${origin})\n`);
63
+ // 3. Lifecycle: tear both down together. Resolve the promise (and thus
64
+ // let the CLI exit) only once everything has stopped.
65
+ await new Promise((resolve) => {
66
+ let shuttingDown = false;
67
+ const shutdown = (reason) => {
68
+ if (shuttingDown)
69
+ return;
70
+ shuttingDown = true;
71
+ process.stderr.write(`${PREFIX} ${reason}, shutting down\n`);
72
+ if (child.exitCode === null && child.signalCode === null) {
73
+ child.kill('SIGTERM');
74
+ }
75
+ void mcp.close().finally(() => resolve());
76
+ };
77
+ process.on('SIGINT', () => shutdown('SIGINT received'));
78
+ process.on('SIGTERM', () => shutdown('SIGTERM received'));
79
+ child.on('exit', (code, signal) => {
80
+ if (shuttingDown)
81
+ return;
82
+ // The Admin UI process died on its own — surface its exit status
83
+ // and bring the MCP server down with it.
84
+ process.stderr.write(`${PREFIX} Admin UI exited (code=${code ?? 'null'}, signal=${signal ?? 'null'})\n`);
85
+ process.exitCode = code ?? 1;
86
+ shuttingDown = true;
87
+ void mcp.close().finally(() => resolve());
88
+ });
89
+ child.on('error', (err) => {
90
+ process.stderr.write(`${PREFIX} failed to spawn Admin UI: ${err.message}\n`);
91
+ process.exitCode = 1;
92
+ shutdown('spawn error');
93
+ });
94
+ });
20
95
  }
21
96
  //# sourceMappingURL=dev.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,0EAA0E;AAC1E,6FAA6F;AAC7F,0EAA0E;AAC1E,gEAAgE;AAMhE,MAAM,mBAAmB,GACvB,4DAA4D;IAC5D,yEAAyE;IACzE,qCAAqC;IACrC,IAAI;IACJ,sBAAsB;IACtB,mEAAmE;IACnE,oEAAoE,CAAC;AAEvE,yEAAyE;AACzE,yEAAyE;AACzE,qEAAqE;AACrE,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAoB,EAAE;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ export type McpOptions = {
2
2
  stdio?: boolean;
3
3
  http?: boolean;
4
4
  port?: number;
5
+ host?: string;
5
6
  config?: string;
6
7
  };
7
8
  export declare function mcpCommand(opts?: McpOptions): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAOF,wBAAsB,UAAU,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBrE"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAsB,UAAU,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBrE"}
@@ -2,28 +2,28 @@
2
2
  //
3
3
  // --stdio: spins up the @kozou/mcp server with a stdio transport, reading
4
4
  // connection details from kozou.config.yaml / environment.
5
- // --http: deferred to v0.1.1 per the Kozou v0.1 design spec §16.1.1 B.
6
- // Prints a hand-off note to stderr and exits cleanly.
5
+ // --http: spins up the @kozou/mcp server with the Streamable HTTP
6
+ // transport (Kozou v0.1 spec §7.1), binding to localhost by default and
7
+ // exposing POST /admin/refresh for cache invalidation (§7.5).
7
8
  //
8
9
  // See Kozou v0.1 design spec §9.1 and §7.
9
- import { SchemaCache, startStdioServer } from '@kozou/mcp';
10
+ import { SchemaCache, startHttpServer, startStdioServer } from '@kozou/mcp';
10
11
  import { loadConfig } from '../config.js';
11
- const HTTP_HANDOFF_MESSAGE = 'kozou mcp --http: HTTP transport is scheduled for v0.1.1.\n' +
12
- ' See Kozou v0.1 design spec §16.1.1 B for the roadmap.\n' +
13
- ' Use --stdio for now (the default).\n';
14
12
  export async function mcpCommand(opts = {}) {
15
- // --http is deferred to v0.1.1 (HTTP transport not yet implemented in
16
- // the underlying @kozou/mcp package).
17
- if (opts.http === true) {
18
- process.stderr.write(HTTP_HANDOFF_MESSAGE);
19
- return;
20
- }
21
13
  const config = await loadConfig({ path: opts.config });
22
14
  const cache = new SchemaCache({
23
15
  connection: config.database.url,
24
16
  schemas: config.database.schemas,
25
17
  ttlMs: config.cache.ttlMs,
26
18
  });
19
+ if (opts.http === true) {
20
+ await startHttpServer(cache, {
21
+ port: opts.port,
22
+ host: opts.host,
23
+ logPrefix: '[kozou mcp]',
24
+ });
25
+ return;
26
+ }
27
27
  await startStdioServer(cache, { logPrefix: '[kozou mcp]' });
28
28
  }
29
29
  //# sourceMappingURL=mcp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,0EAA0E;AAC1E,6DAA6D;AAC7D,uEAAuE;AACvE,wDAAwD;AACxD,EAAE;AACF,0CAA0C;AAE1C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAS1C,MAAM,oBAAoB,GACxB,6DAA6D;IAC7D,2DAA2D;IAC3D,wCAAwC,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAmB,EAAE;IACpD,sEAAsE;IACtE,sCAAsC;IACtC,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEvD,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC;QAC5B,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG;QAC/B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;QAChC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK;KAC1B,CAAC,CAAC;IAEH,MAAM,gBAAgB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,0EAA0E;AAC1E,6DAA6D;AAC7D,kEAAkE;AAClE,0EAA0E;AAC1E,gEAAgE;AAChE,EAAE;AACF,0CAA0C;AAE1C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAU1C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAmB,EAAE;IACpD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEvD,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC;QAC5B,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG;QAC/B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;QAChC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK;KAC1B,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,eAAe,CAAC,KAAK,EAAE;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,aAAa;SACzB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,gBAAgB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;AAC9D,CAAC"}
package/dist/config.d.ts CHANGED
@@ -2,156 +2,32 @@ import { z } from 'zod';
2
2
  declare const configSchema: z.ZodObject<{
3
3
  database: z.ZodObject<{
4
4
  url: z.ZodString;
5
- schemas: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
6
- }, "strip", z.ZodTypeAny, {
7
- url: string;
8
- schemas: string[];
9
- }, {
10
- url: string;
11
- schemas?: string[] | undefined;
12
- }>;
13
- server: z.ZodDefault<z.ZodObject<{
14
- ui: z.ZodDefault<z.ZodObject<{
5
+ schemas: z.ZodDefault<z.ZodArray<z.ZodString>>;
6
+ }, z.core.$strip>;
7
+ server: z.ZodPrefault<z.ZodObject<{
8
+ ui: z.ZodPrefault<z.ZodObject<{
15
9
  port: z.ZodDefault<z.ZodNumber>;
16
10
  host: z.ZodDefault<z.ZodString>;
17
- }, "strip", z.ZodTypeAny, {
18
- port: number;
19
- host: string;
20
- }, {
21
- port?: number | undefined;
22
- host?: string | undefined;
23
- }>>;
24
- mcp: z.ZodDefault<z.ZodObject<{
25
- http: z.ZodDefault<z.ZodObject<{
11
+ }, z.core.$strip>>;
12
+ mcp: z.ZodPrefault<z.ZodObject<{
13
+ http: z.ZodPrefault<z.ZodObject<{
26
14
  port: z.ZodDefault<z.ZodNumber>;
27
15
  host: z.ZodDefault<z.ZodString>;
28
- }, "strip", z.ZodTypeAny, {
29
- port: number;
30
- host: string;
31
- }, {
32
- port?: number | undefined;
33
- host?: string | undefined;
34
- }>>;
16
+ }, z.core.$strip>>;
35
17
  stdio: z.ZodDefault<z.ZodBoolean>;
36
- }, "strip", z.ZodTypeAny, {
37
- http: {
38
- port: number;
39
- host: string;
40
- };
41
- stdio: boolean;
42
- }, {
43
- http?: {
44
- port?: number | undefined;
45
- host?: string | undefined;
46
- } | undefined;
47
- stdio?: boolean | undefined;
48
- }>>;
49
- }, "strip", z.ZodTypeAny, {
50
- ui: {
51
- port: number;
52
- host: string;
53
- };
54
- mcp: {
55
- http: {
56
- port: number;
57
- host: string;
58
- };
59
- stdio: boolean;
60
- };
61
- }, {
62
- ui?: {
63
- port?: number | undefined;
64
- host?: string | undefined;
65
- } | undefined;
66
- mcp?: {
67
- http?: {
68
- port?: number | undefined;
69
- host?: string | undefined;
70
- } | undefined;
71
- stdio?: boolean | undefined;
72
- } | undefined;
73
- }>>;
74
- adapter: z.ZodDefault<z.ZodObject<{
18
+ }, z.core.$strip>>;
19
+ }, z.core.$strip>>;
20
+ adapter: z.ZodPrefault<z.ZodObject<{
75
21
  type: z.ZodDefault<z.ZodLiteral<"postgrest">>;
76
22
  url: z.ZodDefault<z.ZodString>;
77
- }, "strip", z.ZodTypeAny, {
78
- type: "postgrest";
79
- url: string;
80
- }, {
81
- type?: "postgrest" | undefined;
82
- url?: string | undefined;
83
- }>>;
84
- uiHints: z.ZodDefault<z.ZodObject<{
23
+ }, z.core.$strip>>;
24
+ uiHints: z.ZodPrefault<z.ZodObject<{
85
25
  path: z.ZodDefault<z.ZodNullable<z.ZodString>>;
86
- }, "strip", z.ZodTypeAny, {
87
- path: string | null;
88
- }, {
89
- path?: string | null | undefined;
90
- }>>;
91
- cache: z.ZodDefault<z.ZodObject<{
26
+ }, z.core.$strip>>;
27
+ cache: z.ZodPrefault<z.ZodObject<{
92
28
  ttlMs: z.ZodDefault<z.ZodNumber>;
93
- }, "strip", z.ZodTypeAny, {
94
- ttlMs: number;
95
- }, {
96
- ttlMs?: number | undefined;
97
- }>>;
98
- }, "strip", z.ZodTypeAny, {
99
- database: {
100
- url: string;
101
- schemas: string[];
102
- };
103
- server: {
104
- ui: {
105
- port: number;
106
- host: string;
107
- };
108
- mcp: {
109
- http: {
110
- port: number;
111
- host: string;
112
- };
113
- stdio: boolean;
114
- };
115
- };
116
- adapter: {
117
- type: "postgrest";
118
- url: string;
119
- };
120
- uiHints: {
121
- path: string | null;
122
- };
123
- cache: {
124
- ttlMs: number;
125
- };
126
- }, {
127
- database: {
128
- url: string;
129
- schemas?: string[] | undefined;
130
- };
131
- server?: {
132
- ui?: {
133
- port?: number | undefined;
134
- host?: string | undefined;
135
- } | undefined;
136
- mcp?: {
137
- http?: {
138
- port?: number | undefined;
139
- host?: string | undefined;
140
- } | undefined;
141
- stdio?: boolean | undefined;
142
- } | undefined;
143
- } | undefined;
144
- adapter?: {
145
- type?: "postgrest" | undefined;
146
- url?: string | undefined;
147
- } | undefined;
148
- uiHints?: {
149
- path?: string | null | undefined;
150
- } | undefined;
151
- cache?: {
152
- ttlMs?: number | undefined;
153
- } | undefined;
154
- }>;
29
+ }, z.core.$strip>>;
30
+ }, z.core.$strip>;
155
31
  export type KozouConfig = z.infer<typeof configSchema>;
156
32
  export type KozouConfigIssue = {
157
33
  path: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwDxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMhB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIvD,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;gBACrB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE;CAMjF;AAMD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA6CF,wBAAsB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,CA2CnF"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+DxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMhB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIvD,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;gBACrB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE;CAMjF;AAMD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA2DF,wBAAsB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,CA2CnF"}
package/dist/config.js CHANGED
@@ -4,52 +4,64 @@
4
4
  // against the process environment, fills in defaults, and validates the
5
5
  // result with zod. Every field has a default so kozou can run with only the
6
6
  // DATABASE_URL environment variable set, per the Kozou v0.1 design spec §9.2.
7
+ //
8
+ // A literal `$$` escapes to a single `$`, so `$${VAR}` produces the literal
9
+ // text `${VAR}` instead of expanding it. Expansion is single-level by design:
10
+ // a value substituted from the environment is never re-scanned, so a secret
11
+ // that legitimately contains `${...}` (e.g. inside a DATABASE_URL password) is
12
+ // preserved rather than mistaken for a placeholder. See expandEnvVars below.
7
13
  import { readFile } from 'node:fs/promises';
8
14
  import { existsSync } from 'node:fs';
9
15
  import { resolve, isAbsolute } from 'node:path';
10
16
  import { parse as parseYAML } from 'yaml';
11
17
  import { z } from 'zod';
12
18
  // ---- Schema ---------------------------------------------------------------
19
+ // Nested sections use `.prefault({})` rather than `.default({})`: in zod 4
20
+ // `.default(v)` short-circuits to `v` as-is when the input is undefined (so
21
+ // it would need the fully-populated object), whereas `.prefault(v)` feeds
22
+ // `v` back through the schema so each field's own `.default(...)` still
23
+ // applies. `.prefault({})` therefore reproduces the zod 3 behaviour of
24
+ // "absent section -> object filled entirely from inner defaults".
13
25
  const uiServerSchema = z
14
26
  .object({
15
27
  port: z.number().int().min(0).max(65_535).default(3333),
16
28
  host: z.string().min(1).default('0.0.0.0'),
17
29
  })
18
- .default({});
30
+ .prefault({});
19
31
  const mcpHttpServerSchema = z
20
32
  .object({
21
33
  port: z.number().int().min(0).max(65_535).default(3334),
22
34
  host: z.string().min(1).default('0.0.0.0'),
23
35
  })
24
- .default({});
36
+ .prefault({});
25
37
  const mcpServerSchema = z
26
38
  .object({
27
39
  http: mcpHttpServerSchema,
28
40
  stdio: z.boolean().default(false),
29
41
  })
30
- .default({});
42
+ .prefault({});
31
43
  const serverSchema = z
32
44
  .object({
33
45
  ui: uiServerSchema,
34
46
  mcp: mcpServerSchema,
35
47
  })
36
- .default({});
48
+ .prefault({});
37
49
  const adapterSchema = z
38
50
  .object({
39
51
  type: z.literal('postgrest').default('postgrest'),
40
52
  url: z.string().min(1).default('http://postgrest:3000'),
41
53
  })
42
- .default({});
54
+ .prefault({});
43
55
  const uiHintsSchema = z
44
56
  .object({
45
57
  path: z.string().nullable().default(null),
46
58
  })
47
- .default({});
59
+ .prefault({});
48
60
  const cacheSchema = z
49
61
  .object({
50
62
  ttlMs: z.number().int().min(0).default(60_000),
51
63
  })
52
- .default({});
64
+ .prefault({});
53
65
  const databaseSchema = z.object({
54
66
  url: z.string().min(1, 'database.url is required (set DATABASE_URL or kozou.config.yaml)'),
55
67
  schemas: z.array(z.string().min(1)).default(['public']),
@@ -73,10 +85,22 @@ export class KozouConfigError extends Error {
73
85
  }
74
86
  // ---- Loader --------------------------------------------------------------
75
87
  const DEFAULT_CONFIG_PATH = 'kozou.config.yaml';
76
- const ENV_VAR_RE = /\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g;
88
+ // Matches either an escaped `$$` (which becomes a literal `$`) or a
89
+ // `${VAR}` / `${VAR:-default}` placeholder. `$$` is listed first so the
90
+ // alternation consumes it before the placeholder branch can see a stray `$`.
91
+ const ENV_TOKEN_RE = /\$\$|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g;
77
92
  function expandEnvVars(value, env) {
78
93
  if (typeof value === 'string') {
79
- return value.replace(ENV_VAR_RE, (_match, name, fallback) => {
94
+ return value.replace(ENV_TOKEN_RE, (match, name, fallback) => {
95
+ // `$$` -> literal `$`. So `$${VAR}` yields the literal `${VAR}`:
96
+ // the trailing `{VAR}` is left untouched because it no longer has
97
+ // a `$` prefix to start a placeholder.
98
+ if (match === '$$')
99
+ return '$';
100
+ // Otherwise `match` is a `${...}` placeholder and `name` is its
101
+ // (always-present) variable name. The substituted value is taken
102
+ // verbatim and never re-scanned (single-level expansion), so a
103
+ // value containing `${...}` is preserved as-is.
80
104
  const v = env[name];
81
105
  if (v !== undefined)
82
106
  return v;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const PACKAGE_VERSION = "0.1.0";
1
+ export declare const PACKAGE_VERSION: string;
2
2
  export { loadConfig, KozouConfigError } from './config.js';
3
3
  export type { KozouConfig, KozouConfigIssue, LoadConfigOptions } from './config.js';
4
4
  export { inspectCommand } from './commands/inspect.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEpF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxE,YAAY,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,eAAe,QAAc,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEpF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxE,YAAY,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -2,7 +2,18 @@
2
2
  // commands programmatically. The bin entry points live in cli.ts and
3
3
  // create-kozou.ts; this module re-exports the underlying primitives so
4
4
  // integrators can build their own glue if they need to.
5
- export const PACKAGE_VERSION = '0.1.0';
5
+ import { readFileSync } from 'node:fs';
6
+ import { createRequire } from 'node:module';
7
+ // `package.json` is the single source of truth for the version. Read it
8
+ // at module load (the same createRequire idiom commands/dev-runtime.ts
9
+ // uses to resolve a sibling package) instead of hardcoding a copy here,
10
+ // so a release bump in package.json can never drift from this constant.
11
+ // `../package.json` resolves to packages/kozou/package.json from the
12
+ // compiled dist/index.js, and npm always ships package.json in the
13
+ // published tarball.
14
+ const require = createRequire(import.meta.url);
15
+ const pkg = JSON.parse(readFileSync(require.resolve('../package.json'), 'utf8'));
16
+ export const PACKAGE_VERSION = pkg.version;
6
17
  export { loadConfig, KozouConfigError } from './config.js';
7
18
  export { inspectCommand } from './commands/inspect.js';
8
19
  export { mcpCommand } from './commands/mcp.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,qEAAqE;AACrE,uEAAuE;AACvE,wDAAwD;AAExD,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,qEAAqE;AACrE,uEAAuE;AACvE,wDAAwD;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,wEAAwE;AACxE,uEAAuE;AACvE,wEAAwE;AACxE,wEAAwE;AACxE,qEAAqE;AACrE,mEAAmE;AACnE,qBAAqB;AACrB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAE9E,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,qBAAqB,GAAG;IAClC,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAyBD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWpF"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,qBAAqB,GAAG;IAClC,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAyBD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBpF"}
package/dist/scaffold.js CHANGED
@@ -6,8 +6,7 @@
6
6
  // stays a normal file because npm's tarball handling for dotfiles
7
7
  // inside published packages can be surprising).
8
8
  import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
9
- import { existsSync } from 'node:fs';
10
- import { join } from 'node:path';
9
+ import { dirname, join } from 'node:path';
11
10
  import { fileURLToPath } from 'node:url';
12
11
  const DEFAULT_TEMPLATE_DIR = fileURLToPath(new URL('./templates', import.meta.url));
13
12
  export class KozouScaffoldError extends Error {
@@ -44,11 +43,23 @@ export async function createKozouScaffold(opts) {
44
43
  if (target === '') {
45
44
  throw new KozouScaffoldError('create-kozou: target directory is required');
46
45
  }
47
- if (existsSync(target)) {
48
- throw new KozouScaffoldError(`create-kozou: "${target}" already exists`);
49
- }
50
46
  const templatesDir = opts.templatesDir ?? DEFAULT_TEMPLATE_DIR;
51
- await mkdir(target, { recursive: true });
47
+ // Create any missing parent directories, then create the target itself
48
+ // with a NON-recursive mkdir so an already-existing target fails
49
+ // atomically with EEXIST. A recursive mkdir silently succeeds on an
50
+ // existing directory, so the previous existsSync()-then-mkdir guard had
51
+ // a TOCTOU window (the target could be created between the check and the
52
+ // mkdir); letting mkdir own the "must not exist" check closes it.
53
+ await mkdir(dirname(target), { recursive: true });
54
+ try {
55
+ await mkdir(target);
56
+ }
57
+ catch (err) {
58
+ if (err.code === 'EEXIST') {
59
+ throw new KozouScaffoldError(`create-kozou: "${target}" already exists`);
60
+ }
61
+ throw err;
62
+ }
52
63
  await copyRecursive(templatesDir, target);
53
64
  }
54
65
  //# sourceMappingURL=scaffold.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,uEAAuE;AACvE,kEAAkE;AAClE,gDAAgD;AAEhD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,oBAAoB,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AASpF,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,IAAY;IACpD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC;QAC5B,mEAAmE;QACnE,+DAA+D;QAC/D,oCAAoC;QACpC,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACnD,UAAU,GAAG,cAAc,CAAC;QAC9B,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,MAAM,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACnD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;QACD,4DAA4D;IAC9D,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAA2B;IACnE,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,kBAAkB,CAAC,4CAA4C,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,kBAAkB,CAAC,kBAAkB,MAAM,kBAAkB,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,oBAAoB,CAAC;IAC/D,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,uEAAuE;AACvE,kEAAkE;AAClE,gDAAgD;AAEhD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,oBAAoB,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AASpF,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,IAAY;IACpD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC;QAC5B,mEAAmE;QACnE,+DAA+D;QAC/D,oCAAoC;QACpC,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACnD,UAAU,GAAG,cAAc,CAAC;QAC9B,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,MAAM,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACnD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;QACD,4DAA4D;IAC9D,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAA2B;IACnE,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,kBAAkB,CAAC,4CAA4C,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,oBAAoB,CAAC;IAC/D,uEAAuE;IACvE,iEAAiE;IACjE,oEAAoE;IACpE,wEAAwE;IACxE,yEAAyE;IACzE,kEAAkE;IAClE,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,IAAI,kBAAkB,CAAC,kBAAkB,MAAM,kBAAkB,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,MAAM,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAC5C,CAAC"}
@@ -1,15 +1,12 @@
1
1
  # Docker Compose stack for a kozou project.
2
2
  #
3
- # Brings up (v0.1.0):
3
+ # Brings up:
4
4
  # - postgres PostgreSQL 16 (the source of truth)
5
5
  # - postgrest REST adapter consumed by the Kozou DataAdapter
6
6
  # (MIT-licensed external dependency, not bundled)
7
- #
8
- # The `kozou` service block is commented out for v0.1.0: the
9
- # published `ghcr.io/kozou-dev/kozou:v0.1.0` image's entrypoint is
10
- # the `kozou` CLI, which does not bind a port. Host integration
11
- # (`kozou dev` spawning the bundled Admin UI + MCP HTTP server)
12
- # lands in v0.1.1; uncomment the block then.
7
+ # - kozou `kozou dev` - the bundled Admin UI + MCP HTTP server
8
+ # (ghcr.io/kozou-dev/kozou). Binds 0.0.0.0 inside the
9
+ # container so the port mappings below reach your host.
13
10
  #
14
11
  # Customize the credentials in .env before running `docker compose up`.
15
12
 
@@ -42,22 +39,26 @@ services:
42
39
  postgres:
43
40
  condition: service_healthy
44
41
 
45
- # kozou:
46
- # # v0.1.1: reactivate once `kozou dev` spawns the bundled
47
- # # @kozou/svelte-ui Admin UI + MCP HTTP server. v0.1.0 only
48
- # # ships the CLI entrypoint, which exits immediately when
49
- # # run without arguments and therefore would bring no port
50
- # # online.
51
- # image: ghcr.io/kozou-dev/kozou:v0.1.0
52
- # command: ["dev"]
53
- # environment:
54
- # DATABASE_URL: postgres://${POSTGRES_USER:-kozou}:${POSTGRES_PASSWORD:-kozou}@postgres:5432/${POSTGRES_DB:-kozou}
55
- # KOZOU_ADAPTER_URL: http://postgrest:3000
56
- # depends_on:
57
- # postgres:
58
- # condition: service_healthy
59
- # postgrest:
60
- # condition: service_started
61
- # ports:
62
- # - "3333:3333" # Admin UI
63
- # - "3334:3334" # MCP HTTP
42
+ kozou:
43
+ # `kozou dev` spawns the bundled @kozou/svelte-ui Admin UI and the
44
+ # MCP HTTP server (Kozou v0.1 spec §9.1). Both bind 0.0.0.0 inside
45
+ # the container so the port mappings below reach your host.
46
+ image: ghcr.io/kozou-dev/kozou:v0.1.1
47
+ command: ["dev"]
48
+ environment:
49
+ DATABASE_URL: postgres://${POSTGRES_USER:-kozou}:${POSTGRES_PASSWORD:-kozou}@postgres:5432/${POSTGRES_DB:-kozou}
50
+ KOZOU_ADAPTER_URL: http://postgrest:3000
51
+ # The Admin UI is a SvelteKit (adapter-node) app. Without ORIGIN
52
+ # it assumes https and rejects every form POST (create / edit /
53
+ # delete) over plain http with a 403 "Cross-site POST forbidden".
54
+ # Set it to the exact URL you open in the browser; override if you
55
+ # publish the Admin UI on a different host or port.
56
+ ORIGIN: ${KOZOU_ORIGIN:-http://localhost:3333}
57
+ depends_on:
58
+ postgres:
59
+ condition: service_healthy
60
+ postgrest:
61
+ condition: service_started
62
+ ports:
63
+ - "3333:3333" # Admin UI
64
+ - "3334:3334" # MCP HTTP
@@ -9,3 +9,9 @@ POSTGRES_PORT=5432
9
9
  # Used by kozou + postgrest at runtime; defaults match the compose stack.
10
10
  DATABASE_URL=postgres://kozou:change-me@postgres:5432/kozou
11
11
  KOZOU_ADAPTER_URL=http://postgrest:3000
12
+
13
+ # Public URL you open the Admin UI on (v0.1.1). The bundled SvelteKit
14
+ # (adapter-node) server needs this to accept form submissions over plain
15
+ # http — without it, create / edit / delete are rejected with a 403
16
+ # "Cross-site POST forbidden". Override if you serve the UI elsewhere.
17
+ KOZOU_ORIGIN=http://localhost:3333
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kozou",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Kozou CLI: scaffolding, schema introspection, and MCP server entry points. See Kozou v0.1 design spec §9.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -36,17 +36,25 @@
36
36
  "dependencies": {
37
37
  "commander": "^14.0.0",
38
38
  "yaml": "^2.9.0",
39
- "zod": "^3.23.0",
40
- "@kozou/core": "0.1.0",
41
- "@kozou/introspect": "0.1.0",
42
- "@kozou/mcp": "0.1.0"
39
+ "zod": "^4.4.3",
40
+ "@kozou/core": "0.1.1",
41
+ "@kozou/introspect": "0.1.1",
42
+ "@kozou/mcp": "0.1.1",
43
+ "@kozou/svelte-ui": "0.1.1"
43
44
  },
44
45
  "devDependencies": {
46
+ "@modelcontextprotocol/sdk": "^1.0.0",
47
+ "@playwright/test": "^1.50.0",
48
+ "@testcontainers/postgresql": "^12.0.0",
49
+ "@types/pg": "^8.11.10",
50
+ "pg": "^8.13.0",
51
+ "testcontainers": "^12.0.0",
45
52
  "tsx": "^4.19.0"
46
53
  },
47
54
  "scripts": {
48
55
  "typecheck": "tsc --noEmit",
49
56
  "build": "tsc && node scripts/copy-templates.mjs",
50
- "test": "vitest run --coverage"
57
+ "test": "vitest run --coverage",
58
+ "test:e2e": "playwright test"
51
59
  }
52
60
  }