@kici-dev/shared 0.1.3 → 0.1.6

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.
@@ -29,6 +29,16 @@
29
29
  */
30
30
  export type FileChangeCategory = 'new' | 'content' | 'mode' | 'time-only';
31
31
  export type ContentSkipReason = 'binary' | 'too-large' | 'read-failed' | 'sensitive';
32
+ /**
33
+ * Renderer hint for the diff body. The default `'unified-text'` produces
34
+ * a `createTwoFilesPatch`-style block (the v1 shape). `'env-semantic'`
35
+ * routes through the env-file diff renderer (keys + classification, with
36
+ * value masking by default). `'yaml-semantic'` routes through the yaml
37
+ * deep-diff renderer (dotted-path leaf entries, with masking on sensitive
38
+ * paths). `'suppressed'` hides the body and prints a skip-reason marker —
39
+ * used for genuinely-opaque content the caller refuses to capture.
40
+ */
41
+ export type FileDiffMode = 'unified-text' | 'env-semantic' | 'yaml-semantic' | 'suppressed';
32
42
  /**
33
43
  * Per-file drift entry as carried inside a phase's Drift value.
34
44
  * `localPath` and `remotePath` are filled in by the caller that owns the
@@ -53,7 +63,23 @@ export interface FileDriftEntry {
53
63
  remoteContent?: string;
54
64
  /** Set when content capture was intentionally skipped — used by the renderer to explain the gap. */
55
65
  contentSkipped?: ContentSkipReason;
66
+ /**
67
+ * Renderer hint. When omitted, the renderer auto-detects from
68
+ * `remotePath`: `.env` → `'env-semantic'`, `.yaml` / `.yml` →
69
+ * `'yaml-semantic'`, otherwise → `'unified-text'`. Explicit values
70
+ * override the auto-detect. Set to `'suppressed'` to opt out of any
71
+ * inline body and rely on `contentSkipped` for the explanation row.
72
+ */
73
+ diffMode?: FileDiffMode;
56
74
  }
75
+ /**
76
+ * Auto-detect the diff mode for a given entry. Explicit `entry.diffMode`
77
+ * always wins. Otherwise the suffix of `remotePath` is the only signal —
78
+ * we deliberately do NOT sniff `localContent` bytes because the goal of
79
+ * the helper is to produce a deterministic, callsite-readable hint that
80
+ * matches the caller's intent.
81
+ */
82
+ export declare function resolveDiffMode(entry: FileDriftEntry): FileDiffMode;
57
83
  /** Low-level parse output: category + the relative path rsync printed. */
58
84
  export interface ItemizeRecord {
59
85
  itemizeCode: string;
@@ -80,6 +106,21 @@ export interface RenderDriftOpts {
80
106
  color?: boolean;
81
107
  /** Cap on diff body lines per entry (excluding header). Default 200. */
82
108
  maxLines?: number;
109
+ /**
110
+ * When true, env-semantic and yaml-semantic renderers will print the
111
+ * actual values instead of masking them. Off by default so the confirm
112
+ * prompt and the tee'd log file never carry plaintext credentials
113
+ * without an explicit operator opt-in.
114
+ */
115
+ revealEnvValues?: boolean;
116
+ /**
117
+ * Restrict which categories get a diff body rendered. Entries whose
118
+ * category is NOT in this set show only the per-file row, no diff.
119
+ * Default: `['new', 'content']` (every visible drift body). Useful for
120
+ * `--diff-only=content` operator workflows that want to suppress the
121
+ * potentially-huge full-file body of newly-introduced files.
122
+ */
123
+ diffOnlyCategories?: FileChangeCategory[];
83
124
  }
84
125
  /**
85
126
  * Render the unified-diff block for a single FileDriftEntry. Returns an
@@ -92,8 +133,37 @@ export interface RenderDriftOpts {
92
133
  * skip reason. Entries with no content captured (older callers that
93
134
  * didn't fill the fields) also return empty — the caller falls back to
94
135
  * the label-only row.
136
+ *
137
+ * This function ALWAYS renders the unified-text shape regardless of the
138
+ * entry's `diffMode` — it's the v1 path. The renderer dispatch in
139
+ * `renderFileDrifts` decides which shape to invoke per entry; this
140
+ * helper stays the unified-text branch for callers that want to render
141
+ * a single entry in unified shape.
95
142
  */
96
143
  export declare function renderFileDriftWithDiff(entry: FileDriftEntry, opts?: Pick<RenderDriftOpts, 'color' | 'maxLines'>): string[];
144
+ /**
145
+ * Dispatch helper: given a single entry and the render opts, pick the
146
+ * right renderer based on `resolveDiffMode(entry)`. Returns the diff body
147
+ * lines (no surrounding indent applied) — same shape as
148
+ * `renderFileDriftWithDiff` so the caller can nest each line identically
149
+ * regardless of which renderer fired.
150
+ *
151
+ * The placeholder `yaml-semantic` branch deliberately falls back to the
152
+ * unified-text rendering when this entry hasn't been routed through a
153
+ * yaml-aware caller. The dedicated `renderYamlDiff` lives in
154
+ * `idempotency-yaml-diff.ts`; the dispatch wire-up happens here once it's
155
+ * imported.
156
+ */
157
+ export declare function renderFileDriftBody(entry: FileDriftEntry, opts?: RenderDriftOpts): string[];
158
+ /**
159
+ * Yaml renderer registration. The yaml module (`idempotency-yaml-diff.ts`)
160
+ * calls `setYamlDiffRenderer` at its own load time so the file-drift
161
+ * renderer can dispatch to it without taking a static dependency on the
162
+ * `yaml` npm package. Callers that never import the yaml module fall
163
+ * through to unified-text rendering, which is the safe default.
164
+ */
165
+ type YamlDiffRenderer = (entry: FileDriftEntry, opts: RenderDriftOpts) => string[];
166
+ export declare function setYamlDiffRenderer(renderer: YamlDiffRenderer | null): void;
97
167
  /**
98
168
  * Render a FileDriftEntry[] as an aligned multi-line block suitable for
99
169
  * inclusion in a confirm-prompt summary.
@@ -110,4 +180,5 @@ export declare function renderFileDriftWithDiff(entry: FileDriftEntry, opts?: Pi
110
180
  * decides how to nest the block in a wider prompt.
111
181
  */
112
182
  export declare function renderFileDrifts(entries: FileDriftEntry[], opts?: RenderDriftOpts): string[];
183
+ export {};
113
184
  //# sourceMappingURL=idempotency-files.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import "./chunk-gOLHoazu.js";
2
+ import { diffEnvFiles, renderEnvDiff } from "./idempotency-env-diff.js";
2
3
  import { createTwoFilesPatch } from "diff";
3
4
  //#region src/idempotency-files.ts
4
5
  /**
@@ -36,6 +37,20 @@ const ANSI_CYAN = "\x1B[36m";
36
37
  const ANSI_BOLD = "\x1B[1m";
37
38
  const ANSI_RESET = "\x1B[0m";
38
39
  /**
40
+ * Auto-detect the diff mode for a given entry. Explicit `entry.diffMode`
41
+ * always wins. Otherwise the suffix of `remotePath` is the only signal —
42
+ * we deliberately do NOT sniff `localContent` bytes because the goal of
43
+ * the helper is to produce a deterministic, callsite-readable hint that
44
+ * matches the caller's intent.
45
+ */
46
+ function resolveDiffMode(entry) {
47
+ if (entry.diffMode) return entry.diffMode;
48
+ const remote = entry.remotePath.toLowerCase();
49
+ if (remote.endsWith(".env")) return "env-semantic";
50
+ if (remote.endsWith(".yaml") || remote.endsWith(".yml")) return "yaml-semantic";
51
+ return "unified-text";
52
+ }
53
+ /**
39
54
  * Parse one line of `rsync --itemize-changes` output. Returns null for
40
55
  * lines that are not actionable file drift entries:
41
56
  * - "sending incremental file list" header line
@@ -118,6 +133,12 @@ const SKIP_REASON_DISPLAY = {
118
133
  * skip reason. Entries with no content captured (older callers that
119
134
  * didn't fill the fields) also return empty — the caller falls back to
120
135
  * the label-only row.
136
+ *
137
+ * This function ALWAYS renders the unified-text shape regardless of the
138
+ * entry's `diffMode` — it's the v1 path. The renderer dispatch in
139
+ * `renderFileDrifts` decides which shape to invoke per entry; this
140
+ * helper stays the unified-text branch for callers that want to render
141
+ * a single entry in unified shape.
121
142
  */
122
143
  function renderFileDriftWithDiff(entry, opts = {}) {
123
144
  if (entry.category === "mode" || entry.category === "time-only") return [];
@@ -135,6 +156,54 @@ function renderFileDriftWithDiff(entry, opts = {}) {
135
156
  if (truncated) lines.push(`… (${body.length - maxLines} more lines truncated; raw patch in log file)`);
136
157
  return lines;
137
158
  }
159
+ /**
160
+ * Dispatch helper: given a single entry and the render opts, pick the
161
+ * right renderer based on `resolveDiffMode(entry)`. Returns the diff body
162
+ * lines (no surrounding indent applied) — same shape as
163
+ * `renderFileDriftWithDiff` so the caller can nest each line identically
164
+ * regardless of which renderer fired.
165
+ *
166
+ * The placeholder `yaml-semantic` branch deliberately falls back to the
167
+ * unified-text rendering when this entry hasn't been routed through a
168
+ * yaml-aware caller. The dedicated `renderYamlDiff` lives in
169
+ * `idempotency-yaml-diff.ts`; the dispatch wire-up happens here once it's
170
+ * imported.
171
+ */
172
+ function renderFileDriftBody(entry, opts = {}) {
173
+ if (entry.category === "mode" || entry.category === "time-only") return [];
174
+ const mode = resolveDiffMode(entry);
175
+ if (mode === "suppressed") return [SKIP_REASON_DISPLAY[entry.contentSkipped ?? "sensitive"]];
176
+ if (entry.contentSkipped) return [SKIP_REASON_DISPLAY[entry.contentSkipped]];
177
+ if (mode === "env-semantic") return renderEnvDiffBody(entry, opts);
178
+ if (mode === "yaml-semantic") {
179
+ if (yamlDiffRenderer) return yamlDiffRenderer(entry, opts);
180
+ }
181
+ return renderFileDriftWithDiff(entry, {
182
+ color: opts.color,
183
+ maxLines: opts.maxLines
184
+ });
185
+ }
186
+ /**
187
+ * Bridge between the env-diff module and the file-drift renderer. Reads
188
+ * `localContent` + `remoteContent` from the entry and delegates to
189
+ * `diffEnvFiles` + `renderEnvDiff` from `idempotency-env-diff.ts`.
190
+ *
191
+ * NEW entries (no `remoteContent`) treat the remote side as an empty file
192
+ * — every local key becomes an `added` entry.
193
+ */
194
+ function renderEnvDiffBody(entry, opts) {
195
+ const local = entry.localContent ?? "";
196
+ const remote = entry.category === "new" ? "" : entry.remoteContent ?? "";
197
+ if (local === "" && remote === "" && entry.category !== "new") return [];
198
+ return renderEnvDiff(diffEnvFiles(local, remote), {
199
+ reveal: opts.revealEnvValues ?? false,
200
+ color: opts.color ?? false
201
+ });
202
+ }
203
+ let yamlDiffRenderer = null;
204
+ function setYamlDiffRenderer(renderer) {
205
+ yamlDiffRenderer = renderer;
206
+ }
138
207
  function colorize(line, color) {
139
208
  if (!color) return line;
140
209
  if (line.startsWith("+++") || line.startsWith("---")) return `${ANSI_BOLD}${line}${ANSI_RESET}`;
@@ -170,21 +239,19 @@ function renderFileDrifts(entries, opts = {}) {
170
239
  if (ai !== bi) return ai - bi;
171
240
  return a.localPath.localeCompare(b.localPath);
172
241
  });
242
+ const diffOnly = new Set(opts.diffOnlyCategories ?? ["new", "content"]);
173
243
  const lines = [`${entries.length} file(s) drifted: ${summary}`];
174
244
  for (const e of sorted) {
175
245
  const label = CATEGORY_DISPLAY[e.category].padEnd(widest);
176
246
  lines.push(` ${label} ${e.localPath}`);
177
- if (opts.withContent) {
178
- const diff = renderFileDriftWithDiff(e, {
179
- color: opts.color,
180
- maxLines: opts.maxLines
181
- });
247
+ if (opts.withContent && diffOnly.has(e.category)) {
248
+ const diff = renderFileDriftBody(e, opts);
182
249
  for (const dl of diff) lines.push(` ${dl}`);
183
250
  }
184
251
  }
185
252
  return lines;
186
253
  }
187
254
  //#endregion
188
- export { parseItemizeLine, renderFileDriftWithDiff, renderFileDrifts };
255
+ export { parseItemizeLine, renderFileDriftBody, renderFileDriftWithDiff, renderFileDrifts, resolveDiffMode, setYamlDiffRenderer };
189
256
 
190
257
  //# sourceMappingURL=idempotency-files.js.map
@@ -0,0 +1,74 @@
1
+ /**
2
+ * YAML-file semantic diff for the idempotent-step preview path. Parses
3
+ * both sides with the `yaml` npm package, deep-walks the resulting JS
4
+ * trees, and emits one `YamlDiffEntry` per leaf-level path that differs.
5
+ *
6
+ * "Leaf" means the smallest scalar inside the tree: a string, number,
7
+ * boolean, or null. Arrays compare element-by-element by index; objects
8
+ * recurse into their fields. The dotted path follows the JS-property
9
+ * convention (`Database.postgres.User.Password`, `clients[2].name`).
10
+ *
11
+ * The renderer masks every entry whose path contains a sensitive
12
+ * segment (`/password|passwd|secret|api[_-]?key|token|credentials?/i`)
13
+ * unless the operator passes `reveal: true` via the
14
+ * `--reveal-env-values` CLI flag. Non-sensitive entries print their
15
+ * values inline so the operator can see config drift at a glance.
16
+ */
17
+ export type YamlDiffKind = 'added' | 'removed' | 'changed';
18
+ export interface YamlDiffEntry {
19
+ /** Dotted path to the leaf, e.g. "Database.postgres.User.Password" or "auth.clients[0].secret". */
20
+ path: string;
21
+ kind: YamlDiffKind;
22
+ /** Populated for `changed` / `removed`. Scalar leaf value. */
23
+ oldValue?: unknown;
24
+ /** Populated for `added` / `changed`. Scalar leaf value. */
25
+ newValue?: unknown;
26
+ /** True when any segment in `path` matches the sensitive-keyword heuristic. */
27
+ sensitive: boolean;
28
+ }
29
+ /**
30
+ * Returns true when any segment of the dotted path matches the
31
+ * sensitive-keyword heuristic. Numeric array indices (`[0]`) are
32
+ * stripped before the match so a path like `clients[3].token` still
33
+ * matches via the `token` segment.
34
+ */
35
+ export declare function isPathSensitive(dottedPath: string): boolean;
36
+ /**
37
+ * Deep-diff two YAML bodies. Both sides are parsed with the `yaml`
38
+ * package, then a recursive walk emits one entry per leaf that differs.
39
+ * Returns an empty array when the documents are structurally equivalent.
40
+ *
41
+ * Throws when either side fails to parse — the caller (the renderer
42
+ * dispatch) catches and falls back to unified-text rendering on a parse
43
+ * failure so a stray template tag in a yaml-by-suffix file doesn't lose
44
+ * the operator's diff.
45
+ */
46
+ export declare function diffYamlContent(local: string, remote: string): YamlDiffEntry[];
47
+ export interface YamlDiffRenderOpts {
48
+ /** When true, sensitive paths show their values inline; otherwise masked. */
49
+ reveal?: boolean;
50
+ /** When true, color the kind label + values via ANSI escapes. */
51
+ color?: boolean;
52
+ }
53
+ /**
54
+ * Render the yaml-semantic diff body. Returns one entry's worth of
55
+ * lines per `YamlDiffEntry`, plus an empty-state fallback line when
56
+ * there's nothing to show. No surrounding indent applied — the caller
57
+ * decides nesting.
58
+ *
59
+ * Layout:
60
+ *
61
+ * Database.postgres.User.Password: changed (masked — pass --reveal-env-values to show)
62
+ * server.listen: changed
63
+ * - old=80
64
+ * + new=8080
65
+ * features.beta: added
66
+ * + new=true
67
+ *
68
+ * The CLI flag is named `--reveal-env-values` because the same flag
69
+ * governs env-semantic + yaml-semantic value reveals; calling the flag
70
+ * "env-values" reflects the most common case (sops-derived env files)
71
+ * but it activates yaml-side reveal too.
72
+ */
73
+ export declare function renderYamlDiff(entries: YamlDiffEntry[], opts?: YamlDiffRenderOpts): string[];
74
+ //# sourceMappingURL=idempotency-yaml-diff.d.ts.map
@@ -0,0 +1,241 @@
1
+ import "./chunk-gOLHoazu.js";
2
+ import { setYamlDiffRenderer } from "./idempotency-files.js";
3
+ import { parse } from "yaml";
4
+ //#region src/idempotency-yaml-diff.ts
5
+ /**
6
+ * YAML-file semantic diff for the idempotent-step preview path. Parses
7
+ * both sides with the `yaml` npm package, deep-walks the resulting JS
8
+ * trees, and emits one `YamlDiffEntry` per leaf-level path that differs.
9
+ *
10
+ * "Leaf" means the smallest scalar inside the tree: a string, number,
11
+ * boolean, or null. Arrays compare element-by-element by index; objects
12
+ * recurse into their fields. The dotted path follows the JS-property
13
+ * convention (`Database.postgres.User.Password`, `clients[2].name`).
14
+ *
15
+ * The renderer masks every entry whose path contains a sensitive
16
+ * segment (`/password|passwd|secret|api[_-]?key|token|credentials?/i`)
17
+ * unless the operator passes `reveal: true` via the
18
+ * `--reveal-env-values` CLI flag. Non-sensitive entries print their
19
+ * values inline so the operator can see config drift at a glance.
20
+ */
21
+ const ANSI_RED = "\x1B[31m";
22
+ const ANSI_GREEN = "\x1B[32m";
23
+ const ANSI_CYAN = "\x1B[36m";
24
+ const ANSI_RESET = "\x1B[0m";
25
+ const SENSITIVE_SEGMENT_RE = /^(password|passwd|secret|secrets|api[_-]?key|token|credentials?)$/i;
26
+ /**
27
+ * Returns true when any segment of the dotted path matches the
28
+ * sensitive-keyword heuristic. Numeric array indices (`[0]`) are
29
+ * stripped before the match so a path like `clients[3].token` still
30
+ * matches via the `token` segment.
31
+ */
32
+ function isPathSensitive(dottedPath) {
33
+ return dottedPath.split(/[.[\]]+/).filter((s) => s !== "").filter((s) => !/^\d+$/.test(s)).some((s) => SENSITIVE_SEGMENT_RE.test(s));
34
+ }
35
+ /**
36
+ * Deep-diff two YAML bodies. Both sides are parsed with the `yaml`
37
+ * package, then a recursive walk emits one entry per leaf that differs.
38
+ * Returns an empty array when the documents are structurally equivalent.
39
+ *
40
+ * Throws when either side fails to parse — the caller (the renderer
41
+ * dispatch) catches and falls back to unified-text rendering on a parse
42
+ * failure so a stray template tag in a yaml-by-suffix file doesn't lose
43
+ * the operator's diff.
44
+ */
45
+ function diffYamlContent(local, remote) {
46
+ const localTree = local === "" ? void 0 : parse(local);
47
+ const remoteTree = remote === "" ? void 0 : parse(remote);
48
+ const entries = [];
49
+ walkDiff("", localTree, remoteTree, entries);
50
+ entries.sort((a, b) => {
51
+ if (a.kind !== b.kind) {
52
+ const ORDER = {
53
+ added: 0,
54
+ changed: 1,
55
+ removed: 2
56
+ };
57
+ return ORDER[a.kind] - ORDER[b.kind];
58
+ }
59
+ return a.path.localeCompare(b.path);
60
+ });
61
+ return entries;
62
+ }
63
+ /**
64
+ * Recursive walk over `local` and `remote`. For each pair of values at
65
+ * `path`:
66
+ * - Both undefined → emit nothing (key missing in both).
67
+ * - Only local defined → recurse / emit `added`.
68
+ * - Only remote defined → recurse / emit `removed`.
69
+ * - Both defined, structurally compatible (both objects / both arrays)
70
+ * → recurse into children.
71
+ * - Both defined, scalar or shape-mismatched → emit `changed`.
72
+ */
73
+ function walkDiff(path, local, remote, out) {
74
+ const lDefined = local !== void 0;
75
+ const rDefined = remote !== void 0;
76
+ if (!lDefined && !rDefined) return;
77
+ if (lDefined && !rDefined) {
78
+ emitLeafOrTree(path, local, "added", out);
79
+ return;
80
+ }
81
+ if (!lDefined && rDefined) {
82
+ emitLeafOrTree(path, remote, "removed", out);
83
+ return;
84
+ }
85
+ const lObj = isPlainObject(local);
86
+ const rObj = isPlainObject(remote);
87
+ const lArr = Array.isArray(local);
88
+ const rArr = Array.isArray(remote);
89
+ if (lObj && rObj) {
90
+ const lRec = local;
91
+ const rRec = remote;
92
+ const keys = new Set([...Object.keys(lRec), ...Object.keys(rRec)]);
93
+ for (const key of keys) walkDiff(path === "" ? key : `${path}.${key}`, lRec[key], rRec[key], out);
94
+ return;
95
+ }
96
+ if (lArr && rArr) {
97
+ const lArrTyped = local;
98
+ const rArrTyped = remote;
99
+ const len = Math.max(lArrTyped.length, rArrTyped.length);
100
+ for (let i = 0; i < len; i++) walkDiff(`${path}[${i}]`, lArrTyped[i], rArrTyped[i], out);
101
+ return;
102
+ }
103
+ if (deepEqual(local, remote)) return;
104
+ out.push({
105
+ path,
106
+ kind: "changed",
107
+ oldValue: remote,
108
+ newValue: local,
109
+ sensitive: isPathSensitive(path)
110
+ });
111
+ }
112
+ /**
113
+ * When a whole subtree is added or removed, we collapse it into a
114
+ * single entry rather than emitting one per descendant leaf. The
115
+ * value is the entire subtree; the renderer prints it inline (masked
116
+ * when the path is sensitive) or via a JSON one-liner.
117
+ */
118
+ function emitLeafOrTree(path, value, kind, out) {
119
+ const reportedPath = path === "" ? "<root>" : path;
120
+ if (kind === "added") out.push({
121
+ path: reportedPath,
122
+ kind,
123
+ newValue: value,
124
+ sensitive: isPathSensitive(path)
125
+ });
126
+ else out.push({
127
+ path: reportedPath,
128
+ kind,
129
+ oldValue: value,
130
+ sensitive: isPathSensitive(path)
131
+ });
132
+ }
133
+ function isPlainObject(value) {
134
+ if (value === null || typeof value !== "object") return false;
135
+ if (Array.isArray(value)) return false;
136
+ const proto = Object.getPrototypeOf(value);
137
+ return proto === Object.prototype || proto === null;
138
+ }
139
+ /**
140
+ * Cheap structural equality check. Only used as a tie-breaker for the
141
+ * "neither object nor array" branch — scalar leaves go through
142
+ * `===` after a JSON-stringify-equiv comparison. Functions / Dates /
143
+ * other class instances fall back to `Object.is`, which is fine
144
+ * because the `yaml` package only emits plain values for the tag set
145
+ * we use (scalar, sequence, mapping).
146
+ */
147
+ function deepEqual(a, b) {
148
+ if (Object.is(a, b)) return true;
149
+ return JSON.stringify(a) === JSON.stringify(b);
150
+ }
151
+ /**
152
+ * Render the yaml-semantic diff body. Returns one entry's worth of
153
+ * lines per `YamlDiffEntry`, plus an empty-state fallback line when
154
+ * there's nothing to show. No surrounding indent applied — the caller
155
+ * decides nesting.
156
+ *
157
+ * Layout:
158
+ *
159
+ * Database.postgres.User.Password: changed (masked — pass --reveal-env-values to show)
160
+ * server.listen: changed
161
+ * - old=80
162
+ * + new=8080
163
+ * features.beta: added
164
+ * + new=true
165
+ *
166
+ * The CLI flag is named `--reveal-env-values` because the same flag
167
+ * governs env-semantic + yaml-semantic value reveals; calling the flag
168
+ * "env-values" reflects the most common case (sops-derived env files)
169
+ * but it activates yaml-side reveal too.
170
+ */
171
+ function renderYamlDiff(entries, opts = {}) {
172
+ const reveal = opts.reveal ?? false;
173
+ const color = opts.color ?? false;
174
+ if (entries.length === 0) return ["0 yaml leaf(s) drifted (structure matches)"];
175
+ const lines = [];
176
+ for (const entry of entries) {
177
+ const mask = entry.sensitive && !reveal;
178
+ const headTail = mask ? " (masked — pass --reveal-env-values to show)" : "";
179
+ lines.push(`${entry.path}: ${colorizeKind(entry.kind, color)}${headTail}`);
180
+ if (mask) continue;
181
+ if (entry.kind === "changed" || entry.kind === "removed") lines.push(` ${colorize("- old=" + formatValue(entry.oldValue), "old", color)}`);
182
+ if (entry.kind === "changed" || entry.kind === "added") lines.push(` ${colorize("+ new=" + formatValue(entry.newValue), "new", color)}`);
183
+ }
184
+ return lines;
185
+ }
186
+ function formatValue(value) {
187
+ if (value === null) return "null";
188
+ if (value === void 0) return "undefined";
189
+ if (typeof value === "string") return value;
190
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
191
+ try {
192
+ const json = JSON.stringify(value);
193
+ if (json.length <= 240) return json;
194
+ return json.slice(0, 240) + `… (${json.length - 240} more bytes)`;
195
+ } catch {
196
+ return String(value);
197
+ }
198
+ }
199
+ function colorizeKind(kind, color) {
200
+ if (!color) return kind;
201
+ switch (kind) {
202
+ case "added": return `${ANSI_GREEN}${kind}${ANSI_RESET}`;
203
+ case "removed": return `${ANSI_RED}${kind}${ANSI_RESET}`;
204
+ case "changed": return `${ANSI_CYAN}${kind}${ANSI_RESET}`;
205
+ }
206
+ }
207
+ function colorize(text, side, color) {
208
+ if (!color) return text;
209
+ return side === "new" ? `${ANSI_GREEN}${text}${ANSI_RESET}` : `${ANSI_RED}${text}${ANSI_RESET}`;
210
+ }
211
+ /**
212
+ * Bridge between the FileDriftEntry / RenderDriftOpts API surface and
213
+ * the yaml diff renderer. Registered at module load time via
214
+ * `setYamlDiffRenderer` so `renderFileDriftBody` can dispatch yaml
215
+ * entries without a hard dependency on the `yaml` package in
216
+ * `idempotency-files.ts`.
217
+ *
218
+ * On a yaml-parse failure, the renderer returns a single explanatory
219
+ * line and the dispatch falls through (caller-side) to the unified-text
220
+ * body so the operator still sees something useful.
221
+ */
222
+ function renderYamlDiffEntry(entry, opts) {
223
+ const local = entry.localContent ?? "";
224
+ const remote = entry.category === "new" ? "" : entry.remoteContent ?? "";
225
+ if (local === "" && remote === "" && entry.category !== "new") return [];
226
+ let diffs;
227
+ try {
228
+ diffs = diffYamlContent(local, remote);
229
+ } catch (err) {
230
+ return [`(yaml parse failed — ${err.message})`];
231
+ }
232
+ return renderYamlDiff(diffs, {
233
+ reveal: opts.revealEnvValues ?? false,
234
+ color: opts.color ?? false
235
+ });
236
+ }
237
+ setYamlDiffRenderer(renderYamlDiffEntry);
238
+ //#endregion
239
+ export { diffYamlContent, isPathSensitive, renderYamlDiff };
240
+
241
+ //# sourceMappingURL=idempotency-yaml-diff.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=idempotency-yaml-diff.test.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { RingBuffer } from './ring-buffer.js';
2
2
  export { toErrorMessage, serializeError } from './error.js';
3
3
  export { createPool, createDb } from './db.js';
4
- export { parseDatabaseUrl, maskDatabaseUrl, dropAndCreateDatabase, dropDatabaseDirect, ensureDatabase, createDbRole, createReadOnlyDbUser, computeMigrationsHash, storeMigrationContentHash, readStoredMigrationContentHash, isSchemaCurrent, clearDispatchQueueDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, purgeScopedSecretsDirect, seedEnvironmentDirect, seedEnvironmentBindingDirect, setEnvironmentPolicyDirect, listEnvironmentsDirect, showEnvironmentDirect, createEnvironmentTemplateDirect, setEnvironmentSecretDirect, listQueueDirect, showQueueEntryDirect, listExecutionRunsDirect, showExecutionRunDirect, listExecutionJobsDirect, listRegistrationsDirect, showRegistrationDirect, registerWorkflowManualDirect, resetRaftStateDirect, emitKiciEventDirect, seedGenericWebhookSourceDirect, purgeSecretBackendsDirect, apiKeyExistsDirect, seedApiKeyInlineDirect, platformConnectionExistsDirect, countWebhookSourcesByConnectionIdDirect, findAnyUserApiKeyIdDirect, seedSyntheticGithubSourceDirect, seedWebhookSecretDirect, seedSourcePrivateKeyDirect, bumpRegistryVersionDirect, pollKiciEventsDirect, waitForPostgresDirect, waitForRunCompletionDirect, cleanupExecutionRowsDirect, isSchemaCurrentFromFilesDirect, storeMigrationContentHashInTableDirect, createJoinTokenDirect, updateSourceRoutingKeyDirect, prunePeerCredentialsDirect, waitForPlatformRegistrationsDirect, seedUniversalGitSourceDirect, seedCiSecurityFixturesDirect, waitForExecutionRunStatusSinceDirect, latestExecutionRunByStatusDirect, waitForLatestExecutionJobStatusDirect, describeTableColumnsDirect, tableExistsDirect, insertKiciEventRawDirect, showKiciEventDirect, listKiciEventsDirect, deleteKiciEventsDirect, verifyKiciEventNotifyDirect, seedCrossRepoTrustDirect, listCrossRepoTrustBySourceRoutingKeyDirect, deleteCrossRepoTrustDirect, insertCrossRepoTrustStrictDirect, deleteWorkflowRegistrationsDirect, getWorkflowRegistrationByIdDirect, listRegistrationsByRoutingKeyDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, updateWorkflowRegistrationCommitShaDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, getRegistryVersionDirect, bumpRegistryVersionSimpleDirect, upsertCronLastFiredDirect, countCronLastFiredDirect, insertCronLastFiredNowDirect, deleteCronLastFiredDirect, deleteExecutionRunsByWorkflowNameDirect, getGenericWebhookSourceByRoutingKeyDirect, listActiveGenericWebhookSourcesDirect, updateGenericWebhookVerificationConfigDirect, deleteGenericWebhookSourcesByNameDirect, restoreSoftDeletedGenericWebhookSourceDirect, upsertOrgSettingsGlobalWorkflowsDirect, updateOrgSettingsDeniedReposDirect, deleteOrgSettingsByCustomerIdDirect, getExecutionRunSecurityDirect, getHeldRunByIdDirect, countHeldRunsByRunIdDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForEventLogRowByDeliveryIdDirect, resolvePlatformWebhookSourceRoutingKeyDirect, ensureOrgOwnerMemberDirect, deletePeerCredentialsByInstanceIdLikeDirect, insertPeerCredentialExpiredDirect, getPeerCredentialRevokedAtDirect, listActivePeerCredentialsExcludingDirect, clearPeerCredentialsRevokedAtByIdsDirect, countActivePeerCredentialsByInstanceDirect, type ColumnInfo, type KiciEventRow, type CrossRepoTrustRow, type WorkflowRegistrationFullRow, type RegistrationsScopedResult, type LatestExecutionRunResult, type WaitForLatestJobResult, type ExecutionRunSecurityRow, type HeldRunSecurityRow, type EventLogRow as PlatformEventLogRow, type UpsertOrgSettingsOpts, type OrgSettingsRepoPatternEntry, type InsertKiciEventRawOpts, type EmitKiciEventOpts, type SeedGenericWebhookSourceOpts, REGISTERABLE_TRIGGER_TYPES, MIGRATION_HASH_TABLE, type PurgeStaleExecutionResult, type PurgeStaleSourcesResult, type SeedEnvironmentOpts, type SeedEnvironmentResult, type SeedEnvironmentBindingOpts, type SetEnvironmentPolicyOpts, type EnvironmentRow, type EnvironmentVariableRow, type EnvironmentBindingRow, type ShowEnvironmentResult, type CreateEnvironmentTemplateOpts, type SetEnvironmentSecretOpts, type DispatchQueueRow, type ListQueueOpts, type ExecutionRunRow, type ExecutionJobRow, type ListExecutionRunsOpts, type WorkflowRegistrationRow, type ListRegistrationsOpts, type ListRegistrationsResult, type ShowRegistrationResult, type RegisterWorkflowManualOpts, type RegisterWorkflowManualResult, } from './db-admin.js';
4
+ export { parseDatabaseUrl, maskDatabaseUrl, dropAndCreateDatabase, dropDatabaseDirect, ensureDatabase, type EnsureDatabaseOpts, createDbRole, createReadOnlyDbUser, computeMigrationsHash, storeMigrationContentHash, readStoredMigrationContentHash, isSchemaCurrent, clearDispatchQueueDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, purgeScopedSecretsDirect, seedEnvironmentDirect, seedEnvironmentBindingDirect, setEnvironmentPolicyDirect, listEnvironmentsDirect, showEnvironmentDirect, createEnvironmentTemplateDirect, setEnvironmentSecretDirect, listQueueDirect, showQueueEntryDirect, listExecutionRunsDirect, showExecutionRunDirect, listExecutionJobsDirect, listRegistrationsDirect, showRegistrationDirect, registerWorkflowManualDirect, resetRaftStateDirect, emitKiciEventDirect, seedGenericWebhookSourceDirect, purgeSecretBackendsDirect, apiKeyExistsDirect, seedApiKeyInlineDirect, platformConnectionExistsDirect, countWebhookSourcesByConnectionIdDirect, getWebhookSourceByRoutingKeyDirect, findAnyUserApiKeyIdDirect, seedSyntheticGithubSourceDirect, seedWebhookSecretDirect, seedSourcePrivateKeyDirect, bumpRegistryVersionDirect, pollKiciEventsDirect, waitForPostgresDirect, waitForRunCompletionDirect, cleanupExecutionRowsDirect, isSchemaCurrentFromFilesDirect, storeMigrationContentHashInTableDirect, createJoinTokenDirect, updateSourceRoutingKeyDirect, prunePeerCredentialsDirect, waitForPlatformRegistrationsDirect, seedUniversalGitSourceDirect, seedCiSecurityFixturesDirect, waitForExecutionRunStatusSinceDirect, latestExecutionRunByStatusDirect, waitForLatestExecutionJobStatusDirect, describeTableColumnsDirect, tableExistsDirect, insertKiciEventRawDirect, showKiciEventDirect, listKiciEventsDirect, deleteKiciEventsDirect, verifyKiciEventNotifyDirect, seedCrossRepoTrustDirect, listCrossRepoTrustBySourceRoutingKeyDirect, deleteCrossRepoTrustDirect, insertCrossRepoTrustStrictDirect, deleteWorkflowRegistrationsDirect, getWorkflowRegistrationByIdDirect, listRegistrationsByRoutingKeyDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, updateWorkflowRegistrationCommitShaDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, getRegistryVersionDirect, bumpRegistryVersionSimpleDirect, upsertCronLastFiredDirect, countCronLastFiredDirect, insertCronLastFiredNowDirect, deleteCronLastFiredDirect, deleteExecutionRunsByWorkflowNameDirect, getGenericWebhookSourceByRoutingKeyDirect, listActiveGenericWebhookSourcesDirect, updateGenericWebhookVerificationConfigDirect, deleteGenericWebhookSourcesByNameDirect, restoreSoftDeletedGenericWebhookSourceDirect, upsertOrgSettingsGlobalWorkflowsDirect, updateOrgSettingsDeniedReposDirect, deleteOrgSettingsByCustomerIdDirect, getExecutionRunSecurityDirect, getHeldRunByIdDirect, countHeldRunsByRunIdDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForEventLogRowByDeliveryIdDirect, resolvePlatformWebhookSourceRoutingKeyDirect, ensureOrgOwnerMemberDirect, deletePeerCredentialsByInstanceIdLikeDirect, insertPeerCredentialExpiredDirect, getPeerCredentialRevokedAtDirect, listActivePeerCredentialsExcludingDirect, clearPeerCredentialsRevokedAtByIdsDirect, countActivePeerCredentialsByInstanceDirect, type ColumnInfo, type KiciEventRow, type CrossRepoTrustRow, type WorkflowRegistrationFullRow, type RegistrationsScopedResult, type LatestExecutionRunResult, type WaitForLatestJobResult, type ExecutionRunSecurityRow, type HeldRunSecurityRow, type EventLogRow as PlatformEventLogRow, type UpsertOrgSettingsOpts, type OrgSettingsRepoPatternEntry, type InsertKiciEventRawOpts, type EmitKiciEventOpts, type SeedGenericWebhookSourceOpts, REGISTERABLE_TRIGGER_TYPES, MIGRATION_HASH_TABLE, type PurgeStaleExecutionResult, type PurgeStaleSourcesResult, type SeedEnvironmentOpts, type SeedEnvironmentResult, type SeedEnvironmentBindingOpts, type SetEnvironmentPolicyOpts, type EnvironmentRow, type EnvironmentVariableRow, type EnvironmentBindingRow, type ShowEnvironmentResult, type CreateEnvironmentTemplateOpts, type SetEnvironmentSecretOpts, type DispatchQueueRow, type ListQueueOpts, type ExecutionRunRow, type ExecutionJobRow, type ListExecutionRunsOpts, type WorkflowRegistrationRow, type ListRegistrationsOpts, type ListRegistrationsResult, type ShowRegistrationResult, type RegisterWorkflowManualOpts, type RegisterWorkflowManualResult, } from './db-admin.js';
5
5
  export { createMetricsRoutes, type MetricsRoutesDeps } from './routes/metrics.js';
6
6
  export { createHealthRoutes, type HealthRoutesDeps } from './routes/health.js';
7
7
  export { initZx } from './zx.js';
@@ -11,7 +11,7 @@ export { getReconnectDelay } from './reconnect-delay.js';
11
11
  export { formatBytes } from './format-bytes.js';
12
12
  export { formatDuration, formatUptime } from './format-duration.js';
13
13
  export { sha256, sha256File, deriveSharedSecret, normalizeLineEndings } from './crypto.js';
14
- export { initTelemetry, getPrometheusExporter, createMeter, type TelemetryConfig, } from './telemetry/index.js';
14
+ export { initTelemetry, getPrometheusExporter, collectRuntimeMetricNames, createMeter, type TelemetryConfig, } from './telemetry/index.js';
15
15
  export { setupGracefulShutdown, type ShutdownStep, type ShutdownLogger, type ShutdownHandle, type GracefulShutdownOptions, } from './graceful-shutdown.js';
16
16
  export { validateRequiredTools, type ToolRequirement } from './tool-check.js';
17
17
  export { createS3Client, type CreateS3ClientOptions, type SharedS3Config } from './s3-client.js';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import "./chunk-gOLHoazu.js";
2
2
  import { deriveSharedSecret, normalizeLineEndings, sha256, sha256File } from "./crypto.js";
3
3
  import { createDb, createPool } from "./db.js";
4
- import { MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createDbRole, createEnvironmentTemplateDirect, createJoinTokenDirect, createReadOnlyDbUser, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteExecutionRunsByWorkflowNameDirect, deleteGenericWebhookSourcesByNameDirect, deleteKiciEventsDirect, deleteOrgSettingsByCustomerIdDirect, deletePeerCredentialsByInstanceIdLikeDirect, deleteWorkflowRegistrationsDirect, describeTableColumnsDirect, dropAndCreateDatabase, dropDatabaseDirect, emitKiciEventDirect, ensureDatabase, ensureOrgOwnerMemberDirect, findAnyUserApiKeyIdDirect, getExecutionRunSecurityDirect, getGenericWebhookSourceByRoutingKeyDirect, getHeldRunByIdDirect, getPeerCredentialRevokedAtDirect, getRegistryVersionDirect, getWorkflowRegistrationByIdDirect, insertCronLastFiredNowDirect, insertCrossRepoTrustStrictDirect, insertKiciEventRawDirect, insertPeerCredentialExpiredDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, isSchemaCurrent, isSchemaCurrentFromFilesDirect, latestExecutionRunByStatusDirect, listActiveGenericWebhookSourcesDirect, listActivePeerCredentialsExcludingDirect, listCrossRepoTrustBySourceRoutingKeyDirect, listEnvironmentsDirect, listExecutionJobsDirect, listExecutionRunsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedCrossRepoTrustDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, showEnvironmentDirect, showExecutionRunDirect, showKiciEventDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, storeMigrationContentHashInTableDirect, tableExistsDirect, updateGenericWebhookVerificationConfigDirect, updateOrgSettingsDeniedReposDirect, updateSourceRoutingKeyDirect, updateWorkflowRegistrationCommitShaDirect, upsertCronLastFiredDirect, upsertOrgSettingsGlobalWorkflowsDirect, verifyKiciEventNotifyDirect, waitForEventLogRowByDeliveryIdDirect, waitForExecutionRunStatusSinceDirect, waitForLatestExecutionJobStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformRegistrationsDirect, waitForPostgresDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, waitForRunCompletionDirect } from "./db-admin.js";
4
+ import { MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createDbRole, createEnvironmentTemplateDirect, createJoinTokenDirect, createReadOnlyDbUser, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteExecutionRunsByWorkflowNameDirect, deleteGenericWebhookSourcesByNameDirect, deleteKiciEventsDirect, deleteOrgSettingsByCustomerIdDirect, deletePeerCredentialsByInstanceIdLikeDirect, deleteWorkflowRegistrationsDirect, describeTableColumnsDirect, dropAndCreateDatabase, dropDatabaseDirect, emitKiciEventDirect, ensureDatabase, ensureOrgOwnerMemberDirect, findAnyUserApiKeyIdDirect, getExecutionRunSecurityDirect, getGenericWebhookSourceByRoutingKeyDirect, getHeldRunByIdDirect, getPeerCredentialRevokedAtDirect, getRegistryVersionDirect, getWebhookSourceByRoutingKeyDirect, getWorkflowRegistrationByIdDirect, insertCronLastFiredNowDirect, insertCrossRepoTrustStrictDirect, insertKiciEventRawDirect, insertPeerCredentialExpiredDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, isSchemaCurrent, isSchemaCurrentFromFilesDirect, latestExecutionRunByStatusDirect, listActiveGenericWebhookSourcesDirect, listActivePeerCredentialsExcludingDirect, listCrossRepoTrustBySourceRoutingKeyDirect, listEnvironmentsDirect, listExecutionJobsDirect, listExecutionRunsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedCrossRepoTrustDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, showEnvironmentDirect, showExecutionRunDirect, showKiciEventDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, storeMigrationContentHashInTableDirect, tableExistsDirect, updateGenericWebhookVerificationConfigDirect, updateOrgSettingsDeniedReposDirect, updateSourceRoutingKeyDirect, updateWorkflowRegistrationCommitShaDirect, upsertCronLastFiredDirect, upsertOrgSettingsGlobalWorkflowsDirect, verifyKiciEventNotifyDirect, waitForEventLogRowByDeliveryIdDirect, waitForExecutionRunStatusSinceDirect, waitForLatestExecutionJobStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformRegistrationsDirect, waitForPostgresDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, waitForRunCompletionDirect } from "./db-admin.js";
5
5
  import { serializeError, toErrorMessage } from "./error.js";
6
6
  import { formatBytes } from "./format-bytes.js";
7
7
  import { formatDuration, formatUptime } from "./format-duration.js";
@@ -13,7 +13,7 @@ import { initZx } from "./zx.js";
13
13
  import { enrichRequestContext, getRequestContext, requestContext } from "./request-context.js";
14
14
  import { createLogger, guardStartup, logger, setServiceName } from "./logger.js";
15
15
  import { getReconnectDelay } from "./reconnect-delay.js";
16
- import { getPrometheusExporter, initTelemetry } from "./telemetry/init.js";
16
+ import { collectRuntimeMetricNames, getPrometheusExporter, initTelemetry } from "./telemetry/init.js";
17
17
  import { createMeter } from "./telemetry/metrics.js";
18
18
  import "./telemetry/index.js";
19
19
  import { validateRequiredTools } from "./tool-check.js";
@@ -28,4 +28,4 @@ import { BaseColdStore } from "./cold-store/cold-store.js";
28
28
  import { ChunkLru } from "./cold-store/lru.js";
29
29
  import { DEFAULT_TABLE_CONFIG, resolveTableConfig } from "./cold-store/config.js";
30
30
  import "./cold-store/index.js";
31
- export { BaseColdStore, COLD_BUCKET_NAMES, ChunkLru, DEFAULT_TABLE_CONFIG, MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, RingBuffer, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, chunkObjectKey, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, coldDaysToBucket, coldStoreArchiveBytesTotal, coldStoreArchiveCyclesTotal, coldStoreArchiveDurationSeconds, coldStoreArchiveRowsTotal, coldStorePurgeBytesTotal, coldStorePurgeChunksTotal, coldStorePurgeDurationSeconds, coldStoreRehydrateBytesTotal, coldStoreRehydrateDurationSeconds, coldStoreRehydrateRequestsTotal, coldStoreReplayDurationSeconds, coldStoreReplayRowsTotal, coldStoreVerifyFailuresTotal, computeChunkId, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createDb, createDbRole, createEnvironmentTemplateDirect, createHealthRoutes, createJoinTokenDirect, createLogger, createMeter, createMetricsRoutes, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteExecutionRunsByWorkflowNameDirect, deleteGenericWebhookSourcesByNameDirect, deleteKiciEventsDirect, deleteOrgSettingsByCustomerIdDirect, deletePeerCredentialsByInstanceIdLikeDirect, deleteWorkflowRegistrationsDirect, deriveSharedSecret, describeTableColumnsDirect, dropAndCreateDatabase, dropDatabaseDirect, emitKiciEventDirect, encodeChunk, encodeKeySegment, enrichRequestContext, ensureDatabase, ensureOrgOwnerMemberDirect, findAnyUserApiKeyIdDirect, formatBytes, formatDuration, formatUptime, getExecutionRunSecurityDirect, getGenericWebhookSourceByRoutingKeyDirect, getHeldRunByIdDirect, getPeerCredentialRevokedAtDirect, getPrometheusExporter, getReconnectDelay, getRegistryVersionDirect, getRequestContext, getWorkflowRegistrationByIdDirect, guardStartup, initTelemetry, initZx, insertCronLastFiredNowDirect, insertCrossRepoTrustStrictDirect, insertKiciEventRawDirect, insertPeerCredentialExpiredDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, isLongerColdRetention, isSchemaCurrent, isSchemaCurrentFromFilesDirect, latestExecutionRunByStatusDirect, listActiveGenericWebhookSourcesDirect, listActivePeerCredentialsExcludingDirect, listCrossRepoTrustBySourceRoutingKeyDirect, listEnvironmentsDirect, listExecutionJobsDirect, listExecutionRunsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, logger, maskDatabaseUrl, normalizeLineEndings, parseDatabaseUrl, parseManifest, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, requestContext, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, resolveTableConfig, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedCrossRepoTrustDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, serializeError, serializeManifest, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, setServiceName, setupGracefulShutdown, sha256, sha256File, showEnvironmentDirect, showExecutionRunDirect, showKiciEventDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, storeMigrationContentHashInTableDirect, tableExistsDirect, tablePrefix, tenantDayBucketPrefix, tenantDayPrefix, toErrorMessage, updateGenericWebhookVerificationConfigDirect, updateOrgSettingsDeniedReposDirect, updateSourceRoutingKeyDirect, updateWorkflowRegistrationCommitShaDirect, upsertCronLastFiredDirect, upsertOrgSettingsGlobalWorkflowsDirect, validateRequiredTools, verifyKiciEventNotifyDirect, waitForEventLogRowByDeliveryIdDirect, waitForExecutionRunStatusSinceDirect, waitForLatestExecutionJobStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformRegistrationsDirect, waitForPostgresDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, waitForRunCompletionDirect };
31
+ export { BaseColdStore, COLD_BUCKET_NAMES, ChunkLru, DEFAULT_TABLE_CONFIG, MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, RingBuffer, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, chunkObjectKey, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, coldDaysToBucket, coldStoreArchiveBytesTotal, coldStoreArchiveCyclesTotal, coldStoreArchiveDurationSeconds, coldStoreArchiveRowsTotal, coldStorePurgeBytesTotal, coldStorePurgeChunksTotal, coldStorePurgeDurationSeconds, coldStoreRehydrateBytesTotal, coldStoreRehydrateDurationSeconds, coldStoreRehydrateRequestsTotal, coldStoreReplayDurationSeconds, coldStoreReplayRowsTotal, coldStoreVerifyFailuresTotal, collectRuntimeMetricNames, computeChunkId, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createDb, createDbRole, createEnvironmentTemplateDirect, createHealthRoutes, createJoinTokenDirect, createLogger, createMeter, createMetricsRoutes, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteExecutionRunsByWorkflowNameDirect, deleteGenericWebhookSourcesByNameDirect, deleteKiciEventsDirect, deleteOrgSettingsByCustomerIdDirect, deletePeerCredentialsByInstanceIdLikeDirect, deleteWorkflowRegistrationsDirect, deriveSharedSecret, describeTableColumnsDirect, dropAndCreateDatabase, dropDatabaseDirect, emitKiciEventDirect, encodeChunk, encodeKeySegment, enrichRequestContext, ensureDatabase, ensureOrgOwnerMemberDirect, findAnyUserApiKeyIdDirect, formatBytes, formatDuration, formatUptime, getExecutionRunSecurityDirect, getGenericWebhookSourceByRoutingKeyDirect, getHeldRunByIdDirect, getPeerCredentialRevokedAtDirect, getPrometheusExporter, getReconnectDelay, getRegistryVersionDirect, getRequestContext, getWebhookSourceByRoutingKeyDirect, getWorkflowRegistrationByIdDirect, guardStartup, initTelemetry, initZx, insertCronLastFiredNowDirect, insertCrossRepoTrustStrictDirect, insertKiciEventRawDirect, insertPeerCredentialExpiredDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, isLongerColdRetention, isSchemaCurrent, isSchemaCurrentFromFilesDirect, latestExecutionRunByStatusDirect, listActiveGenericWebhookSourcesDirect, listActivePeerCredentialsExcludingDirect, listCrossRepoTrustBySourceRoutingKeyDirect, listEnvironmentsDirect, listExecutionJobsDirect, listExecutionRunsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, logger, maskDatabaseUrl, normalizeLineEndings, parseDatabaseUrl, parseManifest, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, requestContext, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, resolveTableConfig, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedCrossRepoTrustDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, serializeError, serializeManifest, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, setServiceName, setupGracefulShutdown, sha256, sha256File, showEnvironmentDirect, showExecutionRunDirect, showKiciEventDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, storeMigrationContentHashInTableDirect, tableExistsDirect, tablePrefix, tenantDayBucketPrefix, tenantDayPrefix, toErrorMessage, updateGenericWebhookVerificationConfigDirect, updateOrgSettingsDeniedReposDirect, updateSourceRoutingKeyDirect, updateWorkflowRegistrationCommitShaDirect, upsertCronLastFiredDirect, upsertOrgSettingsGlobalWorkflowsDirect, validateRequiredTools, verifyKiciEventNotifyDirect, waitForEventLogRowByDeliveryIdDirect, waitForExecutionRunStatusSinceDirect, waitForLatestExecutionJobStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformRegistrationsDirect, waitForPostgresDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, waitForRunCompletionDirect };
package/dist/logger.d.ts CHANGED
@@ -23,7 +23,10 @@ export interface Logger {
23
23
  }
24
24
  /** Logger creation options */
25
25
  interface LoggerOptions {
26
- /** Use JSON format (default: auto-detect based on TTY) */
26
+ /**
27
+ * Use JSON format (default: auto-detected from KICI_LOG_FORMAT env var, with
28
+ * a TTY fallback). Passing an explicit boolean wins over the env var.
29
+ */
27
30
  json?: boolean;
28
31
  /** Log level (default: 'info') */
29
32
  level?: LogLevel;