@x12i/memorix-retrieval 1.30.0 → 1.31.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.
Files changed (51) hide show
  1. package/catalox-seeds/inputs/entity-descriptors/assets.json +106 -18
  2. package/catalox-seeds/inputs/entity-descriptors/subnets.json +61 -8
  3. package/catalox-seeds/inputs/entity-descriptors/vulnerabilities-groups.json +9 -3
  4. package/catalox-seeds/inputs/entity-descriptors/vulnerabilities.json +121 -6
  5. package/catalox-seeds/inputs/item-descriptors/asset-detail-item.json +0 -1
  6. package/catalox-seeds/inputs/item-descriptors/vulnerability-detail-item.json +1 -0
  7. package/catalox-seeds/inputs/list-descriptors/assets-main-list.json +0 -2
  8. package/catalox-seeds/inputs/list-descriptors/vulnerabilities-main-list.json +2 -0
  9. package/catalox-seeds/memorix-retrieval-descriptors.manifest.json +384 -57
  10. package/dist/analysis/analyze-vulnerability-coverage.d.ts +101 -0
  11. package/dist/analysis/analyze-vulnerability-coverage.d.ts.map +1 -0
  12. package/dist/analysis/analyze-vulnerability-coverage.js +150 -0
  13. package/dist/analysis/analyze-vulnerability-coverage.js.map +1 -0
  14. package/dist/analysis/count-assets-with-vulnerabilities.d.ts +89 -0
  15. package/dist/analysis/count-assets-with-vulnerabilities.d.ts.map +1 -0
  16. package/dist/analysis/count-assets-with-vulnerabilities.js +143 -0
  17. package/dist/analysis/count-assets-with-vulnerabilities.js.map +1 -0
  18. package/dist/analysis/derive-subnet-ip.d.ts +18 -0
  19. package/dist/analysis/derive-subnet-ip.d.ts.map +1 -0
  20. package/dist/analysis/derive-subnet-ip.js +32 -0
  21. package/dist/analysis/derive-subnet-ip.js.map +1 -0
  22. package/dist/descriptors/content-type-labels.d.ts.map +1 -1
  23. package/dist/descriptors/content-type-labels.js +4 -5
  24. package/dist/descriptors/content-type-labels.js.map +1 -1
  25. package/dist/descriptors/descriptor-types.d.ts +48 -0
  26. package/dist/descriptors/descriptor-types.d.ts.map +1 -1
  27. package/dist/mongo/env.d.ts +1 -0
  28. package/dist/mongo/env.d.ts.map +1 -1
  29. package/dist/mongo/env.js +9 -1
  30. package/dist/mongo/env.js.map +1 -1
  31. package/dist/retrieval/fetch-narratives.d.ts +5 -0
  32. package/dist/retrieval/fetch-narratives.d.ts.map +1 -1
  33. package/dist/retrieval/fetch-narratives.js +99 -9
  34. package/dist/retrieval/fetch-narratives.js.map +1 -1
  35. package/dist/tests/analyze-vulnerability-coverage.test.d.ts +2 -0
  36. package/dist/tests/analyze-vulnerability-coverage.test.d.ts.map +1 -0
  37. package/dist/tests/analyze-vulnerability-coverage.test.js +66 -0
  38. package/dist/tests/analyze-vulnerability-coverage.test.js.map +1 -0
  39. package/dist/tests/count-assets-with-vulnerabilities.test.d.ts +2 -0
  40. package/dist/tests/count-assets-with-vulnerabilities.test.d.ts.map +1 -0
  41. package/dist/tests/count-assets-with-vulnerabilities.test.js +95 -0
  42. package/dist/tests/count-assets-with-vulnerabilities.test.js.map +1 -0
  43. package/dist/tests/derive-subnet-ip.test.d.ts +2 -0
  44. package/dist/tests/derive-subnet-ip.test.d.ts.map +1 -0
  45. package/dist/tests/derive-subnet-ip.test.js +17 -0
  46. package/dist/tests/derive-subnet-ip.test.js.map +1 -0
  47. package/dist/tests/env.test.js +1 -1
  48. package/dist/tests/env.test.js.map +1 -1
  49. package/dist/tests/fetch-narratives.test.js +191 -5
  50. package/dist/tests/fetch-narratives.test.js.map +1 -1
  51. package/package.json +2 -2
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Vulnerability-side coverage analysis: asset inventory match, severity, subnet resolution.
3
+ */
4
+ import { type AssetJoinDoc, type VulnerabilityJoinDoc } from "./count-assets-with-vulnerabilities.js";
5
+ export type CidrIndexEntry = {
6
+ cidr: string;
7
+ recordId?: string;
8
+ range: {
9
+ network: number;
10
+ broadcast: number;
11
+ prefix: number;
12
+ } | null;
13
+ };
14
+ export type SubnetMatchResult = {
15
+ status: "known";
16
+ cidr: string;
17
+ recordId?: string;
18
+ } | {
19
+ status: "unknown";
20
+ reason: "unparseable-ip" | "no-containing-cidr";
21
+ };
22
+ export type VulnerabilityAssetMatch = {
23
+ recordId?: string;
24
+ assetIp: string | null;
25
+ hasAssetInInventory: boolean;
26
+ isCriticalOrHigh: boolean;
27
+ severity: string | null;
28
+ };
29
+ export type VulnerabilitySubnetCoverage = {
30
+ assetIp: string | null;
31
+ subnetIp: string | null;
32
+ subnetIpDerivable: boolean;
33
+ subnetKnown: boolean;
34
+ subnetMatch: SubnetMatchResult | null;
35
+ };
36
+ export type VulnerabilityCoverageSummary = {
37
+ totalVulnerabilities: number;
38
+ withAssetInInventory: number;
39
+ withoutAssetInInventory: number;
40
+ criticalOrHighTotal: number;
41
+ criticalOrHighWithAsset: number;
42
+ criticalOrHighWithoutAsset: number;
43
+ derivableSubnetIp: number;
44
+ notDerivableSubnetIp: number;
45
+ knownSubnet: number;
46
+ unknownSubnet: number;
47
+ };
48
+ /** All join IPs present anywhere in the asset inventory. */
49
+ export declare function collectInventoryAssetIps(assets: AssetJoinDoc[]): Set<string>;
50
+ /** Does this vulnerability's assetIp appear in the asset inventory? */
51
+ export declare function vulnerabilityHasAssetInInventory(vuln: VulnerabilityJoinDoc, inventoryIps: Set<string>): boolean;
52
+ export declare function classifyVulnerabilityAssetMatch(vuln: VulnerabilityJoinDoc, inventoryIps: Set<string>): VulnerabilityAssetMatch;
53
+ /**
54
+ * Longest-prefix CIDR match — same semantics as `@x12i/memorix-resolvers` findLongestPrefixMatch.
55
+ * Kept local to avoid coupling memorix-retrieval to memorix-resolvers in unit tests.
56
+ */
57
+ export declare function findLongestPrefixMatchLocal(assetIp: string, cidrIndex: CidrIndexEntry[]): SubnetMatchResult;
58
+ export declare function resolveVulnerabilitySubnetIp(vuln: VulnerabilityJoinDoc): string | null;
59
+ export declare function classifyVulnerabilitySubnet(vuln: VulnerabilityJoinDoc, cidrIndex: CidrIndexEntry[]): VulnerabilitySubnetCoverage;
60
+ export declare function summarizeVulnerabilityCoverage(vulnerabilities: VulnerabilityJoinDoc[], assets: AssetJoinDoc[], cidrIndex?: CidrIndexEntry[]): VulnerabilityCoverageSummary;
61
+ /** Mongo filter: vulnerabilities whose assetIp is in the asset inventory. */
62
+ export declare function buildVulnerabilityAssetMatchFilter(inventoryIps: string[]): {
63
+ "data.assetIp": {
64
+ $in: string[];
65
+ };
66
+ };
67
+ /** Mongo filter: vulnerabilities with no asset inventory match. */
68
+ export declare function buildVulnerabilityAssetMissFilter(inventoryIps: string[]): {
69
+ "data.assetIp": {
70
+ $nin: string[];
71
+ };
72
+ };
73
+ /** Mongo filter: critical or high severity vulnerabilities. */
74
+ export declare function buildCriticalOrHighVulnerabilityFilter(): {
75
+ "data.severity": {
76
+ $in: string[];
77
+ };
78
+ };
79
+ /** Assets with no linked vulnerability = complement of join filter. */
80
+ export declare function buildAssetsWithoutVulnerabilitiesFilter(vulnerabilityIps: string[]): {
81
+ $nor: ({
82
+ "data.assetIps": {
83
+ $in: string[];
84
+ };
85
+ "data.assetIp"?: undefined;
86
+ "data.ip_address"?: undefined;
87
+ } | {
88
+ "data.assetIp": {
89
+ $in: string[];
90
+ };
91
+ "data.assetIps"?: undefined;
92
+ "data.ip_address"?: undefined;
93
+ } | {
94
+ "data.ip_address": {
95
+ $in: string[];
96
+ };
97
+ "data.assetIps"?: undefined;
98
+ "data.assetIp"?: undefined;
99
+ })[];
100
+ };
101
+ //# sourceMappingURL=analyze-vulnerability-coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-vulnerability-coverage.d.ts","sourceRoot":"","sources":["../../src/analysis/analyze-vulnerability-coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Vulnerability-side coverage analysis: asset inventory match, severity, subnet resolution.
3
+ */
4
+ import { deriveSubnetIpFromAssetIp } from "./derive-subnet-ip.js";
5
+ import { collectAssetJoinIps, isCriticalOrHighSeverity, resolveVulnerabilitySeverity, } from "./count-assets-with-vulnerabilities.js";
6
+ function asNonEmptyString(value) {
7
+ if (typeof value !== "string")
8
+ return null;
9
+ const trimmed = value.trim();
10
+ return trimmed.length > 0 ? trimmed : null;
11
+ }
12
+ /** All join IPs present anywhere in the asset inventory. */
13
+ export function collectInventoryAssetIps(assets) {
14
+ const ips = new Set();
15
+ for (const asset of assets) {
16
+ for (const ip of collectAssetJoinIps(asset))
17
+ ips.add(ip);
18
+ }
19
+ return ips;
20
+ }
21
+ /** Does this vulnerability's assetIp appear in the asset inventory? */
22
+ export function vulnerabilityHasAssetInInventory(vuln, inventoryIps) {
23
+ const assetIp = asNonEmptyString(vuln.data?.assetIp);
24
+ return assetIp !== null && inventoryIps.has(assetIp);
25
+ }
26
+ export function classifyVulnerabilityAssetMatch(vuln, inventoryIps) {
27
+ const assetIp = asNonEmptyString(vuln.data?.assetIp);
28
+ const severity = resolveVulnerabilitySeverity(vuln);
29
+ return {
30
+ assetIp,
31
+ hasAssetInInventory: assetIp !== null && inventoryIps.has(assetIp),
32
+ isCriticalOrHigh: isCriticalOrHighSeverity(severity),
33
+ severity,
34
+ };
35
+ }
36
+ /**
37
+ * Longest-prefix CIDR match — same semantics as `@x12i/memorix-resolvers` findLongestPrefixMatch.
38
+ * Kept local to avoid coupling memorix-retrieval to memorix-resolvers in unit tests.
39
+ */
40
+ export function findLongestPrefixMatchLocal(assetIp, cidrIndex) {
41
+ const parts = assetIp.split(".").map((p) => Number(p));
42
+ if (parts.length !== 4 || parts.some((p) => !Number.isInteger(p) || p < 0 || p > 255)) {
43
+ return { status: "unknown", reason: "unparseable-ip" };
44
+ }
45
+ const ipInt = ((parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]) >>> 0;
46
+ let best = null;
47
+ for (const entry of cidrIndex) {
48
+ const range = entry.range;
49
+ if (!range)
50
+ continue;
51
+ if (ipInt >= range.network && ipInt <= range.broadcast) {
52
+ if (!best || range.prefix > best.range.prefix)
53
+ best = { entry, range };
54
+ }
55
+ }
56
+ if (!best)
57
+ return { status: "unknown", reason: "no-containing-cidr" };
58
+ return {
59
+ status: "known",
60
+ cidr: best.entry.cidr,
61
+ recordId: best.entry.recordId,
62
+ };
63
+ }
64
+ export function resolveVulnerabilitySubnetIp(vuln) {
65
+ const stored = asNonEmptyString(vuln.data?.subnetIp);
66
+ if (stored)
67
+ return stored;
68
+ return deriveSubnetIpFromAssetIp(vuln.data?.assetIp);
69
+ }
70
+ export function classifyVulnerabilitySubnet(vuln, cidrIndex) {
71
+ const assetIp = asNonEmptyString(vuln.data?.assetIp);
72
+ const subnetIp = resolveVulnerabilitySubnetIp(vuln);
73
+ const subnetIpDerivable = subnetIp !== null;
74
+ if (!assetIp || !subnetIpDerivable) {
75
+ return {
76
+ assetIp,
77
+ subnetIp,
78
+ subnetIpDerivable,
79
+ subnetKnown: false,
80
+ subnetMatch: null,
81
+ };
82
+ }
83
+ const subnetMatch = findLongestPrefixMatchLocal(assetIp, cidrIndex);
84
+ return {
85
+ assetIp,
86
+ subnetIp,
87
+ subnetIpDerivable,
88
+ subnetKnown: subnetMatch.status === "known",
89
+ subnetMatch,
90
+ };
91
+ }
92
+ export function summarizeVulnerabilityCoverage(vulnerabilities, assets, cidrIndex = []) {
93
+ const inventoryIps = collectInventoryAssetIps(assets);
94
+ let withAssetInInventory = 0;
95
+ let criticalOrHighTotal = 0;
96
+ let criticalOrHighWithAsset = 0;
97
+ let derivableSubnetIp = 0;
98
+ let knownSubnet = 0;
99
+ for (const vuln of vulnerabilities) {
100
+ const match = classifyVulnerabilityAssetMatch(vuln, inventoryIps);
101
+ if (match.hasAssetInInventory)
102
+ withAssetInInventory += 1;
103
+ if (match.isCriticalOrHigh) {
104
+ criticalOrHighTotal += 1;
105
+ if (match.hasAssetInInventory)
106
+ criticalOrHighWithAsset += 1;
107
+ }
108
+ const subnet = classifyVulnerabilitySubnet(vuln, cidrIndex);
109
+ if (subnet.subnetIpDerivable)
110
+ derivableSubnetIp += 1;
111
+ if (subnet.subnetKnown)
112
+ knownSubnet += 1;
113
+ }
114
+ const totalVulnerabilities = vulnerabilities.length;
115
+ return {
116
+ totalVulnerabilities,
117
+ withAssetInInventory,
118
+ withoutAssetInInventory: totalVulnerabilities - withAssetInInventory,
119
+ criticalOrHighTotal,
120
+ criticalOrHighWithAsset,
121
+ criticalOrHighWithoutAsset: criticalOrHighTotal - criticalOrHighWithAsset,
122
+ derivableSubnetIp,
123
+ notDerivableSubnetIp: totalVulnerabilities - derivableSubnetIp,
124
+ knownSubnet,
125
+ unknownSubnet: derivableSubnetIp - knownSubnet,
126
+ };
127
+ }
128
+ /** Mongo filter: vulnerabilities whose assetIp is in the asset inventory. */
129
+ export function buildVulnerabilityAssetMatchFilter(inventoryIps) {
130
+ return { "data.assetIp": { $in: inventoryIps } };
131
+ }
132
+ /** Mongo filter: vulnerabilities with no asset inventory match. */
133
+ export function buildVulnerabilityAssetMissFilter(inventoryIps) {
134
+ return { "data.assetIp": { $nin: inventoryIps } };
135
+ }
136
+ /** Mongo filter: critical or high severity vulnerabilities. */
137
+ export function buildCriticalOrHighVulnerabilityFilter() {
138
+ return { "data.severity": { $in: ["critical", "high"] } };
139
+ }
140
+ /** Assets with no linked vulnerability = complement of join filter. */
141
+ export function buildAssetsWithoutVulnerabilitiesFilter(vulnerabilityIps) {
142
+ return {
143
+ $nor: [
144
+ { "data.assetIps": { $in: vulnerabilityIps } },
145
+ { "data.assetIp": { $in: vulnerabilityIps } },
146
+ { "data.ip_address": { $in: vulnerabilityIps } },
147
+ ],
148
+ };
149
+ }
150
+ //# sourceMappingURL=analyze-vulnerability-coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-vulnerability-coverage.js","sourceRoot":"","sources":["../../src/analysis/analyze-vulnerability-coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Count assets that have at least one linked vulnerability via the
3
+ * `assetVulnerabilities` relation join:
4
+ * assets.data.assetIps[] / assets.data.assetIp ↔ vulnerabilities.data.assetIp
5
+ */
6
+ export type AssetJoinDoc = {
7
+ recordId?: string;
8
+ entityId?: string;
9
+ data?: {
10
+ assetIps?: unknown;
11
+ assetIp?: unknown;
12
+ ip_address?: unknown;
13
+ };
14
+ };
15
+ export type VulnerabilityJoinDoc = {
16
+ data?: {
17
+ assetIp?: unknown;
18
+ subnetIp?: unknown;
19
+ severity?: unknown;
20
+ severityLevel?: unknown;
21
+ riskLevel?: unknown;
22
+ };
23
+ };
24
+ /** Resolve severity from common vulnerability snapshot fields. */
25
+ export declare function resolveVulnerabilitySeverity(vuln: VulnerabilityJoinDoc): string | null;
26
+ export declare function isCriticalOrHighSeverity(severity: string | null): boolean;
27
+ /** Collect all IP values used to join an asset to vulnerabilities. */
28
+ export declare function collectAssetJoinIps(asset: AssetJoinDoc): string[];
29
+ /** Collect distinct vulnerability join IPs from in-memory docs. */
30
+ export declare function collectVulnerabilityJoinIps(vulnerabilities: VulnerabilityJoinDoc[]): Set<string>;
31
+ export declare function assetHasLinkedVulnerability(asset: AssetJoinDoc, vulnerabilityIps: Set<string>): boolean;
32
+ export declare function resolveAssetRecordId(asset: AssetJoinDoc): string;
33
+ export type AssetVulnerabilityExposure = {
34
+ recordId: string;
35
+ hasAnyVulnerability: boolean;
36
+ hasCriticalOrHighVulnerability: boolean;
37
+ vulnerabilityCount: number;
38
+ criticalOrHighCount: number;
39
+ };
40
+ export type AssetsWithVulnerabilitiesSummary = {
41
+ totalAssets: number;
42
+ assetsWithAnyVulnerability: number;
43
+ assetsWithCriticalOrHighVulnerability: number;
44
+ assetsWithoutVulnerabilities: number;
45
+ anyVulnerabilityCoveragePct: number;
46
+ criticalOrHighCoveragePct: number;
47
+ distinctVulnerabilityIps: number;
48
+ distinctVulnerabilityIpsMatchingAssets: number;
49
+ assetIdsWithAnyVulnerability: string[];
50
+ assetIdsWithCriticalOrHighVulnerability: string[];
51
+ /** @deprecated use assetsWithAnyVulnerability */
52
+ assetsWithVulnerabilities: number;
53
+ /** @deprecated use assetIdsWithAnyVulnerability */
54
+ assetIdsWithVulnerabilities: string[];
55
+ /** @deprecated use anyVulnerabilityCoveragePct */
56
+ coveragePct: number;
57
+ };
58
+ export declare function buildVulnerabilityExposureByIp(vulnerabilities: VulnerabilityJoinDoc[]): Map<string, {
59
+ total: number;
60
+ criticalOrHigh: number;
61
+ }>;
62
+ export declare function summarizeAssetVulnerabilityExposure(asset: AssetJoinDoc, exposureByIp: Map<string, {
63
+ total: number;
64
+ criticalOrHigh: number;
65
+ }>): AssetVulnerabilityExposure;
66
+ export declare function summarizeAssetsWithVulnerabilities(assets: AssetJoinDoc[], vulnerabilities: VulnerabilityJoinDoc[]): AssetsWithVulnerabilitiesSummary;
67
+ /** Mongo filter for assets whose join IPs intersect vulnerability IPs. */
68
+ export declare function buildAssetVulnerabilityJoinFilter(vulnerabilityIps: string[]): {
69
+ $or: ({
70
+ "data.assetIps": {
71
+ $in: string[];
72
+ };
73
+ "data.assetIp"?: undefined;
74
+ "data.ip_address"?: undefined;
75
+ } | {
76
+ "data.assetIp": {
77
+ $in: string[];
78
+ };
79
+ "data.assetIps"?: undefined;
80
+ "data.ip_address"?: undefined;
81
+ } | {
82
+ "data.ip_address": {
83
+ $in: string[];
84
+ };
85
+ "data.assetIps"?: undefined;
86
+ "data.assetIp"?: undefined;
87
+ })[];
88
+ };
89
+ //# sourceMappingURL=count-assets-with-vulnerabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"count-assets-with-vulnerabilities.d.ts","sourceRoot":"","sources":["../../src/analysis/count-assets-with-vulnerabilities.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC;CACH,CAAC;AASF,kEAAkE;AAClE,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,GAAG,IAAI,CAMtF;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAEzE;AAQD,sEAAsE;AACtE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,EAAE,CAgBjE;AAED,mEAAmE;AACnE,wBAAgB,2BAA2B,CACzC,eAAe,EAAE,oBAAoB,EAAE,GACtC,GAAG,CAAC,MAAM,CAAC,CAOb;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,YAAY,EACnB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC5B,OAAO,CAET;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAEhE;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,8BAA8B,EAAE,OAAO,CAAC;IACxC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,0BAA0B,EAAE,MAAM,CAAC;IACnC,qCAAqC,EAAE,MAAM,CAAC;IAC9C,4BAA4B,EAAE,MAAM,CAAC;IACrC,2BAA2B,EAAE,MAAM,CAAC;IACpC,yBAAyB,EAAE,MAAM,CAAC;IAClC,wBAAwB,EAAE,MAAM,CAAC;IACjC,sCAAsC,EAAE,MAAM,CAAC;IAC/C,4BAA4B,EAAE,MAAM,EAAE,CAAC;IACvC,uCAAuC,EAAE,MAAM,EAAE,CAAC;IAClD,iDAAiD;IACjD,yBAAyB,EAAE,MAAM,CAAC;IAClC,mDAAmD;IACnD,2BAA2B,EAAE,MAAM,EAAE,CAAC;IACtC,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,wBAAgB,8BAA8B,CAC5C,eAAe,EAAE,oBAAoB,EAAE,GACtC,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,CAexD;AAED,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,YAAY,EACnB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,GACnE,0BAA0B,CAmB5B;AAED,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,YAAY,EAAE,EACtB,eAAe,EAAE,oBAAoB,EAAE,GACtC,gCAAgC,CA8ClC;AAED,0EAA0E;AAC1E,wBAAgB,iCAAiC,CAAC,gBAAgB,EAAE,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;EAQ3E"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Count assets that have at least one linked vulnerability via the
3
+ * `assetVulnerabilities` relation join:
4
+ * assets.data.assetIps[] / assets.data.assetIp ↔ vulnerabilities.data.assetIp
5
+ */
6
+ const CRITICAL_OR_HIGH_SEVERITIES = new Set(["critical", "high"]);
7
+ function normalizeSeverity(value) {
8
+ const text = asNonEmptyString(value);
9
+ return text ? text.toLowerCase() : null;
10
+ }
11
+ /** Resolve severity from common vulnerability snapshot fields. */
12
+ export function resolveVulnerabilitySeverity(vuln) {
13
+ return (normalizeSeverity(vuln.data?.severity) ??
14
+ normalizeSeverity(vuln.data?.severityLevel) ??
15
+ normalizeSeverity(vuln.data?.riskLevel));
16
+ }
17
+ export function isCriticalOrHighSeverity(severity) {
18
+ return severity !== null && CRITICAL_OR_HIGH_SEVERITIES.has(severity);
19
+ }
20
+ function asNonEmptyString(value) {
21
+ if (typeof value !== "string")
22
+ return null;
23
+ const trimmed = value.trim();
24
+ return trimmed.length > 0 ? trimmed : null;
25
+ }
26
+ /** Collect all IP values used to join an asset to vulnerabilities. */
27
+ export function collectAssetJoinIps(asset) {
28
+ const ips = new Set();
29
+ const push = (value) => {
30
+ const ip = asNonEmptyString(value);
31
+ if (ip)
32
+ ips.add(ip);
33
+ };
34
+ push(asset.data?.assetIp);
35
+ push(asset.data?.ip_address);
36
+ const assetIps = asset.data?.assetIps;
37
+ if (Array.isArray(assetIps)) {
38
+ for (const entry of assetIps)
39
+ push(entry);
40
+ }
41
+ return [...ips];
42
+ }
43
+ /** Collect distinct vulnerability join IPs from in-memory docs. */
44
+ export function collectVulnerabilityJoinIps(vulnerabilities) {
45
+ const ips = new Set();
46
+ for (const vuln of vulnerabilities) {
47
+ const ip = asNonEmptyString(vuln.data?.assetIp);
48
+ if (ip)
49
+ ips.add(ip);
50
+ }
51
+ return ips;
52
+ }
53
+ export function assetHasLinkedVulnerability(asset, vulnerabilityIps) {
54
+ return collectAssetJoinIps(asset).some((ip) => vulnerabilityIps.has(ip));
55
+ }
56
+ export function resolveAssetRecordId(asset) {
57
+ return asset.recordId ?? asset.entityId ?? "(unknown)";
58
+ }
59
+ export function buildVulnerabilityExposureByIp(vulnerabilities) {
60
+ const byIp = new Map();
61
+ for (const vuln of vulnerabilities) {
62
+ const ip = asNonEmptyString(vuln.data?.assetIp);
63
+ if (!ip)
64
+ continue;
65
+ const severity = resolveVulnerabilitySeverity(vuln);
66
+ const entry = byIp.get(ip) ?? { total: 0, criticalOrHigh: 0 };
67
+ entry.total += 1;
68
+ if (isCriticalOrHighSeverity(severity))
69
+ entry.criticalOrHigh += 1;
70
+ byIp.set(ip, entry);
71
+ }
72
+ return byIp;
73
+ }
74
+ export function summarizeAssetVulnerabilityExposure(asset, exposureByIp) {
75
+ const recordId = resolveAssetRecordId(asset);
76
+ let vulnerabilityCount = 0;
77
+ let criticalOrHighCount = 0;
78
+ for (const ip of collectAssetJoinIps(asset)) {
79
+ const exposure = exposureByIp.get(ip);
80
+ if (!exposure)
81
+ continue;
82
+ vulnerabilityCount += exposure.total;
83
+ criticalOrHighCount += exposure.criticalOrHigh;
84
+ }
85
+ return {
86
+ recordId,
87
+ hasAnyVulnerability: vulnerabilityCount > 0,
88
+ hasCriticalOrHighVulnerability: criticalOrHighCount > 0,
89
+ vulnerabilityCount,
90
+ criticalOrHighCount,
91
+ };
92
+ }
93
+ export function summarizeAssetsWithVulnerabilities(assets, vulnerabilities) {
94
+ const vulnerabilityIps = collectVulnerabilityJoinIps(vulnerabilities);
95
+ const exposureByIp = buildVulnerabilityExposureByIp(vulnerabilities);
96
+ const assetIdsWithAnyVulnerability = [];
97
+ const assetIdsWithCriticalOrHighVulnerability = [];
98
+ const matchedVulnIps = new Set();
99
+ for (const asset of assets) {
100
+ const exposure = summarizeAssetVulnerabilityExposure(asset, exposureByIp);
101
+ if (!exposure.hasAnyVulnerability)
102
+ continue;
103
+ assetIdsWithAnyVulnerability.push(exposure.recordId);
104
+ if (exposure.hasCriticalOrHighVulnerability) {
105
+ assetIdsWithCriticalOrHighVulnerability.push(exposure.recordId);
106
+ }
107
+ for (const ip of collectAssetJoinIps(asset)) {
108
+ if (vulnerabilityIps.has(ip))
109
+ matchedVulnIps.add(ip);
110
+ }
111
+ }
112
+ const totalAssets = assets.length;
113
+ const assetsWithAnyVulnerability = assetIdsWithAnyVulnerability.length;
114
+ const assetsWithCriticalOrHighVulnerability = assetIdsWithCriticalOrHighVulnerability.length;
115
+ return {
116
+ totalAssets,
117
+ assetsWithAnyVulnerability,
118
+ assetsWithCriticalOrHighVulnerability,
119
+ assetsWithoutVulnerabilities: totalAssets - assetsWithAnyVulnerability,
120
+ anyVulnerabilityCoveragePct: totalAssets === 0 ? 0 : (assetsWithAnyVulnerability / totalAssets) * 100,
121
+ criticalOrHighCoveragePct: totalAssets === 0
122
+ ? 0
123
+ : (assetsWithCriticalOrHighVulnerability / totalAssets) * 100,
124
+ distinctVulnerabilityIps: vulnerabilityIps.size,
125
+ distinctVulnerabilityIpsMatchingAssets: matchedVulnIps.size,
126
+ assetIdsWithAnyVulnerability,
127
+ assetIdsWithCriticalOrHighVulnerability,
128
+ assetsWithVulnerabilities: assetsWithAnyVulnerability,
129
+ assetIdsWithVulnerabilities: assetIdsWithAnyVulnerability,
130
+ coveragePct: totalAssets === 0 ? 0 : (assetsWithAnyVulnerability / totalAssets) * 100,
131
+ };
132
+ }
133
+ /** Mongo filter for assets whose join IPs intersect vulnerability IPs. */
134
+ export function buildAssetVulnerabilityJoinFilter(vulnerabilityIps) {
135
+ return {
136
+ $or: [
137
+ { "data.assetIps": { $in: vulnerabilityIps } },
138
+ { "data.assetIp": { $in: vulnerabilityIps } },
139
+ { "data.ip_address": { $in: vulnerabilityIps } },
140
+ ],
141
+ };
142
+ }
143
+ //# sourceMappingURL=count-assets-with-vulnerabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"count-assets-with-vulnerabilities.js","sourceRoot":"","sources":["../../src/analysis/count-assets-with-vulnerabilities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Derive legacy subnet keys from IPv4 addresses — first three octets.
3
+ * Same rule as `scripts/memorix-2.0-migrate/patches/backfill-assets-snapshots-subnet-ip.mjs`.
4
+ *
5
+ * Example: 10.38.16.147 -> 10.38.16
6
+ */
7
+ export declare function deriveSubnetIpFromAssetIp(value: unknown): string | null;
8
+ export declare function resolveVulnerabilityAssetIp(vuln: {
9
+ data?: {
10
+ assetIp?: unknown;
11
+ };
12
+ }): string | null;
13
+ export declare function deriveSubnetIpForVulnerability(vuln: {
14
+ data?: {
15
+ assetIp?: unknown;
16
+ };
17
+ }): string | null;
18
+ //# sourceMappingURL=derive-subnet-ip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-subnet-ip.d.ts","sourceRoot":"","sources":["../../src/analysis/derive-subnet-ip.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAcvE;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC9B,GAAG,MAAM,GAAG,IAAI,CAKhB;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE;IACnD,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC9B,GAAG,MAAM,GAAG,IAAI,CAEhB"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Derive legacy subnet keys from IPv4 addresses — first three octets.
3
+ * Same rule as `scripts/memorix-2.0-migrate/patches/backfill-assets-snapshots-subnet-ip.mjs`.
4
+ *
5
+ * Example: 10.38.16.147 -> 10.38.16
6
+ */
7
+ const IPV4_RE = /\b(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\b/;
8
+ export function deriveSubnetIpFromAssetIp(value) {
9
+ if (value === null || value === undefined)
10
+ return null;
11
+ const text = String(value).trim();
12
+ if (!text)
13
+ return null;
14
+ const match = text.match(IPV4_RE);
15
+ if (!match)
16
+ return null;
17
+ const octets = [match[1], match[2], match[3], match[4]].map((part) => Number(part));
18
+ if (octets.some((n) => !Number.isInteger(n) || n < 0 || n > 255))
19
+ return null;
20
+ return `${octets[0]}.${octets[1]}.${octets[2]}`;
21
+ }
22
+ export function resolveVulnerabilityAssetIp(vuln) {
23
+ const ip = vuln.data?.assetIp;
24
+ if (typeof ip !== "string")
25
+ return null;
26
+ const trimmed = ip.trim();
27
+ return trimmed.length > 0 ? trimmed : null;
28
+ }
29
+ export function deriveSubnetIpForVulnerability(vuln) {
30
+ return deriveSubnetIpFromAssetIp(resolveVulnerabilityAssetIp(vuln));
31
+ }
32
+ //# sourceMappingURL=derive-subnet-ip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-subnet-ip.js","sourceRoot":"","sources":["../../src/analysis/derive-subnet-ip.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,OAAO,GAAG,gDAAgD,CAAC;AAEjE,MAAM,UAAU,yBAAyB,CAAC,KAAc;IACtD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACnE,MAAM,CAAC,IAAI,CAAC,CACb,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9E,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,IAE3C;IACC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;IAC9B,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IAC1B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,IAE9C;IACC,OAAO,yBAAyB,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;AACtE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"content-type-labels.d.ts","sourceRoot":"","sources":["../../src/descriptors/content-type-labels.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAW9D,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,OAAO,uBAAuB,EAAE,uBAAuB,GAC9D,MAAM,EAAE,CAEV;AAED,2EAA2E;AAC3E,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,OAAO,uBAAuB,EAAE,uBAAuB,GAC9D,MAAM,CAGR;AAED,uFAAuF;AACvF,eAAO,MAAM,8BAA8B,cAAc,CAAC;AAE1D,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,OAAO,uBAAuB,EAAE,uBAAuB,GAC9D,OAAO,CAET"}
1
+ {"version":3,"file":"content-type-labels.d.ts","sourceRoot":"","sources":["../../src/descriptors/content-type-labels.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAU9D,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,OAAO,uBAAuB,EAAE,uBAAuB,GAC9D,MAAM,EAAE,CAEV;AAED,2EAA2E;AAC3E,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,OAAO,uBAAuB,EAAE,uBAAuB,GAC9D,MAAM,CAGR;AAED,uFAAuF;AACvF,eAAO,MAAM,8BAA8B,cAAc,CAAC;AAE1D,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,OAAO,uBAAuB,EAAE,uBAAuB,GAC9D,OAAO,CAET"}
@@ -2,14 +2,13 @@
2
2
  export const MEMORIX_CONTENT_TYPE_LABELS = {
3
3
  scoped: "Scoped records",
4
4
  snapshots: "Snapshots",
5
+ discovery: "Discovery",
6
+ analysis: "Analysis",
7
+ decisions: "Decisions",
5
8
  narratives: "Narratives",
6
- web: "Web",
7
- "web-scoped": "Web (scoped)",
9
+ "ai-processing": "AI processing",
8
10
  raw: "Raw",
9
- inference: "Inference",
10
11
  analytics: "Analytics",
11
- foresights: "Foresights",
12
- analysis: "Analysis",
13
12
  };
14
13
  export function memorixContentTypeLabel(contentType) {
15
14
  return MEMORIX_CONTENT_TYPE_LABELS[contentType] ?? contentType;
@@ -1 +1 @@
1
- {"version":3,"file":"content-type-labels.js","sourceRoot":"","sources":["../../src/descriptors/content-type-labels.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,CAAC,MAAM,2BAA2B,GAA2B;IACjE,MAAM,EAAE,gBAAgB;IACxB,SAAS,EAAE,WAAW;IACtB,UAAU,EAAE,YAAY;IACxB,GAAG,EAAE,KAAK;IACV,YAAY,EAAE,cAAc;IAC5B,GAAG,EAAE,KAAK;IACV,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;IACtB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,UAAU,uBAAuB,CAAC,WAAmB;IACzD,OAAO,2BAA2B,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,MAA+D;IAE/D,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAC1C,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,wBAAwB,CACtC,MAA+D;IAE/D,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAChD,OAAO,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC;AAC9C,CAAC;AAED,uFAAuF;AACvF,MAAM,CAAC,MAAM,8BAA8B,GAAG,WAAW,CAAC;AAE1D,MAAM,UAAU,kCAAkC,CAChD,MAA+D;IAE/D,OAAO,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC,CAAC;AACtE,CAAC"}
1
+ {"version":3,"file":"content-type-labels.js","sourceRoot":"","sources":["../../src/descriptors/content-type-labels.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,CAAC,MAAM,2BAA2B,GAA2B;IACjE,MAAM,EAAE,gBAAgB;IACxB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;IACtB,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,UAAU,EAAE,YAAY;IACxB,eAAe,EAAE,eAAe;IAChC,GAAG,EAAE,KAAK;IACV,SAAS,EAAE,WAAW;CACvB,CAAC;AAEF,MAAM,UAAU,uBAAuB,CAAC,WAAmB;IACzD,OAAO,2BAA2B,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,MAA+D;IAE/D,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAC1C,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,wBAAwB,CACtC,MAA+D;IAE/D,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAChD,OAAO,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC;AAC9C,CAAC;AAED,uFAAuF;AACvF,MAAM,CAAC,MAAM,8BAA8B,GAAG,WAAW,CAAC;AAE1D,MAAM,UAAU,kCAAkC,CAChD,MAA+D;IAE/D,OAAO,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC,CAAC;AACtE,CAAC"}