kozou 0.1.1 → 0.2.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/README.md CHANGED
@@ -21,7 +21,7 @@ npx -p kozou create-kozou my-project
21
21
 
22
22
  The package publishes through `./dist/`. `bin` exposes two entries:
23
23
 
24
- - `kozou` - the main multi-command CLI (`inspect` / `mcp` / `dev`)
24
+ - `kozou` - the main multi-command CLI (`inspect` / `docs` / `mcp` / `dev`)
25
25
  - `create-kozou` - scaffolds a project directory with
26
26
  `docker-compose.yml`, `kozou.config.yaml`, `ui-hints.yaml`,
27
27
  `env.example`, and a starter migration
@@ -38,6 +38,16 @@ DATABASE_URL=postgres://kozou:kozou@localhost:5432/kozou \
38
38
  kozou inspect --format yaml > schema.yaml
39
39
  ```
40
40
 
41
+ ### `kozou docs`
42
+
43
+ Generates a single Markdown schema document from the database DDL +
44
+ `COMMENT` metadata to stdout (or `--output <path>`):
45
+
46
+ ```bash
47
+ DATABASE_URL=postgres://kozou:kozou@localhost:5432/kozou \
48
+ kozou docs --output schema.md
49
+ ```
50
+
41
51
  ### `kozou mcp --stdio`
42
52
 
43
53
  Starts an MCP server over stdio so Claude Code / other AI agents
@@ -105,6 +115,66 @@ The full schema also accepts `server.ui.{port,host}`,
105
115
  `create-kozou` writes. `${VAR}` and `${VAR:-default}` are
106
116
  expanded from the process environment at load time.
107
117
 
118
+ ### Authentication (experimental, `--adapter api`)
119
+
120
+ > **Source-checkout only.** The in-house `@kozou/api` backend is
121
+ > experimental and not yet published to npm, so `kozou dev --adapter api`
122
+ > works only from a source/workspace checkout of this repository. An
123
+ > npm-installed `kozou` does not bundle `@kozou/api`; requesting
124
+ > `--adapter api` there exits with an explicit error. The default
125
+ > `kozou dev` (PostgREST adapter) is unaffected.
126
+
127
+ By default the in-house `@kozou/api` backend (`kozou dev --adapter api`)
128
+ runs **unauthenticated** on loopback. Add an `auth` section to require a
129
+ signed JWT on every API request: kozou verifies the token, then runs each
130
+ request under `SET LOCAL ROLE <role-from-claim>` with the claims published
131
+ to PostgreSQL, so **your own row-level-security policies** decide what each
132
+ request can read and write.
133
+
134
+ ```yaml
135
+ auth:
136
+ jwt:
137
+ secret: ${KOZOU_JWT_SECRET} # HS256 — or publicKey (RS256), or jwksUri
138
+ # publicKey: ${KOZOU_JWT_PUBLIC_KEY}
139
+ # jwksUri: https://your-idp/.well-known/jwks.json # Auth0 / Clerk / Supabase
140
+ algorithms: [HS256]
141
+ issuer: my-issuer # optional
142
+ audience: my-api # optional
143
+ roleClaim: role # claim naming the DB role (default: role)
144
+ allowedRoles: [app_reader, app_admin] # only these roles may be assumed
145
+ defaultRole: app_reader # role when the token omits roleClaim
146
+ anonRole: web_anon # role for requests with no token (else 401)
147
+ ui:
148
+ role: app_admin # role the bundled Admin UI runs as (HS256)
149
+ # token: ${KOZOU_ADAPTER_TOKEN} # RS256 / external IdP: supply a token instead
150
+ ```
151
+
152
+ Provide exactly one of `jwt.secret` (HS256), `jwt.publicKey` (RS256), or
153
+ `jwt.jwksUri` (a provider's remote JWKS endpoint — keys are selected by `kid`,
154
+ cached, and refreshed on rotation).
155
+
156
+ With no `auth:` block, the section is built instead from
157
+ `KOZOU_JWT_SECRET` / `KOZOU_JWT_PUBLIC_KEY` / `KOZOU_JWT_JWKS_URI` /
158
+ `KOZOU_JWT_ALGORITHMS` / `KOZOU_JWT_ISSUER` / `KOZOU_JWT_AUDIENCE` /
159
+ `KOZOU_JWT_ROLE_CLAIM` / `KOZOU_JWT_ALLOWED_ROLES` / `KOZOU_JWT_DEFAULT_ROLE` /
160
+ `KOZOU_JWT_ANON_ROLE` / `KOZOU_UI_ROLE` / `KOZOU_ADAPTER_TOKEN` (algorithms
161
+ and roles are comma-separated). A role outside `allowedRoles` gets `403`. A request with
162
+ no token gets `401` unless `anonRole` is set, in which case it runs under
163
+ that role and your RLS policies decide what it sees (a present but invalid
164
+ token is always `401`). The login role of `database.url` must be `GRANT`ed
165
+ membership in every allowed role, and in `anonRole` when set.
166
+
167
+ #### The bundled Admin UI
168
+
169
+ The Admin UI calls `@kozou/api` server-side, so when `auth` is on it must
170
+ send a token too. Under **HS256** the CLI mints one for the UI claiming
171
+ `auth.ui.role` (or, if unset, no role — the API then applies `defaultRole`);
172
+ set `auth.ui.role` to the role the console should run as. Under **RS256**
173
+ or an external identity provider the CLI cannot mint, so supply a
174
+ ready-made token via `auth.ui.token` (or the `KOZOU_ADAPTER_TOKEN` env);
175
+ without it the UI is rejected with `401` and the CLI logs how to fix it.
176
+ The minted role must satisfy `allowedRoles` or the UI gets `403`.
177
+
108
178
  ## License
109
179
 
110
180
  Apache 2.0. See [LICENSE](../../LICENSE) at the repository root.
package/dist/cli.js CHANGED
@@ -3,6 +3,8 @@
3
3
  // Kozou v0.1 design spec §9.1 via commander.
4
4
  import { Command } from 'commander';
5
5
  import { inspectCommand } from './commands/inspect.js';
6
+ import { codegenCommand } from './commands/codegen.js';
7
+ import { docsCommand } from './commands/docs.js';
6
8
  import { mcpCommand } from './commands/mcp.js';
7
9
  import { devCommand } from './commands/dev.js';
8
10
  import { PACKAGE_VERSION } from './index.js';
@@ -23,6 +25,28 @@ program
23
25
  config: flags.config,
24
26
  });
25
27
  });
28
+ program
29
+ .command('codegen')
30
+ .description('Generate TypeScript row types from the database schema (experimental).')
31
+ .option('--output <path>', 'output file (- for stdout)', '-')
32
+ .option('--config <path>', 'path to kozou.config.yaml')
33
+ .action(async (flags) => {
34
+ await codegenCommand({
35
+ output: flags.output,
36
+ config: flags.config,
37
+ });
38
+ });
39
+ program
40
+ .command('docs')
41
+ .description('Generate a Markdown schema document from the database DDL + COMMENT.')
42
+ .option('--output <path>', 'output file (- for stdout)', '-')
43
+ .option('--config <path>', 'path to kozou.config.yaml')
44
+ .action(async (flags) => {
45
+ await docsCommand({
46
+ output: flags.output,
47
+ config: flags.config,
48
+ });
49
+ });
26
50
  program
27
51
  .command('mcp')
28
52
  .description('Run the MCP server (--stdio default, or --http).')
@@ -44,8 +68,14 @@ program
44
68
  .command('dev')
45
69
  .description('Run the bundled Admin UI + MCP HTTP dev server.')
46
70
  .option('--config <path>', 'path to kozou.config.yaml')
71
+ .option('--adapter <kind>', 'set to "api" for the experimental in-house @kozou/api backend (default: the bundled REST adapter)')
72
+ .option('--api-port <n>', 'port for the in-house @kozou/api server (with --adapter api)', (raw) => parseInt(raw, 10))
47
73
  .action(async (flags) => {
48
- await devCommand({ config: flags.config });
74
+ await devCommand({
75
+ config: flags.config,
76
+ adapter: flags.adapter,
77
+ apiPort: flags.apiPort,
78
+ });
49
79
  });
50
80
  program.parseAsync(process.argv).catch((err) => {
51
81
  process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
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;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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type CodegenOptions = {
2
+ /** Output destination. '-' = stdout (default), otherwise a file path. */
3
+ output?: string;
4
+ /** Path to kozou.config.yaml. Default: ./kozou.config.yaml. */
5
+ config?: string;
6
+ };
7
+ export declare function codegenCommand(opts?: CodegenOptions): Promise<void>;
8
+ //# sourceMappingURL=codegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/commands/codegen.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,cAAc,GAAG;IAC3B,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAsB,cAAc,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC7E"}
@@ -0,0 +1,54 @@
1
+ // `kozou codegen` command implementation.
2
+ //
3
+ // Pipeline (mirrors `kozou inspect`):
4
+ // 1. Load the kozou.config.yaml (or fall back to defaults).
5
+ // 2. Introspect the target Postgres schema (@kozou/introspect).
6
+ // 3. Optionally load UI hints (@kozou/core.loadUIHints).
7
+ // 4. Build a SchemaContext (@kozou/core.buildSchemaContext).
8
+ // 5. Emit TypeScript row types (@kozou/codegen) and write them out.
9
+ //
10
+ // @kozou/codegen is an experimental, unpublished workspace package, so it is
11
+ // imported dynamically and is only resolvable from a source / workspace
12
+ // checkout — a published `kozou` install gets a clear error (mirrors the
13
+ // `--adapter api` handling in dev.ts).
14
+ import { writeFile } from 'node:fs/promises';
15
+ import { buildSchemaContext, loadUIHints } from '@kozou/core';
16
+ import { introspect } from '@kozou/introspect';
17
+ import { loadConfig } from '../config.js';
18
+ const PREFIX = '[kozou codegen]';
19
+ export async function codegenCommand(opts = {}) {
20
+ const output = opts.output ?? '-';
21
+ let codegenModule;
22
+ try {
23
+ codegenModule = await import('@kozou/codegen');
24
+ }
25
+ catch {
26
+ throw new Error(`${PREFIX} needs the experimental @kozou/codegen package, which is not ` +
27
+ 'bundled in this release. Run kozou from a source / workspace checkout to use it.');
28
+ }
29
+ const config = await loadConfig({ path: opts.config });
30
+ const raw = await introspect({
31
+ connection: config.database.url,
32
+ schemas: config.database.schemas,
33
+ });
34
+ let uiHints;
35
+ if (config.uiHints.path !== null && config.uiHints.path !== '') {
36
+ try {
37
+ uiHints = await loadUIHints(config.uiHints.path);
38
+ }
39
+ catch (err) {
40
+ // UI hints are optional; warn but continue without them.
41
+ const message = err instanceof Error ? err.message : String(err);
42
+ process.stderr.write(`${PREFIX} could not load UI hints: ${message}\n`);
43
+ }
44
+ }
45
+ const ctx = await buildSchemaContext({ raw, uiHints });
46
+ const serialized = codegenModule.emitRowTypes(ctx);
47
+ const payload = serialized.endsWith('\n') ? serialized : serialized + '\n';
48
+ if (output === '-') {
49
+ process.stdout.write(payload);
50
+ return;
51
+ }
52
+ await writeFile(output, payload, 'utf8');
53
+ }
54
+ //# sourceMappingURL=codegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.js","sourceRoot":"","sources":["../../src/commands/codegen.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,sCAAsC;AACtC,8DAA8D;AAC9D,kEAAkE;AAClE,2DAA2D;AAC3D,+DAA+D;AAC/D,sEAAsE;AACtE,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,yEAAyE;AACzE,uCAAuC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,MAAM,GAAG,iBAAiB,CAAC;AASjC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAuB,EAAE;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;IAElC,IAAI,aAA8C,CAAC;IACnD,IAAI,CAAC;QACH,aAAa,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,GAAG,MAAM,+DAA+D;YACtE,kFAAkF,CACrF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEvD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG;QAC/B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;KACjC,CAAC,CAAC;IAEH,IAAI,OAA4B,CAAC;IACjC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;QAC/D,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,yDAAyD;YACzD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,6BAA6B,OAAO,IAAI,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC;IAE3E,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IACD,MAAM,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC"}
@@ -1,5 +1,21 @@
1
1
  import type { KozouConfig } from '../config.js';
2
2
  export declare function resolveAdminUiEntry(): string;
3
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;
4
+ export declare function buildAdminUiEnv(config: KozouConfig, origin: string, baseEnv: NodeJS.ProcessEnv, apiAdapterUrl?: string, apiToken?: string): NodeJS.ProcessEnv;
5
+ export type ServiceTokenMinter = {
6
+ signServiceToken(opts: {
7
+ secret: string;
8
+ roleClaim?: string;
9
+ role?: string;
10
+ issuer?: string;
11
+ audience?: string | string[];
12
+ }): Promise<string>;
13
+ };
14
+ export type AdminUiTokenResult = {
15
+ /** Bearer token the Admin UI should send, when one could be obtained. */
16
+ token?: string;
17
+ /** Operator-facing reason the UI will be rejected, when no usable token. */
18
+ warning?: string;
19
+ };
20
+ export declare function resolveAdminUiToken(config: KozouConfig, minter: ServiceTokenMinter, env: NodeJS.ProcessEnv): Promise<AdminUiTokenResult>;
5
21
  //# sourceMappingURL=dev-runtime.d.ts.map
@@ -1 +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"}
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;AAWD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,UAAU,EAC1B,aAAa,CAAC,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAAC,UAAU,CAsBnB;AAID,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,CAAC,IAAI,EAAE;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC9B,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAWF,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,kBAAkB,EAC1B,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,kBAAkB,CAAC,CA8B7B"}
@@ -24,15 +24,88 @@ export function resolveOrigin(config, env) {
24
24
  }
25
25
  // Build the child-process environment for the Admin UI server. Keeping
26
26
  // it pure makes the wiring unit-testable without spawning anything.
27
- export function buildAdminUiEnv(config, origin, baseEnv) {
28
- return {
27
+ //
28
+ // When `apiAdapterUrl` is given (`kozou dev --adapter api`), the UI is
29
+ // pointed at the in-house @kozou/api server via KOZOU_ADAPTER_KIND=api;
30
+ // otherwise it uses the default REST adapter URL from config. On the api
31
+ // path `apiToken` (when present) is exposed as KOZOU_ADAPTER_TOKEN so the
32
+ // UI attaches it as a Bearer token; any inherited value is cleared so a
33
+ // stray env var cannot leak in.
34
+ export function buildAdminUiEnv(config, origin, baseEnv, apiAdapterUrl, apiToken) {
35
+ const adapter = apiAdapterUrl !== undefined
36
+ ? { KOZOU_ADAPTER_KIND: 'api', KOZOU_ADAPTER_URL: apiAdapterUrl }
37
+ : { KOZOU_ADAPTER_URL: config.adapter.url };
38
+ const env = {
29
39
  ...baseEnv,
30
40
  DATABASE_URL: config.database.url,
31
- KOZOU_ADAPTER_URL: config.adapter.url,
41
+ ...adapter,
32
42
  PORT: String(config.server.ui.port),
33
43
  HOST: config.server.ui.host,
34
44
  ORIGIN: origin,
35
45
  NODE_ENV: 'production',
36
46
  };
47
+ if (apiAdapterUrl !== undefined) {
48
+ if (apiToken !== undefined && apiToken.length > 0) {
49
+ env.KOZOU_ADAPTER_TOKEN = apiToken;
50
+ }
51
+ else {
52
+ delete env.KOZOU_ADAPTER_TOKEN;
53
+ }
54
+ }
55
+ return env;
56
+ }
57
+ // Decide what token (if any) the bundled Admin UI should send to @kozou/api,
58
+ // given the resolved config. Pure except for the injected minter:
59
+ // (a) an explicit token (auth.ui.token / KOZOU_ADAPTER_TOKEN) is passed
60
+ // through — the path for RS256 / an external IdP, where the CLI cannot
61
+ // mint;
62
+ // (b) otherwise, with an HS256 secret, the CLI mints a token claiming the
63
+ // configured role (auth.ui.role; absent -> the API's defaultRole);
64
+ // (c) otherwise (an RS256 key with no supplied token) no token is returned
65
+ // and a warning explains how to supply one.
66
+ export async function resolveAdminUiToken(config, minter, env) {
67
+ const auth = config.auth;
68
+ if (auth === undefined)
69
+ return {}; // no auth -> the UI sends no token (unchanged)
70
+ const supplied = auth.ui?.token ?? env.KOZOU_ADAPTER_TOKEN;
71
+ if (supplied !== undefined && supplied.length > 0) {
72
+ return { token: supplied };
73
+ }
74
+ const secret = auth.jwt.secret;
75
+ if (secret !== undefined && secret.length > 0) {
76
+ const role = auth.ui?.role;
77
+ const token = await minter.signServiceToken({
78
+ secret,
79
+ roleClaim: auth.roleClaim,
80
+ role,
81
+ issuer: auth.jwt.issuer,
82
+ audience: auth.jwt.audience,
83
+ });
84
+ const warning = mintedRoleWarning(auth, role);
85
+ return warning !== undefined ? { token, warning } : { token };
86
+ }
87
+ return {
88
+ warning: 'auth uses an RS256 public key, so the CLI cannot mint a token for the ' +
89
+ 'bundled Admin UI; it will be rejected with 401. Set auth.ui.token (or ' +
90
+ 'KOZOU_ADAPTER_TOKEN) to a token from your identity provider, or use an ' +
91
+ 'HS256 secret so the CLI can mint one.',
92
+ };
93
+ }
94
+ // A minted Admin UI token will be rejected with 403 unless the API can
95
+ // resolve an allowed role for it. Surface that as a warning at startup
96
+ // rather than letting the UI fail opaquely.
97
+ function mintedRoleWarning(auth, role) {
98
+ const effective = role !== undefined && role.length > 0 ? role : auth.defaultRole;
99
+ if (effective === undefined || effective.length === 0) {
100
+ return 'auth.ui.role is unset and no defaultRole is configured, so the ' +
101
+ 'minted Admin UI token carries no role and the API will reject it with ' +
102
+ '403. Set auth.ui.role to the role the Admin UI should assume.';
103
+ }
104
+ if (auth.allowedRoles !== undefined && !auth.allowedRoles.includes(effective)) {
105
+ return `the Admin UI token's role "${effective}" is not in allowedRoles, so ` +
106
+ 'the API will reject it with 403. Add it to allowedRoles or change ' +
107
+ 'auth.ui.role.';
108
+ }
109
+ return undefined;
37
110
  }
38
111
  //# sourceMappingURL=dev-runtime.js.map
@@ -1 +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
+ {"version":3,"file":"dev-runtime.js","sourceRoot":"","sources":["../../src/commands/dev-runtime.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,9 @@
1
1
  export type DevOptions = {
2
2
  config?: string;
3
+ /** Set to 'api' for the experimental in-house @kozou/api backend; omit for the default REST adapter. */
4
+ adapter?: string;
5
+ /** Port for the in-house @kozou/api server (used when adapter === 'api'). */
6
+ apiPort?: number;
3
7
  };
4
8
  export declare function devCommand(opts?: DevOptions): Promise<void>;
5
9
  //# sourceMappingURL=dev.d.ts.map
@@ -1 +1 @@
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
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AA+BA,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wGAAwG;IACxG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAwEF,wBAAsB,UAAU,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA+GrE"}
@@ -19,8 +19,58 @@ import { spawn } from 'node:child_process';
19
19
  import { existsSync } from 'node:fs';
20
20
  import { SchemaCache, startHttpServer, isLoopbackHost } from '@kozou/mcp';
21
21
  import { loadConfig } from '../config.js';
22
- import { buildAdminUiEnv, resolveAdminUiEntry, resolveOrigin, } from './dev-runtime.js';
22
+ import { buildAdminUiEnv, resolveAdminUiEntry, resolveAdminUiToken, resolveOrigin, } from './dev-runtime.js';
23
23
  const PREFIX = '[kozou dev]';
24
+ // The in-house @kozou/api server is reached only by the Admin UI's
25
+ // server-side fetch (same host), so bind it to loopback — no need to
26
+ // expose it to the browser or the network.
27
+ const API_HOST = '127.0.0.1';
28
+ const DEFAULT_API_PORT = 3335;
29
+ // Start the in-house @kozou/api server in-process: introspect the
30
+ // configured database, build its SchemaContext, and serve it over a pg
31
+ // pool. @kozou/api is an experimental, unpublished workspace package, so
32
+ // it is imported dynamically and is only resolvable from a source /
33
+ // workspace checkout — a published `kozou` install gets a clear error.
34
+ async function startInhouseApi(config, port) {
35
+ let apiModule;
36
+ try {
37
+ apiModule = await import('@kozou/api');
38
+ }
39
+ catch {
40
+ throw new Error(`${PREFIX} --adapter api needs the experimental @kozou/api package, which is ` +
41
+ 'not bundled in this release. Run kozou from a source / workspace checkout ' +
42
+ 'to use it, or drop --adapter api to use the default REST adapter.');
43
+ }
44
+ const { introspect } = await import('@kozou/introspect');
45
+ const { buildSchemaContext } = await import('@kozou/core');
46
+ const { default: pg } = await import('pg');
47
+ const raw = await introspect({
48
+ connection: config.database.url,
49
+ schemas: config.database.schemas,
50
+ });
51
+ const schema = await buildSchemaContext({ raw });
52
+ const pool = new pg.Pool({ connectionString: config.database.url });
53
+ const server = await apiModule.startApiServer({
54
+ schema,
55
+ db: { query: (text, values) => pool.query(text, values) },
56
+ // When `auth` is configured the API verifies a JWT and runs each request
57
+ // under SET LOCAL ROLE, which needs a dedicated client per request — pass
58
+ // the pool. With no `auth`, the pool is unused and the API stays
59
+ // unauthenticated (loopback-only), exactly as before.
60
+ pool,
61
+ auth: config.auth,
62
+ host: API_HOST,
63
+ port,
64
+ logPrefix: `${PREFIX} api`,
65
+ });
66
+ return {
67
+ url: `http://${API_HOST}:${server.port}`,
68
+ close: async () => {
69
+ await server.close();
70
+ await pool.end();
71
+ },
72
+ };
73
+ }
24
74
  function warnIfPublic(label, host) {
25
75
  if (isLoopbackHost(host))
26
76
  return;
@@ -30,6 +80,10 @@ function warnIfPublic(label, host) {
30
80
  `${PREFIX} avoid it on an untrusted network or put an auth proxy in front.\n`);
31
81
  }
32
82
  export async function devCommand(opts = {}) {
83
+ if (opts.adapter !== undefined && opts.adapter !== 'api') {
84
+ throw new Error(`${PREFIX} unknown --adapter "${opts.adapter}" ` +
85
+ '(the only supported value is "api"; omit it for the default REST adapter).');
86
+ }
33
87
  const config = await loadConfig({ path: opts.config });
34
88
  const adminUiEntry = resolveAdminUiEntry();
35
89
  if (!existsSync(adminUiEntry)) {
@@ -37,6 +91,27 @@ export async function devCommand(opts = {}) {
37
91
  'Reinstall @kozou/svelte-ui (its `build/` output ships in the package), ' +
38
92
  'or in a workspace checkout run `pnpm --filter @kozou/svelte-ui run build`.');
39
93
  }
94
+ // Optional in-house @kozou/api backend (--adapter api), started before
95
+ // the other servers so its URL can be wired into the UI environment.
96
+ const api = opts.adapter === 'api'
97
+ ? await startInhouseApi(config, opts.apiPort ?? DEFAULT_API_PORT)
98
+ : null;
99
+ if (api) {
100
+ process.stderr.write(`${PREFIX} in-house @kozou/api on ${api.url}\n`);
101
+ }
102
+ // When the in-house API enforces auth, resolve the token the bundled Admin
103
+ // UI presents to it: a minted HS256 token, a supplied RS256 / external one,
104
+ // or none (with a warning) when neither is available. @kozou/api is already
105
+ // imported (startInhouseApi succeeded), so this dynamic import is cached.
106
+ let apiToken;
107
+ if (api && config.auth) {
108
+ const apiModule = await import('@kozou/api');
109
+ const resolved = await resolveAdminUiToken(config, apiModule, process.env);
110
+ if (resolved.warning) {
111
+ process.stderr.write(`${PREFIX} WARNING: ${resolved.warning}\n`);
112
+ }
113
+ apiToken = resolved.token;
114
+ }
40
115
  const cache = new SchemaCache({
41
116
  connection: config.database.url,
42
117
  schemas: config.database.schemas,
@@ -53,15 +128,16 @@ export async function devCommand(opts = {}) {
53
128
  warnIfPublic('Admin UI', config.server.ui.host);
54
129
  const origin = resolveOrigin(config, process.env);
55
130
  const child = spawn('node', [adminUiEntry], {
56
- env: buildAdminUiEnv(config, origin, process.env),
131
+ env: buildAdminUiEnv(config, origin, process.env, api?.url, apiToken),
57
132
  stdio: ['ignore', 'pipe', 'pipe'],
58
133
  });
59
134
  child.stdout?.on('data', (b) => process.stdout.write(`${PREFIX} ui | ${b}`));
60
135
  child.stderr?.on('data', (b) => process.stderr.write(`${PREFIX} ui | ${b}`));
61
136
  process.stderr.write(`${PREFIX} Admin UI on http://${config.server.ui.host}:${config.server.ui.port}` +
62
137
  ` (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.
138
+ // 3. Lifecycle: tear everything down together. Resolve the promise (and
139
+ // thus let the CLI exit) only once everything has stopped.
140
+ const closeBackends = () => Promise.allSettled([mcp.close(), api ? api.close() : Promise.resolve()]);
65
141
  await new Promise((resolve) => {
66
142
  let shuttingDown = false;
67
143
  const shutdown = (reason) => {
@@ -72,7 +148,7 @@ export async function devCommand(opts = {}) {
72
148
  if (child.exitCode === null && child.signalCode === null) {
73
149
  child.kill('SIGTERM');
74
150
  }
75
- void mcp.close().finally(() => resolve());
151
+ void closeBackends().finally(() => resolve());
76
152
  };
77
153
  process.on('SIGINT', () => shutdown('SIGINT received'));
78
154
  process.on('SIGTERM', () => shutdown('SIGTERM received'));
@@ -84,7 +160,7 @@ export async function devCommand(opts = {}) {
84
160
  process.stderr.write(`${PREFIX} Admin UI exited (code=${code ?? 'null'}, signal=${signal ?? 'null'})\n`);
85
161
  process.exitCode = code ?? 1;
86
162
  shuttingDown = true;
87
- void mcp.close().finally(() => resolve());
163
+ void closeBackends().finally(() => resolve());
88
164
  });
89
165
  child.on('error', (err) => {
90
166
  process.stderr.write(`${PREFIX} failed to spawn Admin UI: ${err.message}\n`);
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,sEAAsE;AACtE,wEAAwE;AACxE,uEAAuE;AACvE,iEAAiE;AACjE,sEAAsE;AACtE,mCAAmC;AACnC,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,8CAA8C;AAC9C,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,oEAAoE;AACpE,oEAAoE;AAEpE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE1E,OAAO,EAAE,UAAU,EAAoB,MAAM,cAAc,CAAC;AAC5D,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAU1B,MAAM,MAAM,GAAG,aAAa,CAAC;AAE7B,mEAAmE;AACnE,qEAAqE;AACrE,2CAA2C;AAC3C,MAAM,QAAQ,GAAG,WAAW,CAAC;AAC7B,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAI9B,kEAAkE;AAClE,uEAAuE;AACvE,yEAAyE;AACzE,oEAAoE;AACpE,uEAAuE;AACvE,KAAK,UAAU,eAAe,CAAC,MAAmB,EAAE,IAAY;IAC9D,IAAI,SAAsC,CAAC;IAC3C,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,GAAG,MAAM,qEAAqE;YAC5E,4EAA4E;YAC5E,mEAAmE,CACtE,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACzD,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IAC3D,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG;QAC/B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;KACjC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,cAAc,CAAC;QAC5C,MAAM;QACN,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,IAAY,EAAE,MAAkB,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;QAC7E,yEAAyE;QACzE,0EAA0E;QAC1E,iEAAiE;QACjE,sDAAsD;QACtD,IAAI;QACJ,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,SAAS,EAAE,GAAG,MAAM,MAAM;KAC3B,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,EAAE,UAAU,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE;QACxC,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,IAAY;IAC/C,IAAI,cAAc,CAAC,IAAI,CAAC;QAAE,OAAO;IACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,MAAM,aAAa,KAAK,gCAAgC,IAAI,MAAM;QACnE,GAAG,MAAM,kEAAkE;QAC3E,GAAG,MAAM,IAAI,IAAI,wDAAwD;QACzE,GAAG,MAAM,oEAAoE,CAChF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAmB,EAAE;IACpD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CACb,GAAG,MAAM,uBAAuB,IAAI,CAAC,OAAO,IAAI;YAC9C,4EAA4E,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEvD,MAAM,YAAY,GAAG,mBAAmB,EAAE,CAAC;IAC3C,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,GAAG,MAAM,gCAAgC,YAAY,IAAI;YACvD,yEAAyE;YACzE,4EAA4E,CAC/E,CAAC;IACJ,CAAC;IAED,uEAAuE;IACvE,qEAAqE;IACrE,MAAM,GAAG,GACP,IAAI,CAAC,OAAO,KAAK,KAAK;QACpB,CAAC,CAAC,MAAM,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,IAAI,gBAAgB,CAAC;QACjE,CAAC,CAAC,IAAI,CAAC;IACX,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,2BAA2B,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACxE,CAAC;IAED,2EAA2E;IAC3E,4EAA4E;IAC5E,4EAA4E;IAC5E,0EAA0E;IAC1E,IAAI,QAA4B,CAAC;IACjC,IAAI,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3E,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,aAAa,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;QACnE,CAAC;QACD,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC5B,CAAC;IAED,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,8DAA8D;IAC9D,yDAAyD;IACzD,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE;QACvC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;QACjC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;QACjC,SAAS,EAAE,GAAG,MAAM,MAAM;KAC3B,CAAC,CAAC;IAEH,mCAAmC;IACnC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,EAAE;QAC1C,GAAG,EAAE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC;QACrE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;KAClC,CAAC,CAAC;IACH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACrF,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAErF,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,MAAM,uBAAuB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QAC9E,YAAY,MAAM,KAAK,CAC1B,CAAC;IAEF,wEAAwE;IACxE,8DAA8D;IAC9D,MAAM,aAAa,GAAG,GAAqB,EAAE,CAC3C,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAE3E,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,IAAI,YAAY,GAAG,KAAK,CAAC;QAEzB,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAQ,EAAE;YACxC,IAAI,YAAY;gBAAE,OAAO;YACzB,YAAY,GAAG,IAAI,CAAC;YACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,MAAM,mBAAmB,CAAC,CAAC;YAC7D,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;gBACzD,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACxB,CAAC;YACD,KAAK,aAAa,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC;QAE1D,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YAChC,IAAI,YAAY;gBAAE,OAAO;YACzB,iEAAiE;YACjE,yCAAyC;YACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,MAAM,0BAA0B,IAAI,IAAI,MAAM,YAAY,MAAM,IAAI,MAAM,KAAK,CACnF,CAAC;YACF,OAAO,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,CAAC;YAC7B,YAAY,GAAG,IAAI,CAAC;YACpB,KAAK,aAAa,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,8BAA8B,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;YAC7E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type DocsOptions = {
2
+ /** Output destination. '-' = stdout (default), otherwise a file path. */
3
+ output?: string;
4
+ /** Path to kozou.config.yaml. Default: ./kozou.config.yaml. */
5
+ config?: string;
6
+ };
7
+ export declare function docsCommand(opts?: DocsOptions): Promise<void>;
8
+ //# sourceMappingURL=docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"AAoBA,MAAM,MAAM,WAAW,GAAG;IACxB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAsB,WAAW,CAAC,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BvE"}
@@ -0,0 +1,44 @@
1
+ // `kozou docs` command implementation.
2
+ //
3
+ // Pipeline (mirrors `kozou inspect`):
4
+ // 1. Load the kozou.config.yaml (or fall back to defaults).
5
+ // 2. Introspect the target Postgres schema (@kozou/introspect).
6
+ // 3. Optionally load UI hints (@kozou/core.loadUIHints).
7
+ // 4. Build a SchemaContext (@kozou/core.buildSchemaContext).
8
+ // 5. Render a Markdown schema document and write it out.
9
+ //
10
+ // See product_architecture_v3 §3.4 (the "docs" emit target).
11
+ import { writeFile } from 'node:fs/promises';
12
+ import { buildSchemaContext, loadUIHints } from '@kozou/core';
13
+ import { introspect } from '@kozou/introspect';
14
+ import { loadConfig } from '../config.js';
15
+ import { emitMarkdown } from '../docs.js';
16
+ const PREFIX = '[kozou docs]';
17
+ export async function docsCommand(opts = {}) {
18
+ const output = opts.output ?? '-';
19
+ const config = await loadConfig({ path: opts.config });
20
+ const raw = await introspect({
21
+ connection: config.database.url,
22
+ schemas: config.database.schemas,
23
+ });
24
+ let uiHints;
25
+ if (config.uiHints.path !== null && config.uiHints.path !== '') {
26
+ try {
27
+ uiHints = await loadUIHints(config.uiHints.path);
28
+ }
29
+ catch (err) {
30
+ // UI hints are optional; warn but continue without them.
31
+ const message = err instanceof Error ? err.message : String(err);
32
+ process.stderr.write(`${PREFIX} could not load UI hints: ${message}\n`);
33
+ }
34
+ }
35
+ const ctx = await buildSchemaContext({ raw, uiHints });
36
+ const serialized = emitMarkdown(ctx);
37
+ const payload = serialized.endsWith('\n') ? serialized : serialized + '\n';
38
+ if (output === '-') {
39
+ process.stdout.write(payload);
40
+ return;
41
+ }
42
+ await writeFile(output, payload, 'utf8');
43
+ }
44
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,sCAAsC;AACtC,8DAA8D;AAC9D,kEAAkE;AAClE,2DAA2D;AAC3D,+DAA+D;AAC/D,2DAA2D;AAC3D,EAAE;AACF,6DAA6D;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,MAAM,GAAG,cAAc,CAAC;AAS9B,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB,EAAE;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;IAElC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEvD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG;QAC/B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;KACjC,CAAC,CAAC;IAEH,IAAI,OAA4B,CAAC;IACjC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;QAC/D,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,yDAAyD;YACzD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,6BAA6B,OAAO,IAAI,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC;IAE3E,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IACD,MAAM,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC"}
package/dist/config.d.ts CHANGED
@@ -27,6 +27,28 @@ declare const configSchema: z.ZodObject<{
27
27
  cache: z.ZodPrefault<z.ZodObject<{
28
28
  ttlMs: z.ZodDefault<z.ZodNumber>;
29
29
  }, z.core.$strip>>;
30
+ auth: z.ZodOptional<z.ZodObject<{
31
+ jwt: z.ZodObject<{
32
+ secret: z.ZodOptional<z.ZodString>;
33
+ publicKey: z.ZodOptional<z.ZodString>;
34
+ jwksUri: z.ZodOptional<z.ZodString>;
35
+ algorithms: z.ZodOptional<z.ZodArray<z.ZodEnum<{
36
+ HS256: "HS256";
37
+ RS256: "RS256";
38
+ }>>>;
39
+ issuer: z.ZodOptional<z.ZodString>;
40
+ audience: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
41
+ }, z.core.$strip>;
42
+ roleClaim: z.ZodOptional<z.ZodString>;
43
+ allowedRoles: z.ZodOptional<z.ZodArray<z.ZodString>>;
44
+ defaultRole: z.ZodOptional<z.ZodString>;
45
+ anonRole: z.ZodOptional<z.ZodString>;
46
+ claimsGuc: z.ZodOptional<z.ZodString>;
47
+ ui: z.ZodOptional<z.ZodObject<{
48
+ role: z.ZodOptional<z.ZodString>;
49
+ token: z.ZodOptional<z.ZodString>;
50
+ }, z.core.$strip>>;
51
+ }, z.core.$strip>>;
30
52
  }, z.core.$strip>;
31
53
  export type KozouConfig = z.infer<typeof configSchema>;
32
54
  export type KozouConfigIssue = {
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+FxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOhB,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;AA4GF,wBAAsB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,CA6CnF"}
package/dist/config.js CHANGED
@@ -66,12 +66,42 @@ const databaseSchema = z.object({
66
66
  url: z.string().min(1, 'database.url is required (set DATABASE_URL or kozou.config.yaml)'),
67
67
  schemas: z.array(z.string().min(1)).default(['public']),
68
68
  });
69
+ // Opt-in JWT auth for the in-house @kozou/api backend (`kozou dev --adapter
70
+ // api`). Absent -> the API stays unauthenticated and loopback-only. The
71
+ // "exactly one of secret / publicKey" rule is enforced by @kozou/api at
72
+ // server start, so it is intentionally not duplicated here.
73
+ const jwtAuthSchema = z.object({
74
+ secret: z.string().min(1).optional(),
75
+ publicKey: z.string().min(1).optional(),
76
+ jwksUri: z.string().min(1).optional(),
77
+ algorithms: z.array(z.enum(['HS256', 'RS256'])).optional(),
78
+ issuer: z.string().min(1).optional(),
79
+ audience: z.union([z.string().min(1), z.array(z.string().min(1))]).optional(),
80
+ });
81
+ // How the bundled Admin UI authenticates to @kozou/api when auth is on. This
82
+ // is a CLI-only concern (not part of @kozou/api's AuthConfig): under HS256 the
83
+ // CLI mints a token claiming `role`; for RS256 / an external IdP it cannot
84
+ // mint, so `token` carries a ready-made one through to the UI instead.
85
+ const authUiSchema = z.object({
86
+ role: z.string().min(1).optional(),
87
+ token: z.string().min(1).optional(),
88
+ });
89
+ const authSchema = z.object({
90
+ jwt: jwtAuthSchema,
91
+ roleClaim: z.string().min(1).optional(),
92
+ allowedRoles: z.array(z.string().min(1)).optional(),
93
+ defaultRole: z.string().min(1).optional(),
94
+ anonRole: z.string().min(1).optional(),
95
+ claimsGuc: z.string().min(1).optional(),
96
+ ui: authUiSchema.optional(),
97
+ });
69
98
  const configSchema = z.object({
70
99
  database: databaseSchema,
71
100
  server: serverSchema,
72
101
  adapter: adapterSchema,
73
102
  uiHints: uiHintsSchema,
74
103
  cache: cacheSchema,
104
+ auth: authSchema.optional(),
75
105
  });
76
106
  export class KozouConfigError extends Error {
77
107
  issues;
@@ -140,6 +170,67 @@ function injectDatabaseUrlFromEnv(raw, env) {
140
170
  }
141
171
  return obj;
142
172
  }
173
+ function splitList(value) {
174
+ if (value === undefined)
175
+ return undefined;
176
+ const items = value
177
+ .split(',')
178
+ .map((s) => s.trim())
179
+ .filter((s) => s.length > 0);
180
+ return items.length > 0 ? items : undefined;
181
+ }
182
+ // Build the optional `auth` section from KOZOU_JWT_* env vars when the config
183
+ // file did not declare one. Runs AFTER ${VAR} expansion so an env-provided
184
+ // secret / key is taken verbatim and is never re-scanned for placeholders.
185
+ function injectAuthFromEnv(raw, env) {
186
+ if (raw === null || typeof raw !== 'object')
187
+ return raw;
188
+ const obj = raw;
189
+ if (obj.auth !== undefined)
190
+ return obj; // an explicit config section wins
191
+ const secret = env.KOZOU_JWT_SECRET;
192
+ const publicKey = env.KOZOU_JWT_PUBLIC_KEY;
193
+ const jwksUri = env.KOZOU_JWT_JWKS_URI;
194
+ if (!secret && !publicKey && !jwksUri)
195
+ return obj; // no auth env -> stay unauthenticated
196
+ const jwt = {};
197
+ if (secret)
198
+ jwt.secret = secret;
199
+ if (publicKey)
200
+ jwt.publicKey = publicKey;
201
+ if (jwksUri)
202
+ jwt.jwksUri = jwksUri;
203
+ const algorithms = splitList(env.KOZOU_JWT_ALGORITHMS);
204
+ if (algorithms)
205
+ jwt.algorithms = algorithms;
206
+ if (env.KOZOU_JWT_ISSUER)
207
+ jwt.issuer = env.KOZOU_JWT_ISSUER;
208
+ if (env.KOZOU_JWT_AUDIENCE)
209
+ jwt.audience = env.KOZOU_JWT_AUDIENCE;
210
+ const auth = { jwt };
211
+ if (env.KOZOU_JWT_ROLE_CLAIM)
212
+ auth.roleClaim = env.KOZOU_JWT_ROLE_CLAIM;
213
+ const allowedRoles = splitList(env.KOZOU_JWT_ALLOWED_ROLES);
214
+ if (allowedRoles)
215
+ auth.allowedRoles = allowedRoles;
216
+ if (env.KOZOU_JWT_DEFAULT_ROLE)
217
+ auth.defaultRole = env.KOZOU_JWT_DEFAULT_ROLE;
218
+ if (env.KOZOU_JWT_ANON_ROLE)
219
+ auth.anonRole = env.KOZOU_JWT_ANON_ROLE;
220
+ if (env.KOZOU_JWT_CLAIMS_GUC)
221
+ auth.claimsGuc = env.KOZOU_JWT_CLAIMS_GUC;
222
+ // How the bundled Admin UI authenticates: KOZOU_UI_ROLE names the role the
223
+ // CLI mints an HS256 token for; KOZOU_ADAPTER_TOKEN supplies a ready-made
224
+ // token (RS256 / external IdP, where the CLI cannot mint).
225
+ const ui = {};
226
+ if (env.KOZOU_UI_ROLE)
227
+ ui.role = env.KOZOU_UI_ROLE;
228
+ if (env.KOZOU_ADAPTER_TOKEN)
229
+ ui.token = env.KOZOU_ADAPTER_TOKEN;
230
+ if (Object.keys(ui).length > 0)
231
+ auth.ui = ui;
232
+ return { ...obj, auth };
233
+ }
143
234
  export async function loadConfig(opts = {}) {
144
235
  const env = opts.env ?? process.env;
145
236
  const requestedPath = opts.path ?? DEFAULT_CONFIG_PATH;
@@ -162,8 +253,10 @@ export async function loadConfig(opts = {}) {
162
253
  // Fall back to DATABASE_URL env if database.url is not set in the file.
163
254
  const withDbDefault = injectDatabaseUrlFromEnv(raw, env);
164
255
  const expanded = expandEnvVars(withDbDefault, env);
256
+ // Build `auth` from KOZOU_JWT_* env after expansion (env secrets verbatim).
257
+ const withAuth = injectAuthFromEnv(expanded, env);
165
258
  try {
166
- return configSchema.parse(expanded);
259
+ return configSchema.parse(withAuth);
167
260
  }
168
261
  catch (err) {
169
262
  if (err instanceof z.ZodError) {
@@ -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/docs.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { SchemaContext } from '@kozou/core';
2
+ export declare function emitMarkdown(schema: SchemaContext): string;
3
+ //# sourceMappingURL=docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,aAAa,EAMd,MAAM,aAAa,CAAC;AAIrB,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CA+B1D"}
package/dist/docs.js ADDED
@@ -0,0 +1,204 @@
1
+ // Render a human-readable Markdown document from a SchemaContext.
2
+ //
3
+ // This is the "docs" emit target (product_architecture_v3 §3.4): alongside the
4
+ // Admin UI, MCP context, REST API, and TypeScript types, Kozou turns the same
5
+ // DDL + COMMENT into a schema document a person can read, commit, and publish.
6
+ //
7
+ // Pure function — no I/O — so the `kozou docs` CLI (and tests) drive it
8
+ // directly. Content mirrors what the MCP `describe_table` / `describe_view` /
9
+ // `get_concept_context` tools surface, formatted for human reading.
10
+ const BANNER = '> Generated by `kozou docs` from PostgreSQL DDL + COMMENT. Do not edit by hand.';
11
+ export function emitMarkdown(schema) {
12
+ // 1:1 view -> concept, used to surface @example: queries on views.
13
+ const examplesByView = new Map();
14
+ for (const c of schema.concepts)
15
+ examplesByView.set(c.name, c.exampleQueries);
16
+ const sections = ['# Database schema', BANNER];
17
+ const sourceSchemas = schema.meta.sourceSchemas;
18
+ if (sourceSchemas.length > 0) {
19
+ sections.push(`Source schemas: ${sourceSchemas.map(code).join(', ')}.`);
20
+ }
21
+ sections.push(renderContents(schema));
22
+ if (schema.tables.length > 0) {
23
+ sections.push('## Tables');
24
+ for (const t of schema.tables)
25
+ sections.push(renderTable(t));
26
+ }
27
+ if (schema.views.length > 0) {
28
+ sections.push('## Views');
29
+ for (const v of schema.views)
30
+ sections.push(renderView(v, examplesByView.get(v.name) ?? []));
31
+ }
32
+ if (schema.enums.length > 0) {
33
+ sections.push('## Enums');
34
+ for (const e of schema.enums)
35
+ sections.push(renderEnum(e));
36
+ }
37
+ if (schema.tables.length === 0 && schema.views.length === 0 && schema.enums.length === 0) {
38
+ sections.push('_No tables, views, or enums were found in the introspected schema._');
39
+ }
40
+ return sections.join('\n\n') + '\n';
41
+ }
42
+ function renderContents(schema) {
43
+ const lines = ['## Contents'];
44
+ const group = (title, items) => {
45
+ if (items.length === 0)
46
+ return;
47
+ lines.push('', `**${title}**`, '');
48
+ for (const it of items)
49
+ lines.push(`- [${escapeInline(it.label)}](#${it.anchor})`);
50
+ };
51
+ group('Tables', schema.tables.map((t) => ({ label: t.label, anchor: tableAnchor(t) })));
52
+ group('Views', schema.views.map((v) => ({ label: v.label, anchor: viewAnchor(v) })));
53
+ group('Enums', schema.enums.map((e) => ({ label: `${e.schema}.${e.name}`, anchor: enumAnchor(e) })));
54
+ return lines.join('\n');
55
+ }
56
+ function renderTable(t) {
57
+ const out = [
58
+ `<a id="${tableAnchor(t)}"></a>`,
59
+ `### ${escapeInline(t.label)} (${code(t.qualifiedName)})`,
60
+ ];
61
+ pushProse(out, t.description);
62
+ pushAiNotes(out, t.aiDescription);
63
+ pushPolicies(out, t.policy ?? []);
64
+ out.push(renderColumnsTable(t.columns, t.relations));
65
+ return out.join('\n\n');
66
+ }
67
+ function renderView(v, examples) {
68
+ const out = [
69
+ `<a id="${viewAnchor(v)}"></a>`,
70
+ `### ${escapeInline(v.label)} (${code(v.qualifiedName)})`,
71
+ ];
72
+ pushProse(out, v.description);
73
+ pushAiNotes(out, v.aiDescription);
74
+ pushPolicies(out, v.policy ?? []);
75
+ if (v.underlyingTables.length > 0) {
76
+ const tables = v.underlyingTables.map((u) => code(`${u.schema}.${u.name}`)).join(', ');
77
+ out.push(`**Underlying tables:** ${tables}`);
78
+ }
79
+ out.push(renderColumnsTable(v.columns, []));
80
+ for (const ex of examples) {
81
+ out.push(`**Example query — ${escapeInline(ex.description)}**`);
82
+ out.push(fencedSql(ex.sql));
83
+ }
84
+ out.push('**Definition**');
85
+ out.push(fencedSql(v.rawView.definition));
86
+ return out.join('\n\n');
87
+ }
88
+ function renderEnum(e) {
89
+ const out = [
90
+ `<a id="${enumAnchor(e)}"></a>`,
91
+ `### ${code(`${e.schema}.${e.name}`)}`,
92
+ ];
93
+ out.push(e.values.map((val) => `- ${code(val)}`).join('\n'));
94
+ return out.join('\n\n');
95
+ }
96
+ function renderColumnsTable(columns, relations) {
97
+ const fkByField = new Map();
98
+ for (const rel of relations)
99
+ fkByField.set(rel.field, rel);
100
+ const header = '| Column | Type | Null | Default | Key | Description |';
101
+ const divider = '| --- | --- | --- | --- | --- | --- |';
102
+ const rows = columns.map((c) => {
103
+ const key = columnKey(c, fkByField.get(c.name));
104
+ const def = c.defaultExpr ? code(c.defaultExpr) : '';
105
+ const desc = columnDescription(c);
106
+ return `| ${code(c.name)} | ${escapeCell(c.dataType)} | ${c.nullable ? 'yes' : 'no'} | ${def} | ${key} | ${desc} |`;
107
+ });
108
+ return [header, divider, ...rows].join('\n');
109
+ }
110
+ function columnKey(column, fk) {
111
+ const parts = [];
112
+ if (column.isPrimaryKey)
113
+ parts.push('PK');
114
+ if (fk) {
115
+ const ref = fk.references;
116
+ parts.push(`FK → ${escapeCell(`${ref.schema}.${ref.table}.${ref.column}`)}`);
117
+ }
118
+ else if (column.isForeignKey) {
119
+ parts.push('FK');
120
+ }
121
+ return parts.join(', ');
122
+ }
123
+ /** A one-line, table-cell-safe description: cleaned of tag lines, with the
124
+ * enum domain appended when present. */
125
+ function columnDescription(column) {
126
+ const prose = cleanProse(column.description);
127
+ const parts = [];
128
+ if (prose)
129
+ parts.push(escapeCell(prose));
130
+ if (column.enumValues && column.enumValues.length > 0) {
131
+ parts.push(`One of: ${column.enumValues.map(code).join(', ')}.`);
132
+ }
133
+ return parts.join(' ');
134
+ }
135
+ function pushProse(out, description) {
136
+ const prose = cleanProse(description);
137
+ if (prose)
138
+ out.push(prose);
139
+ }
140
+ function pushAiNotes(out, aiDescription) {
141
+ if (!aiDescription)
142
+ return;
143
+ const quoted = aiDescription
144
+ .split('\n')
145
+ .map((line) => `> ${line}`)
146
+ .join('\n');
147
+ out.push(`**AI notes:**\n\n${quoted}`);
148
+ }
149
+ function pushPolicies(out, policies) {
150
+ if (policies.length === 0)
151
+ return;
152
+ const list = policies.map((p) => `- ${escapeInline(p)}`).join('\n');
153
+ out.push(`**Policies:**\n\n${list}`);
154
+ }
155
+ /** Drop `@ai:` / `@policy:` / other tag lines from a COMMENT body, leaving the
156
+ * human prose. Tag lines are surfaced separately as structured sections. */
157
+ function cleanProse(description) {
158
+ if (description === null)
159
+ return null;
160
+ const kept = description.split('\n').filter((line) => !line.trim().startsWith('@'));
161
+ const text = kept.join('\n').trim();
162
+ return text === '' ? null : text;
163
+ }
164
+ function fencedSql(sql) {
165
+ return ['```sql', sql.trim(), '```'].join('\n');
166
+ }
167
+ function code(value) {
168
+ return `\`${value}\``;
169
+ }
170
+ /** Escape a value for inline Markdown text (outside a table cell). */
171
+ function escapeInline(value) {
172
+ return value.replace(/\s+/g, ' ').trim();
173
+ }
174
+ /** Collapse whitespace and escape a value so it is safe inside a Markdown
175
+ * table cell. The backslash is escaped first so a pre-existing `\` cannot
176
+ * swallow the escape we add for the pipe. All regexes are linear (single,
177
+ * unanchored) — no ReDoS. */
178
+ function escapeCell(value) {
179
+ return value
180
+ .replace(/\s+/g, ' ')
181
+ .trim()
182
+ .replace(/\\/g, '\\\\')
183
+ .replace(/\|/g, '\\|');
184
+ }
185
+ function tableAnchor(t) {
186
+ return `table-${slug(t.qualifiedName)}`;
187
+ }
188
+ function viewAnchor(v) {
189
+ return `view-${slug(v.qualifiedName)}`;
190
+ }
191
+ function enumAnchor(e) {
192
+ return `enum-${slug(`${e.schema}.${e.name}`)}`;
193
+ }
194
+ /** A deterministic, renderer-independent anchor slug. Paired with an explicit
195
+ * `<a id>` so the table-of-contents links resolve regardless of how a given
196
+ * Markdown renderer auto-slugs headings. */
197
+ function slug(value) {
198
+ return value
199
+ .toLowerCase()
200
+ .replace(/[^a-z0-9]+/g, '-')
201
+ .replace(/^-+/, '')
202
+ .replace(/-+$/, '');
203
+ }
204
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"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"}
@@ -43,7 +43,7 @@ services:
43
43
  # `kozou dev` spawns the bundled @kozou/svelte-ui Admin UI and the
44
44
  # MCP HTTP server (Kozou v0.1 spec §9.1). Both bind 0.0.0.0 inside
45
45
  # the container so the port mappings below reach your host.
46
- image: ghcr.io/kozou-dev/kozou:v0.1.1
46
+ image: ghcr.io/kozou-dev/kozou:v0.2.0
47
47
  command: ["dev"]
48
48
  environment:
49
49
  DATABASE_URL: postgres://${POSTGRES_USER:-kozou}:${POSTGRES_PASSWORD:-kozou}@postgres:5432/${POSTGRES_DB:-kozou}
@@ -10,8 +10,16 @@ POSTGRES_PORT=5432
10
10
  DATABASE_URL=postgres://kozou:change-me@postgres:5432/kozou
11
11
  KOZOU_ADAPTER_URL=http://postgrest:3000
12
12
 
13
- # Public URL you open the Admin UI on (v0.1.1). The bundled SvelteKit
13
+ # Public URL you open the Admin UI on (v0.2.0). The bundled SvelteKit
14
14
  # (adapter-node) server needs this to accept form submissions over plain
15
15
  # http — without it, create / edit / delete are rejected with a 403
16
16
  # "Cross-site POST forbidden". Override if you serve the UI elsewhere.
17
17
  KOZOU_ORIGIN=http://localhost:3333
18
+
19
+ # JWT auth for the experimental in-house API (`kozou dev --adapter api`).
20
+ # Leave unset to keep it unauthenticated and loopback-only (the default).
21
+ # KOZOU_JWT_SECRET=your-hs256-secret # HS256 — or KOZOU_JWT_PUBLIC_KEY / KOZOU_JWT_JWKS_URI
22
+ # KOZOU_JWT_JWKS_URI=https://your-idp/.well-known/jwks.json # Auth0 / Clerk / Supabase
23
+ # KOZOU_JWT_ANON_ROLE=web_anon # role for requests with no token (else 401)
24
+ # KOZOU_UI_ROLE=app_admin # role the bundled Admin UI runs as (HS256)
25
+ # KOZOU_ADAPTER_TOKEN= # RS256 / external IdP: a ready-made UI token
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kozou",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
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": {
@@ -37,10 +37,10 @@
37
37
  "commander": "^14.0.0",
38
38
  "yaml": "^2.9.0",
39
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"
40
+ "@kozou/core": "0.2.0",
41
+ "@kozou/introspect": "0.2.0",
42
+ "@kozou/mcp": "0.2.0",
43
+ "@kozou/svelte-ui": "0.2.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@modelcontextprotocol/sdk": "^1.0.0",
@@ -49,12 +49,16 @@
49
49
  "@types/pg": "^8.11.10",
50
50
  "pg": "^8.13.0",
51
51
  "testcontainers": "^12.0.0",
52
- "tsx": "^4.19.0"
52
+ "tsx": "^4.19.0",
53
+ "@kozou/api": "0.0.0",
54
+ "@kozou/codegen": "0.0.0"
53
55
  },
54
56
  "scripts": {
55
57
  "typecheck": "tsc --noEmit",
56
58
  "build": "tsc && node scripts/copy-templates.mjs",
57
59
  "test": "vitest run --coverage",
58
- "test:e2e": "playwright test"
60
+ "test:e2e": "playwright test",
61
+ "test:e2e:api": "playwright test --config playwright.kozou-api.config.ts",
62
+ "test:e2e:api:auth": "playwright test --config playwright.kozou-api-auth.config.ts"
59
63
  }
60
64
  }