@westbayberry/dg 2.0.8 → 2.0.10
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/README.md +17 -12
- package/dist/api/analyze.js +134 -34
- package/dist/audit-ui/export.js +3 -4
- package/dist/auth/device-login.js +13 -9
- package/dist/auth/store.js +43 -26
- package/dist/bin/dg.js +5 -0
- package/dist/commands/audit.js +14 -4
- package/dist/commands/config.js +3 -5
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/explain.js +138 -6
- package/dist/commands/licenses.js +37 -24
- package/dist/commands/login.js +12 -3
- package/dist/commands/logout.js +15 -4
- package/dist/commands/scan.js +1 -1
- package/dist/commands/service.js +76 -24
- package/dist/commands/status.js +38 -4
- package/dist/commands/types.js +1 -0
- package/dist/config/settings.js +102 -22
- package/dist/launcher/install-preflight.js +81 -12
- package/dist/launcher/output-redaction.js +5 -3
- package/dist/launcher/preflight-prompt.js +31 -12
- package/dist/launcher/run.js +87 -8
- package/dist/proxy/ca.js +69 -29
- package/dist/proxy/enforcement.js +41 -3
- package/dist/proxy/worker.js +21 -9
- package/dist/runtime/first-run.js +33 -2
- package/dist/runtime/nudges.js +9 -2
- package/dist/scan/analyze-worker.js +18 -8
- package/dist/scan/collect.js +35 -28
- package/dist/scan/command.js +80 -40
- package/dist/scan/discovery.js +9 -3
- package/dist/scan/render.js +22 -6
- package/dist/scan/scanner-report.js +89 -12
- package/dist/scan/staged.js +69 -7
- package/dist/scan-ui/LegacyApp.js +10 -48
- package/dist/scan-ui/components/InteractiveResultsView.js +171 -111
- package/dist/scan-ui/components/ProjectSelector.js +3 -3
- package/dist/scan-ui/components/ScoreHeader.js +8 -4
- package/dist/scan-ui/hooks/useScan.js +74 -27
- package/dist/scan-ui/launch.js +18 -4
- package/dist/service/state.js +15 -4
- package/dist/service/trust-store.js +23 -2
- package/dist/setup/git-hook.js +28 -17
- package/dist/setup/plan.js +302 -18
- package/dist/state/cleanup-registry.js +65 -8
- package/dist/state/locks.js +95 -9
- package/dist/state/sessions.js +66 -2
- package/dist/verify/package-check.js +22 -3
- package/dist/verify/preflight.js +328 -170
- package/package.json +1 -1
package/dist/state/sessions.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { mkdirSync, readdirSync, rmSync, statSync } from "node:fs";
|
|
1
|
+
import { mkdirSync, readdirSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
2
2
|
import { appendFile, mkdir, readdir, rm, stat } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { isProcessAlive } from "./locks.js";
|
|
5
6
|
import { readJsonFile, writeJsonFileAtomic } from "./store.js";
|
|
6
7
|
export async function createSession(paths, id = randomUUID()) {
|
|
7
8
|
assertSessionId(id);
|
|
@@ -136,6 +137,68 @@ export function findStaleSessionsSync(paths, options) {
|
|
|
136
137
|
stale
|
|
137
138
|
};
|
|
138
139
|
}
|
|
140
|
+
export const DEAD_SESSION_TTL_MS = 24 * 60 * 60 * 1000;
|
|
141
|
+
const DEAD_SESSION_PRUNE_MAX = 16;
|
|
142
|
+
export function pruneDeadSessionsSync(paths, options = {}) {
|
|
143
|
+
const olderThanMs = options.olderThanMs ?? DEAD_SESSION_TTL_MS;
|
|
144
|
+
const maxRemovals = options.maxRemovals ?? DEAD_SESSION_PRUNE_MAX;
|
|
145
|
+
const now = options.now?.getTime() ?? Date.now();
|
|
146
|
+
let entries;
|
|
147
|
+
try {
|
|
148
|
+
entries = readdirSync(paths.sessionsDir, {
|
|
149
|
+
withFileTypes: true
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return {
|
|
154
|
+
removed: []
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const removed = [];
|
|
158
|
+
for (const entry of entries) {
|
|
159
|
+
if (removed.length >= maxRemovals) {
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
if (!entry.isDirectory() || !isValidSessionId(entry.name)) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const dir = join(paths.sessionsDir, entry.name);
|
|
166
|
+
let details;
|
|
167
|
+
try {
|
|
168
|
+
details = statSync(dir);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (now - details.mtimeMs < olderThanMs || sessionWorkerAlive(dir)) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
rmSync(dir, {
|
|
178
|
+
force: true,
|
|
179
|
+
recursive: true
|
|
180
|
+
});
|
|
181
|
+
removed.push(entry.name);
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
removed
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function sessionWorkerAlive(dir) {
|
|
192
|
+
let raw;
|
|
193
|
+
try {
|
|
194
|
+
raw = readFileSync(join(dir, "pid"), "utf8");
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
const pid = Number.parseInt(raw.trim(), 10);
|
|
200
|
+
return Number.isInteger(pid) && pid > 0 && isProcessAlive(pid);
|
|
201
|
+
}
|
|
139
202
|
export function sweepStaleSessionsSync(paths, options) {
|
|
140
203
|
const report = findStaleSessionsSync(paths, options);
|
|
141
204
|
for (const id of report.stale) {
|
|
@@ -154,7 +217,8 @@ function sessionFiles(dir) {
|
|
|
154
217
|
ca: join(dir, "ca.pem"),
|
|
155
218
|
block: join(dir, "block.json"),
|
|
156
219
|
hash: join(dir, "hash.json"),
|
|
157
|
-
log: join(dir, "log.jsonl")
|
|
220
|
+
log: join(dir, "log.jsonl"),
|
|
221
|
+
pid: join(dir, "pid")
|
|
158
222
|
};
|
|
159
223
|
}
|
|
160
224
|
function assertSessionId(id) {
|
|
@@ -3,7 +3,7 @@ import { resolve } from "node:path";
|
|
|
3
3
|
import { analyzePackages, AnalyzeError } from "../api/analyze.js";
|
|
4
4
|
import { createTheme } from "../presentation/theme.js";
|
|
5
5
|
import { resolvePresentation } from "../presentation/mode.js";
|
|
6
|
-
import { isSupportedLockfilePath } from "./preflight.js";
|
|
6
|
+
import { isRemotePackageSpec, isSupportedLockfilePath } from "./preflight.js";
|
|
7
7
|
import { authStatus } from "../auth/store.js";
|
|
8
8
|
import { EXIT_TOOL_ERROR, EXIT_UNAVAILABLE } from "../commands/types.js";
|
|
9
9
|
const REGISTRIES = { npm: "npm", pypi: "pypi" };
|
|
@@ -16,6 +16,9 @@ function parseSpec(target) {
|
|
|
16
16
|
const registry = target.slice(0, colon).toLowerCase();
|
|
17
17
|
const ecosystem = REGISTRIES[registry];
|
|
18
18
|
if (!ecosystem) {
|
|
19
|
+
if (registry === "cargo") {
|
|
20
|
+
return { error: `the cargo registry is not yet supported. ${DEEP_VERIFY_HINT}` };
|
|
21
|
+
}
|
|
19
22
|
return { error: `unknown registry '${registry}'. ${DEEP_VERIFY_HINT}` };
|
|
20
23
|
}
|
|
21
24
|
const rest = target.slice(colon + 1).trim();
|
|
@@ -187,6 +190,7 @@ export async function maybeVerifyPackage(args) {
|
|
|
187
190
|
let verbose = false;
|
|
188
191
|
let sarif = false;
|
|
189
192
|
let outputPath = null;
|
|
193
|
+
let outputFlagMissingPath;
|
|
190
194
|
let target;
|
|
191
195
|
let unknownFlag;
|
|
192
196
|
for (let index = 0; index < rest.length; index += 1) {
|
|
@@ -204,8 +208,14 @@ export async function maybeVerifyPackage(args) {
|
|
|
204
208
|
sarif = true;
|
|
205
209
|
}
|
|
206
210
|
else if (arg === "--output" || arg === "-o") {
|
|
207
|
-
|
|
208
|
-
|
|
211
|
+
const next = rest[index + 1];
|
|
212
|
+
if (!next || next.startsWith("-")) {
|
|
213
|
+
outputFlagMissingPath = outputFlagMissingPath ?? arg;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
outputPath = next;
|
|
217
|
+
index += 1;
|
|
218
|
+
}
|
|
209
219
|
}
|
|
210
220
|
else if (arg.startsWith("-")) {
|
|
211
221
|
unknownFlag = unknownFlag ?? arg;
|
|
@@ -220,6 +230,15 @@ export async function maybeVerifyPackage(args) {
|
|
|
220
230
|
if (isSupportedLockfilePath(target) || existsSync(resolve(target))) {
|
|
221
231
|
return { handled: false, result: noop };
|
|
222
232
|
}
|
|
233
|
+
if (isRemotePackageSpec(target)) {
|
|
234
|
+
return { handled: false, result: noop };
|
|
235
|
+
}
|
|
236
|
+
if (outputFlagMissingPath) {
|
|
237
|
+
return {
|
|
238
|
+
handled: true,
|
|
239
|
+
result: { exitCode: 2, stdout: "", stderr: `dg verify: ${outputFlagMissingPath} requires a path. Run 'dg verify --help'.\n` }
|
|
240
|
+
};
|
|
241
|
+
}
|
|
223
242
|
if (unknownFlag) {
|
|
224
243
|
return {
|
|
225
244
|
handled: true,
|