@koda-sl/baker-cli 0.422.0-dev.f9f855bf1 → 0.423.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.
Files changed (29) hide show
  1. package/README.md +211 -45
  2. package/dist/{chunk-VF77MVEM.js → chunk-3X2EMLBQ.js} +3 -3
  3. package/dist/{chunk-D76DSHL2.js → chunk-5JVAP5DC.js} +28 -1
  4. package/dist/{chunk-D76DSHL2.js.map → chunk-5JVAP5DC.js.map} +1 -1
  5. package/dist/{chunk-4RN4CBIQ.js → chunk-G5L5FX2B.js} +3 -3
  6. package/dist/{chunk-HFH5HQTP.js → chunk-S36N4SOX.js} +43 -4
  7. package/dist/chunk-S36N4SOX.js.map +1 -0
  8. package/dist/chunk-SWYBHYB5.js +24919 -0
  9. package/dist/chunk-SWYBHYB5.js.map +1 -0
  10. package/dist/{chunk-TTBMFAGF.js → chunk-XNFV6BQU.js} +4 -4
  11. package/dist/cli.js +9568 -14799
  12. package/dist/cli.js.map +1 -1
  13. package/dist/{client-OA2QMHOI.js → client-PIKJZFRA.js} +4 -4
  14. package/dist/engine/index.d.ts +8 -0
  15. package/dist/engine/index.js +3 -3
  16. package/dist/{env-Q5FUIVIJ.js → env-6UAIAY4M.js} +6 -2
  17. package/dist/{output-NMXF2VIL.js → output-CFDBWWYJ.js} +5 -5
  18. package/dist/{shared-PD226SU6.js → shared-3O5RKQYZ.js} +6 -6
  19. package/package.json +4 -1
  20. package/dist/chunk-FQ7WNNOG.js +0 -11637
  21. package/dist/chunk-FQ7WNNOG.js.map +0 -1
  22. package/dist/chunk-HFH5HQTP.js.map +0 -1
  23. /package/dist/{chunk-VF77MVEM.js.map → chunk-3X2EMLBQ.js.map} +0 -0
  24. /package/dist/{chunk-4RN4CBIQ.js.map → chunk-G5L5FX2B.js.map} +0 -0
  25. /package/dist/{chunk-TTBMFAGF.js.map → chunk-XNFV6BQU.js.map} +0 -0
  26. /package/dist/{client-OA2QMHOI.js.map → client-PIKJZFRA.js.map} +0 -0
  27. /package/dist/{env-Q5FUIVIJ.js.map → env-6UAIAY4M.js.map} +0 -0
  28. /package/dist/{output-NMXF2VIL.js.map → output-CFDBWWYJ.js.map} +0 -0
  29. /package/dist/{shared-PD226SU6.js.map → shared-3O5RKQYZ.js.map} +0 -0
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  debugLogHttp,
3
3
  readBodyForLog
4
- } from "./chunk-HFH5HQTP.js";
4
+ } from "./chunk-S36N4SOX.js";
5
5
  import {
6
6
  getEnv
7
- } from "./chunk-D76DSHL2.js";
7
+ } from "./chunk-5JVAP5DC.js";
8
8
 
9
9
  // src/client.ts
10
10
  var MAX_RATE_LIMIT_RETRIES = 3;
@@ -208,4 +208,4 @@ export {
208
208
  apiGet,
209
209
  apiPost
210
210
  };
211
- //# sourceMappingURL=chunk-4RN4CBIQ.js.map
211
+ //# sourceMappingURL=chunk-G5L5FX2B.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  debugLogSetting
3
- } from "./chunk-D76DSHL2.js";
3
+ } from "./chunk-5JVAP5DC.js";
4
4
 
5
5
  // src/debugLog.ts
6
6
  import { appendFileSync, mkdirSync, renameSync, statSync } from "fs";
@@ -33,6 +33,45 @@ function redactSecrets(input) {
33
33
  }
34
34
  return out;
35
35
  }
36
+ var CREDENTIAL_VALUE = "[credential value]";
37
+ var CREDENTIAL_PUT_PATH = "/api/credentials/put";
38
+ function withoutCredentialValue(url, body) {
39
+ let path;
40
+ try {
41
+ path = new URL(url).pathname;
42
+ } catch {
43
+ path = url;
44
+ }
45
+ if (path !== CREDENTIAL_PUT_PATH || body === null || typeof body !== "object" || !("value" in body)) {
46
+ return body;
47
+ }
48
+ return { ...body, value: CREDENTIAL_VALUE };
49
+ }
50
+ var PUT_FLAGS_WITH_VALUES = /* @__PURE__ */ new Set(["--host", "--label"]);
51
+ function argvWithoutCredentialValue(argv) {
52
+ if (argv[0] !== "credentials" || argv[1] !== "put") {
53
+ return argv;
54
+ }
55
+ let nameSeen = false;
56
+ let keepNext = false;
57
+ let redactNext = false;
58
+ return argv.map((arg, index) => {
59
+ if (index < 2) return arg;
60
+ if (keepNext || redactNext) {
61
+ const kept = keepNext ? arg : CREDENTIAL_VALUE;
62
+ keepNext = false;
63
+ redactNext = false;
64
+ return kept;
65
+ }
66
+ if (arg.startsWith("--value=")) return `--value=${CREDENTIAL_VALUE}`;
67
+ redactNext = arg === "--value";
68
+ keepNext = PUT_FLAGS_WITH_VALUES.has(arg);
69
+ if (arg.startsWith("-")) return arg;
70
+ const isName = !nameSeen;
71
+ nameSeen = true;
72
+ return isName ? arg : CREDENTIAL_VALUE;
73
+ });
74
+ }
36
75
  function resolveTarget() {
37
76
  const raw = debugLogSetting();
38
77
  if (!raw) {
@@ -98,7 +137,7 @@ function errorToPlain(err) {
98
137
  var invocationStartedAt;
99
138
  function logInvocation(argv) {
100
139
  invocationStartedAt = Date.now();
101
- append({ kind: "invocation", argv, cwd: process.cwd() });
140
+ append({ kind: "invocation", argv: argvWithoutCredentialValue(argv), cwd: process.cwd() });
102
141
  }
103
142
  function logExit(code) {
104
143
  append({
@@ -127,7 +166,7 @@ function debugLogHttp(entry) {
127
166
  method: entry.method,
128
167
  url: entry.url,
129
168
  durationMs: entry.durationMs,
130
- request: entry.requestBody,
169
+ request: withoutCredentialValue(entry.url, entry.requestBody),
131
170
  status: entry.status,
132
171
  ok: entry.ok,
133
172
  response: entry.responseBody,
@@ -173,4 +212,4 @@ export {
173
212
  readBodyForLog,
174
213
  installStreamTaps
175
214
  };
176
- //# sourceMappingURL=chunk-HFH5HQTP.js.map
215
+ //# sourceMappingURL=chunk-S36N4SOX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/debugLog.ts"],"sourcesContent":["// Full-fidelity debug capture for the whole CLI.\n//\n// Set BAKER_DEBUG_LOG to turn it on:\n// BAKER_DEBUG_LOG=1 -> appends to ./baker-cli-debug.jsonl\n// BAKER_DEBUG_LOG=/tmp/baker.jsonl -> appends to that file\n// BAKER_DEBUG_LOG=0|false|off|no -> disabled (same as unset)\n//\n// When enabled, every HTTP request/response (both the REST client and the\n// canvas engine client), every byte written to stdout/stderr, and the command\n// invocation are appended as JSONL entries. Known secret shapes are redacted\n// before anything is written (best-effort — see redactSecrets). Logging is\n// always fail-open: a logging error is swallowed so it can never break a\n// command. The file rotates once past MAX_BYTES so an always-on capture cannot\n// fill the disk.\n\nimport { appendFileSync, mkdirSync, renameSync, statSync } from \"node:fs\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { debugLogSetting } from \"./env.ts\";\n\nconst DEFAULT_FILE = \"baker-cli-debug.jsonl\";\nconst BOOLEAN_ON = new Set([\"1\", \"true\", \"on\", \"yes\"]);\nconst BOOLEAN_OFF = new Set([\"0\", \"false\", \"off\", \"no\"]);\n\n// Rotate once the active file passes this size (one older generation, `<file>.1`,\n// is kept). Bounds growth for the always-on sandbox capture without a per-write stat.\nconst MAX_BYTES = 64 * 1024 * 1024;\n\n// Best-effort redaction. Response/request bodies are stored as escaped strings, so\n// key/value matching is unreliable there; instead we scrub the token *values*\n// themselves (quote-agnostic) plus the auth header and Baker keys. This is not\n// exhaustive — a secret in an unrecognized shape can still be written. See README.\nconst REDACTIONS: ReadonlyArray<readonly [RegExp, string]> = [\n [/Bearer\\s+[A-Za-z0-9._-]+/g, \"Bearer [redacted]\"], // Authorization headers\n // Both prefixes, captured rather than listed twice: `bkr_` does not contain\n // the literal `bk_`, so the company-key rule matched no part of the read-only\n // credential a Session review runs with.\n [/\\b(bkr?)_[A-Za-z0-9]+/g, \"$1_[redacted]\"], // Baker API keys\n [/eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g, \"[redacted-jwt]\"], // JWTs / id tokens\n [/ya29\\.[A-Za-z0-9._-]+/g, \"[redacted-google-token]\"], // Google OAuth access tokens\n [/1\\/\\/[A-Za-z0-9._-]+/g, \"[redacted-google-refresh]\"], // Google refresh tokens\n [/EAA[A-Za-z0-9]{20,}/g, \"[redacted-meta-token]\"], // Meta/Facebook access tokens\n];\n\nexport function redactSecrets(input: string): string {\n let out = input;\n for (const [pattern, replacement] of REDACTIONS) {\n out = out.replace(pattern, replacement);\n }\n return out;\n}\n\nconst CREDENTIAL_VALUE = \"[credential value]\";\nconst CREDENTIAL_PUT_PATH = \"/api/credentials/put\";\n\n/**\n * `baker credentials put` carries a credential's value, the one payload this\n * log must never hold whatever its shape: the Session review reads this file.\n * Keyed on the route, not on a secret pattern, so a value no rule recognises\n * is still dropped.\n */\nfunction withoutCredentialValue(url: string, body: unknown): unknown {\n let path: string;\n try {\n path = new URL(url).pathname;\n } catch {\n path = url;\n }\n if (path !== CREDENTIAL_PUT_PATH || body === null || typeof body !== \"object\" || !(\"value\" in body)) {\n return body;\n }\n return { ...body, value: CREDENTIAL_VALUE };\n}\n\nconst PUT_FLAGS_WITH_VALUES = new Set([\"--host\", \"--label\"]);\n\n/** A value typed after `credentials put` (refused by the command, but already in argv) never reaches the log. */\nfunction argvWithoutCredentialValue(argv: string[]): string[] {\n if (argv[0] !== \"credentials\" || argv[1] !== \"put\") {\n return argv;\n }\n let nameSeen = false;\n let keepNext = false;\n let redactNext = false;\n return argv.map((arg, index) => {\n if (index < 2) return arg;\n if (keepNext || redactNext) {\n const kept = keepNext ? arg : CREDENTIAL_VALUE;\n keepNext = false;\n redactNext = false;\n return kept;\n }\n if (arg.startsWith(\"--value=\")) return `--value=${CREDENTIAL_VALUE}`;\n redactNext = arg === \"--value\";\n keepNext = PUT_FLAGS_WITH_VALUES.has(arg);\n if (arg.startsWith(\"-\")) return arg;\n const isName = !nameSeen;\n nameSeen = true;\n return isName ? arg : CREDENTIAL_VALUE;\n });\n}\n\nfunction resolveTarget(): string | undefined {\n const raw = debugLogSetting();\n if (!raw) {\n return undefined;\n }\n const lower = raw.toLowerCase();\n if (BOOLEAN_OFF.has(lower)) {\n return undefined;\n }\n const target = BOOLEAN_ON.has(lower) ? DEFAULT_FILE : raw;\n return isAbsolute(target) ? target : resolve(process.cwd(), target);\n}\n\nexport function isDebugLogEnabled(): boolean {\n return resolveTarget() !== undefined;\n}\n\nlet sessionId: string | undefined;\nfunction getSessionId(): string {\n if (!sessionId) {\n sessionId = `${process.pid}-${Date.now()}`;\n }\n return sessionId;\n}\n\n// Per-resolved-path bookkeeping so the hot path skips redundant syscalls: the\n// directory is ensured once and the current size is read once (via statSync),\n// then tracked in-process. Resets when the resolved path changes.\nlet trackedPath: string | undefined;\nlet bytesInFile = 0;\n\nfunction ensureReady(filePath: string): void {\n if (trackedPath !== filePath) {\n trackedPath = filePath;\n mkdirSync(dirname(filePath), { recursive: true });\n try {\n bytesInFile = statSync(filePath).size;\n } catch {\n bytesInFile = 0;\n }\n }\n}\n\nfunction append(entry: Record<string, unknown>): void {\n const filePath = resolveTarget();\n if (!filePath) {\n return;\n }\n try {\n const payload = { ts: new Date().toISOString(), session: getSessionId(), ...entry };\n const line = `${redactSecrets(JSON.stringify(payload))}\\n`;\n ensureReady(filePath);\n const size = Buffer.byteLength(line);\n if (bytesInFile + size > MAX_BYTES) {\n renameSync(filePath, `${filePath}.1`);\n bytesInFile = 0;\n }\n appendFileSync(filePath, line);\n bytesInFile += size;\n } catch {\n // Fail-open: debug logging must never break a command.\n }\n}\n\nfunction errorToPlain(err: unknown): Record<string, unknown> {\n if (err instanceof Error) {\n const code = (err as { code?: unknown }).code;\n return { name: err.name, message: err.message, ...(typeof code === \"string\" ? { code } : {}) };\n }\n return { message: String(err) };\n}\n\nlet invocationStartedAt: number | undefined;\n\nexport function logInvocation(argv: string[]): void {\n invocationStartedAt = Date.now();\n append({ kind: \"invocation\", argv: argvWithoutCredentialValue(argv), cwd: process.cwd() });\n}\n\n/**\n * Close an invocation with its outcome and its wall time.\n *\n * Until this existed the log could say what was called and what every HTTP hop\n * cost, and nothing at all about whether the command succeeded or how long the\n * whole thing took — so \"this verb is slow\" and \"this verb fails half the time\"\n * were both unanswerable from the one record that sees every call. `durationMs`\n * is measured from `logInvocation`, which runs before any command does.\n */\nexport function logExit(code: number): void {\n append({\n kind: \"exit\",\n code,\n ...(invocationStartedAt === undefined ? {} : { durationMs: Date.now() - invocationStartedAt }),\n });\n}\n\nlet exitHookInstalled = false;\n\n/**\n * Write the exit record however the process ends.\n *\n * `process.on(\"exit\")` is the only hook that sees all of them — a clean return, a\n * `process.exit` from the error handler, an unhandled rejection — and it is\n * synchronous-only, which is exactly what `appendFileSync` needs. Installed once,\n * and only when logging is on, so the disabled path adds no listener at all.\n */\nexport function installExitRecord(): void {\n if (exitHookInstalled || !isDebugLogEnabled()) {\n return;\n }\n exitHookInstalled = true;\n process.on(\"exit\", (code) => {\n logExit(typeof code === \"number\" ? code : 0);\n });\n}\n\nexport type HttpLogEntry = {\n source: \"cli\" | \"canvas\";\n method: string;\n url: string;\n requestBody?: unknown;\n status?: number;\n ok?: boolean;\n responseBody?: string;\n durationMs?: number;\n error?: unknown;\n};\n\nexport function debugLogHttp(entry: HttpLogEntry): void {\n if (!isDebugLogEnabled()) {\n return;\n }\n append({\n kind: \"http\",\n source: entry.source,\n method: entry.method,\n url: entry.url,\n durationMs: entry.durationMs,\n request: withoutCredentialValue(entry.url, entry.requestBody),\n status: entry.status,\n ok: entry.ok,\n response: entry.responseBody,\n error: entry.error === undefined ? undefined : errorToPlain(entry.error),\n });\n}\n\n// Reads a response body for logging without consuming it for the real caller.\nexport async function readBodyForLog(response: Response): Promise<string | undefined> {\n if (!isDebugLogEnabled()) {\n return undefined;\n }\n try {\n return await response.clone().text();\n } catch {\n return undefined;\n }\n}\n\n// Method syntax (bivariant) so a real `process.stdout`/`stderr` and a plain\n// test double both satisfy it.\ntype Writable = { write(...args: unknown[]): boolean };\n\n// Wraps a stream's `write` so every chunk is mirrored into the debug log while\n// the original write semantics (args + return value) are preserved. A single\n// streaming TextDecoder per stream decodes byte chunks so a multi-byte character\n// split across two writes is reassembled instead of garbled.\nexport function tapStream(name: string, stream: Writable): void {\n const original = stream.write.bind(stream) as (...args: unknown[]) => boolean;\n const decoder = new TextDecoder(\"utf-8\");\n stream.write = ((chunk: unknown, ...rest: unknown[]): boolean => {\n try {\n const text =\n typeof chunk === \"string\"\n ? chunk\n : chunk instanceof Uint8Array\n ? decoder.decode(chunk, { stream: true })\n : String(chunk);\n append({ kind: \"output\", stream: name, text });\n } catch {\n // ignore capture failures\n }\n return original(chunk, ...rest);\n }) as typeof stream.write;\n}\n\nlet tapsInstalled = false;\n\n// Mirrors everything written to stdout/stderr into the debug log. Installed once,\n// only when enabled, so the common (disabled) path leaves the streams untouched.\nexport function installStreamTaps(): void {\n if (tapsInstalled || !isDebugLogEnabled()) {\n return;\n }\n tapsInstalled = true;\n tapStream(\"stdout\", process.stdout);\n tapStream(\"stderr\", process.stderr);\n}\n"],"mappings":"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","names":[]}