nsauditor-ai 0.1.72 → 0.1.73

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/cli.mjs +79 -1
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -1038,6 +1038,84 @@ Docs: https://www.nsauditor.com/ai/ | Pricing: https://www.nsauditor.com/ai/
1038
1038
  console.log('── Installation provenance ──');
1039
1039
  console.log(` nsauditor-ai (CE): ${ceVersion}`);
1040
1040
  console.log(` @nsasoft/nsauditor-ai-ee (EE): ${eeVersion}`);
1041
+ } else if (rawArgs.includes('--reset')) {
1042
+ // CE-0.1.73 — atomic dual-channel license-state reset for macOS
1043
+ // license-rotation flow. Discovered EE 0.11.0 first-install
1044
+ // rehearsal (2026-05-23): customer rotates EE license, gets
1045
+ // `license_id_mismatch` because the persisted licenseId binding
1046
+ // (from a prior install) doesn't match the new JWT's licenseId.
1047
+ //
1048
+ // Single-surface clearing ("rm ~/.nsauditor/license-state.json")
1049
+ // is a HALF-fix on macOS — _readLicenseState (license.mjs:402-434)
1050
+ // ALSO reads from Keychain NSAUDITOR_LICENSE_ID, and Keychain wins
1051
+ // on read (license.mjs:429: `state.licenseId = kcId; // Keychain
1052
+ // wins`). Customer must additionally run
1053
+ // `security delete-generic-password -s nsauditor-ai -a
1054
+ // NSAUDITOR_LICENSE_ID` for the replay-defense check
1055
+ // (license.mjs:664-670) to pass. This subcommand does both
1056
+ // atomically so customers don't have to run cryptic `security`
1057
+ // commands blind from a support email.
1058
+ //
1059
+ // Default: preserves NSAUDITOR_LICENSE_KEY (the JWT itself) for
1060
+ // immediate re-activation on next license check. --purge also
1061
+ // removes the JWT (forces full re-install with `license install`).
1062
+ const purge = rawArgs.includes('--purge');
1063
+ const { _getLicenseStateFilePath } = await import('./utils/license.mjs');
1064
+ const { keychainDelete } = await import('./utils/keychain.mjs');
1065
+ const fsp = await import('fs/promises');
1066
+
1067
+ const cleared = { stateFile: false, keychainId: false, jwtPurged: false };
1068
+
1069
+ // 1. Delete license-state.json (cross-platform path resolver).
1070
+ const statePath = _getLicenseStateFilePath();
1071
+ try {
1072
+ await fsp.unlink(statePath);
1073
+ cleared.stateFile = true;
1074
+ } catch (e) {
1075
+ if (e && e.code !== 'ENOENT') {
1076
+ console.warn(`⚠ Could not delete ${statePath}: ${e.message}`);
1077
+ }
1078
+ }
1079
+
1080
+ // 2. Delete macOS Keychain NSAUDITOR_LICENSE_ID entry. Linux /
1081
+ // Windows have no Keychain side-channel — file delete is
1082
+ // sufficient there.
1083
+ if (process.platform === 'darwin') {
1084
+ try {
1085
+ cleared.keychainId = await keychainDelete('NSAUDITOR_LICENSE_ID');
1086
+ } catch { /* not fatal — file delete is the primary surface */ }
1087
+ }
1088
+
1089
+ // 3. Optionally purge the JWT itself (forces full re-install).
1090
+ // Darwin-only for now; file-based JWT purge on Linux/Windows
1091
+ // requires editing ~/.nsauditor/.env which we leave to the
1092
+ // operator (deleting the file would also remove unrelated env
1093
+ // vars the operator may have placed there).
1094
+ if (purge && process.platform === 'darwin') {
1095
+ try {
1096
+ cleared.jwtPurged = await keychainDelete('NSAUDITOR_LICENSE_KEY');
1097
+ } catch { /* not fatal */ }
1098
+ }
1099
+
1100
+ console.log('✓ License state reset');
1101
+ console.log(` License state file: ${cleared.stateFile ? 'deleted (' + statePath + ')' : 'not found (already clean)'}`);
1102
+ if (process.platform === 'darwin') {
1103
+ console.log(` Keychain NSAUDITOR_LICENSE_ID: ${cleared.keychainId ? 'deleted' : 'not found (already clean)'}`);
1104
+ }
1105
+ if (purge) {
1106
+ if (process.platform === 'darwin') {
1107
+ console.log(` Keychain NSAUDITOR_LICENSE_KEY (JWT): ${cleared.jwtPurged ? 'purged' : 'not found (already clean)'}`);
1108
+ } else {
1109
+ console.log(' JWT (NSAUDITOR_LICENSE_KEY): file-based JWT not purged on this platform — remove the NSAUDITOR_LICENSE_KEY line manually from ~/.nsauditor/.env if needed.');
1110
+ }
1111
+ console.log('');
1112
+ console.log(' Re-install with: nsauditor-ai license install <KEY>');
1113
+ } else {
1114
+ console.log(' JWT (NSAUDITOR_LICENSE_KEY): preserved (default) — next license check will re-bind.');
1115
+ console.log('');
1116
+ console.log(' Verify with: nsauditor-ai license --status');
1117
+ console.log(' (Add --purge to additionally clear the JWT for full uninstall.)');
1118
+ }
1041
1119
  } else if (rawArgs.includes('install')) {
1042
1120
  // CE-0.1.30.4 — install command. Verify the JWT FIRST, then persist
1043
1121
  // to a platform-appropriate location (macOS Keychain / file).
@@ -1099,7 +1177,7 @@ Docs: https://www.nsauditor.com/ai/ | Pricing: https://www.nsauditor.com/ai/
1099
1177
  console.log('');
1100
1178
  console.log(' Verify with: nsauditor-ai license --status');
1101
1179
  } else {
1102
- console.log('Usage: nsauditor-ai license --status | --capabilities | --plugins | install <KEY>');
1180
+ console.log('Usage: nsauditor-ai license --status | --capabilities | --plugins | install <KEY> | --reset [--purge]');
1103
1181
  }
1104
1182
  process.exit(0);
1105
1183
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nsauditor-ai",
3
- "version": "0.1.72",
3
+ "version": "0.1.73",
4
4
  "description": "Modular AI-assisted network security audit platform — Community Edition",
5
5
  "type": "module",
6
6
  "private": false,