nsauditor-ai 0.2.33 → 0.2.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,6 +17,8 @@ NSAuditor AI is the open-source core of a privacy-first security intelligence pl
17
17
 
18
18
  ## What's New
19
19
 
20
+ **Internal-provenance strip + a false-clean closure (CE 0.2.34 / Enterprise 0.32.9).** Paired with Enterprise 0.32.9. The evidence pack a customer hands their auditor no longer carries internal engineering markers — **686 unexplained occurrences → 0** on a rebuilt three-cloud pack, with a positive control so the zero is a measurement rather than an absence of looking. Two behavioural fixes ride with it: a cloud plugin that returns `up:false` (optional SDK absent, credentials unusable) now fail-closes an evidence gap on every in-scope control of that cloud instead of leaving them PASS, and an archived scan conclusion re-mapped through the new build warns instead of failing clean. CE's side: the MCP `scan_cloud` summary strips **both** spellings of the evidence-gap routing prefix, so an operator pairing this CE with an older Enterprise still gets a clean one-line summary. **⚠️ If you suppress by `titlePattern` on the old violation text, re-point it — see the [Enterprise CHANGELOG](https://github.com/nsasoft/nsauditor-ai-ee/blob/main/CHANGELOG.md).**
21
+
20
22
  **Capability-claim honesty pass, part 2 — the air-gapped-delivery class (CE 0.2.33 / Enterprise 0.32.8).** Paired with Enterprise 0.32.8, a **documentation-and-prose release** — no detection, routing, or compliance behaviour changes. 0.32.7 withdrew six phantom capability *flags*; an audit of the air-gapped-delivery claims found the same class one layer down, in prose, across **27 sites** (distinct lines) in the three published packages. **CE fix this cycle — `--out` with a version-named directory.** `--out .../ee-0.32.8` silently wrote artifacts to the *parent* directory: the file-vs-directory check keyed on "has an extension", and `path.parse('ee-0.32.8').ext` is `'.8'`. The same shape broke `v1.2.3` and `release-2026.07`. An extension now counts as file-like only if it starts with a letter, so version-named output directories work and `--out report.json` still resolves to its parent. Found by the pre-publish smoke gate running the documented command end-to-end. **CE docs change this cycle:** the ZDE section's *"Fully air-gappable. Every feature works without internet access"* is corrected to **"Air-gappable, once configured for it"** — scanning, analysis, license verification and evidence-pack generation all run with no outbound network access, and Enterprise adds offline CVE matching under `NSAUDITOR_OFFLINE_ONLY=1` (which emits an explicit coverage gap rather than a silent clean when the local store cannot answer), but a **default** scan still attempts NVD egress unless that variable is set, and the only other outbound paths — AI enrichment and the GRC push — are opt-in and off by default. The claim that Enterprise "includes offline NVD feeds" is **WITHDRAWN**: no feed data is delivered with the product, and populating the local store is the operator's. Held by a new mutation-proven guard (`tests/capability_claim_honesty.test.mjs`) that fails the build both if the absolute claim returns **and** if the honest qualifier is deleted. On the Enterprise side the same sweep found **five** rendered runtime strings — prose that reaches the assessor-facing evidence pack — making claims the code does not support. Plugin count UNCHANGED at 28; all seven coverage matrices UNCHANGED. See **[CHANGELOG.md](./CHANGELOG.md)** for the full per-release history.
21
23
 
22
24
  **Cross-framework routing + capability-claim honesty pass (CE 0.2.32 / Enterprise 0.32.7).** Paired with Enterprise 0.32.7, a **matrix-neutral** release. The network-scan analysis agents' findings now route in **all seven compliance frameworks** — a host serving cleartext or exposing SMB previously failed the SOC 2 report and read clean in HIPAA / NIST CSF / ISO 27001 / CIS v8 / PCI / GDPR off the *same scan*; that gap is closed (48 mapping rules across the seven framework files, a mutation-proven drift guard, all coverage matrices byte-identical). And a **capability-claim honesty pass** withdraws several Pro/Enterprise capabilities that were advertised without a shipping implementation. **CE code change this cycle:** the tier-capability map (`utils/capabilities.mjs`) drops six flags — `verificationEngine`, `brandedReports`, `usageMetering`, `dockerIsolation` (no implementation) and `zdePolicyEngine`, `enterpriseCTEM` (real cores ship + are claimed in prose; no distinct engine behind the name) — in lockstep with Enterprise and both licensing repos, so `nsauditor-ai license --capabilities` and every minted license now name only capabilities that ship. `resolveCapabilities(tier)` derives from tier and ignores the JWT capability array, so **issued licenses are unaffected**. Plugin count UNCHANGED at 28; all seven coverage matrices UNCHANGED. See **[CHANGELOG.md](./CHANGELOG.md)** for the full per-release history.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nsauditor-ai",
3
- "version": "0.2.33",
3
+ "version": "0.2.34",
4
4
  "description": "Modular AI-assisted network security audit platform — Community Edition",
5
5
  "type": "module",
6
6
  "private": false,
@@ -26,11 +26,19 @@ export const GAP_CLAUSE_RE =
26
26
  // Substrate-evidence PASS prose (1220/1222 push these into the same issues[] as
27
27
  // violations) — informational; never a lead clause while any alternative exists.
28
28
  const PASS_CLAUSE_RE = /substrate evidence:/i;
29
- // EE compliance-routing tag (e.g. 'EE-RT.1.2 multi-region-enumeration-incomplete: ')
30
- // leading many gap emissions — anchor plumbing for the EE framework JSONs, not
31
- // operator prose. Stripped at THIS presentation layer only (routing matches the
32
- // RAW issue strings EE-side) so the 160-char slice spends its budget on substance.
33
- const ROUTING_PREFIX_RE = /^EE-RT\.[\dx.]+ [a-z][a-z-]*: /;
29
+ // EE compliance-routing tag leading many gap emissions — anchor plumbing for the EE
30
+ // framework JSONs, not operator prose. Stripped at THIS presentation layer only (routing
31
+ // matches the RAW issue strings EE-side) so the 160-char slice spends its budget on
32
+ // substance; the [⚠ EVIDENCE GAP] badge already says it is a gap.
33
+ //
34
+ // TWO SPELLINGS, and the old one must stay. EE renamed the prefix in its A1 cycle ③ —
35
+ // `EE-RT.1.2 multi-region-enumeration-incomplete: ` became
36
+ // `Evidence gap (multi-region enumeration incomplete): ` — because it renders as the
37
+ // violation TITLE in the customer's evidence pack and an internal roadmap id has no
38
+ // business there. CE ships independently of EE and an operator can pair ANY supported EE
39
+ // with this CE, so dropping the old alternative would leave the old prefix unstripped on
40
+ // every paired-with-older-EE run. Recognise both.
41
+ const ROUTING_PREFIX_RE = /^(?:EE-RT\.[\dx.]+ [a-z][a-z-]*|Evidence gap \((?:scan time budget exceeded|multi-region enumeration incomplete)\)): /;
34
42
 
35
43
  function classifyClause(s) {
36
44
  if (PASS_CLAUSE_RE.test(s)) return 'pass';
@@ -57,11 +57,33 @@ export async function checkPlugins({ discover, pkgRoot = PKG_ROOT } = {}) {
57
57
  const fn = discover || (await import('./plugin_discovery.mjs')).discoverPlugins;
58
58
  const result = await fn(pkgRoot);
59
59
  const plugins = Array.isArray(result) ? result : (result?.plugins ?? []);
60
+ // `discoverPlugins` reads THREE sources: CE plugins under `pkgRoot`, the EE package
61
+ // resolved GLOBALLY (it is a separate npm package, so `pkgRoot` cannot and should not
62
+ // reach it), and NSAUDITOR_PLUGIN_PATH. Reporting the aggregate count beside a single
63
+ // `basePath` produced "28 plugins loaded / basePath: <dir>" for a directory containing
64
+ // NONE of them — a false report from the command an operator runs to check their install.
65
+ // Each plugin already carries `_source`; use it, so `basePath` describes what it counts.
66
+ const bySource = {};
67
+ for (const p of plugins) bySource[p?._source ?? 'unknown'] = (bySource[p?._source ?? 'unknown'] ?? 0) + 1;
68
+ const ceCount = bySource.ce ?? 0;
69
+ const others = Object.entries(bySource).filter(([k]) => k !== 'ce');
70
+ // Only claim attribution we actually have. An injected `discover` (tests, embedders) may
71
+ // return plugins without `_source`; asserting "0 at basePath" there would be a different
72
+ // false report from the one this fix removes.
73
+ const attributable = Object.keys(bySource).some((k) => k !== 'unknown');
74
+ const suffix = others.length ? ` (+ ${others.map(([k, n]) => `${n} ${k}`).join(', ')})` : '';
60
75
  return {
61
76
  name: 'plugins',
62
77
  status: STATUSES.OK,
63
- message: `${plugins.length} plugin${plugins.length === 1 ? '' : 's'} loaded`,
64
- details: { count: plugins.length, basePath: pkgRoot },
78
+ message: attributable
79
+ ? `${ceCount} plugin${ceCount === 1 ? '' : 's'} at basePath${suffix}`
80
+ : `${plugins.length} plugin${plugins.length === 1 ? '' : 's'} loaded`,
81
+ details: {
82
+ count: plugins.length,
83
+ basePathCount: attributable ? ceCount : plugins.length,
84
+ bySource,
85
+ basePath: pkgRoot,
86
+ },
65
87
  };
66
88
  } catch (err) {
67
89
  return {