@node9/proxy 2.44.0 → 2.45.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/dist/cli.js CHANGED
@@ -35079,12 +35079,6 @@ function isReadable(filePath) {
35079
35079
  return false;
35080
35080
  }
35081
35081
  }
35082
- function scoreLabel(score) {
35083
- if (score >= 80) return import_chalk3.default.green(`${score}/100 Good`);
35084
- if (score >= 50) return import_chalk3.default.yellow(`${score}/100 Moderate risk`);
35085
- if (score >= 25) return import_chalk3.default.red(`${score}/100 High risk`);
35086
- return import_chalk3.default.red.bold(`${score}/100 Critical`);
35087
- }
35088
35082
  function runBlast() {
35089
35083
  const home = import_os42.default.homedir();
35090
35084
  const cwd = process.cwd();
@@ -35115,7 +35109,7 @@ function registerBlastCommand(program2) {
35115
35109
  program2.command("blast").description("Map what an AI agent can currently reach on this machine").action(() => {
35116
35110
  const home = import_os42.default.homedir();
35117
35111
  const cwd = process.cwd();
35118
- const { reachable, envFindings, score } = runBlast();
35112
+ const { reachable, envFindings } = runBlast();
35119
35113
  const width = labelColumnWidth([
35120
35114
  ...reachable.map((p) => p.label),
35121
35115
  ...envFindings.map((f) => f.key)
@@ -35147,21 +35141,24 @@ function registerBlastCommand(program2) {
35147
35141
  console.log(" " + import_chalk3.default.dim("\u2500".repeat(70)));
35148
35142
  if (reachable.length === 0 && envFindings.length === 0) {
35149
35143
  console.log(" " + import_chalk3.default.green("\u2705 No sensitive files or environment secrets found."));
35150
- console.log(" Security Score: " + scoreLabel(score));
35151
35144
  } else {
35152
35145
  console.log(
35153
- " Security Score: " + scoreLabel(score) + import_chalk3.default.dim(
35154
- ` (${reachable.length} file${reachable.length !== 1 ? "s" : ""}, ${envFindings.length} env var${envFindings.length !== 1 ? "s" : ""})`
35155
- )
35146
+ import_chalk3.default.bold(
35147
+ ` ${reachable.length} file${reachable.length !== 1 ? "s" : ""} and ${envFindings.length} env var${envFindings.length !== 1 ? "s" : ""}`
35148
+ ) + import_chalk3.default.dim(" every AI agent you start can read.")
35156
35149
  );
35157
35150
  console.log("");
35158
35151
  console.log(
35159
35152
  import_chalk3.default.dim(
35160
- " Every AI agent you start can read the files and env vars listed above.\n Run `node9 shield enable project-jail` to restrict agent file access.\n Run `node9 mask` to redact secrets from existing session history."
35153
+ " Run `node9 shield enable project-jail` to restrict agent file access.\n Run `node9 mask` to redact secrets from existing session history."
35161
35154
  )
35162
35155
  );
35163
35156
  }
35164
35157
  console.log("");
35158
+ console.log(
35159
+ import_chalk3.default.dim(" Machine score: ") + import_chalk3.default.cyan("node9 posture") + import_chalk3.default.dim(" (this list is its Secrets section)")
35160
+ );
35161
+ console.log("");
35165
35162
  });
35166
35163
  }
35167
35164
  var import_chalk3, import_fs49, import_path51, import_os42;
@@ -35274,13 +35271,14 @@ var init_scan_derive = __esm({
35274
35271
  });
35275
35272
 
35276
35273
  // src/protection.ts
35277
- var PROTECTIVE_SHIELD_DISCOUNTS;
35274
+ function isProtectiveShield(name) {
35275
+ return PROTECTIVE_SHIELDS.has(name);
35276
+ }
35277
+ var PROTECTIVE_SHIELDS;
35278
35278
  var init_protection = __esm({
35279
35279
  "src/protection.ts"() {
35280
35280
  "use strict";
35281
- PROTECTIVE_SHIELD_DISCOUNTS = {
35282
- "project-jail": 0.7
35283
- };
35281
+ PROTECTIVE_SHIELDS = /* @__PURE__ */ new Set(["project-jail"]);
35284
35282
  }
35285
35283
  });
35286
35284
 
@@ -35321,20 +35319,6 @@ var init_scan_json = __esm({
35321
35319
  function defaultHistoryPath() {
35322
35320
  return import_path52.default.join(import_os43.default.homedir(), ".node9", "scan-history.json");
35323
35321
  }
35324
- function readPreviousScan(opts = {}) {
35325
- const filePath = opts.path ?? defaultHistoryPath();
35326
- try {
35327
- if (!import_fs50.default.existsSync(filePath)) return null;
35328
- const raw = import_fs50.default.readFileSync(filePath, "utf8");
35329
- const parsed = JSON.parse(raw);
35330
- if (!Array.isArray(parsed) || parsed.length === 0) return null;
35331
- const last = parsed[parsed.length - 1];
35332
- if (!isValidRecord(last)) return null;
35333
- return last;
35334
- } catch {
35335
- return null;
35336
- }
35337
- }
35338
35322
  function appendScanHistory(record2, opts = {}) {
35339
35323
  const filePath = opts.path ?? defaultHistoryPath();
35340
35324
  const cap = opts.cap ?? SCAN_HISTORY_CAP;
@@ -35362,15 +35346,6 @@ function appendScanHistory(record2, opts = {}) {
35362
35346
  );
35363
35347
  }
35364
35348
  }
35365
- function computeScanDelta(current, previous, now = Date.now()) {
35366
- if (!previous) return null;
35367
- const prevMs = Date.parse(previous.timestamp);
35368
- if (Number.isNaN(prevMs)) return null;
35369
- const scoreDelta = current.score - previous.score;
35370
- const daysAgo = Math.max(0, Math.floor((now - prevMs) / 864e5));
35371
- if (scoreDelta === 0 && daysAgo === 0) return null;
35372
- return { scoreDelta, daysAgo };
35373
- }
35374
35349
  function isValidRecord(x) {
35375
35350
  if (typeof x !== "object" || x === null) return false;
35376
35351
  const r = x;
@@ -36032,7 +36007,7 @@ async function runUploadHistory(opts) {
36032
36007
  ` Parsed ${linesParsed.toLocaleString()} JSONL lines from ${filesScanned} session${filesScanned === 1 ? "" : "s"} (skipped ${linesSkipped} malformed)`
36033
36008
  )
36034
36009
  );
36035
- console.log(import_chalk5.default.gray(` Findings: ${findings.length}, score: ${summary.score}/100`));
36010
+ console.log(import_chalk5.default.gray(` Findings: ${findings.length}`));
36036
36011
  const scanUrl = creds.apiUrl.endsWith("/policies/sync") ? creds.apiUrl.replace(/\/policies\/sync$/, "/scan/report") : `${creds.apiUrl.replace(/\/$/, "")}/scan/report`;
36037
36012
  await postJson(scanUrl, creds.apiKey, {
36038
36013
  ...summary,
@@ -37813,6 +37788,9 @@ function renderCompactScorecard(input) {
37813
37788
  );
37814
37789
  console.log("");
37815
37790
  }
37791
+ console.log(
37792
+ import_chalk6.default.dim("\u2192 Machine score: run ") + import_chalk6.default.cyan("node9 posture") + import_chalk6.default.dim(" for this machine's score and what to fix first.")
37793
+ );
37816
37794
  console.log(
37817
37795
  import_chalk6.default.dim("\u2192 ") + import_chalk6.default.cyan("npx node9-ai scan") + import_chalk6.default.dim(" run this on your machine")
37818
37796
  );
@@ -37923,6 +37901,9 @@ function renderNarrativeScorecard(input) {
37923
37901
  }
37924
37902
  console.log("");
37925
37903
  }
37904
+ console.log(
37905
+ import_chalk6.default.dim("\u2192 Machine score: run ") + import_chalk6.default.cyan("node9 posture") + import_chalk6.default.dim(" for this machine's score and what to fix first.")
37906
+ );
37926
37907
  console.log(
37927
37908
  import_chalk6.default.dim("\u2192 ") + import_chalk6.default.cyan("npx node9-ai scan") + import_chalk6.default.dim(" run this on your machine")
37928
37909
  );
@@ -38165,24 +38146,24 @@ function renderPanelScorecard(input, now = /* @__PURE__ */ new Date()) {
38165
38146
  const shieldImpacts = rollupByShield(summary.sections);
38166
38147
  const shieldLines = [];
38167
38148
  const ranked = [...shieldImpacts].sort((a, b) => {
38168
- const aDiscount = PROTECTIVE_SHIELD_DISCOUNTS[a.shieldName] ?? 0;
38169
- const bDiscount = PROTECTIVE_SHIELD_DISCOUNTS[b.shieldName] ?? 0;
38170
- if (aDiscount !== bDiscount) return bDiscount - aDiscount;
38149
+ const aProt = isProtectiveShield(a.shieldName) ? 1 : 0;
38150
+ const bProt = isProtectiveShield(b.shieldName) ? 1 : 0;
38151
+ if (aProt !== bProt) return bProt - aProt;
38171
38152
  return b.totalCatches - a.totalCatches;
38172
38153
  });
38173
38154
  for (const impact of ranked) {
38174
38155
  if (impact.totalCatches === 0) continue;
38175
- const discount = PROTECTIVE_SHIELD_DISCOUNTS[impact.shieldName] ?? 0;
38156
+ const protective = isProtectiveShield(impact.shieldName);
38176
38157
  const isOn = enabledSet.has(impact.shieldName);
38177
- const icon = discount > 0 ? "\u{1F6E1}\uFE0F " : "\u2610 ";
38158
+ const icon = protective ? "\u{1F6E1}\uFE0F " : "\u2610 ";
38178
38159
  const wouldCatch = `catches ${impact.totalCatches} op${impact.totalCatches !== 1 ? "s" : ""}`;
38179
- const suffix = isOn ? "\u2713 enabled" : discount > 0 ? "\u2192 blocks these reads in-path" : "";
38160
+ const suffix = isOn ? "\u2713 enabled" : protective ? "\u2192 blocks these reads in-path" : "";
38180
38161
  shieldLines.push(
38181
38162
  mkLine(
38182
- [icon, discount > 0 ? import_chalk6.default.cyan : import_chalk6.default.dim],
38163
+ [icon, protective ? import_chalk6.default.cyan : import_chalk6.default.dim],
38183
38164
  [impact.shieldName.padEnd(14), import_chalk6.default.bold],
38184
38165
  [wouldCatch.padEnd(22), import_chalk6.default.dim],
38185
- [suffix, isOn || discount > 0 ? import_chalk6.default.green.bold : import_chalk6.default.dim]
38166
+ [suffix, isOn || protective ? import_chalk6.default.green.bold : import_chalk6.default.dim]
38186
38167
  )
38187
38168
  );
38188
38169
  if (impact.topRuleLabels.length > 0) {
@@ -38211,10 +38192,10 @@ function renderPanelScorecard(input, now = /* @__PURE__ */ new Date()) {
38211
38192
  shieldLines.push(mkLine([" no hits in your history \u2014 install proactively", import_chalk6.default.dim]));
38212
38193
  }
38213
38194
  const topRec = ranked.find(
38214
- (r) => r.totalCatches > 0 && (PROTECTIVE_SHIELD_DISCOUNTS[r.shieldName] ?? 0) > 0 && !enabledSet.has(r.shieldName)
38195
+ (r) => r.totalCatches > 0 && isProtectiveShield(r.shieldName) && !enabledSet.has(r.shieldName)
38215
38196
  );
38216
38197
  const allCovered = !topRec && ranked.some(
38217
- (r) => r.totalCatches > 0 && (PROTECTIVE_SHIELD_DISCOUNTS[r.shieldName] ?? 0) > 0 && enabledSet.has(r.shieldName)
38198
+ (r) => r.totalCatches > 0 && isProtectiveShield(r.shieldName) && enabledSet.has(r.shieldName)
38218
38199
  );
38219
38200
  if (topRec) {
38220
38201
  const cta = `\u2192 node9 shield enable ${topRec.shieldName} (start here \u2014 widest coverage)`;
@@ -38419,9 +38400,7 @@ function registerScanCommand(program2) {
38419
38400
  process.stdout.write(JSON.stringify(envelope, null, 2) + "\n");
38420
38401
  return;
38421
38402
  }
38422
- let scanDelta2 = null;
38423
38403
  if (!screenshotMode) {
38424
- const previous = readPreviousScan();
38425
38404
  const currentRecord = {
38426
38405
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
38427
38406
  score: blast.score,
@@ -38433,7 +38412,6 @@ function registerScanCommand(program2) {
38433
38412
  totalCalls: scan.totalToolCalls
38434
38413
  };
38435
38414
  appendScanHistory(currentRecord);
38436
- scanDelta2 = computeScanDelta(currentRecord, previous);
38437
38415
  }
38438
38416
  if (options.compact) {
38439
38417
  renderCompactScorecard({
@@ -38472,19 +38450,9 @@ function registerScanCommand(program2) {
38472
38450
  }
38473
38451
  {
38474
38452
  const totalRisky = scan.canaryFindings.length + totalFindings + scan.dlpFindings.length;
38475
- const score = classifyScore(blast.score);
38476
- const severityDisplay = score.band === "critical" ? import_chalk6.default.red.bold(score.label) : score.color(score.label);
38477
- const trendSuffix = (() => {
38478
- if (!scanDelta2) return "";
38479
- const { scoreDelta, daysAgo } = scanDelta2;
38480
- if (scoreDelta === 0) return "";
38481
- const arrow = scoreDelta > 0 ? import_chalk6.default.green(`\u25B2${scoreDelta}`) : import_chalk6.default.red(`\u25BC${Math.abs(scoreDelta)}`);
38482
- const since = daysAgo === 0 ? "today" : daysAgo === 1 ? "yesterday" : `${daysAgo} days ago`;
38483
- return import_chalk6.default.dim(" \xB7 ") + arrow + import_chalk6.default.dim(` since ${since}`);
38484
- })();
38485
- if (!useInkForHero) {
38453
+ if (!useInkForHero && totalRisky > 0) {
38486
38454
  console.log(
38487
- " " + (score.band === "critical" ? import_chalk6.default.red.bold("\u26A0 ") : "") + import_chalk6.default.bold("Security Score ") + score.color.bold(`${blast.score}/100`) + " " + severityDisplay + trendSuffix + import_chalk6.default.dim(" \xB7 ") + (totalRisky > 0 ? import_chalk6.default.red.bold(`${totalRisky} risky operation${totalRisky !== 1 ? "s" : ""}`) : import_chalk6.default.green("No risky operations"))
38455
+ " " + import_chalk6.default.red.bold(`${totalRisky} risky operation${totalRisky !== 1 ? "s" : ""}`) + import_chalk6.default.dim(" in the scanned history")
38488
38456
  );
38489
38457
  }
38490
38458
  const cardParts = [];
@@ -38566,6 +38534,10 @@ function registerScanCommand(program2) {
38566
38534
  keyed
38567
38535
  });
38568
38536
  }
38537
+ console.log(
38538
+ import_chalk6.default.dim(" Machine score: run ") + import_chalk6.default.cyan("node9 posture") + import_chalk6.default.dim(" for this machine's score and what to fix first.")
38539
+ );
38540
+ console.log("");
38569
38541
  const cta = isWired ? "\u2705 node9 is active" : "\u2192 install node9 to enable protection";
38570
38542
  console.log(" " + import_chalk6.default.green(cta));
38571
38543
  console.log(
@@ -38760,6 +38732,10 @@ function registerScanCommand(program2) {
38760
38732
  );
38761
38733
  console.log("");
38762
38734
  }
38735
+ console.log(
38736
+ import_chalk6.default.dim(" Machine score: run ") + import_chalk6.default.cyan("node9 posture") + import_chalk6.default.dim(" for this machine's score and what to fix first.")
38737
+ );
38738
+ console.log("");
38763
38739
  if (isWired) {
38764
38740
  console.log(import_chalk6.default.green(" \u2705 node9 is active \u2014 your future sessions are protected."));
38765
38741
  console.log(
@@ -78234,6 +78210,7 @@ init_agent_wiring();
78234
78210
  init_codex_trust();
78235
78211
  init_sync();
78236
78212
  init_service();
78213
+ init_posture();
78237
78214
  function printAgentSection(label3, hookPairs, wrapped) {
78238
78215
  console.log(import_chalk22.default.bold(` ${label3}`));
78239
78216
  for (const { name, present } of hookPairs) {
@@ -78314,6 +78291,13 @@ function registerStatusCommand(program2) {
78314
78291
  console.log("");
78315
78292
  const modeLabel = levelLabel(settings.mode);
78316
78293
  console.log(` Mode: ${modeLabel}`);
78294
+ const posture = await runPosture().catch(() => null);
78295
+ if (posture) {
78296
+ const tier = posture.tier === "good" ? import_chalk22.default.green("Good") : posture.tier === "at-risk" ? import_chalk22.default.yellow("At risk") : import_chalk22.default.red("Critical");
78297
+ console.log(
78298
+ ` Score: ${import_chalk22.default.bold(`${posture.score}/100`)} (${tier})` + import_chalk22.default.gray(" \xB7 node9 posture for the breakdown")
78299
+ );
78300
+ }
78317
78301
  const wsGoverned = mergedConfig.policySource === "workspace";
78318
78302
  if (wsGoverned) {
78319
78303
  console.log(` Policy: ${import_chalk22.default.cyan("Workspace config (app.node9.ai)")}`);
package/dist/cli.mjs CHANGED
@@ -35073,12 +35073,6 @@ function isReadable(filePath) {
35073
35073
  return false;
35074
35074
  }
35075
35075
  }
35076
- function scoreLabel(score) {
35077
- if (score >= 80) return chalk3.green(`${score}/100 Good`);
35078
- if (score >= 50) return chalk3.yellow(`${score}/100 Moderate risk`);
35079
- if (score >= 25) return chalk3.red(`${score}/100 High risk`);
35080
- return chalk3.red.bold(`${score}/100 Critical`);
35081
- }
35082
35076
  function runBlast() {
35083
35077
  const home = os43.homedir();
35084
35078
  const cwd = process.cwd();
@@ -35109,7 +35103,7 @@ function registerBlastCommand(program2) {
35109
35103
  program2.command("blast").description("Map what an AI agent can currently reach on this machine").action(() => {
35110
35104
  const home = os43.homedir();
35111
35105
  const cwd = process.cwd();
35112
- const { reachable, envFindings, score } = runBlast();
35106
+ const { reachable, envFindings } = runBlast();
35113
35107
  const width = labelColumnWidth([
35114
35108
  ...reachable.map((p) => p.label),
35115
35109
  ...envFindings.map((f) => f.key)
@@ -35141,21 +35135,24 @@ function registerBlastCommand(program2) {
35141
35135
  console.log(" " + chalk3.dim("\u2500".repeat(70)));
35142
35136
  if (reachable.length === 0 && envFindings.length === 0) {
35143
35137
  console.log(" " + chalk3.green("\u2705 No sensitive files or environment secrets found."));
35144
- console.log(" Security Score: " + scoreLabel(score));
35145
35138
  } else {
35146
35139
  console.log(
35147
- " Security Score: " + scoreLabel(score) + chalk3.dim(
35148
- ` (${reachable.length} file${reachable.length !== 1 ? "s" : ""}, ${envFindings.length} env var${envFindings.length !== 1 ? "s" : ""})`
35149
- )
35140
+ chalk3.bold(
35141
+ ` ${reachable.length} file${reachable.length !== 1 ? "s" : ""} and ${envFindings.length} env var${envFindings.length !== 1 ? "s" : ""}`
35142
+ ) + chalk3.dim(" every AI agent you start can read.")
35150
35143
  );
35151
35144
  console.log("");
35152
35145
  console.log(
35153
35146
  chalk3.dim(
35154
- " Every AI agent you start can read the files and env vars listed above.\n Run `node9 shield enable project-jail` to restrict agent file access.\n Run `node9 mask` to redact secrets from existing session history."
35147
+ " Run `node9 shield enable project-jail` to restrict agent file access.\n Run `node9 mask` to redact secrets from existing session history."
35155
35148
  )
35156
35149
  );
35157
35150
  }
35158
35151
  console.log("");
35152
+ console.log(
35153
+ chalk3.dim(" Machine score: ") + chalk3.cyan("node9 posture") + chalk3.dim(" (this list is its Secrets section)")
35154
+ );
35155
+ console.log("");
35159
35156
  });
35160
35157
  }
35161
35158
  var init_blast = __esm({
@@ -35263,13 +35260,14 @@ var init_scan_derive = __esm({
35263
35260
  });
35264
35261
 
35265
35262
  // src/protection.ts
35266
- var PROTECTIVE_SHIELD_DISCOUNTS;
35263
+ function isProtectiveShield(name) {
35264
+ return PROTECTIVE_SHIELDS.has(name);
35265
+ }
35266
+ var PROTECTIVE_SHIELDS;
35267
35267
  var init_protection = __esm({
35268
35268
  "src/protection.ts"() {
35269
35269
  "use strict";
35270
- PROTECTIVE_SHIELD_DISCOUNTS = {
35271
- "project-jail": 0.7
35272
- };
35270
+ PROTECTIVE_SHIELDS = /* @__PURE__ */ new Set(["project-jail"]);
35273
35271
  }
35274
35272
  });
35275
35273
 
@@ -35313,20 +35311,6 @@ import os44 from "os";
35313
35311
  function defaultHistoryPath() {
35314
35312
  return path54.join(os44.homedir(), ".node9", "scan-history.json");
35315
35313
  }
35316
- function readPreviousScan(opts = {}) {
35317
- const filePath = opts.path ?? defaultHistoryPath();
35318
- try {
35319
- if (!fs52.existsSync(filePath)) return null;
35320
- const raw = fs52.readFileSync(filePath, "utf8");
35321
- const parsed = JSON.parse(raw);
35322
- if (!Array.isArray(parsed) || parsed.length === 0) return null;
35323
- const last = parsed[parsed.length - 1];
35324
- if (!isValidRecord(last)) return null;
35325
- return last;
35326
- } catch {
35327
- return null;
35328
- }
35329
- }
35330
35314
  function appendScanHistory(record2, opts = {}) {
35331
35315
  const filePath = opts.path ?? defaultHistoryPath();
35332
35316
  const cap = opts.cap ?? SCAN_HISTORY_CAP;
@@ -35354,15 +35338,6 @@ function appendScanHistory(record2, opts = {}) {
35354
35338
  );
35355
35339
  }
35356
35340
  }
35357
- function computeScanDelta(current, previous, now = Date.now()) {
35358
- if (!previous) return null;
35359
- const prevMs = Date.parse(previous.timestamp);
35360
- if (Number.isNaN(prevMs)) return null;
35361
- const scoreDelta = current.score - previous.score;
35362
- const daysAgo = Math.max(0, Math.floor((now - prevMs) / 864e5));
35363
- if (scoreDelta === 0 && daysAgo === 0) return null;
35364
- return { scoreDelta, daysAgo };
35365
- }
35366
35341
  function isValidRecord(x) {
35367
35342
  if (typeof x !== "object" || x === null) return false;
35368
35343
  const r = x;
@@ -36026,7 +36001,7 @@ async function runUploadHistory(opts) {
36026
36001
  ` Parsed ${linesParsed.toLocaleString()} JSONL lines from ${filesScanned} session${filesScanned === 1 ? "" : "s"} (skipped ${linesSkipped} malformed)`
36027
36002
  )
36028
36003
  );
36029
- console.log(chalk5.gray(` Findings: ${findings.length}, score: ${summary.score}/100`));
36004
+ console.log(chalk5.gray(` Findings: ${findings.length}`));
36030
36005
  const scanUrl = creds.apiUrl.endsWith("/policies/sync") ? creds.apiUrl.replace(/\/policies\/sync$/, "/scan/report") : `${creds.apiUrl.replace(/\/$/, "")}/scan/report`;
36031
36006
  await postJson(scanUrl, creds.apiKey, {
36032
36007
  ...summary,
@@ -37807,6 +37782,9 @@ function renderCompactScorecard(input) {
37807
37782
  );
37808
37783
  console.log("");
37809
37784
  }
37785
+ console.log(
37786
+ chalk6.dim("\u2192 Machine score: run ") + chalk6.cyan("node9 posture") + chalk6.dim(" for this machine's score and what to fix first.")
37787
+ );
37810
37788
  console.log(
37811
37789
  chalk6.dim("\u2192 ") + chalk6.cyan("npx node9-ai scan") + chalk6.dim(" run this on your machine")
37812
37790
  );
@@ -37917,6 +37895,9 @@ function renderNarrativeScorecard(input) {
37917
37895
  }
37918
37896
  console.log("");
37919
37897
  }
37898
+ console.log(
37899
+ chalk6.dim("\u2192 Machine score: run ") + chalk6.cyan("node9 posture") + chalk6.dim(" for this machine's score and what to fix first.")
37900
+ );
37920
37901
  console.log(
37921
37902
  chalk6.dim("\u2192 ") + chalk6.cyan("npx node9-ai scan") + chalk6.dim(" run this on your machine")
37922
37903
  );
@@ -38159,24 +38140,24 @@ function renderPanelScorecard(input, now = /* @__PURE__ */ new Date()) {
38159
38140
  const shieldImpacts = rollupByShield(summary.sections);
38160
38141
  const shieldLines = [];
38161
38142
  const ranked = [...shieldImpacts].sort((a, b) => {
38162
- const aDiscount = PROTECTIVE_SHIELD_DISCOUNTS[a.shieldName] ?? 0;
38163
- const bDiscount = PROTECTIVE_SHIELD_DISCOUNTS[b.shieldName] ?? 0;
38164
- if (aDiscount !== bDiscount) return bDiscount - aDiscount;
38143
+ const aProt = isProtectiveShield(a.shieldName) ? 1 : 0;
38144
+ const bProt = isProtectiveShield(b.shieldName) ? 1 : 0;
38145
+ if (aProt !== bProt) return bProt - aProt;
38165
38146
  return b.totalCatches - a.totalCatches;
38166
38147
  });
38167
38148
  for (const impact of ranked) {
38168
38149
  if (impact.totalCatches === 0) continue;
38169
- const discount = PROTECTIVE_SHIELD_DISCOUNTS[impact.shieldName] ?? 0;
38150
+ const protective = isProtectiveShield(impact.shieldName);
38170
38151
  const isOn = enabledSet.has(impact.shieldName);
38171
- const icon = discount > 0 ? "\u{1F6E1}\uFE0F " : "\u2610 ";
38152
+ const icon = protective ? "\u{1F6E1}\uFE0F " : "\u2610 ";
38172
38153
  const wouldCatch = `catches ${impact.totalCatches} op${impact.totalCatches !== 1 ? "s" : ""}`;
38173
- const suffix = isOn ? "\u2713 enabled" : discount > 0 ? "\u2192 blocks these reads in-path" : "";
38154
+ const suffix = isOn ? "\u2713 enabled" : protective ? "\u2192 blocks these reads in-path" : "";
38174
38155
  shieldLines.push(
38175
38156
  mkLine(
38176
- [icon, discount > 0 ? chalk6.cyan : chalk6.dim],
38157
+ [icon, protective ? chalk6.cyan : chalk6.dim],
38177
38158
  [impact.shieldName.padEnd(14), chalk6.bold],
38178
38159
  [wouldCatch.padEnd(22), chalk6.dim],
38179
- [suffix, isOn || discount > 0 ? chalk6.green.bold : chalk6.dim]
38160
+ [suffix, isOn || protective ? chalk6.green.bold : chalk6.dim]
38180
38161
  )
38181
38162
  );
38182
38163
  if (impact.topRuleLabels.length > 0) {
@@ -38205,10 +38186,10 @@ function renderPanelScorecard(input, now = /* @__PURE__ */ new Date()) {
38205
38186
  shieldLines.push(mkLine([" no hits in your history \u2014 install proactively", chalk6.dim]));
38206
38187
  }
38207
38188
  const topRec = ranked.find(
38208
- (r) => r.totalCatches > 0 && (PROTECTIVE_SHIELD_DISCOUNTS[r.shieldName] ?? 0) > 0 && !enabledSet.has(r.shieldName)
38189
+ (r) => r.totalCatches > 0 && isProtectiveShield(r.shieldName) && !enabledSet.has(r.shieldName)
38209
38190
  );
38210
38191
  const allCovered = !topRec && ranked.some(
38211
- (r) => r.totalCatches > 0 && (PROTECTIVE_SHIELD_DISCOUNTS[r.shieldName] ?? 0) > 0 && enabledSet.has(r.shieldName)
38192
+ (r) => r.totalCatches > 0 && isProtectiveShield(r.shieldName) && enabledSet.has(r.shieldName)
38212
38193
  );
38213
38194
  if (topRec) {
38214
38195
  const cta = `\u2192 node9 shield enable ${topRec.shieldName} (start here \u2014 widest coverage)`;
@@ -38413,9 +38394,7 @@ function registerScanCommand(program2) {
38413
38394
  process.stdout.write(JSON.stringify(envelope, null, 2) + "\n");
38414
38395
  return;
38415
38396
  }
38416
- let scanDelta2 = null;
38417
38397
  if (!screenshotMode) {
38418
- const previous = readPreviousScan();
38419
38398
  const currentRecord = {
38420
38399
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
38421
38400
  score: blast.score,
@@ -38427,7 +38406,6 @@ function registerScanCommand(program2) {
38427
38406
  totalCalls: scan.totalToolCalls
38428
38407
  };
38429
38408
  appendScanHistory(currentRecord);
38430
- scanDelta2 = computeScanDelta(currentRecord, previous);
38431
38409
  }
38432
38410
  if (options.compact) {
38433
38411
  renderCompactScorecard({
@@ -38466,19 +38444,9 @@ function registerScanCommand(program2) {
38466
38444
  }
38467
38445
  {
38468
38446
  const totalRisky = scan.canaryFindings.length + totalFindings + scan.dlpFindings.length;
38469
- const score = classifyScore(blast.score);
38470
- const severityDisplay = score.band === "critical" ? chalk6.red.bold(score.label) : score.color(score.label);
38471
- const trendSuffix = (() => {
38472
- if (!scanDelta2) return "";
38473
- const { scoreDelta, daysAgo } = scanDelta2;
38474
- if (scoreDelta === 0) return "";
38475
- const arrow = scoreDelta > 0 ? chalk6.green(`\u25B2${scoreDelta}`) : chalk6.red(`\u25BC${Math.abs(scoreDelta)}`);
38476
- const since = daysAgo === 0 ? "today" : daysAgo === 1 ? "yesterday" : `${daysAgo} days ago`;
38477
- return chalk6.dim(" \xB7 ") + arrow + chalk6.dim(` since ${since}`);
38478
- })();
38479
- if (!useInkForHero) {
38447
+ if (!useInkForHero && totalRisky > 0) {
38480
38448
  console.log(
38481
- " " + (score.band === "critical" ? chalk6.red.bold("\u26A0 ") : "") + chalk6.bold("Security Score ") + score.color.bold(`${blast.score}/100`) + " " + severityDisplay + trendSuffix + chalk6.dim(" \xB7 ") + (totalRisky > 0 ? chalk6.red.bold(`${totalRisky} risky operation${totalRisky !== 1 ? "s" : ""}`) : chalk6.green("No risky operations"))
38449
+ " " + chalk6.red.bold(`${totalRisky} risky operation${totalRisky !== 1 ? "s" : ""}`) + chalk6.dim(" in the scanned history")
38482
38450
  );
38483
38451
  }
38484
38452
  const cardParts = [];
@@ -38560,6 +38528,10 @@ function registerScanCommand(program2) {
38560
38528
  keyed
38561
38529
  });
38562
38530
  }
38531
+ console.log(
38532
+ chalk6.dim(" Machine score: run ") + chalk6.cyan("node9 posture") + chalk6.dim(" for this machine's score and what to fix first.")
38533
+ );
38534
+ console.log("");
38563
38535
  const cta = isWired ? "\u2705 node9 is active" : "\u2192 install node9 to enable protection";
38564
38536
  console.log(" " + chalk6.green(cta));
38565
38537
  console.log(
@@ -38754,6 +38726,10 @@ function registerScanCommand(program2) {
38754
38726
  );
38755
38727
  console.log("");
38756
38728
  }
38729
+ console.log(
38730
+ chalk6.dim(" Machine score: run ") + chalk6.cyan("node9 posture") + chalk6.dim(" for this machine's score and what to fix first.")
38731
+ );
38732
+ console.log("");
38757
38733
  if (isWired) {
38758
38734
  console.log(chalk6.green(" \u2705 node9 is active \u2014 your future sessions are protected."));
38759
38735
  console.log(
@@ -78214,6 +78190,7 @@ import chalk22 from "chalk";
78214
78190
  import fs88 from "fs";
78215
78191
  import path86 from "path";
78216
78192
  import os73 from "os";
78193
+ init_posture();
78217
78194
  function printAgentSection(label3, hookPairs, wrapped) {
78218
78195
  console.log(chalk22.bold(` ${label3}`));
78219
78196
  for (const { name, present } of hookPairs) {
@@ -78294,6 +78271,13 @@ function registerStatusCommand(program2) {
78294
78271
  console.log("");
78295
78272
  const modeLabel = levelLabel(settings.mode);
78296
78273
  console.log(` Mode: ${modeLabel}`);
78274
+ const posture = await runPosture().catch(() => null);
78275
+ if (posture) {
78276
+ const tier = posture.tier === "good" ? chalk22.green("Good") : posture.tier === "at-risk" ? chalk22.yellow("At risk") : chalk22.red("Critical");
78277
+ console.log(
78278
+ ` Score: ${chalk22.bold(`${posture.score}/100`)} (${tier})` + chalk22.gray(" \xB7 node9 posture for the breakdown")
78279
+ );
78280
+ }
78297
78281
  const wsGoverned = mergedConfig.policySource === "workspace";
78298
78282
  if (wsGoverned) {
78299
78283
  console.log(` Policy: ${chalk22.cyan("Workspace config (app.node9.ai)")}`);