@vyuhlabs/dxkit 2.5.1 → 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.
- package/CHANGELOG.md +318 -0
- package/README.md +150 -28
- package/dist/allowlist/categories.d.ts +120 -0
- package/dist/allowlist/categories.d.ts.map +1 -0
- package/dist/allowlist/categories.js +194 -0
- package/dist/allowlist/categories.js.map +1 -0
- package/dist/allowlist/cli.d.ts +95 -0
- package/dist/allowlist/cli.d.ts.map +1 -0
- package/dist/allowlist/cli.js +454 -0
- package/dist/allowlist/cli.js.map +1 -0
- package/dist/allowlist/diff.d.ts +67 -0
- package/dist/allowlist/diff.d.ts.map +1 -0
- package/dist/allowlist/diff.js +147 -0
- package/dist/allowlist/diff.js.map +1 -0
- package/dist/allowlist/file.d.ts +249 -0
- package/dist/allowlist/file.d.ts.map +1 -0
- package/dist/allowlist/file.js +497 -0
- package/dist/allowlist/file.js.map +1 -0
- package/dist/allowlist/gather.d.ts +61 -0
- package/dist/allowlist/gather.d.ts.map +1 -0
- package/dist/allowlist/gather.js +143 -0
- package/dist/allowlist/gather.js.map +1 -0
- package/dist/allowlist/hint.d.ts +80 -0
- package/dist/allowlist/hint.d.ts.map +1 -0
- package/dist/allowlist/hint.js +271 -0
- package/dist/allowlist/hint.js.map +1 -0
- package/dist/allowlist/inline.d.ts +149 -0
- package/dist/allowlist/inline.d.ts.map +1 -0
- package/dist/allowlist/inline.js +306 -0
- package/dist/allowlist/inline.js.map +1 -0
- package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
- package/dist/analyzers/tools/tool-registry.js +25 -8
- package/dist/analyzers/tools/tool-registry.js.map +1 -1
- package/dist/baseline/baseline-file.d.ts +7 -0
- package/dist/baseline/baseline-file.d.ts.map +1 -1
- package/dist/baseline/baseline-file.js +22 -1
- package/dist/baseline/baseline-file.js.map +1 -1
- package/dist/baseline/check-renderers.d.ts +13 -1
- package/dist/baseline/check-renderers.d.ts.map +1 -1
- package/dist/baseline/check-renderers.js +67 -1
- package/dist/baseline/check-renderers.js.map +1 -1
- package/dist/baseline/check.d.ts +33 -7
- package/dist/baseline/check.d.ts.map +1 -1
- package/dist/baseline/check.js +90 -64
- package/dist/baseline/check.js.map +1 -1
- package/dist/baseline/create.d.ts +35 -7
- package/dist/baseline/create.d.ts.map +1 -1
- package/dist/baseline/create.js +43 -5
- package/dist/baseline/create.js.map +1 -1
- package/dist/baseline/entry-to-located.d.ts +6 -1
- package/dist/baseline/entry-to-located.d.ts.map +1 -1
- package/dist/baseline/entry-to-located.js +20 -2
- package/dist/baseline/entry-to-located.js.map +1 -1
- package/dist/baseline/finding-identity.d.ts.map +1 -1
- package/dist/baseline/finding-identity.js +15 -13
- package/dist/baseline/finding-identity.js.map +1 -1
- package/dist/baseline/modes.d.ts +140 -0
- package/dist/baseline/modes.d.ts.map +1 -0
- package/dist/baseline/modes.js +179 -0
- package/dist/baseline/modes.js.map +1 -0
- package/dist/baseline/policy.d.ts +64 -0
- package/dist/baseline/policy.d.ts.map +1 -1
- package/dist/baseline/policy.js +102 -1
- package/dist/baseline/policy.js.map +1 -1
- package/dist/baseline/producers/health.d.ts +2 -2
- package/dist/baseline/producers/health.d.ts.map +1 -1
- package/dist/baseline/producers/health.js.map +1 -1
- package/dist/baseline/producers/index.d.ts +11 -5
- package/dist/baseline/producers/index.d.ts.map +1 -1
- package/dist/baseline/producers/index.js +12 -9
- package/dist/baseline/producers/index.js.map +1 -1
- package/dist/baseline/producers/quality.d.ts +3 -3
- package/dist/baseline/producers/quality.d.ts.map +1 -1
- package/dist/baseline/producers/quality.js.map +1 -1
- package/dist/baseline/producers/secret-hmac.d.ts +2 -2
- package/dist/baseline/producers/secret-hmac.d.ts.map +1 -1
- package/dist/baseline/producers/secret-hmac.js.map +1 -1
- package/dist/baseline/producers/security.d.ts +2 -2
- package/dist/baseline/producers/security.d.ts.map +1 -1
- package/dist/baseline/producers/security.js.map +1 -1
- package/dist/baseline/producers/stale-allow.d.ts +70 -0
- package/dist/baseline/producers/stale-allow.d.ts.map +1 -0
- package/dist/baseline/producers/stale-allow.js +111 -0
- package/dist/baseline/producers/stale-allow.js.map +1 -0
- package/dist/baseline/producers/tests.d.ts +2 -2
- package/dist/baseline/producers/tests.d.ts.map +1 -1
- package/dist/baseline/producers/tests.js.map +1 -1
- package/dist/baseline/ref-baseline.d.ts +114 -0
- package/dist/baseline/ref-baseline.d.ts.map +1 -0
- package/dist/baseline/ref-baseline.js +260 -0
- package/dist/baseline/ref-baseline.js.map +1 -0
- package/dist/baseline/sanitize.d.ts +80 -0
- package/dist/baseline/sanitize.d.ts.map +1 -0
- package/dist/baseline/sanitize.js +91 -0
- package/dist/baseline/sanitize.js.map +1 -0
- package/dist/baseline/show.d.ts.map +1 -1
- package/dist/baseline/show.js +9 -3
- package/dist/baseline/show.js.map +1 -1
- package/dist/baseline/types.d.ts +73 -26
- package/dist/baseline/types.d.ts.map +1 -1
- package/dist/baseline/types.js +7 -1
- package/dist/baseline/types.js.map +1 -1
- package/dist/baseline/visibility.d.ts +61 -0
- package/dist/baseline/visibility.d.ts.map +1 -0
- package/dist/baseline/visibility.js +121 -0
- package/dist/baseline/visibility.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +154 -13
- package/dist/cli.js.map +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +0 -10
- package/dist/constants.js.map +1 -1
- package/dist/detect.d.ts.map +1 -1
- package/dist/detect.js +0 -15
- package/dist/detect.js.map +1 -1
- package/dist/doctor.d.ts +78 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +590 -101
- package/dist/doctor.js.map +1 -1
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +15 -0
- package/dist/generator.js.map +1 -1
- package/dist/issue-cli.d.ts +62 -0
- package/dist/issue-cli.d.ts.map +1 -0
- package/dist/issue-cli.js +252 -0
- package/dist/issue-cli.js.map +1 -0
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +2 -0
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +2 -0
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/index.d.ts +25 -0
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +44 -0
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/java.d.ts.map +1 -1
- package/dist/languages/java.js +2 -0
- package/dist/languages/java.js.map +1 -1
- package/dist/languages/kotlin.d.ts.map +1 -1
- package/dist/languages/kotlin.js +2 -0
- package/dist/languages/kotlin.js.map +1 -1
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +11 -1
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/ruby.d.ts.map +1 -1
- package/dist/languages/ruby.js +2 -0
- package/dist/languages/ruby.js.map +1 -1
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +2 -0
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/types.d.ts +45 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +2 -0
- package/dist/languages/typescript.js.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +0 -5
- package/dist/prompts.js.map +1 -1
- package/dist/setup-branch-protection.d.ts +34 -0
- package/dist/setup-branch-protection.d.ts.map +1 -0
- package/dist/setup-branch-protection.js +190 -0
- package/dist/setup-branch-protection.js.map +1 -0
- package/dist/setup-gh.d.ts +75 -0
- package/dist/setup-gh.d.ts.map +1 -0
- package/dist/setup-gh.js +213 -0
- package/dist/setup-gh.js.map +1 -0
- package/dist/setup-prebuild.d.ts +34 -0
- package/dist/setup-prebuild.d.ts.map +1 -0
- package/dist/setup-prebuild.js +181 -0
- package/dist/setup-prebuild.js.map +1 -0
- package/dist/ship-installers.d.ts.map +1 -1
- package/dist/ship-installers.js +19 -4
- package/dist/ship-installers.js.map +1 -1
- package/dist/types.d.ts +24 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/update.d.ts +41 -0
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +154 -15
- package/dist/update.js.map +1 -1
- package/dist/upgrade.d.ts +88 -0
- package/dist/upgrade.d.ts.map +1 -0
- package/dist/upgrade.js +324 -0
- package/dist/upgrade.js.map +1 -0
- package/package.json +1 -1
- package/templates/.claude/skills/dxkit-action/SKILL.md +111 -17
- package/templates/.claude/skills/dxkit-config/SKILL.md +7 -7
- package/templates/.claude/skills/dxkit-fix/SKILL.md +165 -0
- package/templates/.claude/skills/dxkit-hooks/SKILL.md +8 -8
- package/templates/.claude/skills/dxkit-init/SKILL.md +3 -3
- package/templates/.claude/skills/dxkit-learn/SKILL.md +9 -9
- package/templates/.claude/skills/dxkit-onboard/SKILL.md +274 -0
- package/templates/.claude/skills/dxkit-reports/SKILL.md +18 -18
- package/templates/.claude/skills/dxkit-update/SKILL.md +164 -0
- package/templates/.devcontainer/devcontainer.json +6 -15
- package/templates/.devcontainer/post-create.sh +19 -4
- package/dist/baseline/producers/licenses.d.ts +0 -23
- package/dist/baseline/producers/licenses.d.ts.map +0 -1
- package/dist/baseline/producers/licenses.js +0 -46
- package/dist/baseline/producers/licenses.js.map +0 -1
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `vyuh-dxkit allowlist <subcommand>` — orchestrates the user-facing
|
|
4
|
+
* write/read paths over the allowlist module.
|
|
5
|
+
*
|
|
6
|
+
* Subcommands (Sprint 1 chunk):
|
|
7
|
+
*
|
|
8
|
+
* - `add <file>:<line>` — inline annotation insertion. Kind-agnostic;
|
|
9
|
+
* the annotation grammar carries category + reason only. Refuses
|
|
10
|
+
* non-inline-compatible categories (accepted-risk / deferred).
|
|
11
|
+
*
|
|
12
|
+
* - `add --fingerprint=<id> --kind=<kind>` — file-level allowlist
|
|
13
|
+
* entry. Persists to `.dxkit/allowlist.json` (or its sanitized
|
|
14
|
+
* mode + gitignored reasons sidecar). Required for any
|
|
15
|
+
* accepted-risk / deferred suppression OR any kind that lacks a
|
|
16
|
+
* stable single-line attachment point.
|
|
17
|
+
*
|
|
18
|
+
* - `list` — print every entry across the file-level allowlist.
|
|
19
|
+
* Reads only; no mutation. Honors `--json` for structured output.
|
|
20
|
+
*
|
|
21
|
+
* - `show <fingerprint>` — print one entry's full detail. Falls
|
|
22
|
+
* back to a "no entry found" message when the fingerprint isn't
|
|
23
|
+
* present.
|
|
24
|
+
*
|
|
25
|
+
* Subcommands `audit` and `prune` land in a follow-up commit.
|
|
26
|
+
*
|
|
27
|
+
* # Architectural posture
|
|
28
|
+
*
|
|
29
|
+
* Every IO goes through `loadAllowlist` / `saveAllowlist` in
|
|
30
|
+
* `src/allowlist/file.ts` (arch-rule 1 enforces this). Inline
|
|
31
|
+
* annotation insertion goes through `insertAnnotation` in
|
|
32
|
+
* `src/allowlist/inline.ts`. Per-kind / per-category validation
|
|
33
|
+
* goes through `categories.ts` helpers. NO duplicated taxonomy or
|
|
34
|
+
* IO logic here — this file is pure orchestration.
|
|
35
|
+
*/
|
|
36
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
37
|
+
if (k2 === undefined) k2 = k;
|
|
38
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
39
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
40
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
41
|
+
}
|
|
42
|
+
Object.defineProperty(o, k2, desc);
|
|
43
|
+
}) : (function(o, m, k, k2) {
|
|
44
|
+
if (k2 === undefined) k2 = k;
|
|
45
|
+
o[k2] = m[k];
|
|
46
|
+
}));
|
|
47
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
48
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
49
|
+
}) : function(o, v) {
|
|
50
|
+
o["default"] = v;
|
|
51
|
+
});
|
|
52
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
53
|
+
var ownKeys = function(o) {
|
|
54
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
55
|
+
var ar = [];
|
|
56
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
57
|
+
return ar;
|
|
58
|
+
};
|
|
59
|
+
return ownKeys(o);
|
|
60
|
+
};
|
|
61
|
+
return function (mod) {
|
|
62
|
+
if (mod && mod.__esModule) return mod;
|
|
63
|
+
var result = {};
|
|
64
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
65
|
+
__setModuleDefault(result, mod);
|
|
66
|
+
return result;
|
|
67
|
+
};
|
|
68
|
+
})();
|
|
69
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
70
|
+
exports.ALLOWLIST_FILENAME = exports.DEFAULT_EXPIRY_DAYS = exports.ALLOWLIST_SUBCOMMANDS = void 0;
|
|
71
|
+
exports.runAllowlist = runAllowlist;
|
|
72
|
+
exports.runAllowlistAdd = runAllowlistAdd;
|
|
73
|
+
exports.runAllowlistList = runAllowlistList;
|
|
74
|
+
exports.runAllowlistShow = runAllowlistShow;
|
|
75
|
+
exports.runAllowlistAudit = runAllowlistAudit;
|
|
76
|
+
exports.runAllowlistPrune = runAllowlistPrune;
|
|
77
|
+
const path = __importStar(require("path"));
|
|
78
|
+
const child_process_1 = require("child_process");
|
|
79
|
+
const logger = __importStar(require("../logger"));
|
|
80
|
+
const languages_1 = require("../languages");
|
|
81
|
+
const categories_1 = require("./categories");
|
|
82
|
+
Object.defineProperty(exports, "DEFAULT_EXPIRY_DAYS", { enumerable: true, get: function () { return categories_1.DEFAULT_EXPIRY_DAYS; } });
|
|
83
|
+
const file_1 = require("./file");
|
|
84
|
+
Object.defineProperty(exports, "ALLOWLIST_FILENAME", { enumerable: true, get: function () { return file_1.ALLOWLIST_FILENAME; } });
|
|
85
|
+
const inline_1 = require("./inline");
|
|
86
|
+
/** Subcommands recognized under `vyuh-dxkit allowlist`. */
|
|
87
|
+
exports.ALLOWLIST_SUBCOMMANDS = ['add', 'list', 'show', 'audit', 'prune'];
|
|
88
|
+
/**
|
|
89
|
+
* Dispatch entry point called from `src/cli.ts`. Validates the
|
|
90
|
+
* subcommand name + routes to the per-subcommand handler. Unknown
|
|
91
|
+
* subcommands exit with a clear error and the list of recognized
|
|
92
|
+
* names.
|
|
93
|
+
*/
|
|
94
|
+
async function runAllowlist(cwd, subcommand, args) {
|
|
95
|
+
if (!subcommand || !isAllowlistSubcommand(subcommand)) {
|
|
96
|
+
logger.fail(`Unknown allowlist subcommand: ${JSON.stringify(subcommand ?? '(none)')}. ` +
|
|
97
|
+
`Expected one of: ${exports.ALLOWLIST_SUBCOMMANDS.join(', ')}.`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
switch (subcommand) {
|
|
101
|
+
case 'add':
|
|
102
|
+
return runAllowlistAdd(cwd, {
|
|
103
|
+
target: args.positionalAfter,
|
|
104
|
+
category: args.values.category,
|
|
105
|
+
reason: args.values.reason,
|
|
106
|
+
kind: args.values.kind,
|
|
107
|
+
fingerprint: args.values.fingerprint,
|
|
108
|
+
expires: args.values.expires,
|
|
109
|
+
acknowledgedSeverity: args.values['acknowledged-severity'],
|
|
110
|
+
addedBy: args.values['added-by'],
|
|
111
|
+
mode: args.values.mode,
|
|
112
|
+
});
|
|
113
|
+
case 'list':
|
|
114
|
+
return runAllowlistList(cwd, { json: !!args.values.json });
|
|
115
|
+
case 'show':
|
|
116
|
+
return runAllowlistShow(cwd, {
|
|
117
|
+
fingerprint: args.positionalAfter,
|
|
118
|
+
json: !!args.values.json,
|
|
119
|
+
});
|
|
120
|
+
case 'audit': {
|
|
121
|
+
const horizonRaw = args.values['soon-days'];
|
|
122
|
+
const horizon = horizonRaw ? parseInt(horizonRaw, 10) : undefined;
|
|
123
|
+
return runAllowlistAudit(cwd, {
|
|
124
|
+
json: !!args.values.json,
|
|
125
|
+
soonToExpireDays: Number.isFinite(horizon) ? horizon : undefined,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
case 'prune':
|
|
129
|
+
return runAllowlistPrune(cwd, {
|
|
130
|
+
json: !!args.values.json,
|
|
131
|
+
dryRun: !!args.values['dry-run'],
|
|
132
|
+
yes: !!args.values.yes,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// ─── add ──────────────────────────────────────────────────────────────────
|
|
137
|
+
async function runAllowlistAdd(cwd, opts) {
|
|
138
|
+
// Validate category up-front so the rest of the flow can assume
|
|
139
|
+
// it's a canonical value.
|
|
140
|
+
const category = parseCategory(opts.category);
|
|
141
|
+
const reason = (opts.reason ?? '').trim();
|
|
142
|
+
if (!reason) {
|
|
143
|
+
logger.fail('--reason is required (non-empty rationale string)');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
// Two routing paths: inline annotation insertion vs file-level entry.
|
|
147
|
+
// The target shape decides:
|
|
148
|
+
// - `<file>:<line>` → inline (category must be inline-compatible)
|
|
149
|
+
// - `--fingerprint=<id> --kind=<kind>` → file-level
|
|
150
|
+
const inlineTarget = parseInlineTarget(opts.target);
|
|
151
|
+
if (inlineTarget) {
|
|
152
|
+
return runAddInline({ cwd, target: inlineTarget, category, reason });
|
|
153
|
+
}
|
|
154
|
+
// File-level form
|
|
155
|
+
return runAddFileLevel({ cwd, opts, category, reason });
|
|
156
|
+
}
|
|
157
|
+
function parseInlineTarget(target) {
|
|
158
|
+
if (!target)
|
|
159
|
+
return null;
|
|
160
|
+
const m = target.match(/^(.+):(\d+)$/);
|
|
161
|
+
if (!m)
|
|
162
|
+
return null;
|
|
163
|
+
return { file: m[1], line: parseInt(m[2], 10) };
|
|
164
|
+
}
|
|
165
|
+
async function runAddInline(args) {
|
|
166
|
+
const { cwd, target, category, reason } = args;
|
|
167
|
+
if (!categories_1.INLINE_COMPATIBLE_CATEGORIES.has(category)) {
|
|
168
|
+
logger.fail(`category ${JSON.stringify(category)} is file-only — ` +
|
|
169
|
+
`use --fingerprint=<id> --kind=<kind> form instead. ` +
|
|
170
|
+
`Inline-compatible categories: ${[...categories_1.INLINE_COMPATIBLE_CATEGORIES].join(', ')}.`);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
const absPath = path.resolve(cwd, target.file);
|
|
174
|
+
const lang = inferLanguage(target.file);
|
|
175
|
+
if (!lang || !lang.commentSyntax) {
|
|
176
|
+
logger.fail(`cannot infer language from file extension for ${JSON.stringify(target.file)}; ` +
|
|
177
|
+
`inline annotation requires a known language pack with commentSyntax`);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
const result = (0, inline_1.insertAnnotation)(absPath, target.line, { category, reason }, lang);
|
|
181
|
+
logger.info(`Inserted ${result.position} allowlist annotation at ${target.file}:${result.annotationLine} ` +
|
|
182
|
+
`(category=${category})`);
|
|
183
|
+
}
|
|
184
|
+
async function runAddFileLevel(args) {
|
|
185
|
+
const { cwd, opts, category, reason } = args;
|
|
186
|
+
const fingerprint = opts.fingerprint?.trim();
|
|
187
|
+
const kindRaw = opts.kind?.trim();
|
|
188
|
+
if (!fingerprint || !kindRaw) {
|
|
189
|
+
logger.fail(`file-level allowlist entry requires --fingerprint=<16-hex> and --kind=<kind> ` +
|
|
190
|
+
`(or pass <file>:<line> for inline annotation when kind+category are inline-compatible)`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
const kind = kindRaw;
|
|
194
|
+
if (!(0, categories_1.isCategoryValidForKind)(kind, category)) {
|
|
195
|
+
logger.fail(`category ${JSON.stringify(category)} does not apply to kind ${JSON.stringify(kind)}`);
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
const expiresAt = resolveExpiresAt(opts.expires, category);
|
|
199
|
+
const addedBy = opts.addedBy?.trim() || resolveGitUserEmail(cwd);
|
|
200
|
+
if (!addedBy) {
|
|
201
|
+
logger.fail(`--added-by is required (or set git config user.email so it can be inferred)`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
const addedAt = todayISO();
|
|
205
|
+
const acknowledgedSeverity = parseSeverityOpt(opts.acknowledgedSeverity);
|
|
206
|
+
const entry = {
|
|
207
|
+
fingerprint,
|
|
208
|
+
kind,
|
|
209
|
+
category,
|
|
210
|
+
reason,
|
|
211
|
+
addedBy,
|
|
212
|
+
addedAt,
|
|
213
|
+
...(expiresAt !== undefined ? { expiresAt } : {}),
|
|
214
|
+
...(acknowledgedSeverity !== undefined ? { acknowledgedSeverity } : {}),
|
|
215
|
+
};
|
|
216
|
+
// Resolve effective mode (CLI override → existing file mode → default 'full').
|
|
217
|
+
const mode = resolveMode(cwd, opts.mode);
|
|
218
|
+
const validationErrors = (0, file_1.validateAllowlistEntry)(entry, mode);
|
|
219
|
+
if (validationErrors.length > 0) {
|
|
220
|
+
logger.fail(`allowlist entry failed validation:`);
|
|
221
|
+
for (const e of validationErrors) {
|
|
222
|
+
logger.fail(` - ${e.field}: ${e.message}`);
|
|
223
|
+
}
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
const existing = (0, file_1.loadAllowlist)(cwd) ?? (0, file_1.emptyAllowlistFile)(mode);
|
|
227
|
+
if ((0, file_1.findEntry)(existing, fingerprint)) {
|
|
228
|
+
logger.fail(`allowlist already contains entry for fingerprint ${fingerprint}. ` +
|
|
229
|
+
`Run \`vyuh-dxkit allowlist show ${fingerprint}\` to inspect, or remove first.`);
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
const updated = { ...(0, file_1.addEntry)(existing, entry), mode };
|
|
233
|
+
(0, file_1.saveAllowlist)(cwd, updated);
|
|
234
|
+
logger.info(`Added allowlist entry for fingerprint ${fingerprint} (kind=${kind}, category=${category})` +
|
|
235
|
+
(expiresAt ? `, expires ${expiresAt}` : ''));
|
|
236
|
+
}
|
|
237
|
+
// ─── list ─────────────────────────────────────────────────────────────────
|
|
238
|
+
async function runAllowlistList(cwd, opts) {
|
|
239
|
+
const file = (0, file_1.loadAllowlist)(cwd);
|
|
240
|
+
if (opts.json) {
|
|
241
|
+
process.stdout.write(JSON.stringify(file ?? (0, file_1.emptyAllowlistFile)('full'), null, 2) + '\n');
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (!file || file.entries.length === 0) {
|
|
245
|
+
logger.info(`No allowlist entries. Run \`vyuh-dxkit allowlist add\` to create one.`);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
logger.info(`${file.entries.length} allowlist entr${file.entries.length === 1 ? 'y' : 'ies'} ` +
|
|
249
|
+
`(mode=${file.mode}, schema=${file.schemaVersion}):`);
|
|
250
|
+
for (const entry of file.entries) {
|
|
251
|
+
const expires = entry.expiresAt ? ` · expires ${entry.expiresAt}` : '';
|
|
252
|
+
const reasonPreview = entry.reason ? ` — ${truncate(entry.reason, 60)}` : '';
|
|
253
|
+
logger.info(` ${entry.fingerprint} ${entry.kind}/${entry.category}` +
|
|
254
|
+
` (added ${entry.addedAt}${expires})${reasonPreview}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// ─── show ─────────────────────────────────────────────────────────────────
|
|
258
|
+
async function runAllowlistShow(cwd, opts) {
|
|
259
|
+
const fp = opts.fingerprint?.trim();
|
|
260
|
+
if (!fp) {
|
|
261
|
+
logger.fail(`Usage: vyuh-dxkit allowlist show <fingerprint>`);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
const file = (0, file_1.loadAllowlist)(cwd);
|
|
265
|
+
if (!file) {
|
|
266
|
+
logger.fail(`No allowlist file at ${(0, file_1.pathForAllowlist)(cwd)}`);
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
const entry = (0, file_1.findEntry)(file, fp);
|
|
270
|
+
if (!entry) {
|
|
271
|
+
logger.fail(`No allowlist entry for fingerprint ${fp}`);
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
if (opts.json) {
|
|
275
|
+
process.stdout.write(JSON.stringify(entry, null, 2) + '\n');
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
logger.info(`Fingerprint: ${entry.fingerprint}`);
|
|
279
|
+
logger.info(`Kind: ${entry.kind}`);
|
|
280
|
+
logger.info(`Category: ${entry.category}`);
|
|
281
|
+
logger.info(`Added at: ${entry.addedAt}`);
|
|
282
|
+
if (entry.addedBy)
|
|
283
|
+
logger.info(`Added by: ${entry.addedBy}`);
|
|
284
|
+
if (entry.expiresAt)
|
|
285
|
+
logger.info(`Expires at: ${entry.expiresAt}`);
|
|
286
|
+
if (entry.acknowledgedSeverity) {
|
|
287
|
+
logger.info(`Acknowledged sev.: ${entry.acknowledgedSeverity}`);
|
|
288
|
+
}
|
|
289
|
+
if (entry.reason)
|
|
290
|
+
logger.info(`Reason: ${entry.reason}`);
|
|
291
|
+
}
|
|
292
|
+
// ─── audit ────────────────────────────────────────────────────────────────
|
|
293
|
+
async function runAllowlistAudit(cwd, opts) {
|
|
294
|
+
const file = (0, file_1.loadAllowlist)(cwd);
|
|
295
|
+
if (!file) {
|
|
296
|
+
if (opts.json) {
|
|
297
|
+
process.stdout.write(JSON.stringify({ expired: [], soonToExpire: [], missingRationale: [] }, null, 2) + '\n');
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
logger.info(`No allowlist file at ${(0, file_1.pathForAllowlist)(cwd)} — nothing to audit.`);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const report = (0, file_1.auditAllowlist)(file, { soonToExpireDays: opts.soonToExpireDays });
|
|
304
|
+
if (opts.json) {
|
|
305
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const total = file.entries.length;
|
|
309
|
+
const horizon = opts.soonToExpireDays ?? 14;
|
|
310
|
+
logger.info(`Allowlist audit: ${total} entr${total === 1 ? 'y' : 'ies'} ` +
|
|
311
|
+
`(mode=${file.mode}); soon-to-expire window=${horizon} days`);
|
|
312
|
+
if (report.expired.length === 0 &&
|
|
313
|
+
report.soonToExpire.length === 0 &&
|
|
314
|
+
report.missingRationale.length === 0) {
|
|
315
|
+
logger.success(`No issues found.`);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (report.expired.length > 0) {
|
|
319
|
+
logger.warn(`Expired (${report.expired.length}) — run \`vyuh-dxkit allowlist prune\` to remove:`);
|
|
320
|
+
for (const e of report.expired) {
|
|
321
|
+
logger.info(` ${e.fingerprint} ${e.kind}/${e.category} expired ${e.expiresAt}`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (report.soonToExpire.length > 0) {
|
|
325
|
+
logger.warn(`Soon to expire (${report.soonToExpire.length}; within ${horizon} days) — review or extend:`);
|
|
326
|
+
for (const { entry, daysRemaining } of report.soonToExpire) {
|
|
327
|
+
logger.info(` ${entry.fingerprint} ${entry.kind}/${entry.category}` +
|
|
328
|
+
` expires ${entry.expiresAt} (in ${daysRemaining}d)`);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (report.missingRationale.length > 0) {
|
|
332
|
+
logger.warn(`Missing rationale (${report.missingRationale.length}) — ` +
|
|
333
|
+
`add a reason or sync the gitignored reasons sidecar:`);
|
|
334
|
+
for (const e of report.missingRationale) {
|
|
335
|
+
logger.info(` ${e.fingerprint} ${e.kind}/${e.category}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// ─── prune ────────────────────────────────────────────────────────────────
|
|
340
|
+
async function runAllowlistPrune(cwd, opts) {
|
|
341
|
+
const file = (0, file_1.loadAllowlist)(cwd);
|
|
342
|
+
if (!file) {
|
|
343
|
+
logger.info(`No allowlist file at ${(0, file_1.pathForAllowlist)(cwd)} — nothing to prune.`);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const { kept, removed } = (0, file_1.pruneExpired)(file);
|
|
347
|
+
if (opts.json) {
|
|
348
|
+
process.stdout.write(JSON.stringify({ dryRun: !!opts.dryRun, removed, keptCount: kept.entries.length }, null, 2) +
|
|
349
|
+
'\n');
|
|
350
|
+
if (!opts.dryRun && removed.length > 0)
|
|
351
|
+
(0, file_1.saveAllowlist)(cwd, kept);
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (removed.length === 0) {
|
|
355
|
+
logger.info(`No expired entries — allowlist is clean.`);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const verb = opts.dryRun ? 'Would remove' : 'Removing';
|
|
359
|
+
logger.warn(`${verb} ${removed.length} expired entr${removed.length === 1 ? 'y' : 'ies'}:`);
|
|
360
|
+
for (const e of removed) {
|
|
361
|
+
logger.info(` ${e.fingerprint} ${e.kind}/${e.category} expired ${e.expiresAt}`);
|
|
362
|
+
}
|
|
363
|
+
if (opts.dryRun) {
|
|
364
|
+
logger.info(`(dry-run — no changes written; rerun without --dry-run to apply)`);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
(0, file_1.saveAllowlist)(cwd, kept);
|
|
368
|
+
logger.success(`Pruned ${removed.length} expired entries.`);
|
|
369
|
+
}
|
|
370
|
+
// ─── Internals ────────────────────────────────────────────────────────────
|
|
371
|
+
function isAllowlistSubcommand(value) {
|
|
372
|
+
return exports.ALLOWLIST_SUBCOMMANDS.includes(value);
|
|
373
|
+
}
|
|
374
|
+
function parseCategory(raw) {
|
|
375
|
+
if (!raw) {
|
|
376
|
+
logger.fail(`--category is required. One of: ${categories_1.ALL_CATEGORIES.join(', ')}.`);
|
|
377
|
+
process.exit(1);
|
|
378
|
+
}
|
|
379
|
+
if (!categories_1.ALL_CATEGORIES.includes(raw)) {
|
|
380
|
+
logger.fail(`--category ${JSON.stringify(raw)} is not a known category. ` +
|
|
381
|
+
`One of: ${categories_1.ALL_CATEGORIES.join(', ')}.`);
|
|
382
|
+
process.exit(1);
|
|
383
|
+
}
|
|
384
|
+
return raw;
|
|
385
|
+
}
|
|
386
|
+
const VALID_SEVERITIES = ['critical', 'high', 'medium', 'low'];
|
|
387
|
+
function parseSeverityOpt(raw) {
|
|
388
|
+
if (raw === undefined)
|
|
389
|
+
return undefined;
|
|
390
|
+
if (!VALID_SEVERITIES.includes(raw)) {
|
|
391
|
+
logger.fail(`--acknowledged-severity ${JSON.stringify(raw)} is not a known severity. ` +
|
|
392
|
+
`One of: ${VALID_SEVERITIES.join(', ')}.`);
|
|
393
|
+
process.exit(1);
|
|
394
|
+
}
|
|
395
|
+
return raw;
|
|
396
|
+
}
|
|
397
|
+
function resolveExpiresAt(raw, category) {
|
|
398
|
+
if (raw !== undefined) {
|
|
399
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(raw)) {
|
|
400
|
+
logger.fail(`--expires must be ISO date YYYY-MM-DD; got ${JSON.stringify(raw)}`);
|
|
401
|
+
process.exit(1);
|
|
402
|
+
}
|
|
403
|
+
return raw;
|
|
404
|
+
}
|
|
405
|
+
if ((0, categories_1.requiresExpiry)(category)) {
|
|
406
|
+
// Default to DEFAULT_EXPIRY_DAYS from today
|
|
407
|
+
return (0, categories_1.defaultExpiryDate)(new Date());
|
|
408
|
+
}
|
|
409
|
+
return undefined;
|
|
410
|
+
}
|
|
411
|
+
function resolveMode(cwd, override) {
|
|
412
|
+
if (override !== undefined) {
|
|
413
|
+
if (!file_1.ALL_MODES.includes(override)) {
|
|
414
|
+
logger.fail(`--mode ${JSON.stringify(override)} is not a known mode. ` +
|
|
415
|
+
`One of: ${file_1.ALL_MODES.join(', ')}.`);
|
|
416
|
+
process.exit(1);
|
|
417
|
+
}
|
|
418
|
+
return override;
|
|
419
|
+
}
|
|
420
|
+
const existing = (0, file_1.loadAllowlist)(cwd);
|
|
421
|
+
return existing?.mode ?? 'full';
|
|
422
|
+
}
|
|
423
|
+
function resolveGitUserEmail(cwd) {
|
|
424
|
+
try {
|
|
425
|
+
const out = (0, child_process_1.execSync)('git config --get user.email', {
|
|
426
|
+
cwd,
|
|
427
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
428
|
+
encoding: 'utf8',
|
|
429
|
+
}).trim();
|
|
430
|
+
return out || undefined;
|
|
431
|
+
}
|
|
432
|
+
catch {
|
|
433
|
+
return undefined;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
function inferLanguage(file) {
|
|
437
|
+
const ext = path.extname(file).toLowerCase();
|
|
438
|
+
if (!ext)
|
|
439
|
+
return undefined;
|
|
440
|
+
for (const lang of languages_1.LANGUAGES) {
|
|
441
|
+
if (lang.sourceExtensions.includes(ext))
|
|
442
|
+
return lang;
|
|
443
|
+
}
|
|
444
|
+
return undefined;
|
|
445
|
+
}
|
|
446
|
+
function todayISO(now = new Date()) {
|
|
447
|
+
return now.toISOString().slice(0, 10);
|
|
448
|
+
}
|
|
449
|
+
function truncate(s, max) {
|
|
450
|
+
if (s.length <= max)
|
|
451
|
+
return s;
|
|
452
|
+
return s.slice(0, max - 1) + '…';
|
|
453
|
+
}
|
|
454
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/allowlist/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Allowlist delta — what changed between two repo states.
|
|
3
|
+
*
|
|
4
|
+
* The guardrail check posts a PR comment whenever new allowlist
|
|
5
|
+
* entries appear on the PR branch. Reviewers see the suppressions
|
|
6
|
+
* being introduced and can sanity-check the typed category / reason
|
|
7
|
+
* / expiry without manually grepping for `dxkit-allow:` lines.
|
|
8
|
+
*
|
|
9
|
+
* # Two-state comparison
|
|
10
|
+
*
|
|
11
|
+
* `computeAllowlistDelta` compares the current on-disk allowlist
|
|
12
|
+
* (loaded via the canonical `loadAllowlist`) against the allowlist
|
|
13
|
+
* at the baseline's commit SHA (read via `git show <sha>:.dxkit/...`).
|
|
14
|
+
* Each entry's identity is its `fingerprint`; the delta is the
|
|
15
|
+
* symmetric difference of the two fingerprint sets, hydrated back
|
|
16
|
+
* to the full entries on each side.
|
|
17
|
+
*
|
|
18
|
+
* added — entries present in current but not at the baseline SHA
|
|
19
|
+
* removed — entries present at the baseline SHA but not in current
|
|
20
|
+
*
|
|
21
|
+
* # Graceful degradation
|
|
22
|
+
*
|
|
23
|
+
* When the baseline SHA isn't reachable (shallow clone, force-push
|
|
24
|
+
* orphaned base), the delta reports `baselineAccessible: false` and
|
|
25
|
+
* an empty `added` / `removed`. Callers (the renderer) treat that
|
|
26
|
+
* as "delta unavailable" rather than "no changes" — surfacing the
|
|
27
|
+
* incident so the customer can either deepen the clone or accept
|
|
28
|
+
* the missing review signal.
|
|
29
|
+
*
|
|
30
|
+
* Architectural posture:
|
|
31
|
+
* - All IO goes through `loadAllowlist` (CLAUDE.md arch rule 1).
|
|
32
|
+
* - `git show` is the only direct git interaction; failure modes
|
|
33
|
+
* return null without throwing.
|
|
34
|
+
* - Pure function over both inputs (current allowlist + git-resolved
|
|
35
|
+
* baseline allowlist) — testable independently of git state.
|
|
36
|
+
*/
|
|
37
|
+
import { type AllowlistEntry } from './file';
|
|
38
|
+
export interface AllowlistDelta {
|
|
39
|
+
/** Entries present in current but not at the baseline SHA. */
|
|
40
|
+
readonly added: ReadonlyArray<AllowlistEntry>;
|
|
41
|
+
/** Entries present at the baseline SHA but not in current. */
|
|
42
|
+
readonly removed: ReadonlyArray<AllowlistEntry>;
|
|
43
|
+
/** False when the baseline SHA wasn't reachable (shallow clone,
|
|
44
|
+
* force-push that orphaned the base). When false, added/removed
|
|
45
|
+
* are always empty — callers surface "delta unavailable" rather
|
|
46
|
+
* than "no changes." */
|
|
47
|
+
readonly baselineAccessible: boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compute the delta between the current on-disk allowlist and the
|
|
51
|
+
* allowlist at the baseline's commit SHA. Returns a structurally
|
|
52
|
+
* empty delta with `baselineAccessible: false` when the baseline
|
|
53
|
+
* SHA can't be read.
|
|
54
|
+
*
|
|
55
|
+
* `baselineCommitSha` must be a non-empty hex SHA; an empty string
|
|
56
|
+
* (the canonical "no commit" value baseline-create uses outside a
|
|
57
|
+
* git repo) yields `baselineAccessible: false` immediately.
|
|
58
|
+
*/
|
|
59
|
+
export declare function computeAllowlistDelta(cwd: string, baselineCommitSha: string): AllowlistDelta;
|
|
60
|
+
/**
|
|
61
|
+
* Pure delta over two entry arrays. Exposed for testability —
|
|
62
|
+
* callers without git state can synthesize before/after fixtures
|
|
63
|
+
* directly. Uses fingerprint equality (the canonical identity
|
|
64
|
+
* predicate) for set diff.
|
|
65
|
+
*/
|
|
66
|
+
export declare function diffEntries(prior: ReadonlyArray<AllowlistEntry>, current: ReadonlyArray<AllowlistEntry>): AllowlistDelta;
|
|
67
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/allowlist/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,OAAO,EAKL,KAAK,cAAc,EAEpB,MAAM,QAAQ,CAAC;AAEhB,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC9C,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAChD;;;6BAGyB;IACzB,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,cAAc,CAyB5F;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,EACpC,OAAO,EAAE,aAAa,CAAC,cAAc,CAAC,GACrC,cAAc,CAehB"}
|