@westbayberry/dg 1.2.0 → 1.2.1

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 (2) hide show
  1. package/dist/index.mjs +556 -518
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1894,6 +1894,7 @@ __export(auth_exports, {
1894
1894
  pollAuthSession: () => pollAuthSession,
1895
1895
  preflightAuthCheck: () => preflightAuthCheck,
1896
1896
  readTermsAcceptedAt: () => readTermsAcceptedAt,
1897
+ recordScanCapReached: () => recordScanCapReached,
1897
1898
  recordScanNoticeShown: () => recordScanNoticeShown,
1898
1899
  saveCredentials: () => saveCredentials,
1899
1900
  saveCredentialsFromToken: () => saveCredentialsFromToken,
@@ -2283,18 +2284,28 @@ function writeCachedAuthStatus(status) {
2283
2284
  } catch {
2284
2285
  }
2285
2286
  }
2287
+ function recordScanCapReached(scansUsed, maxScans, reason) {
2288
+ writeCachedAuthStatus({
2289
+ authenticated: !!getStoredApiKey(),
2290
+ freeTierCapReached: true,
2291
+ scansUsed,
2292
+ scansLimit: maxScans,
2293
+ capReason: reason,
2294
+ fetchedAt: Date.now()
2295
+ });
2296
+ }
2286
2297
  async function preflightAuthCheck(apiUrl) {
2287
2298
  if (process.env.DG_SIMULATE_FREE_CAP_REACHED === "1") {
2288
2299
  throw new PreflightFreeCapReachedError(5, 5);
2289
2300
  }
2301
+ const apiKey = getStoredApiKey();
2290
2302
  const cached = readCachedAuthStatus();
2291
- if (cached) {
2303
+ if (cached && cached.authenticated === !!apiKey) {
2292
2304
  if (cached.freeTierCapReached) {
2293
2305
  throw new PreflightFreeCapReachedError(cached.scansUsed, cached.scansLimit ?? cached.scansUsed, cached.capReason ?? "monthly_limit");
2294
2306
  }
2295
2307
  return cached;
2296
2308
  }
2297
- const apiKey = getStoredApiKey();
2298
2309
  const headers = {};
2299
2310
  if (apiKey) {
2300
2311
  headers["Authorization"] = `Bearer ${apiKey}`;
@@ -2324,17 +2335,17 @@ async function preflightAuthCheck(apiUrl) {
2324
2335
  } catch {
2325
2336
  }
2326
2337
  if (body.freeTierCapReached) {
2327
- const capReason = body.capReason === "prefix_cap" ? "prefix_cap" : "monthly_limit";
2338
+ const capReason2 = body.capReason === "prefix_cap" ? "prefix_cap" : "monthly_limit";
2328
2339
  const status2 = {
2329
2340
  authenticated: !!apiKey,
2330
2341
  freeTierCapReached: true,
2331
2342
  scansUsed: body.scansUsed ?? 0,
2332
2343
  scansLimit: body.maxScans ?? 0,
2333
- capReason,
2344
+ capReason: capReason2,
2334
2345
  fetchedAt: Date.now()
2335
2346
  };
2336
2347
  writeCachedAuthStatus(status2);
2337
- throw new PreflightFreeCapReachedError(status2.scansUsed, status2.scansLimit ?? 0, capReason);
2348
+ throw new PreflightFreeCapReachedError(status2.scansUsed, status2.scansLimit ?? 0, capReason2);
2338
2349
  }
2339
2350
  }
2340
2351
  if (!resp.ok) {
@@ -2352,18 +2363,20 @@ async function preflightAuthCheck(apiUrl) {
2352
2363
  data = await resp.json();
2353
2364
  } catch {
2354
2365
  }
2366
+ const capReason = data.capReason === "prefix_cap" ? "prefix_cap" : "monthly_limit";
2355
2367
  const status = {
2356
2368
  authenticated: !!apiKey,
2357
2369
  freeTierCapReached: !!data.freeTierCapReached,
2358
2370
  scansUsed: data.scansUsed ?? 0,
2359
2371
  scansLimit: data.scansLimit ?? null,
2372
+ capReason,
2360
2373
  tier: data.tier,
2361
2374
  name: data.name,
2362
2375
  fetchedAt: Date.now()
2363
2376
  };
2364
2377
  writeCachedAuthStatus(status);
2365
2378
  if (status.freeTierCapReached) {
2366
- throw new PreflightFreeCapReachedError(status.scansUsed, status.scansLimit ?? 0);
2379
+ throw new PreflightFreeCapReachedError(status.scansUsed, status.scansLimit ?? 0, capReason);
2367
2380
  }
2368
2381
  return status;
2369
2382
  }
@@ -43388,6 +43401,153 @@ var init_pip_wrapper = __esm({
43388
43401
  }
43389
43402
  });
43390
43403
 
43404
+ // src/wrapper/route.ts
43405
+ function routeVerdict(input) {
43406
+ const { verdict, mode, strict, dgForce } = input;
43407
+ const refuseHard = mode === "block" || strict;
43408
+ const refuseWarn = strict;
43409
+ const D = (outcome, refuseExitCode, extra) => ({
43410
+ verdict,
43411
+ outcome,
43412
+ refuseExitCode,
43413
+ bypassed: false,
43414
+ ...extra
43415
+ });
43416
+ if (verdict === "free_cap") return D("refuse", 1);
43417
+ if (verdict === "pass") return D("install", 0);
43418
+ if (dgForce && (verdict === "warn" || verdict === "block")) {
43419
+ return D("install", 0, { audit: "override", bypassed: true });
43420
+ }
43421
+ switch (verdict) {
43422
+ case "warn":
43423
+ if (mode === "off") return D("install", 0);
43424
+ if (refuseWarn) return D("refuse", 1);
43425
+ return D("prompt", 1);
43426
+ // warn/block mode → prompt; decline → 1
43427
+ case "block":
43428
+ if (mode === "off") return D("install", 0);
43429
+ return D("refuse", 2, { audit: "block" });
43430
+ case "analysis_incomplete":
43431
+ if (dgForce) return D("install", 0, { bypassed: true });
43432
+ if (refuseHard) return D("refuse", 4);
43433
+ return D("install", 0);
43434
+ // off/warn → install with a "could not verify" notice
43435
+ case "scan_failed":
43436
+ case "tree_failed":
43437
+ if (dgForce) return D("install", 0, { bypassed: true });
43438
+ if (refuseHard) return D("refuse", 2);
43439
+ return D("install", 0);
43440
+ // best-effort under off/warn
43441
+ case "resolve_failed":
43442
+ if (dgForce) return D("passthrough", 0, { bypassed: true });
43443
+ if (refuseHard) return D("refuse", 2);
43444
+ return D("passthrough", 0);
43445
+ // nothing resolved to scan → hand off to the installer
43446
+ default: {
43447
+ const _never = verdict;
43448
+ void _never;
43449
+ return D(refuseHard ? "refuse" : "install", refuseHard ? 4 : 0);
43450
+ }
43451
+ }
43452
+ }
43453
+ var init_route = __esm({
43454
+ "src/wrapper/route.ts"() {
43455
+ "use strict";
43456
+ }
43457
+ });
43458
+
43459
+ // src/wrapper/run.ts
43460
+ function verdictFromResult(result, gates = {}) {
43461
+ if (gates.scanFailed) return "scan_failed";
43462
+ if (gates.treeFailed) return "tree_failed";
43463
+ if (gates.resolveFailed) return "resolve_failed";
43464
+ const action = result?.action;
43465
+ if (action === "pass" || action === "warn" || action === "block") return action;
43466
+ return "analysis_incomplete";
43467
+ }
43468
+ function scanVerdictOf(decision) {
43469
+ if (decision.bypassed && (decision.verdict === "warn" || decision.verdict === "block")) {
43470
+ return "override";
43471
+ }
43472
+ switch (decision.verdict) {
43473
+ case "pass":
43474
+ return "pass";
43475
+ case "warn":
43476
+ return "warn";
43477
+ case "block":
43478
+ return "block";
43479
+ case "analysis_incomplete":
43480
+ return "analysis_incomplete";
43481
+ case "scan_failed":
43482
+ case "tree_failed":
43483
+ case "resolve_failed":
43484
+ return "scan_failed";
43485
+ default:
43486
+ return "skipped";
43487
+ }
43488
+ }
43489
+ async function executeDecision(decision, ctx, presenter) {
43490
+ await presenter.announce(decision, ctx);
43491
+ if (decision.audit) {
43492
+ await presenter.audit(decision.audit, ctx);
43493
+ }
43494
+ const scanVerdict = scanVerdictOf(decision);
43495
+ const base = (installRan, installExitCode) => ({
43496
+ scanVerdict,
43497
+ installRan,
43498
+ installExitCode,
43499
+ error: ctx.error,
43500
+ suppressedByAllowlist: ctx.suppressedCount > 0 ? ctx.suppressedCount : void 0
43501
+ });
43502
+ switch (decision.outcome) {
43503
+ case "refuse":
43504
+ presenter.emit(base(false, null));
43505
+ return decision.refuseExitCode;
43506
+ case "install": {
43507
+ const code = await presenter.runInstall(ctx.installArgs);
43508
+ presenter.emit(base(true, code));
43509
+ return code;
43510
+ }
43511
+ case "passthrough": {
43512
+ const code = await presenter.runInstall(ctx.passthroughArgs);
43513
+ presenter.emit(base(true, code));
43514
+ return code;
43515
+ }
43516
+ case "prompt": {
43517
+ const proceed = await presenter.confirmProceed(ctx);
43518
+ if (!proceed) {
43519
+ presenter.emit(base(false, null));
43520
+ return decision.refuseExitCode;
43521
+ }
43522
+ if (presenter.onPromptAccepted) await presenter.onPromptAccepted(ctx);
43523
+ const code = await presenter.runInstall(ctx.installArgs);
43524
+ presenter.emit(base(true, code));
43525
+ return code;
43526
+ }
43527
+ default: {
43528
+ const _never = decision.outcome;
43529
+ void _never;
43530
+ return 1;
43531
+ }
43532
+ }
43533
+ }
43534
+ var init_run = __esm({
43535
+ "src/wrapper/run.ts"() {
43536
+ "use strict";
43537
+ }
43538
+ });
43539
+
43540
+ // src/wrapper/json.ts
43541
+ function emitWrapperJson(config, result) {
43542
+ if (!config.json) return;
43543
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
43544
+ }
43545
+ var init_json = __esm({
43546
+ "src/wrapper/json.ts"() {
43547
+ "use strict";
43548
+ }
43549
+ });
43550
+
43391
43551
  // src/security/artifact_integrity.ts
43392
43552
  function normalize(h, algo) {
43393
43553
  if (!h) return void 0;
@@ -44879,10 +45039,6 @@ function note(config, text) {
44879
45039
  if (config.quiet) return;
44880
45040
  process.stderr.write(text);
44881
45041
  }
44882
- function emitWrapperJson(config, result) {
44883
- if (!config.json) return;
44884
- process.stdout.write(JSON.stringify(result, null, 2) + "\n");
44885
- }
44886
45042
  function wrapperPackagesFromResult(result, topLevelNames) {
44887
45043
  return result.packages.map((p) => ({
44888
45044
  name: p.name,
@@ -45367,11 +45523,7 @@ async function runStatic(config) {
45367
45523
  printTrialBanner(result, config);
45368
45524
  process.exit(scanExitCode(result.action, config.mode));
45369
45525
  }
45370
- function mergeProjectConfig(config, _argv) {
45371
- return config;
45372
- }
45373
45526
  async function runStaticNpm(npmArgs, config) {
45374
- config = mergeProjectConfig(config, process.argv.slice(2));
45375
45527
  const parsed = parseNpmArgs(npmArgs);
45376
45528
  if (!parsed.shouldScan) {
45377
45529
  const code = await runNpm(parsed.rawArgs);
@@ -45623,156 +45775,110 @@ async function scanAndInstallStatic(resolved, parsed, config) {
45623
45775
  );
45624
45776
  }
45625
45777
  }
45626
- if (result.action === "pass") {
45627
- const topLevel = resolved.map((p) => `${p.name} ${p.version}`);
45628
- const passLine = topLevel.length === 1 ? ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel[0]} is safe` : ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel.length} packages safe`;
45629
- const installLine = topLevel.length === 1 ? ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel[0]}` : ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel.join(", ")}`;
45630
- process.stderr.write(`${passLine}
45778
+ const npmInstallArgs = buildInstallArgs(parsed, topLevelSpecs, tree.packages, config);
45779
+ const npmTopLevelNames = new Set(resolved.map((p) => p.name));
45780
+ const npmDecision = routeVerdict({
45781
+ verdict: verdictFromResult(result),
45782
+ mode: config.mode,
45783
+ strict: config.strict,
45784
+ dgForce: parsed.dgForce
45785
+ });
45786
+ const npmPresenter = {
45787
+ async announce(d) {
45788
+ if (d.verdict === "pass") {
45789
+ const topLevel2 = resolved.map((p) => `${p.name} ${p.version}`);
45790
+ const passLine = topLevel2.length === 1 ? ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel2[0]} is safe` : ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel2.length} packages safe`;
45791
+ const installLine = topLevel2.length === 1 ? ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel2[0]}` : ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel2.join(", ")}`;
45792
+ process.stderr.write(`${passLine}
45631
45793
  ${installLine}
45632
45794
  `);
45633
- if (parsed.dgNoScripts || config.strict) {
45634
- const why = config.strict ? "--strict" : "--dg-no-scripts";
45635
- process.stderr.write(import_chalk5.default.dim(` ${why}: lifecycle scripts will be suppressed during install.
45795
+ if (parsed.dgNoScripts || config.strict) {
45796
+ const why = config.strict ? "--strict" : "--dg-no-scripts";
45797
+ process.stderr.write(import_chalk5.default.dim(` ${why}: lifecycle scripts will be suppressed during install.
45636
45798
  `));
45637
- }
45638
- printTrialBanner(result, config);
45639
- process.stderr.write("\n");
45640
- const code = await runNpm(buildInstallArgs(parsed, topLevelSpecs, tree.packages, config), { stdoutToStderr: !!config.json });
45641
- emitWrapperJson(config, {
45642
- ecosystem: "npm",
45643
- packages: wrapperPackagesFromResult(result, new Set(resolved.map((p) => p.name))),
45644
- scanVerdict: "pass",
45645
- installRan: true,
45646
- installExitCode: code
45647
- });
45648
- process.exit(code);
45649
- }
45650
- const output = renderResultStatic(result, config);
45651
- (config.json ? process.stderr : process.stdout).write(output + "\n");
45652
- printTrialBanner(result, config);
45653
- if (result.action === "warn") {
45654
- const { promptYesNo: promptYesNo2 } = await Promise.resolve().then(() => (init_prompt(), prompt_exports));
45655
- const topLevel = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
45656
- process.stderr.write(
45657
- ` ${import_chalk5.default.yellow("\u26A0")} ${import_chalk5.default.bold("DG flagged")} ${topLevel}.
45658
- `
45659
- );
45660
- const proceed = await promptYesNo2({
45661
- defaultAnswer: "y",
45662
- message: ` Proceed?`
45663
- });
45664
- if (!proceed) {
45665
- process.stderr.write(import_chalk5.default.dim(" Install cancelled by user.\n\n"));
45666
- emitWrapperJson(config, {
45667
- ecosystem: "npm",
45668
- packages: wrapperPackagesFromResult(result, new Set(resolved.map((p) => p.name))),
45669
- scanVerdict: "warn",
45670
- installRan: false,
45671
- installExitCode: null
45672
- });
45673
- process.exit(1);
45674
- }
45675
- const code = await runNpm(buildInstallArgs(parsed, topLevelSpecs, tree.packages, config), { stdoutToStderr: !!config.json });
45676
- emitWrapperJson(config, {
45677
- ecosystem: "npm",
45678
- packages: wrapperPackagesFromResult(result, new Set(resolved.map((p) => p.name))),
45679
- scanVerdict: "warn",
45680
- installRan: true,
45681
- installExitCode: code
45682
- });
45683
- process.exit(code);
45684
- }
45685
- if (result.action === "block") {
45686
- if (parsed.dgForce) {
45687
- const { dispatchInstallAudit: dispatchInstallAudit3 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
45688
- await dispatchInstallAudit3({
45689
- ecosystem: "npm",
45690
- packages: result.packages,
45691
- decisionAction: "override",
45692
- bypassed: true,
45693
- bypassReason: parsed.dgForceReason
45694
- });
45695
- process.stderr.write(
45696
- import_chalk5.default.yellow(
45697
- import_chalk5.default.bold(
45698
- " --dg-force: Bypassing block. Install at your own risk.\n\n"
45699
- )
45700
- )
45701
- );
45702
- const code = await runNpm(buildInstallArgs(parsed, topLevelSpecs, tree.packages, config), { stdoutToStderr: !!config.json });
45703
- emitWrapperJson(config, {
45704
- ecosystem: "npm",
45705
- packages: wrapperPackagesFromResult(result, new Set(resolved.map((p) => p.name))),
45706
- scanVerdict: "override",
45707
- installRan: true,
45708
- installExitCode: code
45709
- });
45710
- process.exit(code);
45711
- }
45712
- const { dispatchInstallAudit: dispatchInstallAudit2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
45713
- await dispatchInstallAudit2({
45714
- ecosystem: "npm",
45715
- packages: result.packages,
45716
- decisionAction: "block",
45717
- bypassed: false
45718
- });
45719
- const topLevelBlocked = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
45720
- const blockedSpecArg = topLevelSpecs.length > 0 ? topLevelSpecs.join(" ") : topLevelBlocked.split(", ").map((s) => s.replace(/ /g, "@")).join(" ");
45721
- process.stderr.write(
45722
- ` ${import_chalk5.default.red("\u2717")} ${import_chalk5.default.bold("DG blocked")} ${topLevelBlocked}.
45799
+ }
45800
+ printTrialBanner(result, config);
45801
+ process.stderr.write("\n");
45802
+ return;
45803
+ }
45804
+ const output = renderResultStatic(result, config);
45805
+ (config.json ? process.stderr : process.stdout).write(output + "\n");
45806
+ printTrialBanner(result, config);
45807
+ const topLevel = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
45808
+ if (d.verdict === "warn") {
45809
+ process.stderr.write(` ${import_chalk5.default.yellow("\u26A0")} ${import_chalk5.default.bold("DG flagged")} ${topLevel}.
45810
+ `);
45811
+ } else if (d.verdict === "block") {
45812
+ if (d.outcome === "install") {
45813
+ process.stderr.write(import_chalk5.default.yellow(import_chalk5.default.bold(" --dg-force: Bypassing block. Install at your own risk.\n\n")));
45814
+ } else {
45815
+ const blockedSpecArg = topLevelSpecs.length > 0 ? topLevelSpecs.join(" ") : topLevel.split(", ").map((s) => s.replace(/ /g, "@")).join(" ");
45816
+ process.stderr.write(
45817
+ ` ${import_chalk5.default.red("\u2717")} ${import_chalk5.default.bold("DG blocked")} ${topLevel}.
45723
45818
  Real install was NOT run. To override:
45724
45819
  ` + import_chalk5.default.dim(` npm install ${blockedSpecArg} --dg-force --dg-force-reason="<reason>"
45725
45820
 
45726
45821
  `)
45727
- );
45728
- emitWrapperJson(config, {
45729
- ecosystem: "npm",
45730
- packages: wrapperPackagesFromResult(result, new Set(resolved.map((p) => p.name))),
45731
- scanVerdict: "block",
45732
- installRan: false,
45733
- installExitCode: null
45734
- });
45735
- process.exit(2);
45736
- }
45737
- if (result.action === "analysis_incomplete") {
45738
- const topLevel = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
45739
- const refuse = (config.mode === "block" || config.strict) && !parsed.dgForce;
45740
- if (refuse) {
45741
- const specArg = topLevelSpecs.length > 0 ? topLevelSpecs.join(" ") : resolved.map((p) => `${p.name}@${p.version}`).join(" ");
45742
- process.stderr.write(
45743
- ` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG could not verify")} ${topLevel} \u2014 treating as unverified, not safe.
45822
+ );
45823
+ }
45824
+ } else if (d.verdict === "analysis_incomplete") {
45825
+ if (d.outcome === "refuse") {
45826
+ const specArg = topLevelSpecs.length > 0 ? topLevelSpecs.join(" ") : resolved.map((p) => `${p.name}@${p.version}`).join(" ");
45827
+ process.stderr.write(
45828
+ ` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG could not verify")} ${topLevel} \u2014 treating as unverified, not safe.
45744
45829
  Real install was NOT run (--mode block). To override:
45745
45830
  ` + import_chalk5.default.dim(` npm install ${specArg} --dg-force --dg-force-reason="<reason>"
45746
45831
 
45747
45832
  `)
45748
- );
45833
+ );
45834
+ } else {
45835
+ process.stderr.write(import_chalk5.default.dim(` DG could not fully verify ${topLevel}; proceeding (mode is not block).
45836
+
45837
+ `));
45838
+ }
45839
+ }
45840
+ },
45841
+ async confirmProceed() {
45842
+ const { promptYesNo: promptYesNo2 } = await Promise.resolve().then(() => (init_prompt(), prompt_exports));
45843
+ const proceed = await promptYesNo2({ defaultAnswer: "y", message: ` Proceed?` });
45844
+ if (!proceed) process.stderr.write(import_chalk5.default.dim(" Install cancelled by user.\n\n"));
45845
+ return proceed;
45846
+ },
45847
+ runInstall: (args) => runNpm(args, { stdoutToStderr: !!config.json }),
45848
+ async audit(kind) {
45849
+ const { dispatchInstallAudit: dispatchInstallAudit2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
45850
+ await dispatchInstallAudit2({
45851
+ ecosystem: "npm",
45852
+ packages: result.packages,
45853
+ decisionAction: kind,
45854
+ bypassed: kind === "override",
45855
+ bypassReason: kind === "override" ? parsed.dgForceReason : void 0
45856
+ });
45857
+ },
45858
+ emit(record) {
45749
45859
  emitWrapperJson(config, {
45750
45860
  ecosystem: "npm",
45751
- packages: wrapperPackagesFromResult(result, new Set(resolved.map((p) => p.name))),
45752
- scanVerdict: "analysis_incomplete",
45753
- installRan: false,
45754
- installExitCode: null
45861
+ packages: wrapperPackagesFromResult(result, npmTopLevelNames),
45862
+ scanVerdict: record.scanVerdict,
45863
+ installRan: record.installRan,
45864
+ installExitCode: record.installExitCode,
45865
+ error: record.error
45755
45866
  });
45756
- process.exit(4);
45757
45867
  }
45758
- process.stderr.write(
45759
- import_chalk5.default.dim(` DG could not fully verify ${topLevel}; proceeding (mode is not block).
45760
-
45761
- `)
45762
- );
45763
- const code = await runNpm(buildInstallArgs(parsed, topLevelSpecs, tree.packages, config), { stdoutToStderr: !!config.json });
45764
- emitWrapperJson(config, {
45765
- ecosystem: "npm",
45766
- packages: wrapperPackagesFromResult(result, new Set(resolved.map((p) => p.name))),
45767
- scanVerdict: "analysis_incomplete",
45768
- installRan: true,
45769
- installExitCode: code
45770
- });
45771
- process.exit(code);
45772
- }
45868
+ };
45869
+ const npmCtx = {
45870
+ ecosystem: "npm",
45871
+ apiKind: "npm",
45872
+ installArgs: npmInstallArgs,
45873
+ passthroughArgs: parsed.rawArgs,
45874
+ result,
45875
+ resolved,
45876
+ suppressedCount: 0,
45877
+ dgForceReason: parsed.dgForceReason
45878
+ };
45879
+ process.exit(await executeDecision(npmDecision, npmCtx, npmPresenter));
45773
45880
  }
45774
45881
  async function runStaticPip(pipArgs, config) {
45775
- config = mergeProjectConfig(config, process.argv.slice(2));
45776
45882
  const parsed = parsePipArgs(pipArgs);
45777
45883
  if (!parsed.shouldScan) {
45778
45884
  const code = await runPip(parsed.rawArgs, { stdoutToStderr: !!config.json });
@@ -45933,141 +46039,101 @@ async function runStaticPip(pipArgs, config) {
45933
46039
  }
45934
46040
  }
45935
46041
  const pipTopLevelNames = new Set(resolved.map((p) => p.name));
45936
- if (result.action === "pass") {
45937
- const topLevel = resolved.map((p) => `${p.name} ${p.version}`);
45938
- const passLine = topLevel.length === 1 ? ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel[0]} is safe` : ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel.length} packages safe`;
45939
- const installLine = topLevel.length === 1 ? ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel[0]}` : ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel.join(", ")}`;
45940
- process.stderr.write(`${passLine}
46042
+ const pipDecision = routeVerdict({
46043
+ verdict: verdictFromResult(result),
46044
+ mode: config.mode,
46045
+ strict: config.strict,
46046
+ dgForce: parsed.dgForce
46047
+ });
46048
+ const pipPresenter = {
46049
+ async announce(d) {
46050
+ if (d.verdict === "pass") {
46051
+ const topLevel2 = resolved.map((p) => `${p.name} ${p.version}`);
46052
+ const passLine = topLevel2.length === 1 ? ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel2[0]} is safe` : ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.bold("DG verified:")} ${topLevel2.length} packages safe`;
46053
+ const installLine = topLevel2.length === 1 ? ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel2[0]}` : ` ${import_chalk5.default.green("\u2713")} Installing ${topLevel2.join(", ")}`;
46054
+ process.stderr.write(`${passLine}
45941
46055
  ${installLine}
45942
46056
  `);
45943
- printTrialBanner(result, config);
45944
- process.stderr.write("\n");
45945
- const code = await runPip(pipInstallArgs, { stdoutToStderr: !!config.json });
45946
- emitWrapperJson(config, {
45947
- ecosystem: "pypi",
45948
- packages: wrapperPackagesFromResult(result, pipTopLevelNames),
45949
- scanVerdict: "pass",
45950
- installRan: true,
45951
- installExitCode: code
45952
- });
45953
- process.exit(code);
45954
- }
45955
- const output = renderResultStatic(result, config);
45956
- (config.json ? process.stderr : process.stdout).write(output + "\n");
45957
- printTrialBanner(result, config);
45958
- if (result.action === "warn") {
45959
- const { promptYesNo: promptYesNo2 } = await Promise.resolve().then(() => (init_prompt(), prompt_exports));
45960
- const topLevel = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
45961
- process.stderr.write(
45962
- ` ${import_chalk5.default.yellow("\u26A0")} ${import_chalk5.default.bold("DG flagged")} ${topLevel}.
45963
- `
45964
- );
45965
- const proceed = await promptYesNo2({ defaultAnswer: "y", message: " Proceed?" });
45966
- if (!proceed) {
45967
- process.stderr.write(import_chalk5.default.dim(" Install cancelled by user.\n\n"));
45968
- emitWrapperJson(config, {
45969
- ecosystem: "pypi",
45970
- packages: wrapperPackagesFromResult(result, pipTopLevelNames),
45971
- scanVerdict: "warn",
45972
- installRan: false,
45973
- installExitCode: null
45974
- });
45975
- process.exit(1);
45976
- }
45977
- const code = await runPip(pipInstallArgs, { stdoutToStderr: !!config.json });
45978
- emitWrapperJson(config, {
45979
- ecosystem: "pypi",
45980
- packages: wrapperPackagesFromResult(result, pipTopLevelNames),
45981
- scanVerdict: "warn",
45982
- installRan: true,
45983
- installExitCode: code
45984
- });
45985
- process.exit(code);
45986
- }
45987
- if (result.action === "block") {
45988
- if (parsed.dgForce) {
45989
- const { dispatchInstallAudit: dispatchInstallAudit3 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
45990
- await dispatchInstallAudit3({
45991
- ecosystem: "pypi",
45992
- packages: result.packages,
45993
- decisionAction: "override",
45994
- bypassed: true,
45995
- bypassReason: parsed.dgForceReason
45996
- });
45997
- process.stderr.write(
45998
- import_chalk5.default.yellow(import_chalk5.default.bold(" --dg-force: Bypassing block. Install at your own risk.\n\n"))
45999
- );
46000
- const code = await runPip(pipInstallArgs, { stdoutToStderr: !!config.json });
46001
- emitWrapperJson(config, {
46002
- ecosystem: "pypi",
46003
- packages: wrapperPackagesFromResult(result, pipTopLevelNames),
46004
- scanVerdict: "override",
46005
- installRan: true,
46006
- installExitCode: code
46007
- });
46008
- process.exit(code);
46009
- }
46010
- const { dispatchInstallAudit: dispatchInstallAudit2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
46011
- await dispatchInstallAudit2({
46012
- ecosystem: "pypi",
46013
- packages: result.packages,
46014
- decisionAction: "block",
46015
- bypassed: false
46016
- });
46017
- const pipTopLevelBlocked = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
46018
- const pipBlockedSpecArg = resolved.map((p) => `${p.name}==${p.version}`).join(" ");
46019
- process.stderr.write(
46020
- ` ${import_chalk5.default.red("\u2717")} ${import_chalk5.default.bold("DG blocked")} ${pipTopLevelBlocked}.
46057
+ printTrialBanner(result, config);
46058
+ process.stderr.write("\n");
46059
+ return;
46060
+ }
46061
+ const output = renderResultStatic(result, config);
46062
+ (config.json ? process.stderr : process.stdout).write(output + "\n");
46063
+ printTrialBanner(result, config);
46064
+ const topLevel = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
46065
+ if (d.verdict === "warn") {
46066
+ process.stderr.write(` ${import_chalk5.default.yellow("\u26A0")} ${import_chalk5.default.bold("DG flagged")} ${topLevel}.
46067
+ `);
46068
+ } else if (d.verdict === "block") {
46069
+ if (d.outcome === "install") {
46070
+ process.stderr.write(import_chalk5.default.yellow(import_chalk5.default.bold(" --dg-force: Bypassing block. Install at your own risk.\n\n")));
46071
+ } else {
46072
+ const pipBlockedSpecArg = resolved.map((p) => `${p.name}==${p.version}`).join(" ");
46073
+ process.stderr.write(
46074
+ ` ${import_chalk5.default.red("\u2717")} ${import_chalk5.default.bold("DG blocked")} ${topLevel}.
46021
46075
  Real install was NOT run. To override:
46022
46076
  ` + import_chalk5.default.dim(` pip install ${pipBlockedSpecArg} --dg-force --dg-force-reason="<reason>"
46023
46077
 
46024
46078
  `)
46025
- );
46026
- emitWrapperJson(config, {
46027
- ecosystem: "pypi",
46028
- packages: wrapperPackagesFromResult(result, pipTopLevelNames),
46029
- scanVerdict: "block",
46030
- installRan: false,
46031
- installExitCode: null
46032
- });
46033
- process.exit(2);
46034
- }
46035
- if (result.action === "analysis_incomplete") {
46036
- const pipTopLevel = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
46037
- const refuse = (config.mode === "block" || config.strict) && !parsed.dgForce;
46038
- if (refuse) {
46039
- const pipSpecArg = resolved.map((p) => `${p.name}==${p.version}`).join(" ");
46040
- process.stderr.write(
46041
- ` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG could not verify")} ${pipTopLevel} \u2014 treating as unverified, not safe.
46079
+ );
46080
+ }
46081
+ } else if (d.verdict === "analysis_incomplete") {
46082
+ if (d.outcome === "refuse") {
46083
+ const pipSpecArg = resolved.map((p) => `${p.name}==${p.version}`).join(" ");
46084
+ process.stderr.write(
46085
+ ` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG could not verify")} ${topLevel} \u2014 treating as unverified, not safe.
46042
46086
  Real install was NOT run (--mode block). To override:
46043
46087
  ` + import_chalk5.default.dim(` pip install ${pipSpecArg} --dg-force --dg-force-reason="<reason>"
46044
46088
 
46045
46089
  `)
46046
- );
46090
+ );
46091
+ } else {
46092
+ process.stderr.write(import_chalk5.default.dim(` DG could not fully verify ${topLevel}; proceeding (mode is not block).
46093
+
46094
+ `));
46095
+ }
46096
+ }
46097
+ },
46098
+ async confirmProceed() {
46099
+ const { promptYesNo: promptYesNo2 } = await Promise.resolve().then(() => (init_prompt(), prompt_exports));
46100
+ const proceed = await promptYesNo2({ defaultAnswer: "y", message: " Proceed?" });
46101
+ if (!proceed) process.stderr.write(import_chalk5.default.dim(" Install cancelled by user.\n\n"));
46102
+ return proceed;
46103
+ },
46104
+ runInstall: (args) => runPip(args, { stdoutToStderr: !!config.json }),
46105
+ async audit(kind) {
46106
+ const { dispatchInstallAudit: dispatchInstallAudit2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
46107
+ await dispatchInstallAudit2({
46108
+ ecosystem: "pypi",
46109
+ packages: result.packages,
46110
+ decisionAction: kind,
46111
+ bypassed: kind === "override",
46112
+ bypassReason: kind === "override" ? parsed.dgForceReason : void 0
46113
+ });
46114
+ },
46115
+ emit(record) {
46047
46116
  emitWrapperJson(config, {
46048
46117
  ecosystem: "pypi",
46049
46118
  packages: wrapperPackagesFromResult(result, pipTopLevelNames),
46050
- scanVerdict: "analysis_incomplete",
46051
- installRan: false,
46052
- installExitCode: null
46119
+ scanVerdict: record.scanVerdict,
46120
+ installRan: record.installRan,
46121
+ installExitCode: record.installExitCode,
46122
+ error: record.error
46053
46123
  });
46054
- process.exit(4);
46055
46124
  }
46056
- process.stderr.write(
46057
- import_chalk5.default.dim(` DG could not fully verify ${pipTopLevel}; proceeding (mode is not block).
46058
-
46059
- `)
46060
- );
46061
- const code = await runPip(pipInstallArgs, { stdoutToStderr: !!config.json });
46062
- emitWrapperJson(config, {
46063
- ecosystem: "pypi",
46064
- packages: wrapperPackagesFromResult(result, pipTopLevelNames),
46065
- scanVerdict: "analysis_incomplete",
46066
- installRan: true,
46067
- installExitCode: code
46068
- });
46069
- process.exit(code);
46070
- }
46125
+ };
46126
+ const pipCtx = {
46127
+ ecosystem: "pypi",
46128
+ apiKind: "pypi",
46129
+ installArgs: pipInstallArgs,
46130
+ passthroughArgs: parsed.rawArgs,
46131
+ result,
46132
+ resolved,
46133
+ suppressedCount: 0,
46134
+ dgForceReason: parsed.dgForceReason
46135
+ };
46136
+ process.exit(await executeDecision(pipDecision, pipCtx, pipPresenter));
46071
46137
  }
46072
46138
  async function runStaticLogin() {
46073
46139
  const {
@@ -46181,6 +46247,9 @@ var init_static_output = __esm({
46181
46247
  init_npm_wrapper();
46182
46248
  init_pip_wrapper();
46183
46249
  init_wrapper_shared();
46250
+ init_route();
46251
+ init_run();
46252
+ init_json();
46184
46253
  init_artifact_integrity();
46185
46254
  init_sanitize();
46186
46255
  init_format_helpers();
@@ -50847,6 +50916,11 @@ async function runNpmScan(packages, skippedCount, config, dispatch) {
50847
50916
  dispatch({ type: "SCAN_COMPLETE", result, durationMs: Date.now() - startMs, skippedCount });
50848
50917
  } catch (error) {
50849
50918
  if (error instanceof FreeCapReachedError) {
50919
+ try {
50920
+ const { recordScanCapReached: recordScanCapReached2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
50921
+ recordScanCapReached2(error.scansUsed, error.maxScans, error.reason);
50922
+ } catch {
50923
+ }
50850
50924
  dispatch({ type: "FREE_CAP_REACHED", scansUsed: error.scansUsed, maxScans: error.maxScans, capReason: error.reason });
50851
50925
  return;
50852
50926
  }
@@ -50926,6 +51000,11 @@ async function scanProjects(projects, config, dispatch) {
50926
51000
  dispatch({ type: "SCAN_COMPLETE", result: merged, durationMs: merged.durationMs, skippedCount: 0, discoveredTotal });
50927
51001
  } catch (error) {
50928
51002
  if (error instanceof FreeCapReachedError) {
51003
+ try {
51004
+ const { recordScanCapReached: recordScanCapReached2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
51005
+ recordScanCapReached2(error.scansUsed, error.maxScans, error.reason);
51006
+ } catch {
51007
+ }
50929
51008
  dispatch({ type: "FREE_CAP_REACHED", scansUsed: error.scansUsed, maxScans: error.maxScans, capReason: error.reason });
50930
51009
  return;
50931
51010
  }
@@ -51740,6 +51819,8 @@ function reducer4(_state, action) {
51740
51819
  return { phase: "blocked", result: action.result, dgForce: action.dgForce };
51741
51820
  case "INCOMPLETE":
51742
51821
  return { phase: "incomplete", result: action.result, message: action.message, proceed: action.proceed };
51822
+ case "REFUSED":
51823
+ return { phase: "refused", result: action.result, message: action.message };
51743
51824
  case "INSTALLING":
51744
51825
  return { phase: "installing" };
51745
51826
  case "DONE":
@@ -51779,8 +51860,8 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
51779
51860
  try {
51780
51861
  if (!parsed.shouldScan) {
51781
51862
  dispatch({ type: "PASSTHROUGH" });
51782
- const code = await opts.runInstall(parsed.rawArgs);
51783
- dispatch({ type: "DONE", exitCode: code });
51863
+ const code2 = await opts.runInstall(parsed.rawArgs);
51864
+ dispatch({ type: "DONE", exitCode: code2 });
51784
51865
  return;
51785
51866
  }
51786
51867
  let specs;
@@ -51788,8 +51869,8 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
51788
51869
  specs = opts.inferSpecsFromContext(parsed);
51789
51870
  if (specs.length === 0) {
51790
51871
  dispatch({ type: "PASSTHROUGH" });
51791
- const code = await opts.runInstall(parsed.rawArgs);
51792
- dispatch({ type: "DONE", exitCode: code });
51872
+ const code2 = await opts.runInstall(parsed.rawArgs);
51873
+ dispatch({ type: "DONE", exitCode: code2 });
51793
51874
  return;
51794
51875
  }
51795
51876
  } else {
@@ -51799,8 +51880,8 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
51799
51880
  const { resolved } = await opts.resolvePackages(specs);
51800
51881
  if (resolved.length === 0) {
51801
51882
  dispatch({ type: "PASSTHROUGH" });
51802
- const code = await opts.runInstall(parsed.rawArgs);
51803
- dispatch({ type: "DONE", exitCode: code });
51883
+ const code2 = await opts.runInstall(parsed.rawArgs);
51884
+ dispatch({ type: "DONE", exitCode: code2 });
51804
51885
  return;
51805
51886
  }
51806
51887
  const isRequirementsInstall = opts.ecosystem === "pypi" && (parsed.rawArgs.includes("-r") || parsed.rawArgs.includes("--requirement"));
@@ -51841,103 +51922,88 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
51841
51922
  const chalk18 = (await Promise.resolve().then(() => __toESM(require_source(), 1))).default;
51842
51923
  const line = formatPassLine(result, chalk18);
51843
51924
  process.stderr.write(" " + line + "\n\n");
51844
- const code = await opts.runInstall(installArgs);
51845
- process.exit(code);
51925
+ const code2 = await opts.runInstall(installArgs);
51926
+ process.exit(code2);
51846
51927
  return;
51847
51928
  }
51848
- if (result.action === "warn") {
51849
- if (parsed.dgForce) {
51850
- const { recordBypassLocally: recordBypassLocally2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
51851
- recordBypassLocally2({
51852
- ecosystem: opts.ecosystem,
51853
- verdict: "warn",
51854
- trigger: "dg-force",
51855
- reason: parsed.dgForceReason,
51856
- packages: result.packages.map((p) => ({ name: p.name, version: p.version, score: p.score }))
51857
- });
51858
- dispatch({ type: "WARN", result, dgForce: true });
51859
- dispatch({ type: "INSTALLING" });
51860
- const code = await opts.runInstall(installArgs);
51861
- dispatch({ type: "DONE", exitCode: code });
51862
- return;
51863
- }
51864
- dispatch({ type: "WARN", result, dgForce: false });
51865
- const shouldProceed = await new Promise((resolve3) => {
51866
- pendingInstall.current = () => resolve3(true);
51867
- rejectRef.current = () => resolve3(false);
51929
+ const verdict = verdictFromResult(result);
51930
+ const decision = routeVerdict({
51931
+ verdict,
51932
+ mode: config.mode,
51933
+ strict: config.strict,
51934
+ dgForce: parsed.dgForce
51935
+ });
51936
+ const bypassVerdict = decision.verdict === "block" ? "block" : "warn";
51937
+ const recordBypass = async (trigger) => {
51938
+ const { recordBypassLocally: recordBypassLocally2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
51939
+ recordBypassLocally2({
51940
+ ecosystem: opts.ecosystem,
51941
+ verdict: bypassVerdict,
51942
+ trigger,
51943
+ reason: trigger === "dg-force" ? parsed.dgForceReason : void 0,
51944
+ packages: result.packages.map((p) => ({ name: p.name, version: p.version, score: p.score }))
51868
51945
  });
51869
- if (shouldProceed) {
51870
- const { recordBypassLocally: recordBypassLocally2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
51871
- recordBypassLocally2({
51872
- ecosystem: opts.ecosystem,
51873
- verdict: "warn",
51874
- trigger: "interactive-confirm",
51875
- packages: result.packages.map((p) => ({ name: p.name, version: p.version, score: p.score }))
51876
- });
51877
- dispatch({ type: "INSTALLING" });
51878
- const code = await opts.runInstall(installArgs);
51879
- dispatch({ type: "DONE", exitCode: code });
51880
- } else {
51881
- dispatch({ type: "DONE", exitCode: 1 });
51946
+ };
51947
+ const refusedMessage = () => {
51948
+ const list = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
51949
+ if (decision.verdict === "block") {
51950
+ return `DG blocked ${list}. Real install was NOT run. Re-run with --dg-force --dg-force-reason="<reason>" to override.`;
51882
51951
  }
51883
- return;
51884
- }
51885
- if (result.action === "block") {
51886
- if (parsed.dgForce) {
51887
- const { recordBypassLocally: recordBypassLocally2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
51888
- recordBypassLocally2({
51889
- ecosystem: opts.ecosystem,
51890
- verdict: "block",
51891
- trigger: "dg-force",
51892
- reason: parsed.dgForceReason,
51893
- packages: result.packages.map((p) => ({ name: p.name, version: p.version, score: p.score }))
51894
- });
51895
- dispatch({ type: "BLOCKED", result, dgForce: true });
51896
- dispatch({ type: "INSTALLING" });
51897
- const code = await opts.runInstall(installArgs);
51898
- dispatch({ type: "DONE", exitCode: code });
51899
- return;
51952
+ if (decision.verdict === "analysis_incomplete") {
51953
+ return `DG could not fully analyze ${list} (analysis incomplete). Refusing in ${config.strict ? "--strict" : "--mode block"} \u2014 unverified is not safe. Use --mode warn or --dg-force to bypass.`;
51900
51954
  }
51901
- dispatch({ type: "BLOCKED", result, dgForce: false });
51902
- const shouldProceed = await new Promise((resolve3) => {
51903
- pendingInstall.current = () => resolve3(true);
51904
- rejectRef.current = () => resolve3(false);
51905
- });
51906
- if (shouldProceed) {
51907
- const { recordBypassLocally: recordBypassLocally2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
51908
- recordBypassLocally2({
51909
- ecosystem: opts.ecosystem,
51910
- verdict: "block",
51911
- trigger: "interactive-confirm",
51912
- packages: result.packages.map((p) => ({ name: p.name, version: p.version, score: p.score }))
51955
+ return `DG flagged ${list}. Refusing in --strict. Use --mode warn or --dg-force to proceed.`;
51956
+ };
51957
+ const presenter = {
51958
+ announce(d) {
51959
+ if (d.outcome === "refuse") {
51960
+ dispatch({ type: "REFUSED", result, message: refusedMessage() });
51961
+ return;
51962
+ }
51963
+ switch (d.verdict) {
51964
+ case "warn":
51965
+ dispatch({ type: "WARN", result, dgForce: d.bypassed });
51966
+ return;
51967
+ case "block":
51968
+ dispatch({ type: "BLOCKED", result, dgForce: d.bypassed });
51969
+ return;
51970
+ case "analysis_incomplete":
51971
+ dispatch({ type: "INCOMPLETE", result, proceed: true, message: "DG could not fully analyze the install set (analysis incomplete)." });
51972
+ return;
51973
+ default:
51974
+ return;
51975
+ }
51976
+ },
51977
+ confirmProceed() {
51978
+ return new Promise((resolve3) => {
51979
+ pendingInstall.current = () => resolve3(true);
51980
+ rejectRef.current = () => resolve3(false);
51913
51981
  });
51982
+ },
51983
+ async runInstall(args) {
51914
51984
  dispatch({ type: "INSTALLING" });
51915
- const code = await opts.runInstall(installArgs);
51916
- dispatch({ type: "DONE", exitCode: code });
51917
- } else {
51918
- dispatch({ type: "DONE", exitCode: 2 });
51919
- }
51920
- return;
51921
- }
51922
- {
51923
- const refuseHard = config.mode === "block" || config.strict;
51924
- const baseMsg = "DG could not fully analyze the install set (analysis incomplete).";
51925
- if (refuseHard && !parsed.dgForce) {
51926
- dispatch({
51927
- type: "INCOMPLETE",
51928
- result,
51929
- proceed: false,
51930
- message: `${baseMsg} Refusing install in ${config.strict ? "--strict" : "--mode block"} \u2014 unverified is not safe. Use --mode warn or --dg-force to bypass.`
51931
- });
51932
- dispatch({ type: "DONE", exitCode: 4 });
51933
- return;
51985
+ return opts.runInstall(args);
51986
+ },
51987
+ async audit(kind) {
51988
+ if (kind === "override") await recordBypass("dg-force");
51989
+ },
51990
+ onPromptAccepted: () => recordBypass("interactive-confirm"),
51991
+ emit() {
51934
51992
  }
51935
- dispatch({ type: "INCOMPLETE", result, proceed: true, message: baseMsg });
51936
- dispatch({ type: "INSTALLING" });
51937
- const code = await opts.runInstall(installArgs);
51938
- dispatch({ type: "DONE", exitCode: code });
51939
- return;
51940
- }
51993
+ };
51994
+ const ctx = {
51995
+ ecosystem: opts.ecosystem,
51996
+ apiKind: opts.ecosystem,
51997
+ installArgs,
51998
+ passthroughArgs: parsed.rawArgs,
51999
+ result,
52000
+ resolved,
52001
+ suppressedCount: 0,
52002
+ dgForceReason: parsed.dgForceReason
52003
+ };
52004
+ const code = await executeDecision(decision, ctx, presenter);
52005
+ dispatch({ type: "DONE", exitCode: code });
52006
+ return;
51941
52007
  } catch (error) {
51942
52008
  if (error instanceof FreeCapReachedError) {
51943
52009
  dispatch({ type: "FREE_CAP_REACHED" });
@@ -51979,6 +52045,8 @@ var init_useWrapperBase = __esm({
51979
52045
  import_react37 = __toESM(require_react(), 1);
51980
52046
  init_client();
51981
52047
  init_wrapper_shared();
52048
+ init_route();
52049
+ init_run();
51982
52050
  init_npm_wrapper();
51983
52051
  init_pip_wrapper();
51984
52052
  NPM_OPTIONS = {
@@ -52388,9 +52456,10 @@ var init_WrapperApp = __esm({
52388
52456
  case "blocked":
52389
52457
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Box_default, { flexDirection: "column", children: [
52390
52458
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(WrapperVerdictLine, { result: state.result, verdict: "block", dgForce: state.dgForce }),
52391
- showDetails && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ResultsView, { result: state.result, config, durationMs: state.result.durationMs }) }),
52392
- !state.dgForce && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ConfirmPrompt, { message: "", onConfirm: handleConfirm, onReject: handleReject })
52459
+ showDetails && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ResultsView, { result: state.result, config, durationMs: state.result.durationMs }) })
52393
52460
  ] });
52461
+ case "refused":
52462
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ErrorView, { error: new Error(state.message) });
52394
52463
  case "incomplete":
52395
52464
  if (state.proceed) {
52396
52465
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Text, { color: "yellow", children: [
@@ -52915,7 +52984,6 @@ async function resolveTopLevel5(parsed) {
52915
52984
  if (at <= 0) return s;
52916
52985
  return `${s.slice(0, at)}==${s.slice(at + 1)}`;
52917
52986
  });
52918
- void parsePipSpec;
52919
52987
  return await resolvePackages2(normalized);
52920
52988
  }
52921
52989
  async function resolveTransitive4(parsed) {
@@ -53044,10 +53112,6 @@ __export(wrapper_factory_exports, {
53044
53112
  runEcosystemWrapper: () => runEcosystemWrapper
53045
53113
  });
53046
53114
  import { spawn as spawn6 } from "node:child_process";
53047
- function emitJson(config, result) {
53048
- if (!config.json) return;
53049
- process.stdout.write(JSON.stringify(result, null, 2) + "\n");
53050
- }
53051
53115
  function shimSentinelEnv3() {
53052
53116
  return childInstallEnv();
53053
53117
  }
@@ -53110,7 +53174,7 @@ async function runEcosystemWrapper(adapter7, args, config) {
53110
53174
  `)
53111
53175
  );
53112
53176
  }
53113
- emitJson(config, {
53177
+ emitWrapperJson(config, {
53114
53178
  ecosystem: adapter7.ecosystem,
53115
53179
  packages: [],
53116
53180
  scanVerdict: "scan_failed",
@@ -53167,7 +53231,7 @@ async function runEcosystemWrapper(adapter7, args, config) {
53167
53231
  `)
53168
53232
  );
53169
53233
  }
53170
- emitJson(config, {
53234
+ emitWrapperJson(config, {
53171
53235
  ecosystem: adapter7.ecosystem,
53172
53236
  packages: [],
53173
53237
  scanVerdict: "scan_failed",
@@ -53198,7 +53262,7 @@ async function runEcosystemWrapper(adapter7, args, config) {
53198
53262
 
53199
53263
  `)
53200
53264
  );
53201
- emitJson(config, {
53265
+ emitWrapperJson(config, {
53202
53266
  ecosystem: adapter7.ecosystem,
53203
53267
  packages: [],
53204
53268
  scanVerdict: "scan_failed",
@@ -53215,7 +53279,7 @@ async function runEcosystemWrapper(adapter7, args, config) {
53215
53279
 
53216
53280
  `)
53217
53281
  );
53218
- emitJson(config, {
53282
+ emitWrapperJson(config, {
53219
53283
  ecosystem: adapter7.ecosystem,
53220
53284
  packages: [],
53221
53285
  scanVerdict: "scan_failed",
@@ -53231,184 +53295,155 @@ async function runEcosystemWrapper(adapter7, args, config) {
53231
53295
  `)
53232
53296
  );
53233
53297
  }
53234
- const code2 = await spawnRealBinary(adapter7, installArgs);
53235
- emitJson(config, {
53298
+ const code = await spawnRealBinary(adapter7, installArgs);
53299
+ emitWrapperJson(config, {
53236
53300
  ecosystem: adapter7.ecosystem,
53237
53301
  packages: [],
53238
53302
  scanVerdict: "scan_failed",
53239
53303
  installRan: true,
53240
- installExitCode: code2,
53304
+ installExitCode: code,
53241
53305
  error: { code: "scan_failed", message: err.message }
53242
53306
  });
53243
- return code2;
53307
+ return code;
53244
53308
  }
53245
53309
  const allowlist = loadAllowlist(process.cwd());
53246
53310
  const { result: filteredResult, suppressedCount } = applyAllowlist(allowlist, result, adapter7.apiKind);
53247
53311
  result = filteredResult;
53248
53312
  const topLevelNames = new Set(resolved.map((p) => p.name));
53249
- if (result.action === "pass") {
53250
- const topLevel = resolved.map((p) => `${p.name} ${p.version}`);
53251
- const passLine = topLevel.length === 1 ? ` ${import_chalk19.default.green("\u2713")} ${import_chalk19.default.bold("DG verified:")} ${topLevel[0]} is safe` : ` ${import_chalk19.default.green("\u2713")} ${import_chalk19.default.bold("DG verified:")} ${topLevel.length} packages safe`;
53252
- const installLine = topLevel.length === 1 ? ` ${import_chalk19.default.green("\u2713")} Installing ${topLevel[0]}` : ` ${import_chalk19.default.green("\u2713")} Installing ${topLevel.join(", ")}`;
53253
- if (!config.json && !config.quiet) {
53254
- process.stderr.write(`${passLine}
53313
+ const verdict = verdictFromResult(result);
53314
+ const decision = routeVerdict({
53315
+ verdict,
53316
+ mode: config.mode,
53317
+ strict: config.strict,
53318
+ dgForce: parsed.dgForce
53319
+ });
53320
+ const ctx = {
53321
+ ecosystem: adapter7.ecosystem,
53322
+ apiKind: adapter7.apiKind,
53323
+ installArgs,
53324
+ passthroughArgs: parsed.rawArgs,
53325
+ result,
53326
+ resolved,
53327
+ suppressedCount,
53328
+ dgForceReason: parsed.dgForceReason,
53329
+ error: verdict === "analysis_incomplete" && decision.outcome === "refuse" ? { code: "analysis_incomplete", message: "scanner could not fully analyze the install set" } : void 0
53330
+ };
53331
+ const presenter = {
53332
+ announce(d) {
53333
+ switch (d.verdict) {
53334
+ case "pass": {
53335
+ if (config.json || config.quiet) return;
53336
+ const topLevel = resolved.map((p) => `${p.name} ${p.version}`);
53337
+ const passLine = topLevel.length === 1 ? ` ${import_chalk19.default.green("\u2713")} ${import_chalk19.default.bold("DG verified:")} ${topLevel[0]} is safe` : ` ${import_chalk19.default.green("\u2713")} ${import_chalk19.default.bold("DG verified:")} ${topLevel.length} packages safe`;
53338
+ const installLine = topLevel.length === 1 ? ` ${import_chalk19.default.green("\u2713")} Installing ${topLevel[0]}` : ` ${import_chalk19.default.green("\u2713")} Installing ${topLevel.join(", ")}`;
53339
+ process.stderr.write(`${passLine}
53255
53340
  ${installLine}
53256
53341
  `);
53257
- if (suppressedCount > 0) {
53258
- process.stderr.write(import_chalk19.default.dim(` (${suppressedCount} finding${suppressedCount === 1 ? "" : "s"} suppressed by .dg-allowlist.json)
53342
+ if (suppressedCount > 0) {
53343
+ process.stderr.write(import_chalk19.default.dim(` (${suppressedCount} finding${suppressedCount === 1 ? "" : "s"} suppressed by .dg-allowlist.json)
53259
53344
  `));
53260
- }
53261
- process.stderr.write("\n");
53262
- }
53263
- const code2 = await spawnRealBinary(adapter7, installArgs);
53264
- emitJson(config, {
53265
- ecosystem: adapter7.ecosystem,
53266
- packages: packagesFromResult(result, topLevelNames),
53267
- scanVerdict: "pass",
53268
- installRan: true,
53269
- installExitCode: code2,
53270
- suppressedByAllowlist: suppressedCount > 0 ? suppressedCount : void 0
53271
- });
53272
- return code2;
53273
- }
53274
- if (result.action === "warn") {
53275
- if (!config.json && !config.quiet) {
53276
- const topLevelList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
53277
- process.stderr.write(` ${import_chalk19.default.yellow("\u26A0")} ${import_chalk19.default.bold("DG flagged")} ${topLevelList}.
53345
+ }
53346
+ process.stderr.write("\n");
53347
+ return;
53348
+ }
53349
+ case "warn": {
53350
+ if (config.json || config.quiet) return;
53351
+ const topLevelList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
53352
+ process.stderr.write(` ${import_chalk19.default.yellow("\u26A0")} ${import_chalk19.default.bold("DG flagged")} ${topLevelList}.
53278
53353
  `);
53279
- const blockedPkgs = result.packages.filter((p) => derivePackageActionPublic(p) === "warn");
53280
- for (const p of blockedPkgs.slice(0, 5)) {
53281
- if (p.findings && p.findings.length > 0) {
53282
- for (const f of p.findings.slice(0, 3)) {
53283
- process.stderr.write(import_chalk19.default.dim(` \u2022 ${f.title ?? "finding"}
53354
+ const flaggedPkgs = result.packages.filter((p) => derivePackageActionPublic(p) === "warn");
53355
+ for (const p of flaggedPkgs.slice(0, 5)) {
53356
+ if (p.findings && p.findings.length > 0) {
53357
+ for (const f of p.findings.slice(0, 3)) {
53358
+ process.stderr.write(import_chalk19.default.dim(` \u2022 ${f.title ?? "finding"}
53359
+ `));
53360
+ }
53361
+ }
53362
+ }
53363
+ if (suppressedCount > 0) {
53364
+ process.stderr.write(import_chalk19.default.dim(` (${suppressedCount} additional finding${suppressedCount === 1 ? "" : "s"} suppressed by .dg-allowlist.json)
53284
53365
  `));
53285
53366
  }
53367
+ return;
53286
53368
  }
53287
- }
53288
- if (suppressedCount > 0) {
53289
- process.stderr.write(import_chalk19.default.dim(` (${suppressedCount} additional finding${suppressedCount === 1 ? "" : "s"} suppressed by .dg-allowlist.json)
53369
+ case "block": {
53370
+ if (d.outcome === "install") {
53371
+ if (!config.json && !config.quiet) {
53372
+ process.stderr.write(import_chalk19.default.yellow.bold(` --dg-force: bypassing block. Install at your own risk.
53373
+
53290
53374
  `));
53375
+ }
53376
+ } else if (!config.json) {
53377
+ const blockedList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
53378
+ process.stderr.write(
53379
+ ` ${import_chalk19.default.red("\u2717")} ${import_chalk19.default.bold("DG blocked")} ${blockedList}.
53380
+ Real install was NOT run. To override:
53381
+ ` + import_chalk19.default.dim(` ${adapter7.realBinaryName} ${parsed.rawArgs.join(" ")} --dg-force --dg-force-reason="<reason>"
53382
+
53383
+ `)
53384
+ );
53385
+ }
53386
+ return;
53387
+ }
53388
+ case "analysis_incomplete": {
53389
+ const list = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
53390
+ if (d.outcome === "refuse") {
53391
+ if (!config.json) {
53392
+ process.stderr.write(
53393
+ ` ${import_chalk19.default.red("\u2717")} ${import_chalk19.default.bold("DG could not verify")} ${list} \u2014 analysis incomplete.
53394
+ ` + import_chalk19.default.dim(` --mode ${config.strict ? "strict" : "block"} \u21D2 refusing install (unverified is not safe). Use --mode warn or --dg-force to bypass.
53395
+
53396
+ `)
53397
+ );
53398
+ }
53399
+ } else if (!config.json && !config.quiet) {
53400
+ process.stderr.write(
53401
+ import_chalk19.default.yellow(` \u26A0 DG could not fully verify ${list} (analysis incomplete). Proceeding with install (mode=${config.mode}).
53402
+ `)
53403
+ );
53404
+ }
53405
+ return;
53406
+ }
53407
+ default:
53408
+ return;
53409
+ }
53410
+ },
53411
+ async confirmProceed() {
53412
+ if (!(process.stderr.isTTY && !process.env.CI && !config.json)) {
53413
+ if (!config.json && !config.quiet) process.stderr.write(import_chalk19.default.dim(" Proceeding (non-interactive).\n"));
53414
+ return true;
53291
53415
  }
53292
- }
53293
- if (process.stderr.isTTY && !process.env.CI && !config.json) {
53294
53416
  const { promptYesNo: promptYesNo2 } = await Promise.resolve().then(() => (init_prompt(), prompt_exports));
53295
53417
  const proceed = await promptYesNo2({ defaultAnswer: "y", message: " Proceed?" });
53296
- if (!proceed) {
53297
- process.stderr.write(import_chalk19.default.dim(" Install cancelled by user.\n\n"));
53298
- emitJson(config, {
53299
- ecosystem: adapter7.ecosystem,
53300
- packages: packagesFromResult(result, topLevelNames),
53301
- scanVerdict: "warn",
53302
- installRan: false,
53303
- installExitCode: null
53304
- });
53305
- return 1;
53306
- }
53307
- } else if (!config.json && !config.quiet) {
53308
- process.stderr.write(import_chalk19.default.dim(" Proceeding (non-interactive).\n"));
53309
- }
53310
- const code2 = await spawnRealBinary(adapter7, installArgs);
53311
- emitJson(config, {
53312
- ecosystem: adapter7.ecosystem,
53313
- packages: packagesFromResult(result, topLevelNames),
53314
- scanVerdict: "warn",
53315
- installRan: true,
53316
- installExitCode: code2,
53317
- suppressedByAllowlist: suppressedCount > 0 ? suppressedCount : void 0
53318
- });
53319
- return code2;
53320
- }
53321
- if (result.action === "block") {
53322
- if (parsed.dgForce) {
53418
+ if (!proceed) process.stderr.write(import_chalk19.default.dim(" Install cancelled by user.\n\n"));
53419
+ return proceed;
53420
+ },
53421
+ runInstall: (args2) => spawnRealBinary(adapter7, args2),
53422
+ async audit(kind) {
53323
53423
  try {
53324
53424
  await dispatchInstallAudit({
53325
53425
  ecosystem: adapter7.apiKind,
53326
53426
  packages: result.packages,
53327
- decisionAction: "override",
53328
- bypassed: true,
53329
- bypassReason: parsed.dgForceReason
53427
+ decisionAction: kind,
53428
+ bypassed: kind === "override",
53429
+ bypassReason: kind === "override" ? parsed.dgForceReason : void 0
53330
53430
  });
53331
53431
  } catch {
53332
53432
  }
53333
- if (!config.json && !config.quiet) {
53334
- process.stderr.write(import_chalk19.default.yellow.bold(` --dg-force: bypassing block. Install at your own risk.
53335
-
53336
- `));
53337
- }
53338
- const code2 = await spawnRealBinary(adapter7, installArgs);
53339
- emitJson(config, {
53433
+ },
53434
+ emit(record) {
53435
+ emitWrapperJson(config, {
53340
53436
  ecosystem: adapter7.ecosystem,
53341
53437
  packages: packagesFromResult(result, topLevelNames),
53342
- scanVerdict: "override",
53343
- installRan: true,
53344
- installExitCode: code2
53345
- });
53346
- return code2;
53347
- }
53348
- try {
53349
- await dispatchInstallAudit({
53350
- ecosystem: adapter7.apiKind,
53351
- packages: result.packages,
53352
- decisionAction: "block",
53353
- bypassed: false
53438
+ scanVerdict: record.scanVerdict,
53439
+ installRan: record.installRan,
53440
+ installExitCode: record.installExitCode,
53441
+ error: record.error,
53442
+ suppressedByAllowlist: record.suppressedByAllowlist
53354
53443
  });
53355
- } catch {
53356
53444
  }
53357
- const blockedList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
53358
- if (!config.json) {
53359
- process.stderr.write(
53360
- ` ${import_chalk19.default.red("\u2717")} ${import_chalk19.default.bold("DG blocked")} ${blockedList}.
53361
- Real install was NOT run. To override:
53362
- ` + import_chalk19.default.dim(` ${adapter7.realBinaryName} ${parsed.rawArgs.join(" ")} --dg-force --dg-force-reason="<reason>"
53363
-
53364
- `)
53365
- );
53366
- }
53367
- emitJson(config, {
53368
- ecosystem: adapter7.ecosystem,
53369
- packages: packagesFromResult(result, topLevelNames),
53370
- scanVerdict: "block",
53371
- installRan: false,
53372
- installExitCode: null
53373
- });
53374
- return 2;
53375
- }
53376
- const refuseHard = config.mode === "block" || config.strict;
53377
- const unverifiedList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
53378
- if (refuseHard && !parsed.dgForce) {
53379
- if (!config.json) {
53380
- process.stderr.write(
53381
- ` ${import_chalk19.default.red("\u2717")} ${import_chalk19.default.bold("DG could not verify")} ${unverifiedList} \u2014 analysis incomplete.
53382
- ` + import_chalk19.default.dim(` --mode ${config.strict ? "strict" : "block"} \u21D2 refusing install (unverified is not safe). Use --mode warn or --dg-force to bypass.
53383
-
53384
- `)
53385
- );
53386
- }
53387
- emitJson(config, {
53388
- ecosystem: adapter7.ecosystem,
53389
- packages: packagesFromResult(result, topLevelNames),
53390
- scanVerdict: "analysis_incomplete",
53391
- installRan: false,
53392
- installExitCode: null,
53393
- error: { code: "analysis_incomplete", message: "scanner could not fully analyze the install set" }
53394
- });
53395
- return 4;
53396
- }
53397
- if (!config.json && !config.quiet) {
53398
- process.stderr.write(
53399
- import_chalk19.default.yellow(` \u26A0 DG could not fully verify ${unverifiedList} (analysis incomplete). Proceeding with install (mode=${config.mode}).
53400
- `)
53401
- );
53402
- }
53403
- const code = await spawnRealBinary(adapter7, installArgs);
53404
- emitJson(config, {
53405
- ecosystem: adapter7.ecosystem,
53406
- packages: packagesFromResult(result, topLevelNames),
53407
- scanVerdict: "analysis_incomplete",
53408
- installRan: true,
53409
- installExitCode: code
53410
- });
53411
- return code;
53445
+ };
53446
+ return await executeDecision(decision, ctx, presenter);
53412
53447
  }
53413
53448
  var import_chalk19;
53414
53449
  var init_wrapper_factory = __esm({
@@ -53423,6 +53458,9 @@ var init_wrapper_factory = __esm({
53423
53458
  init_wrapper_shared();
53424
53459
  init_npm_wrapper();
53425
53460
  init_pip_wrapper();
53461
+ init_route();
53462
+ init_run();
53463
+ init_json();
53426
53464
  }
53427
53465
  });
53428
53466