@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,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vyuh-dxkit upgrade` — combined CLI for the dxkit upgrade flow.
|
|
3
|
+
*
|
|
4
|
+
* Two modes, one subcommand:
|
|
5
|
+
*
|
|
6
|
+
* `--plan [--json]` — preview only. Emits UpgradePlan JSON
|
|
7
|
+
* (consumed by dxkit-update skill) or text-prose summary. No
|
|
8
|
+
* mutations. Used to inspect what an upgrade would do before
|
|
9
|
+
* committing.
|
|
10
|
+
*
|
|
11
|
+
* (no flag, or `--yes`) — execute. Runs the three-step upgrade:
|
|
12
|
+
* 1. `npm install @vyuhlabs/dxkit@<target>` (binary)
|
|
13
|
+
* 2. `npx vyuh-dxkit update` (scaffold refresh)
|
|
14
|
+
* 3. `npx vyuh-dxkit doctor` (verify)
|
|
15
|
+
* Then prints devcontainer-rebuild instructions if .devcontainer/
|
|
16
|
+
* was refreshed.
|
|
17
|
+
*
|
|
18
|
+
* Architectural mirror of the doctor → dxkit-fix pattern: structured
|
|
19
|
+
* CLI output (--plan --json) for skill consumption, execution mode
|
|
20
|
+
* for direct human use. Same shape, different content.
|
|
21
|
+
*/
|
|
22
|
+
export type DeltaKind = 'none' | 'patch' | 'minor' | 'major' | 'downgrade';
|
|
23
|
+
export interface UpgradeStep {
|
|
24
|
+
/** Shell command to run (verbatim — what gets executed). */
|
|
25
|
+
command: string;
|
|
26
|
+
/** One-line purpose shown in plan + before each execution. */
|
|
27
|
+
purpose: string;
|
|
28
|
+
/** Optional steps the customer can decline (e.g. devcontainer rebuild). */
|
|
29
|
+
optional?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface UpgradePlan {
|
|
32
|
+
schema: 'upgrade-plan.v1';
|
|
33
|
+
generatedAt: string;
|
|
34
|
+
cwd: string;
|
|
35
|
+
current: {
|
|
36
|
+
/** Installed binary version (from `npx vyuh-dxkit --version`). */
|
|
37
|
+
binary: string | null;
|
|
38
|
+
/** Scaffold version recorded in manifest. */
|
|
39
|
+
scaffold: string | null;
|
|
40
|
+
};
|
|
41
|
+
/** Target version — `--target=X.Y.Z` or 'latest' from npm. */
|
|
42
|
+
target: string;
|
|
43
|
+
delta: DeltaKind;
|
|
44
|
+
/**
|
|
45
|
+
* Recommended execution sequence. Each step is independently
|
|
46
|
+
* idempotent — re-running is safe.
|
|
47
|
+
*/
|
|
48
|
+
steps: UpgradeStep[];
|
|
49
|
+
/**
|
|
50
|
+
* Customer-facing warnings (peer-dep risks, breaking changes,
|
|
51
|
+
* "devcontainer will need rebuild after"). Empty when nothing
|
|
52
|
+
* actionable.
|
|
53
|
+
*/
|
|
54
|
+
warnings: string[];
|
|
55
|
+
/**
|
|
56
|
+
* Brief note pointing the customer at the canonical changelog.
|
|
57
|
+
* Detailed per-version highlight parsing is a future enhancement —
|
|
58
|
+
* for now we keep this simple and link to the source of truth.
|
|
59
|
+
*/
|
|
60
|
+
changelogNote: string;
|
|
61
|
+
}
|
|
62
|
+
export interface UpgradeOpts {
|
|
63
|
+
/** Pin to a specific version. Default: latest from npm. */
|
|
64
|
+
target?: string;
|
|
65
|
+
/** Skip interactive confirmations. */
|
|
66
|
+
yes?: boolean;
|
|
67
|
+
/** Print commands without executing. */
|
|
68
|
+
dryRun?: boolean;
|
|
69
|
+
/** Emit plan only; don't execute. */
|
|
70
|
+
planOnly?: boolean;
|
|
71
|
+
/** Emit plan as JSON instead of prose (only meaningful with planOnly). */
|
|
72
|
+
json?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Injectable version reads. Useful for tests that need deterministic
|
|
75
|
+
* plans without subprocess fanout; production code leaves these
|
|
76
|
+
* undefined and the readers shell out as needed.
|
|
77
|
+
*/
|
|
78
|
+
_readBinary?: (cwd: string) => string | null;
|
|
79
|
+
_readLatest?: () => string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Classify the delta between two semver-shaped strings. Returns
|
|
83
|
+
* `'none'` if equal, `'downgrade'` if target < current.
|
|
84
|
+
*/
|
|
85
|
+
export declare function classifyDelta(current: string | null, target: string): DeltaKind;
|
|
86
|
+
export declare function buildUpgradePlan(cwd: string, opts?: UpgradeOpts): UpgradePlan;
|
|
87
|
+
export declare function runUpgrade(cwd: string, opts?: UpgradeOpts): Promise<void>;
|
|
88
|
+
//# sourceMappingURL=upgrade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAQH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,CAAC;AAE3E,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE;QACP,kEAAkE;QAClE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,6CAA6C;QAC7C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC;IACF,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,wCAAwC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC7C,WAAW,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B;AA4CD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAY/E;AAMD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,WAAW,CA6FjF;AAyHD,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAcnF"}
|
package/dist/upgrade.js
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `vyuh-dxkit upgrade` — combined CLI for the dxkit upgrade flow.
|
|
4
|
+
*
|
|
5
|
+
* Two modes, one subcommand:
|
|
6
|
+
*
|
|
7
|
+
* `--plan [--json]` — preview only. Emits UpgradePlan JSON
|
|
8
|
+
* (consumed by dxkit-update skill) or text-prose summary. No
|
|
9
|
+
* mutations. Used to inspect what an upgrade would do before
|
|
10
|
+
* committing.
|
|
11
|
+
*
|
|
12
|
+
* (no flag, or `--yes`) — execute. Runs the three-step upgrade:
|
|
13
|
+
* 1. `npm install @vyuhlabs/dxkit@<target>` (binary)
|
|
14
|
+
* 2. `npx vyuh-dxkit update` (scaffold refresh)
|
|
15
|
+
* 3. `npx vyuh-dxkit doctor` (verify)
|
|
16
|
+
* Then prints devcontainer-rebuild instructions if .devcontainer/
|
|
17
|
+
* was refreshed.
|
|
18
|
+
*
|
|
19
|
+
* Architectural mirror of the doctor → dxkit-fix pattern: structured
|
|
20
|
+
* CLI output (--plan --json) for skill consumption, execution mode
|
|
21
|
+
* for direct human use. Same shape, different content.
|
|
22
|
+
*/
|
|
23
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
26
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
27
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
28
|
+
}
|
|
29
|
+
Object.defineProperty(o, k2, desc);
|
|
30
|
+
}) : (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
o[k2] = m[k];
|
|
33
|
+
}));
|
|
34
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
35
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
36
|
+
}) : function(o, v) {
|
|
37
|
+
o["default"] = v;
|
|
38
|
+
});
|
|
39
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
40
|
+
var ownKeys = function(o) {
|
|
41
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
42
|
+
var ar = [];
|
|
43
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
44
|
+
return ar;
|
|
45
|
+
};
|
|
46
|
+
return ownKeys(o);
|
|
47
|
+
};
|
|
48
|
+
return function (mod) {
|
|
49
|
+
if (mod && mod.__esModule) return mod;
|
|
50
|
+
var result = {};
|
|
51
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
52
|
+
__setModuleDefault(result, mod);
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
})();
|
|
56
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
+
exports.classifyDelta = classifyDelta;
|
|
58
|
+
exports.buildUpgradePlan = buildUpgradePlan;
|
|
59
|
+
exports.runUpgrade = runUpgrade;
|
|
60
|
+
const fs = __importStar(require("fs"));
|
|
61
|
+
const path = __importStar(require("path"));
|
|
62
|
+
const child_process_1 = require("child_process");
|
|
63
|
+
const logger = __importStar(require("./logger"));
|
|
64
|
+
// ────────────────────────────────────────────────────────────────────
|
|
65
|
+
// Version helpers
|
|
66
|
+
// ────────────────────────────────────────────────────────────────────
|
|
67
|
+
function readScaffoldVersion(cwd) {
|
|
68
|
+
const manifestPath = path.join(cwd, '.vyuh-dxkit.json');
|
|
69
|
+
if (!fs.existsSync(manifestPath))
|
|
70
|
+
return null;
|
|
71
|
+
try {
|
|
72
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
73
|
+
return manifest.version ?? null;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function readBinaryVersion(cwd) {
|
|
80
|
+
try {
|
|
81
|
+
const out = (0, child_process_1.execSync)('npx --no-install vyuh-dxkit --version 2>/dev/null', {
|
|
82
|
+
cwd,
|
|
83
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
84
|
+
encoding: 'utf-8',
|
|
85
|
+
});
|
|
86
|
+
return out.trim() || null;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function readLatestPublished() {
|
|
93
|
+
try {
|
|
94
|
+
const out = (0, child_process_1.execSync)('npm view @vyuhlabs/dxkit version 2>/dev/null', {
|
|
95
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
96
|
+
encoding: 'utf-8',
|
|
97
|
+
timeout: 15000,
|
|
98
|
+
});
|
|
99
|
+
return out.trim();
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// npm registry unreachable — return empty so caller can decide
|
|
103
|
+
return '';
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Classify the delta between two semver-shaped strings. Returns
|
|
108
|
+
* `'none'` if equal, `'downgrade'` if target < current.
|
|
109
|
+
*/
|
|
110
|
+
function classifyDelta(current, target) {
|
|
111
|
+
if (!current || !target)
|
|
112
|
+
return 'none';
|
|
113
|
+
const [c1, c2, c3] = current.split('.').map((n) => parseInt(n, 10));
|
|
114
|
+
const [t1, t2, t3] = target.split('.').map((n) => parseInt(n, 10));
|
|
115
|
+
if (Number.isNaN(c1) || Number.isNaN(t1))
|
|
116
|
+
return 'none';
|
|
117
|
+
if (t1 > c1)
|
|
118
|
+
return 'major';
|
|
119
|
+
if (t1 < c1)
|
|
120
|
+
return 'downgrade';
|
|
121
|
+
if (t2 > c2)
|
|
122
|
+
return 'minor';
|
|
123
|
+
if (t2 < c2)
|
|
124
|
+
return 'downgrade';
|
|
125
|
+
if (t3 > c3)
|
|
126
|
+
return 'patch';
|
|
127
|
+
if (t3 < c3)
|
|
128
|
+
return 'downgrade';
|
|
129
|
+
return 'none';
|
|
130
|
+
}
|
|
131
|
+
// ────────────────────────────────────────────────────────────────────
|
|
132
|
+
// Plan construction
|
|
133
|
+
// ────────────────────────────────────────────────────────────────────
|
|
134
|
+
function buildUpgradePlan(cwd, opts = {}) {
|
|
135
|
+
const scaffold = readScaffoldVersion(cwd);
|
|
136
|
+
const binary = (opts._readBinary ?? readBinaryVersion)(cwd);
|
|
137
|
+
const latest = opts.target ?? (opts._readLatest ?? readLatestPublished)();
|
|
138
|
+
// Use binary version as the "current" anchor for delta classification —
|
|
139
|
+
// it's what npm install will replace. Scaffold version informs whether
|
|
140
|
+
// vyuh-dxkit update is needed even when binary is already up to date.
|
|
141
|
+
const delta = classifyDelta(binary, latest);
|
|
142
|
+
const steps = [];
|
|
143
|
+
const warnings = [];
|
|
144
|
+
if (!latest) {
|
|
145
|
+
warnings.push('Could not query npm for the latest version (registry unreachable or rate-limited). ' +
|
|
146
|
+
'Pass --target=X.Y.Z to upgrade to a specific version.');
|
|
147
|
+
}
|
|
148
|
+
// Step 1: binary upgrade. Always included unless delta is none AND
|
|
149
|
+
// scaffold already matches.
|
|
150
|
+
if (delta !== 'none' || (scaffold && binary && scaffold !== binary)) {
|
|
151
|
+
if (latest) {
|
|
152
|
+
steps.push({
|
|
153
|
+
command: `npm install @vyuhlabs/dxkit@${latest}`,
|
|
154
|
+
purpose: `Install dxkit binary ${binary ?? '(missing)'} → ${latest}`,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Step 2: scaffold refresh. Always run when scaffold ≠ binary OR after
|
|
159
|
+
// a binary upgrade (scaffold may need updating to match the new binary).
|
|
160
|
+
if (latest) {
|
|
161
|
+
steps.push({
|
|
162
|
+
command: 'npx vyuh-dxkit update',
|
|
163
|
+
purpose: 'Refresh scaffold (.devcontainer, .githooks, .claude/skills, CI workflows)',
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// Step 3: verify with doctor.
|
|
167
|
+
if (latest) {
|
|
168
|
+
steps.push({
|
|
169
|
+
command: 'npx vyuh-dxkit doctor',
|
|
170
|
+
purpose: 'Verify operational health post-upgrade',
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
// Optional: devcontainer rebuild reminder. We mark this optional so
|
|
174
|
+
// dxkit-update can surface it as a "you also need to do this manually"
|
|
175
|
+
// step rather than something the CLI can execute.
|
|
176
|
+
const hasDevcontainer = fs.existsSync(path.join(cwd, '.devcontainer', 'devcontainer.json'));
|
|
177
|
+
if (hasDevcontainer && delta !== 'none') {
|
|
178
|
+
steps.push({
|
|
179
|
+
command: '# Rebuild devcontainer: VSCode Command Palette → "Dev Containers: Rebuild Container"',
|
|
180
|
+
purpose: 'Pick up devcontainer.json changes (if any) — manual step',
|
|
181
|
+
optional: true,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
// Warnings.
|
|
185
|
+
if (delta === 'major') {
|
|
186
|
+
warnings.push(`Major version jump (${binary} → ${latest}). Read CHANGELOG.md for breaking changes ` +
|
|
187
|
+
'before running the upgrade.');
|
|
188
|
+
}
|
|
189
|
+
if (delta === 'downgrade') {
|
|
190
|
+
warnings.push(`Target version ${latest} is OLDER than installed ${binary}. ` +
|
|
191
|
+
'Downgrades are not officially supported; baseline + manifest schemas may differ.');
|
|
192
|
+
}
|
|
193
|
+
if (scaffold && binary && scaffold !== binary) {
|
|
194
|
+
warnings.push(`Scaffold version (${scaffold}) doesn't match binary (${binary}). ` +
|
|
195
|
+
'Step 2 (vyuh-dxkit update) will reconcile.');
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
schema: 'upgrade-plan.v1',
|
|
199
|
+
generatedAt: new Date().toISOString(),
|
|
200
|
+
cwd,
|
|
201
|
+
current: { binary, scaffold },
|
|
202
|
+
target: latest,
|
|
203
|
+
delta,
|
|
204
|
+
steps,
|
|
205
|
+
warnings,
|
|
206
|
+
changelogNote: latest
|
|
207
|
+
? `For per-version details: https://github.com/vyuh-labs/dxkit/blob/main/CHANGELOG.md`
|
|
208
|
+
: '',
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
// ────────────────────────────────────────────────────────────────────
|
|
212
|
+
// Renderers
|
|
213
|
+
// ────────────────────────────────────────────────────────────────────
|
|
214
|
+
function renderPlanProse(plan) {
|
|
215
|
+
logger.header('vyuh-dxkit upgrade --plan');
|
|
216
|
+
logger.info(`Current: scaffold ${plan.current.scaffold ?? '(none)'} + binary ${plan.current.binary ?? '(none)'}`);
|
|
217
|
+
logger.info(`Target: ${plan.target || '(latest unavailable)'}`);
|
|
218
|
+
logger.info(`Delta: ${plan.delta}`);
|
|
219
|
+
if (plan.warnings.length) {
|
|
220
|
+
console.log(''); // slop-ok
|
|
221
|
+
for (const w of plan.warnings)
|
|
222
|
+
logger.warn(w);
|
|
223
|
+
}
|
|
224
|
+
if (plan.steps.length) {
|
|
225
|
+
console.log(''); // slop-ok
|
|
226
|
+
logger.info('Plan:');
|
|
227
|
+
plan.steps.forEach((s, i) => {
|
|
228
|
+
const marker = s.optional ? '○' : '●';
|
|
229
|
+
logger.dim(` ${marker} [${i + 1}/${plan.steps.length}] ${s.purpose}`);
|
|
230
|
+
logger.dim(` ${s.command}`);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
if (plan.changelogNote) {
|
|
234
|
+
console.log(''); // slop-ok
|
|
235
|
+
logger.dim(plan.changelogNote);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// ────────────────────────────────────────────────────────────────────
|
|
239
|
+
// Execution
|
|
240
|
+
// ────────────────────────────────────────────────────────────────────
|
|
241
|
+
function runStep(step, cwd, dryRun) {
|
|
242
|
+
if (step.optional) {
|
|
243
|
+
// Optional steps are never auto-executed — surfaced for the
|
|
244
|
+
// customer to do manually.
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
logger.info(`→ ${step.purpose}`);
|
|
248
|
+
logger.dim(` ${step.command}`);
|
|
249
|
+
if (dryRun) {
|
|
250
|
+
logger.dim(' (dry-run; skipping)');
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
// Shell out to a real shell so npx/npm work the same way as the
|
|
254
|
+
// customer's terminal would. We DON'T use spawnSync's shell:true
|
|
255
|
+
// bash escaping concerns because the commands here are all dxkit-
|
|
256
|
+
// controlled — no customer input flows into them.
|
|
257
|
+
const result = (0, child_process_1.spawnSync)('bash', ['-c', step.command], {
|
|
258
|
+
cwd,
|
|
259
|
+
stdio: 'inherit',
|
|
260
|
+
});
|
|
261
|
+
return result.status === 0;
|
|
262
|
+
}
|
|
263
|
+
async function runUpgradeExecution(cwd, plan, opts) {
|
|
264
|
+
// Print the plan so the customer sees what's about to happen.
|
|
265
|
+
renderPlanProse(plan);
|
|
266
|
+
if (plan.steps.length === 0) {
|
|
267
|
+
console.log(''); // slop-ok
|
|
268
|
+
logger.success('Already up to date — nothing to do.');
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (!opts.yes && !opts.dryRun) {
|
|
272
|
+
// We don't bundle a real prompt library here — the upgrade is
|
|
273
|
+
// intended either non-interactive (--yes) or driven by the
|
|
274
|
+
// dxkit-update skill (which handles confirmation). Surface the
|
|
275
|
+
// hint so a direct human invocation knows to add --yes.
|
|
276
|
+
console.log(''); // slop-ok
|
|
277
|
+
logger.warn('Interactive confirmation is not implemented for this command. ' +
|
|
278
|
+
'Re-run with --yes to execute, --dry-run to print without executing, ' +
|
|
279
|
+
'or use the dxkit-update skill for a guided upgrade.');
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
console.log(''); // slop-ok
|
|
283
|
+
logger.header('Executing upgrade');
|
|
284
|
+
const optionalAfter = [];
|
|
285
|
+
for (const step of plan.steps) {
|
|
286
|
+
if (step.optional) {
|
|
287
|
+
optionalAfter.push(step);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const ok = runStep(step, cwd, !!opts.dryRun);
|
|
291
|
+
if (!ok) {
|
|
292
|
+
logger.fail(`Step failed: ${step.purpose}`);
|
|
293
|
+
logger.dim(' Upgrade aborted. Re-run `vyuh-dxkit doctor` to see current state.');
|
|
294
|
+
process.exitCode = 1;
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
console.log(''); // slop-ok
|
|
299
|
+
logger.success(`Upgraded to ${plan.target}.`);
|
|
300
|
+
if (optionalAfter.length) {
|
|
301
|
+
console.log(''); // slop-ok
|
|
302
|
+
logger.info('Manual steps still required:');
|
|
303
|
+
for (const s of optionalAfter)
|
|
304
|
+
logger.dim(` • ${s.purpose}\n ${s.command}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// ────────────────────────────────────────────────────────────────────
|
|
308
|
+
// Entry point
|
|
309
|
+
// ────────────────────────────────────────────────────────────────────
|
|
310
|
+
async function runUpgrade(cwd, opts = {}) {
|
|
311
|
+
const plan = buildUpgradePlan(cwd, opts);
|
|
312
|
+
if (opts.planOnly) {
|
|
313
|
+
if (opts.json) {
|
|
314
|
+
// Logger already routes to stderr in --json mode (cli.ts sets it).
|
|
315
|
+
console.log(JSON.stringify(plan, null, 2)); // slop-ok
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
renderPlanProse(plan);
|
|
319
|
+
}
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
await runUpgradeExecution(cwd, plan, opts);
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=upgrade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -42,20 +42,22 @@ Skip items where reachability is "no" (graphify can't find a call path) UNLESS t
|
|
|
42
42
|
# 2. Remove the secret from the file
|
|
43
43
|
# 3. If the secret was committed: `git filter-repo` or BFG to scrub history
|
|
44
44
|
# 4. Re-scan to confirm gitleaks no longer reports it
|
|
45
|
-
vyuh-dxkit vulnerabilities --json | jq '.summary.findings'
|
|
45
|
+
npx vyuh-dxkit vulnerabilities --json | jq '.summary.findings'
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
Don't try to redact the secret in place — the git history still has it. Rotation is the only true fix.
|
|
49
49
|
|
|
50
|
+
If the "secret" is actually a placeholder in test code (e.g., `"sk_test_xxxxxxxxxxxx"` with no real credential value), confirm with the developer and allowlist via `dxkit-allow:test-fixture` — see "Allowlisting (when fix is not viable)" below.
|
|
51
|
+
|
|
50
52
|
### SAST finding (semgrep)
|
|
51
53
|
|
|
52
54
|
```bash
|
|
53
55
|
# 1. Read the finding's rule + line range from the report
|
|
54
56
|
# 2. Open the file, understand why semgrep flagged it
|
|
55
|
-
# 3. Either FIX (preferred) or
|
|
57
|
+
# 3. Either FIX (preferred) or ALLOWLIST (carefully — see below)
|
|
56
58
|
```
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
If the finding is a true false positive or intentional pattern (test fixture, mitigated externally), suppress via dxkit's allowlist — NOT via semgrep's `// nosemgrep:`. The dxkit allowlist is the canonical surface (single source of truth across every scanner), carries a typed category + reason, and is audit-trackable through `vyuh-dxkit allowlist audit`. See "Allowlisting (when fix is not viable)" below.
|
|
59
61
|
|
|
60
62
|
### Dependency vulnerability
|
|
61
63
|
|
|
@@ -63,13 +65,15 @@ Suppression is `// nosemgrep: <rule-id>` on the offending line. Use sparingly
|
|
|
63
65
|
# Find the patched version (osv-scanner / npm-audit / etc. report it)
|
|
64
66
|
npm install <pkg>@<patched-version>
|
|
65
67
|
# Re-run the scan
|
|
66
|
-
vyuh-dxkit vulnerabilities
|
|
68
|
+
npx vyuh-dxkit vulnerabilities
|
|
67
69
|
```
|
|
68
70
|
|
|
69
71
|
For peer-dep conflicts: `npm install <pkg>@<patched-version> --legacy-peer-deps` (matches the post-create.sh fallback chain).
|
|
70
72
|
|
|
71
73
|
For Python: `pip install --upgrade <pkg>=<patched>` then re-pip-freeze. For Go: `go get <pkg>@<patched>` then `go mod tidy`. For Ruby: edit Gemfile, `bundle update <pkg>`. For Rust: `cargo update -p <pkg> --precise <patched>`.
|
|
72
74
|
|
|
75
|
+
If no patched version exists OR the upgrade breaks other constraints AND the risk is mitigated externally (network policy, WAF, runtime guard), allowlist with `category=mitigated-externally` and a reason describing the mitigation. If the team is accepting the risk while waiting on a fix, `category=accepted-risk` + an expiry tied to the fix deadline.
|
|
76
|
+
|
|
73
77
|
### Test gap
|
|
74
78
|
|
|
75
79
|
```bash
|
|
@@ -78,7 +82,7 @@ For Python: `pip install --upgrade <pkg>=<patched>` then re-pip-freeze. For Go:
|
|
|
78
82
|
# 3. Run the test runner to confirm it passes
|
|
79
83
|
npm test # or pytest, go test, cargo test, etc.
|
|
80
84
|
# 4. Re-run test-gaps to confirm the file dropped off the list
|
|
81
|
-
vyuh-dxkit test-gaps
|
|
85
|
+
npx vyuh-dxkit test-gaps
|
|
82
86
|
```
|
|
83
87
|
|
|
84
88
|
Don't write tests that just import the module — write tests that exercise behavior. Useless tests inflate the count but don't move the dimension.
|
|
@@ -93,13 +97,95 @@ Don't write tests that just import the module — write tests that exercise beha
|
|
|
93
97
|
|
|
94
98
|
If the finding is a false positive, add `// slop-ok: <reason>` on the offending line (or `# slop-ok` for non-JS).
|
|
95
99
|
|
|
100
|
+
## Allowlisting (when fix is not viable)
|
|
101
|
+
|
|
102
|
+
**Fix first.** The allowlist is the SECOND option, not the first. When you reach for it, choose deliberately — every allowlist entry is a future maintenance burden the customer's team will revisit.
|
|
103
|
+
|
|
104
|
+
Five typed categories signal WHY the suppression is in place:
|
|
105
|
+
|
|
106
|
+
| Category | Meaning | Where it lives |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| `false-positive` | Scanner is wrong about this code | Inline annotation OR file-level |
|
|
109
|
+
| `test-fixture` | Intentional pattern in a fixture / test file | Inline annotation OR file-level |
|
|
110
|
+
| `mitigated-externally` | Real risk but neutralized at runtime (WAF, env, etc.) | Inline annotation OR file-level |
|
|
111
|
+
| `accepted-risk` | Real risk, accepted by the team, signed off | File-level only (needs expiry + acknowledged severity) |
|
|
112
|
+
| `deferred` | Real, will fix later, tracked work | File-level only (needs expiry) |
|
|
113
|
+
|
|
114
|
+
`accepted-risk` and `deferred` require an `expiresAt` date because they describe assertions that should age out — by default the CLI sets 90 days. `false-positive`, `test-fixture`, and `mitigated-externally` describe assertions that don't naturally stale; they may omit expiry.
|
|
115
|
+
|
|
116
|
+
### The two surfaces
|
|
117
|
+
|
|
118
|
+
**Inline annotation** is the natural fit for source-anchored findings (secrets, code, config, dep-vuln, hygiene) with an inline-compatible category. The annotation lives next to the line it suppresses:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
api_key = "sk_test_xxxx" # dxkit-allow:test-fixture reason="placeholder in unit test"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Or, for long source lines, above:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// dxkit-allow:false-positive reason="regex matches intentional placeholder"
|
|
128
|
+
const apiKey = "sk_test_xxxx";
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The grammar is uniform across every language; only the comment marker varies (`#` for python/ruby, `//` for typescript/go/rust/csharp/kotlin/java). Don't type it by hand — let dxkit insert it for you (see CLI below).
|
|
132
|
+
|
|
133
|
+
**File-level allowlist** lives at `.dxkit/allowlist.json` and is the surface for:
|
|
134
|
+
|
|
135
|
+
- Cross-file or whole-file findings (duplication, coverage-gap, test-gap, god-file, large-file, stale-file)
|
|
136
|
+
- Findings with no stable single-line attachment (dep-vuln, secret-hmac)
|
|
137
|
+
- Any `accepted-risk` or `deferred` suppression regardless of kind
|
|
138
|
+
|
|
139
|
+
### Add an allowlist entry (canonical path)
|
|
140
|
+
|
|
141
|
+
Don't hand-edit the annotation comment or the JSON file — let the CLI insert it correctly:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Inline annotation at file:line — for source-anchored findings
|
|
145
|
+
# with an inline-compatible category
|
|
146
|
+
npx vyuh-dxkit allowlist add src/auth/oauth.ts:42 \
|
|
147
|
+
--category=test-fixture --reason="placeholder in unit test"
|
|
148
|
+
|
|
149
|
+
# File-level entry — for everything else (kind + fingerprint required;
|
|
150
|
+
# both come straight from the guardrail check's output)
|
|
151
|
+
npx vyuh-dxkit allowlist add --fingerprint=a3f9c0e8b7d2e1f4 \
|
|
152
|
+
--kind=dep-vuln --category=accepted-risk \
|
|
153
|
+
--reason="WAF rule X mitigates this CVE" --expires=2026-08-22
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The guardrail's block message gives you the exact command to paste for every blocked finding — file path + line for inline-compatible kinds, fingerprint + kind for everything else. Just copy-paste.
|
|
157
|
+
|
|
158
|
+
### When the finding only carries an id (sanitized / ref-based baseline)
|
|
159
|
+
|
|
160
|
+
If you're seeing a blocked finding labelled `<sanitized>` (in `baseline show` output) OR with no `file`/`line` columns in the PR-comment table, the repo's baseline mode is `committed-sanitized` or `ref-based` and the human-readable locator was stripped at write time. Two options:
|
|
161
|
+
|
|
162
|
+
- **Inspect the finding in the current scan.** The fingerprint pairs against the live scan's output, which is rich (always). Re-run the matching analyzer (`vyuh-dxkit vulnerabilities`, `vyuh-dxkit health`, etc.) and grep the JSON output for the fingerprint — that finding has full file:line context.
|
|
163
|
+
- **Allowlist by fingerprint anyway.** File-level allowlist entries only need fingerprint + kind, both of which the guardrail message still provides. The category + reason apply regardless of whether the locator is visible at baseline time.
|
|
164
|
+
|
|
165
|
+
The fingerprint contract is preserved across all three modes — `committed-full`, `committed-sanitized`, `ref-based` all produce the same identity bytes for the same finding. Sanitization only strips the human-readable rendering; it doesn't change which findings pair across runs.
|
|
166
|
+
|
|
167
|
+
### Review what's allowlisted
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npx vyuh-dxkit allowlist list # all entries (text)
|
|
171
|
+
npx vyuh-dxkit allowlist show <fingerprint> # one entry's full detail
|
|
172
|
+
npx vyuh-dxkit allowlist audit # expired / soon-to-expire / missing-rationale
|
|
173
|
+
npx vyuh-dxkit allowlist prune # remove expired entries
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Run `audit` periodically — `accepted-risk` and `deferred` entries that pass their expiry should either be re-justified (renew expiry) or pruned (remove the entry; the underlying finding will re-flag on the next scan).
|
|
177
|
+
|
|
178
|
+
### Stale annotations
|
|
179
|
+
|
|
180
|
+
If the underlying finding is fixed but the inline annotation lingers, the next scan emits a `stale-allow` finding pointing at the orphaned comment. The remediation is always to remove the annotation — dxkit refuses to allowlist a stale-allow finding (allowlisting the warning that an annotation is stale would defeat the entire model).
|
|
181
|
+
|
|
96
182
|
## Verification — never skip
|
|
97
183
|
|
|
98
184
|
After each fix:
|
|
99
185
|
|
|
100
186
|
```bash
|
|
101
187
|
# Re-run the SPECIFIC analyzer that flagged the finding
|
|
102
|
-
vyuh-dxkit vulnerabilities # or quality / test-gaps / health
|
|
188
|
+
npx vyuh-dxkit vulnerabilities # or quality / test-gaps / health
|
|
103
189
|
```
|
|
104
190
|
|
|
105
191
|
The fix is verified when:
|
|
@@ -111,14 +197,19 @@ If the finding's still there: the fix didn't work, try again.
|
|
|
111
197
|
|
|
112
198
|
## Baseline decisions
|
|
113
199
|
|
|
114
|
-
Once a finding is fixed
|
|
200
|
+
Once a finding is processed (fixed, allowlisted, or accepted), the workflow depends on which path you took:
|
|
115
201
|
|
|
116
202
|
| Scenario | Action |
|
|
117
203
|
|---|---|
|
|
118
|
-
| Fix landed via a code change | Commit the code. Baseline
|
|
119
|
-
|
|
|
120
|
-
|
|
|
121
|
-
|
|
|
204
|
+
| Fix landed via a code change | Commit the code. Baseline + allowlist are unchanged. Future scans confirm the fix held. |
|
|
205
|
+
| Genuine false positive OR intentional pattern | `vyuh-dxkit allowlist add` with `category=false-positive` or `test-fixture`. Commit the annotation / allowlist file. Baseline is unchanged. |
|
|
206
|
+
| Real risk neutralized externally (WAF, runtime guard) | `vyuh-dxkit allowlist add` with `category=mitigated-externally` + a reason describing the mitigation. Baseline unchanged. |
|
|
207
|
+
| Real risk, accepted by team, won't fix | `vyuh-dxkit allowlist add` with `category=accepted-risk` + `--expires=YYYY-MM-DD` (defaults 90 days). Acknowledged-severity required for high/critical. |
|
|
208
|
+
| Real risk, will fix later (tracked work) | `vyuh-dxkit allowlist add` with `category=deferred` + `--expires=YYYY-MM-DD`. The expiry forces re-review when the deadline passes. |
|
|
209
|
+
| Fix landed via a config change (e.g., new entry in `.dxkit-ignore`) | Re-baseline: `npx vyuh-dxkit baseline create --force`. Commit both `.dxkit-ignore` and the new baseline. |
|
|
210
|
+
| Brownfield acceptance (the whole CURRENT state is known mess; future regressions must be net-new) | Re-baseline with an explicit reason in the commit message. Reserve this for the deliberate "draw a line here" moment, not per-finding suppression. |
|
|
211
|
+
|
|
212
|
+
**Prefer the allowlist over re-baselining for per-finding decisions.** The allowlist carries a typed category + reason + (when relevant) expiry; the baseline carries only "this finding was here." Future maintainers reading `vyuh-dxkit allowlist show <fingerprint>` see WHY the suppression is in place; reading the baseline file shows only that the finding existed at capture time. Per-finding decisions belong in the allowlist; codebase-wide brownfield acceptance belongs in the baseline.
|
|
122
213
|
|
|
123
214
|
**Never** re-baseline a finding silently — the commit message should explain why the regression is accepted. Future maintainers reading `git log .dxkit/baselines/` should see the rationale.
|
|
124
215
|
|
|
@@ -127,24 +218,27 @@ Once a finding is fixed AND verified gone, the workflow depends on what changed:
|
|
|
127
218
|
After fixing N findings, run the guardrail check before pushing:
|
|
128
219
|
|
|
129
220
|
```bash
|
|
130
|
-
vyuh-dxkit guardrail check
|
|
221
|
+
npx vyuh-dxkit guardrail check
|
|
131
222
|
```
|
|
132
223
|
|
|
133
224
|
Exit 0 = your fixes didn't introduce any net-new regressions (you only removed/fixed things). Exit 1 = something new appeared; address that before pushing.
|
|
134
225
|
|
|
135
226
|
## When fixes get expensive
|
|
136
227
|
|
|
137
|
-
Sometimes the right call is: don't fix,
|
|
228
|
+
Sometimes the right call is: don't fix, allowlist (or re-baseline if it's brownfield-wide).
|
|
138
229
|
|
|
139
230
|
Examples:
|
|
140
|
-
- Legacy code on a deprecation path (sunset > fix)
|
|
141
|
-
- A SAST finding in vendored code you don't maintain
|
|
142
|
-
- A test gap on a one-off script that doesn't merit tests
|
|
231
|
+
- Legacy code on a deprecation path (sunset > fix) → `accepted-risk` with expiry matching the sunset date
|
|
232
|
+
- A SAST finding in vendored code you don't maintain → `mitigated-externally` if the vendor patches separately, else `accepted-risk`
|
|
233
|
+
- A test gap on a one-off script that doesn't merit tests → `accepted-risk`
|
|
234
|
+
- An import line flagged by a scanner that you've reviewed and confirmed safe → `false-positive` inline annotation at the import
|
|
143
235
|
|
|
144
|
-
In those cases:
|
|
236
|
+
In those cases: `vyuh-dxkit allowlist add` is the right tool for per-finding decisions (typed reason + expiry where relevant). Reserve "accept as baseline" for the deliberate one-shot brownfield moment ("this entire current state is known mess; today's findings are the new baseline"). The two surfaces complement each other — allowlist for individual judgment calls, baseline for the codebase-wide line in the sand.
|
|
145
237
|
|
|
146
238
|
## Hand-offs
|
|
147
239
|
|
|
148
240
|
- For ignore-file edits as part of a fix → `dxkit-config` skill
|
|
149
241
|
- For hook-related issues during a fix push → `dxkit-hooks` skill
|
|
150
242
|
- For re-running reports between fixes → `dxkit-reports` skill
|
|
243
|
+
- For broken dxkit install (hooks not firing, vyuh-dxkit not on PATH) → `dxkit-fix` skill
|
|
244
|
+
- For allowlist management beyond the per-finding `add` path (auditing existing entries, pruning expired ones, reviewing the team's overall suppression posture) → run `npx vyuh-dxkit allowlist audit` / `list` / `prune` directly; no separate skill yet
|