@vyuhlabs/dxkit 2.5.2 → 2.6.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 (146) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/README.md +102 -0
  3. package/dist/allowlist/categories.d.ts +120 -0
  4. package/dist/allowlist/categories.d.ts.map +1 -0
  5. package/dist/allowlist/categories.js +194 -0
  6. package/dist/allowlist/categories.js.map +1 -0
  7. package/dist/allowlist/cli.d.ts +95 -0
  8. package/dist/allowlist/cli.d.ts.map +1 -0
  9. package/dist/allowlist/cli.js +454 -0
  10. package/dist/allowlist/cli.js.map +1 -0
  11. package/dist/allowlist/diff.d.ts +67 -0
  12. package/dist/allowlist/diff.d.ts.map +1 -0
  13. package/dist/allowlist/diff.js +147 -0
  14. package/dist/allowlist/diff.js.map +1 -0
  15. package/dist/allowlist/file.d.ts +249 -0
  16. package/dist/allowlist/file.d.ts.map +1 -0
  17. package/dist/allowlist/file.js +497 -0
  18. package/dist/allowlist/file.js.map +1 -0
  19. package/dist/allowlist/gather.d.ts +61 -0
  20. package/dist/allowlist/gather.d.ts.map +1 -0
  21. package/dist/allowlist/gather.js +143 -0
  22. package/dist/allowlist/gather.js.map +1 -0
  23. package/dist/allowlist/hint.d.ts +80 -0
  24. package/dist/allowlist/hint.d.ts.map +1 -0
  25. package/dist/allowlist/hint.js +271 -0
  26. package/dist/allowlist/hint.js.map +1 -0
  27. package/dist/allowlist/inline.d.ts +149 -0
  28. package/dist/allowlist/inline.d.ts.map +1 -0
  29. package/dist/allowlist/inline.js +306 -0
  30. package/dist/allowlist/inline.js.map +1 -0
  31. package/dist/baseline/baseline-file.d.ts +7 -0
  32. package/dist/baseline/baseline-file.d.ts.map +1 -1
  33. package/dist/baseline/baseline-file.js +22 -1
  34. package/dist/baseline/baseline-file.js.map +1 -1
  35. package/dist/baseline/check-renderers.d.ts +13 -1
  36. package/dist/baseline/check-renderers.d.ts.map +1 -1
  37. package/dist/baseline/check-renderers.js +67 -1
  38. package/dist/baseline/check-renderers.js.map +1 -1
  39. package/dist/baseline/check.d.ts +33 -7
  40. package/dist/baseline/check.d.ts.map +1 -1
  41. package/dist/baseline/check.js +90 -64
  42. package/dist/baseline/check.js.map +1 -1
  43. package/dist/baseline/create.d.ts +35 -7
  44. package/dist/baseline/create.d.ts.map +1 -1
  45. package/dist/baseline/create.js +43 -5
  46. package/dist/baseline/create.js.map +1 -1
  47. package/dist/baseline/entry-to-located.d.ts +6 -1
  48. package/dist/baseline/entry-to-located.d.ts.map +1 -1
  49. package/dist/baseline/entry-to-located.js +20 -2
  50. package/dist/baseline/entry-to-located.js.map +1 -1
  51. package/dist/baseline/finding-identity.d.ts.map +1 -1
  52. package/dist/baseline/finding-identity.js +15 -13
  53. package/dist/baseline/finding-identity.js.map +1 -1
  54. package/dist/baseline/modes.d.ts +140 -0
  55. package/dist/baseline/modes.d.ts.map +1 -0
  56. package/dist/baseline/modes.js +179 -0
  57. package/dist/baseline/modes.js.map +1 -0
  58. package/dist/baseline/policy.d.ts +64 -0
  59. package/dist/baseline/policy.d.ts.map +1 -1
  60. package/dist/baseline/policy.js +102 -1
  61. package/dist/baseline/policy.js.map +1 -1
  62. package/dist/baseline/producers/health.d.ts +2 -2
  63. package/dist/baseline/producers/health.d.ts.map +1 -1
  64. package/dist/baseline/producers/health.js.map +1 -1
  65. package/dist/baseline/producers/index.d.ts +11 -5
  66. package/dist/baseline/producers/index.d.ts.map +1 -1
  67. package/dist/baseline/producers/index.js +12 -9
  68. package/dist/baseline/producers/index.js.map +1 -1
  69. package/dist/baseline/producers/quality.d.ts +3 -3
  70. package/dist/baseline/producers/quality.d.ts.map +1 -1
  71. package/dist/baseline/producers/quality.js.map +1 -1
  72. package/dist/baseline/producers/secret-hmac.d.ts +2 -2
  73. package/dist/baseline/producers/secret-hmac.d.ts.map +1 -1
  74. package/dist/baseline/producers/secret-hmac.js.map +1 -1
  75. package/dist/baseline/producers/security.d.ts +2 -2
  76. package/dist/baseline/producers/security.d.ts.map +1 -1
  77. package/dist/baseline/producers/security.js.map +1 -1
  78. package/dist/baseline/producers/stale-allow.d.ts +70 -0
  79. package/dist/baseline/producers/stale-allow.d.ts.map +1 -0
  80. package/dist/baseline/producers/stale-allow.js +111 -0
  81. package/dist/baseline/producers/stale-allow.js.map +1 -0
  82. package/dist/baseline/producers/tests.d.ts +2 -2
  83. package/dist/baseline/producers/tests.d.ts.map +1 -1
  84. package/dist/baseline/producers/tests.js.map +1 -1
  85. package/dist/baseline/ref-baseline.d.ts +114 -0
  86. package/dist/baseline/ref-baseline.d.ts.map +1 -0
  87. package/dist/baseline/ref-baseline.js +260 -0
  88. package/dist/baseline/ref-baseline.js.map +1 -0
  89. package/dist/baseline/sanitize.d.ts +80 -0
  90. package/dist/baseline/sanitize.d.ts.map +1 -0
  91. package/dist/baseline/sanitize.js +91 -0
  92. package/dist/baseline/sanitize.js.map +1 -0
  93. package/dist/baseline/show.d.ts.map +1 -1
  94. package/dist/baseline/show.js +9 -3
  95. package/dist/baseline/show.js.map +1 -1
  96. package/dist/baseline/types.d.ts +73 -26
  97. package/dist/baseline/types.d.ts.map +1 -1
  98. package/dist/baseline/types.js +7 -1
  99. package/dist/baseline/types.js.map +1 -1
  100. package/dist/baseline/visibility.d.ts +61 -0
  101. package/dist/baseline/visibility.d.ts.map +1 -0
  102. package/dist/baseline/visibility.js +121 -0
  103. package/dist/baseline/visibility.js.map +1 -0
  104. package/dist/cli.d.ts.map +1 -1
  105. package/dist/cli.js +88 -3
  106. package/dist/cli.js.map +1 -1
  107. package/dist/doctor.d.ts.map +1 -1
  108. package/dist/doctor.js +106 -16
  109. package/dist/doctor.js.map +1 -1
  110. package/dist/issue-cli.d.ts +62 -0
  111. package/dist/issue-cli.d.ts.map +1 -0
  112. package/dist/issue-cli.js +252 -0
  113. package/dist/issue-cli.js.map +1 -0
  114. package/dist/languages/csharp.d.ts.map +1 -1
  115. package/dist/languages/csharp.js +1 -0
  116. package/dist/languages/csharp.js.map +1 -1
  117. package/dist/languages/go.d.ts.map +1 -1
  118. package/dist/languages/go.js +1 -0
  119. package/dist/languages/go.js.map +1 -1
  120. package/dist/languages/java.d.ts.map +1 -1
  121. package/dist/languages/java.js +1 -0
  122. package/dist/languages/java.js.map +1 -1
  123. package/dist/languages/kotlin.d.ts.map +1 -1
  124. package/dist/languages/kotlin.js +1 -0
  125. package/dist/languages/kotlin.js.map +1 -1
  126. package/dist/languages/python.d.ts.map +1 -1
  127. package/dist/languages/python.js +1 -0
  128. package/dist/languages/python.js.map +1 -1
  129. package/dist/languages/ruby.d.ts.map +1 -1
  130. package/dist/languages/ruby.js +1 -0
  131. package/dist/languages/ruby.js.map +1 -1
  132. package/dist/languages/rust.d.ts.map +1 -1
  133. package/dist/languages/rust.js +1 -0
  134. package/dist/languages/rust.js.map +1 -1
  135. package/dist/languages/types.d.ts +25 -0
  136. package/dist/languages/types.d.ts.map +1 -1
  137. package/dist/languages/typescript.d.ts.map +1 -1
  138. package/dist/languages/typescript.js +1 -0
  139. package/dist/languages/typescript.js.map +1 -1
  140. package/package.json +1 -1
  141. package/templates/.claude/skills/dxkit-action/SKILL.md +105 -11
  142. package/templates/.claude/skills/dxkit-onboard/SKILL.md +31 -3
  143. package/dist/baseline/producers/licenses.d.ts +0 -23
  144. package/dist/baseline/producers/licenses.d.ts.map +0 -1
  145. package/dist/baseline/producers/licenses.js +0 -46
  146. package/dist/baseline/producers/licenses.js.map +0 -1
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ /**
3
+ * Allowlist delta — what changed between two repo states.
4
+ *
5
+ * The guardrail check posts a PR comment whenever new allowlist
6
+ * entries appear on the PR branch. Reviewers see the suppressions
7
+ * being introduced and can sanity-check the typed category / reason
8
+ * / expiry without manually grepping for `dxkit-allow:` lines.
9
+ *
10
+ * # Two-state comparison
11
+ *
12
+ * `computeAllowlistDelta` compares the current on-disk allowlist
13
+ * (loaded via the canonical `loadAllowlist`) against the allowlist
14
+ * at the baseline's commit SHA (read via `git show <sha>:.dxkit/...`).
15
+ * Each entry's identity is its `fingerprint`; the delta is the
16
+ * symmetric difference of the two fingerprint sets, hydrated back
17
+ * to the full entries on each side.
18
+ *
19
+ * added — entries present in current but not at the baseline SHA
20
+ * removed — entries present at the baseline SHA but not in current
21
+ *
22
+ * # Graceful degradation
23
+ *
24
+ * When the baseline SHA isn't reachable (shallow clone, force-push
25
+ * orphaned base), the delta reports `baselineAccessible: false` and
26
+ * an empty `added` / `removed`. Callers (the renderer) treat that
27
+ * as "delta unavailable" rather than "no changes" — surfacing the
28
+ * incident so the customer can either deepen the clone or accept
29
+ * the missing review signal.
30
+ *
31
+ * Architectural posture:
32
+ * - All IO goes through `loadAllowlist` (CLAUDE.md arch rule 1).
33
+ * - `git show` is the only direct git interaction; failure modes
34
+ * return null without throwing.
35
+ * - Pure function over both inputs (current allowlist + git-resolved
36
+ * baseline allowlist) — testable independently of git state.
37
+ */
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.computeAllowlistDelta = computeAllowlistDelta;
40
+ exports.diffEntries = diffEntries;
41
+ const child_process_1 = require("child_process");
42
+ const file_1 = require("./file");
43
+ /**
44
+ * Compute the delta between the current on-disk allowlist and the
45
+ * allowlist at the baseline's commit SHA. Returns a structurally
46
+ * empty delta with `baselineAccessible: false` when the baseline
47
+ * SHA can't be read.
48
+ *
49
+ * `baselineCommitSha` must be a non-empty hex SHA; an empty string
50
+ * (the canonical "no commit" value baseline-create uses outside a
51
+ * git repo) yields `baselineAccessible: false` immediately.
52
+ */
53
+ function computeAllowlistDelta(cwd, baselineCommitSha) {
54
+ const current = (0, file_1.loadAllowlist)(cwd);
55
+ const empty = { added: [], removed: [], baselineAccessible: false };
56
+ if (!baselineCommitSha)
57
+ return empty;
58
+ const baselineFile = readAllowlistAtSha(cwd, baselineCommitSha);
59
+ if (baselineFile === null) {
60
+ // git unreachable OR file genuinely didn't exist at the
61
+ // baseline SHA. We can still produce a useful delta in the
62
+ // "file didn't exist" case — every current entry is "added"
63
+ // (the customer adopted the allowlist after baseline-create).
64
+ // Distinguish the two cases by checking whether the SHA is at
65
+ // least resolvable.
66
+ if (!shaReachable(cwd, baselineCommitSha))
67
+ return empty;
68
+ // SHA reachable but file absent → current entries are all new.
69
+ return {
70
+ added: current?.entries ?? [],
71
+ removed: [],
72
+ baselineAccessible: true,
73
+ };
74
+ }
75
+ const currentEntries = current?.entries ?? [];
76
+ return diffEntries(baselineFile.entries, currentEntries);
77
+ }
78
+ /**
79
+ * Pure delta over two entry arrays. Exposed for testability —
80
+ * callers without git state can synthesize before/after fixtures
81
+ * directly. Uses fingerprint equality (the canonical identity
82
+ * predicate) for set diff.
83
+ */
84
+ function diffEntries(prior, current) {
85
+ const priorByFp = new Map();
86
+ for (const e of prior)
87
+ priorByFp.set(e.fingerprint, e);
88
+ const currentByFp = new Map();
89
+ for (const e of current)
90
+ currentByFp.set(e.fingerprint, e);
91
+ const added = [];
92
+ for (const [fp, e] of currentByFp) {
93
+ if (!priorByFp.has(fp))
94
+ added.push(e);
95
+ }
96
+ const removed = [];
97
+ for (const [fp, e] of priorByFp) {
98
+ if (!currentByFp.has(fp))
99
+ removed.push(e);
100
+ }
101
+ return { added, removed, baselineAccessible: true };
102
+ }
103
+ // ─── Internals ────────────────────────────────────────────────────────────
104
+ function readAllowlistAtSha(cwd, sha) {
105
+ const gitPath = `${file_1.ALLOWLIST_DIR}/${file_1.ALLOWLIST_FILENAME}`;
106
+ let raw;
107
+ try {
108
+ raw = (0, child_process_1.execFileSync)('git', ['show', `${sha}:${gitPath}`], {
109
+ cwd,
110
+ stdio: ['ignore', 'pipe', 'ignore'],
111
+ encoding: 'utf8',
112
+ });
113
+ }
114
+ catch {
115
+ return null;
116
+ }
117
+ let parsed;
118
+ try {
119
+ parsed = JSON.parse(raw);
120
+ }
121
+ catch {
122
+ // File existed at the SHA but isn't valid JSON. Treat the same
123
+ // as "absent" — no useful delta computable.
124
+ return null;
125
+ }
126
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
127
+ return null;
128
+ const obj = parsed;
129
+ if (obj.schemaVersion !== file_1.ALLOWLIST_SCHEMA_VERSION)
130
+ return null;
131
+ if (!Array.isArray(obj.entries))
132
+ return null;
133
+ return parsed;
134
+ }
135
+ function shaReachable(cwd, sha) {
136
+ try {
137
+ (0, child_process_1.execFileSync)('git', ['cat-file', '-e', sha], {
138
+ cwd,
139
+ stdio: ['ignore', 'ignore', 'ignore'],
140
+ });
141
+ return true;
142
+ }
143
+ catch {
144
+ return false;
145
+ }
146
+ }
147
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/allowlist/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * On-disk allowlist file — `.dxkit/allowlist.json` + optional sidecar
3
+ * `.dxkit/allowlist-reasons.local.json`.
4
+ *
5
+ * The allowlist file is the durable contract for per-finding
6
+ * suppressions: customer has reviewed this fingerprint, categorized
7
+ * the reason, and accepts that the guardrail should let the finding
8
+ * pass on future runs.
9
+ *
10
+ * Identity is the 16-char hex fingerprint from
11
+ * `src/analyzers/tools/fingerprint.ts` (CLAUDE.md Rule 9). An entry
12
+ * matches a finding when their fingerprint strings are byte-equal.
13
+ *
14
+ * # Two modes, one schema
15
+ *
16
+ * The mode is recorded in `.dxkit/policy.json` (out of scope for this
17
+ * module — consumers pass it in via `AllowlistMode`). Both modes use
18
+ * the same `AllowlistFile` shape on disk; sanitized mode just drops
19
+ * the human-readable fields and pushes them to a sidecar:
20
+ *
21
+ * `'full'` — every field present on the entry. Default for
22
+ * private repos. The committed file carries the full audit trail.
23
+ *
24
+ * `'sanitized'` — entries carry `fingerprint + kind + category +
25
+ * addedAt + expiresAt + acknowledgedSeverity` only. The
26
+ * `reason` + `addedBy` fields live in the gitignored sidecar
27
+ * `.dxkit/allowlist-reasons.local.json`, keyed by fingerprint.
28
+ * Default for public repos. Loaders merge the sidecar back when
29
+ * present; readers tolerate its absence (no reason field, but
30
+ * the suppression still applies because matching is by
31
+ * fingerprint).
32
+ *
33
+ * # Validation surface
34
+ *
35
+ * `validateAllowlistFile` enforces every Sprint-0-locked rule:
36
+ * - `reason` is required (full mode) / required in sidecar
37
+ * (sanitized mode)
38
+ * - `category` is one of the five canonical values
39
+ * - `category` is valid for the entry's `kind`
40
+ * - `requiresExpiry(category)` ⇒ `expiresAt` is present + parseable
41
+ * - `acknowledgedSeverity` is required when `category` is
42
+ * `accepted-risk` AND `severity` is `high`/`critical`
43
+ */
44
+ import type { IdentityKind } from '../baseline/producers';
45
+ import type { FindingSeverity } from '../baseline/types';
46
+ import { type AllowlistCategory } from './categories';
47
+ export declare const ALLOWLIST_SCHEMA_VERSION: "dxkit-allowlist/v1";
48
+ export type AllowlistSchemaVersion = typeof ALLOWLIST_SCHEMA_VERSION;
49
+ export declare const ALLOWLIST_REASONS_SCHEMA_VERSION: "dxkit-allowlist-reasons/v1";
50
+ export type AllowlistReasonsSchemaVersion = typeof ALLOWLIST_REASONS_SCHEMA_VERSION;
51
+ export declare const ALLOWLIST_DIR = ".dxkit";
52
+ export declare const ALLOWLIST_FILENAME = "allowlist.json";
53
+ export declare const ALLOWLIST_REASONS_FILENAME = "allowlist-reasons.local.json";
54
+ /**
55
+ * Single source of truth for mode values. The `AllowlistMode` union
56
+ * is derived from this array via `(typeof ...)[number]`, so adding
57
+ * a new mode means appending one string here — the runtime checks
58
+ * below pick it up via `ALL_MODES.includes(...)` without any
59
+ * literal-value drift between type and runtime.
60
+ */
61
+ export declare const ALL_MODES: readonly ["full", "sanitized"];
62
+ export type AllowlistMode = (typeof ALL_MODES)[number];
63
+ /**
64
+ * One allowlist entry. Two-shape contract:
65
+ * - Full mode: every optional field may be present on disk.
66
+ * - Sanitized mode on disk: `reason` + `addedBy` are absent; the
67
+ * loader merges them in from the sidecar when present.
68
+ *
69
+ * The TypeScript type allows the union so a single in-memory shape
70
+ * serves both modes; the validator enforces shape invariants.
71
+ */
72
+ export interface AllowlistEntry {
73
+ /** SHA-1[0:16] canonical fingerprint matching the target finding. */
74
+ readonly fingerprint: string;
75
+ /** Identity kind of the target finding (matches CLAUDE.md Rule 9
76
+ * canonical kinds). */
77
+ readonly kind: IdentityKind;
78
+ /** Suppression category — one of the five Sprint-0-locked enum
79
+ * values. */
80
+ readonly category: AllowlistCategory;
81
+ /** Human-readable rationale. Required in full mode; lives in
82
+ * sidecar in sanitized mode. */
83
+ readonly reason?: string;
84
+ /** Who added the entry. Required in full mode; lives in sidecar
85
+ * in sanitized mode. Free-form (typically email, git user, or
86
+ * Slack handle). */
87
+ readonly addedBy?: string;
88
+ /** ISO `YYYY-MM-DD` of when the entry was added. */
89
+ readonly addedAt: string;
90
+ /** ISO `YYYY-MM-DD` after which the entry stops suppressing the
91
+ * finding. Required for `accepted-risk` + `deferred` categories;
92
+ * optional otherwise. */
93
+ readonly expiresAt?: string;
94
+ /** Severity at which the suppression was acknowledged. Required
95
+ * when `category` is `accepted-risk` and the finding's severity
96
+ * is `high` or `critical` — see `validateAllowlistEntry`. */
97
+ readonly acknowledgedSeverity?: FindingSeverity;
98
+ }
99
+ export interface AllowlistFile {
100
+ readonly schemaVersion: AllowlistSchemaVersion;
101
+ readonly mode: AllowlistMode;
102
+ readonly entries: ReadonlyArray<AllowlistEntry>;
103
+ }
104
+ /**
105
+ * The gitignored sidecar that carries the human-readable fields in
106
+ * sanitized mode. Sparse — only the fields that need to live
107
+ * outside the committed file appear. Loaders are lenient when the
108
+ * sidecar is absent (no entry merges; suppression still works by
109
+ * fingerprint).
110
+ */
111
+ export interface AllowlistReasonsSidecar {
112
+ readonly schemaVersion: AllowlistReasonsSchemaVersion;
113
+ readonly reasons: Readonly<Record<string, {
114
+ readonly reason: string;
115
+ readonly addedBy: string;
116
+ }>>;
117
+ }
118
+ export interface ValidationError {
119
+ readonly fingerprint?: string;
120
+ readonly field: string;
121
+ readonly message: string;
122
+ }
123
+ export declare function pathForAllowlist(cwd: string): string;
124
+ export declare function pathForAllowlistReasons(cwd: string): string;
125
+ /**
126
+ * Create an empty allowlist file in the requested mode. Useful for
127
+ * the `vyuh-dxkit allowlist add` CLI path when no file exists yet.
128
+ */
129
+ export declare function emptyAllowlistFile(mode?: AllowlistMode): AllowlistFile;
130
+ /**
131
+ * Read the on-disk allowlist + (when present) merge the sidecar
132
+ * reasons. Returns `null` when the main file doesn't exist —
133
+ * callers treat that as "no allowlist configured."
134
+ *
135
+ * Throws on:
136
+ * - Malformed JSON in either file
137
+ * - Unrecognized `schemaVersion`
138
+ * - Root is not an object
139
+ *
140
+ * The sidecar's absence is NOT an error: customers in sanitized
141
+ * mode may have a committed allowlist on disk without the sidecar
142
+ * cloned (CI checkout, fresh teammate clone). The fingerprint-only
143
+ * file is still functional as a suppression list.
144
+ */
145
+ export declare function loadAllowlist(cwd: string): AllowlistFile | null;
146
+ /**
147
+ * Load the gitignored reasons sidecar. Returns `null` when missing.
148
+ * Throws on malformed JSON or wrong schemaVersion.
149
+ */
150
+ export declare function loadAllowlistReasons(cwd: string): AllowlistReasonsSidecar | null;
151
+ /**
152
+ * Persist the allowlist to disk. Writes the sidecar separately in
153
+ * sanitized mode: the committed file gets the structural fields;
154
+ * the sidecar gets `reason` + `addedBy`.
155
+ *
156
+ * Validation runs before writing — invalid input throws and the
157
+ * file isn't touched. Use `validateAllowlistFile` directly when
158
+ * you want non-throwing error reporting.
159
+ */
160
+ export declare function saveAllowlist(cwd: string, file: AllowlistFile): void;
161
+ /** Find an entry by fingerprint. */
162
+ export declare function findEntry(file: AllowlistFile, fingerprint: string): AllowlistEntry | undefined;
163
+ /**
164
+ * Add an entry. Returns a NEW `AllowlistFile` (immutable update).
165
+ * Throws if `entry.fingerprint` already exists.
166
+ */
167
+ export declare function addEntry(file: AllowlistFile, entry: AllowlistEntry): AllowlistFile;
168
+ /**
169
+ * Remove an entry by fingerprint. Returns a NEW `AllowlistFile`.
170
+ * Silently no-ops when the fingerprint isn't present (CLI surfaces
171
+ * the "not found" case through a separate read step).
172
+ */
173
+ export declare function removeEntry(file: AllowlistFile, fingerprint: string): AllowlistFile;
174
+ /**
175
+ * Whether the allowlist suppresses a given finding. Pure
176
+ * fingerprint match. Expiry handling is layered on top by
177
+ * `isEntryActive` (kept separate so the guardrail can distinguish
178
+ * "matched but expired" from "no match").
179
+ */
180
+ export declare function matchesFinding(file: AllowlistFile, fingerprint: string): boolean;
181
+ /**
182
+ * Whether an entry is currently active (within its expiry window).
183
+ * Entries without `expiresAt` are always active. Entries past their
184
+ * expiry are inactive — guardrail treats the underlying finding as
185
+ * un-allowlisted and the next run flags the suppression as stale.
186
+ */
187
+ export declare function isEntryActive(entry: AllowlistEntry, now?: Date): boolean;
188
+ /**
189
+ * Days remaining until an entry expires, or `null` when it has no
190
+ * expiry. Negative values mean already expired by that many days.
191
+ */
192
+ export declare function daysUntilExpiry(entry: AllowlistEntry, now?: Date): number | null;
193
+ /** One entry in a soon-to-expire audit bucket, with the days
194
+ * remaining so callers can render time-to-expiry context. */
195
+ export interface SoonToExpire {
196
+ readonly entry: AllowlistEntry;
197
+ readonly daysRemaining: number;
198
+ }
199
+ /**
200
+ * Audit report partitioning the file's entries into the three
201
+ * actionable categories the `vyuh-dxkit allowlist audit` subcommand
202
+ * surfaces. Pure function — no I/O, no side effects.
203
+ *
204
+ * - `expired` — entries past their `expiresAt`. Prune candidates.
205
+ * The underlying suppression no longer applies on the next
206
+ * guardrail run.
207
+ * - `soonToExpire` — entries whose `expiresAt` is within
208
+ * `soonToExpireDays` (default 14). Customer should review whether
209
+ * the deferred work is still in plan and either fix the finding,
210
+ * extend the expiry, or remove the entry.
211
+ * - `missingRationale` — entries with empty / whitespace-only
212
+ * reason. In full mode this should never happen (validator
213
+ * rejects); in sanitized mode it may occur when the sidecar is
214
+ * missing or stale.
215
+ */
216
+ export interface AuditReport {
217
+ readonly expired: ReadonlyArray<AllowlistEntry>;
218
+ readonly soonToExpire: ReadonlyArray<SoonToExpire>;
219
+ readonly missingRationale: ReadonlyArray<AllowlistEntry>;
220
+ }
221
+ export interface AuditOptions {
222
+ readonly now?: Date;
223
+ /** Window in days within which `expiresAt` is considered "soon."
224
+ * Default 14 — chosen to match a typical sprint cadence. */
225
+ readonly soonToExpireDays?: number;
226
+ }
227
+ export declare function auditAllowlist(file: AllowlistFile, options?: AuditOptions): AuditReport;
228
+ /**
229
+ * Remove expired entries from the file. Returns a new file (immutable)
230
+ * plus the list of removed entries so the CLI can render what changed.
231
+ * Pure function — no I/O.
232
+ */
233
+ export declare function pruneExpired(file: AllowlistFile, now?: Date): {
234
+ kept: AllowlistFile;
235
+ removed: ReadonlyArray<AllowlistEntry>;
236
+ };
237
+ /**
238
+ * Validate every entry in the file against the canonical taxonomy
239
+ * + Sprint-0-locked rules. Pure function; returns an array of
240
+ * `ValidationError` rather than throwing so callers can render
241
+ * structured error messages.
242
+ */
243
+ export declare function validateAllowlistFile(file: AllowlistFile): ReadonlyArray<ValidationError>;
244
+ /**
245
+ * Validate a single entry. Exposed independently so the CLI's
246
+ * `allowlist add` can pre-flight before mutating the file.
247
+ */
248
+ export declare function validateAllowlistEntry(entry: AllowlistEntry, mode: AllowlistMode): ReadonlyArray<ValidationError>;
249
+ //# sourceMappingURL=file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/allowlist/file.ts"],"names":[],"mappings":"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"}