@mitre/hdf-parsers 3.6.0 → 3.7.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/index.d.ts +34 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +110 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -28,7 +28,27 @@ interface BaselineMerge {
|
|
|
28
28
|
* @param results - Parsed HDF Results (from parseResults() or equivalent)
|
|
29
29
|
* @returns FlattenResult with flattened data and merge metadata
|
|
30
30
|
*/
|
|
31
|
-
declare function flattenOverlays(results: HDFResults): FlattenResult;
|
|
31
|
+
export declare function flattenOverlays(results: HDFResults): FlattenResult;
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region typescript/saf-supplement.d.ts
|
|
34
|
+
interface SafNormalizeResult {
|
|
35
|
+
/** The normalized JSON string (byte-identical to the input when nothing was rewritten). */
|
|
36
|
+
output: string;
|
|
37
|
+
/** One deprecation warning per rewritten legacy key. */
|
|
38
|
+
warnings: string[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Rewrite the legacy SAF-supplement top-level keys into v3-native carriers so a
|
|
42
|
+
* SAF-produced document becomes valid v3 before schema validation: `target` → a
|
|
43
|
+
* components[] entry (type validated; id → name and, for cloudAccount, accountId;
|
|
44
|
+
* boundary → labels.boundary; merged into a matching existing component rather
|
|
45
|
+
* than duplicated); `passthrough` → extensions.passthrough.
|
|
46
|
+
*
|
|
47
|
+
* Deliberately narrow: input that is not a JSON object, or carries neither legacy
|
|
48
|
+
* key, is returned BYTE-IDENTICAL with no warnings. A target whose type is not a
|
|
49
|
+
* valid component type is left in place (with a warning) for the schema to reject.
|
|
50
|
+
*/
|
|
51
|
+
export declare function normalizeSafSupplement(input: string): SafNormalizeResult;
|
|
32
52
|
//#endregion
|
|
33
53
|
//#region typescript/index.d.ts
|
|
34
54
|
/**
|
|
@@ -37,50 +57,53 @@ declare function flattenOverlays(results: HDFResults): FlattenResult;
|
|
|
37
57
|
* same regex instead of re-implementing it. Matches the Go side at
|
|
38
58
|
* hdf-parsers/go/parsers.go.
|
|
39
59
|
*/
|
|
40
|
-
declare function normalizeTimestamps(input: string): string;
|
|
60
|
+
export declare function normalizeTimestamps(input: string): string;
|
|
41
61
|
/**
|
|
42
62
|
* Result of parsing operation
|
|
43
63
|
*/
|
|
44
|
-
interface ParseResult<T> {
|
|
64
|
+
export interface ParseResult<T> {
|
|
45
65
|
success: boolean;
|
|
46
66
|
data?: T;
|
|
47
67
|
error?: string;
|
|
48
68
|
type?: 'results' | 'baseline' | 'system' | 'plan' | 'evidencePackage' | 'comparison';
|
|
69
|
+
/** Non-fatal notices from pre-validation normalization (e.g. a legacy
|
|
70
|
+
* SAF-supplement shape rewritten to v3-native); callers surface these. */
|
|
71
|
+
warnings?: string[];
|
|
49
72
|
}
|
|
50
73
|
/**
|
|
51
74
|
* Parse HDF Results document from string or bytes
|
|
52
75
|
* @param input - JSON string or Uint8Array to parse
|
|
53
76
|
* @returns ParseResult with parsed data or error
|
|
54
77
|
*/
|
|
55
|
-
declare function parseResults(input: string | Uint8Array): ParseResult<HDFResults>;
|
|
78
|
+
export declare function parseResults(input: string | Uint8Array): ParseResult<HDFResults>;
|
|
56
79
|
/**
|
|
57
80
|
* Parse HDF Baseline document from string or bytes
|
|
58
81
|
* @param input - JSON string or Uint8Array to parse
|
|
59
82
|
* @returns ParseResult with parsed data or error
|
|
60
83
|
*/
|
|
61
|
-
declare function parseBaseline(input: string | Uint8Array): ParseResult<HDFBaseline>;
|
|
84
|
+
export declare function parseBaseline(input: string | Uint8Array): ParseResult<HDFBaseline>;
|
|
62
85
|
/**
|
|
63
86
|
* Parse HDF System document from string or bytes
|
|
64
87
|
*/
|
|
65
|
-
declare function parseSystem(input: string | Uint8Array): ParseResult<HDFSystem>;
|
|
88
|
+
export declare function parseSystem(input: string | Uint8Array): ParseResult<HDFSystem>;
|
|
66
89
|
/**
|
|
67
90
|
* Parse HDF Plan document from string or bytes
|
|
68
91
|
*/
|
|
69
|
-
declare function parsePlan(input: string | Uint8Array): ParseResult<HDFPlan>;
|
|
92
|
+
export declare function parsePlan(input: string | Uint8Array): ParseResult<HDFPlan>;
|
|
70
93
|
/**
|
|
71
94
|
* Parse HDF Evidence Package document from string or bytes
|
|
72
95
|
*/
|
|
73
|
-
declare function parseEvidencePackage(input: string | Uint8Array): ParseResult<HDFEvidencePackage>;
|
|
96
|
+
export declare function parseEvidencePackage(input: string | Uint8Array): ParseResult<HDFEvidencePackage>;
|
|
74
97
|
/**
|
|
75
98
|
* Parse HDF Comparison document from string or bytes
|
|
76
99
|
*/
|
|
77
|
-
declare function parseComparison(input: string | Uint8Array): ParseResult<HDFComparison>;
|
|
100
|
+
export declare function parseComparison(input: string | Uint8Array): ParseResult<HDFComparison>;
|
|
78
101
|
/**
|
|
79
102
|
* Parse HDF document with auto-detection of type
|
|
80
103
|
* @param input - JSON string or Uint8Array to parse
|
|
81
104
|
* @returns ParseResult with parsed data, type indicator, or error
|
|
82
105
|
*/
|
|
83
|
-
declare function parse(input: string | Uint8Array): ParseResult<HDFResults | HDFBaseline | HDFSystem | HDFPlan | HDFEvidencePackage | HDFComparison>;
|
|
106
|
+
export declare function parse(input: string | Uint8Array): ParseResult<HDFResults | HDFBaseline | HDFSystem | HDFPlan | HDFEvidencePackage | HDFComparison>;
|
|
84
107
|
//#endregion
|
|
85
|
-
export {
|
|
108
|
+
export type { BaselineMerge, FlattenMetadata, FlattenResult, SafNormalizeResult };
|
|
86
109
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../typescript/flatten.ts","../typescript/index.ts"],"mappings":";;UAIiB;EACf,SAAS;EACT,UAAU;;UAGK;EACf;EACA;EACA,QAAQ;EACR;;UAGe;EACf;EACA;EACA;EACA;EACA;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../typescript/flatten.ts","../typescript/saf-supplement.ts","../typescript/index.ts"],"mappings":";;UAIiB;EACf,SAAS;EACT,UAAU;;UAGK;EACf;EACA;EACA,QAAQ;EACR;;UAGe;EACf;EACA;EACA;EACA;EACA;;;;;;;;;;;;;wBA2Hc,gBAAgB,SAAS,aAAa;;;UC9HrC;;EAEf;;EAEA;;;;;;;;;;;;;wBAkBc,uBAAuB,gBAAgB;;;;;;;;;wBCNvC,oBAAoB;;;;iBAOnB,YAAY;EAC3B;EACA,OAAO;EACP;EACA;;;EAGA;;;;;;;wBAQc,aAAa,gBAAgB,aAAa,YAAY;;;;;;wBAwDtD,cAAc,gBAAgB,aAAa,YAAY;;;;wBA6CvD,YAAY,gBAAgB,aAAa,YAAY;;;;wBAsBrD,UAAU,gBAAgB,aAAa,YAAY;;;;wBAsBnD,qBAAqB,gBAAgB,aAAa,YAAY;;;;wBAsB9D,gBAAgB,gBAAgB,aAAa,YAAY;;;;;;wBAwBzD,MACd,gBAAgB,aACf,YAAY,aAAa,cAAc,YAAY,UAAU,qBAAqB"}
|
package/dist/index.js
CHANGED
|
@@ -167,6 +167,112 @@ function flattenOverlays(results) {
|
|
|
167
167
|
};
|
|
168
168
|
}
|
|
169
169
|
//#endregion
|
|
170
|
+
//#region typescript/saf-supplement.ts
|
|
171
|
+
const SAF_TARGET_DEPRECATION = "deprecated: top-level 'target' (saf supplement target write) was normalized into components[]; emit a component directly — this compatibility shim will be removed in a future release";
|
|
172
|
+
const SAF_PROVENANCE_DEPRECATION = "deprecated: top-level 'passthrough' was normalized into extensions.passthrough; write provenance under extensions — this compatibility shim will be removed in a future release";
|
|
173
|
+
const VALID_COMPONENT_TYPES = /* @__PURE__ */ new Set([
|
|
174
|
+
"aiModel",
|
|
175
|
+
"application",
|
|
176
|
+
"artifact",
|
|
177
|
+
"cloudAccount",
|
|
178
|
+
"cloudResource",
|
|
179
|
+
"containerImage",
|
|
180
|
+
"containerInstance",
|
|
181
|
+
"containerPlatform",
|
|
182
|
+
"database",
|
|
183
|
+
"dataset",
|
|
184
|
+
"host",
|
|
185
|
+
"network",
|
|
186
|
+
"repository"
|
|
187
|
+
]);
|
|
188
|
+
function isObject(v) {
|
|
189
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Rewrite the legacy SAF-supplement top-level keys into v3-native carriers so a
|
|
193
|
+
* SAF-produced document becomes valid v3 before schema validation: `target` → a
|
|
194
|
+
* components[] entry (type validated; id → name and, for cloudAccount, accountId;
|
|
195
|
+
* boundary → labels.boundary; merged into a matching existing component rather
|
|
196
|
+
* than duplicated); `passthrough` → extensions.passthrough.
|
|
197
|
+
*
|
|
198
|
+
* Deliberately narrow: input that is not a JSON object, or carries neither legacy
|
|
199
|
+
* key, is returned BYTE-IDENTICAL with no warnings. A target whose type is not a
|
|
200
|
+
* valid component type is left in place (with a warning) for the schema to reject.
|
|
201
|
+
*/
|
|
202
|
+
function normalizeSafSupplement(input) {
|
|
203
|
+
let doc;
|
|
204
|
+
try {
|
|
205
|
+
doc = JSON.parse(input);
|
|
206
|
+
} catch {
|
|
207
|
+
return {
|
|
208
|
+
output: input,
|
|
209
|
+
warnings: []
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (!isObject(doc) || !("target" in doc) && !("passthrough" in doc)) return {
|
|
213
|
+
output: input,
|
|
214
|
+
warnings: []
|
|
215
|
+
};
|
|
216
|
+
const warnings = [];
|
|
217
|
+
if ("target" in doc) {
|
|
218
|
+
if (rewriteTarget(doc)) warnings.push(SAF_TARGET_DEPRECATION);
|
|
219
|
+
else warnings.push(`${SAF_TARGET_DEPRECATION} (target.type is not a recognized component type; left for schema validation)`);
|
|
220
|
+
}
|
|
221
|
+
if ("passthrough" in doc) {
|
|
222
|
+
rewritePassthrough(doc);
|
|
223
|
+
warnings.push(SAF_PROVENANCE_DEPRECATION);
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
output: JSON.stringify(doc),
|
|
227
|
+
warnings
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/** Lift a legacy top-level `target` object into components[]; returns false
|
|
231
|
+
* (leaving `target` in place) when it is not an object or its type is invalid. */
|
|
232
|
+
function rewriteTarget(doc) {
|
|
233
|
+
const tgt = doc.target;
|
|
234
|
+
if (!isObject(tgt)) return false;
|
|
235
|
+
const typ = typeof tgt.type === "string" ? tgt.type : "";
|
|
236
|
+
if (!VALID_COMPONENT_TYPES.has(typ)) return false;
|
|
237
|
+
const id = typeof tgt.id === "string" ? tgt.id : "";
|
|
238
|
+
const boundary = typeof tgt.boundary === "string" ? tgt.boundary : "";
|
|
239
|
+
const comps = Array.isArray(doc.components) ? doc.components : [];
|
|
240
|
+
let merged = false;
|
|
241
|
+
for (const c of comps) if (isObject(c) && c.name === id && c.type === typ) {
|
|
242
|
+
applyBoundaryLabel(c, boundary);
|
|
243
|
+
merged = true;
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
if (!merged) {
|
|
247
|
+
const c = {
|
|
248
|
+
type: typ,
|
|
249
|
+
name: id
|
|
250
|
+
};
|
|
251
|
+
if (typ === "cloudAccount") c.accountId = id;
|
|
252
|
+
applyBoundaryLabel(c, boundary);
|
|
253
|
+
comps.push(c);
|
|
254
|
+
}
|
|
255
|
+
doc.components = comps;
|
|
256
|
+
delete doc.target;
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
/** Record the legacy target.boundary as a component label (the deferred
|
|
260
|
+
* first-class-field decision — ADR-0015). No-op for an empty boundary. */
|
|
261
|
+
function applyBoundaryLabel(c, boundary) {
|
|
262
|
+
if (boundary === "") return;
|
|
263
|
+
const labels = isObject(c.labels) ? c.labels : {};
|
|
264
|
+
if (!("boundary" in labels)) labels.boundary = boundary;
|
|
265
|
+
c.labels = labels;
|
|
266
|
+
}
|
|
267
|
+
/** Move the legacy top-level `passthrough` under extensions.passthrough, merging
|
|
268
|
+
* into any existing extensions without clobbering other keys. */
|
|
269
|
+
function rewritePassthrough(doc) {
|
|
270
|
+
const ext = isObject(doc.extensions) ? doc.extensions : {};
|
|
271
|
+
if (!("passthrough" in ext)) ext.passthrough = doc.passthrough;
|
|
272
|
+
doc.extensions = ext;
|
|
273
|
+
delete doc.passthrough;
|
|
274
|
+
}
|
|
275
|
+
//#endregion
|
|
170
276
|
//#region typescript/index.ts
|
|
171
277
|
const NO_TZ_TIMESTAMP_REGEX = /"(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?)"/g;
|
|
172
278
|
/**
|
|
@@ -184,7 +290,7 @@ function normalizeTimestamps(input) {
|
|
|
184
290
|
* @returns ParseResult with parsed data or error
|
|
185
291
|
*/
|
|
186
292
|
function parseResults(input) {
|
|
187
|
-
const jsonStr = normalizeTimestamps(typeof input === "string" ? input : new TextDecoder().decode(input));
|
|
293
|
+
const { output: jsonStr, warnings } = normalizeSafSupplement(normalizeTimestamps(typeof input === "string" ? input : new TextDecoder().decode(input)));
|
|
188
294
|
if (jsonStr.trim().length === 0) return {
|
|
189
295
|
success: false,
|
|
190
296
|
error: "Input is empty"
|
|
@@ -205,7 +311,8 @@ function parseResults(input) {
|
|
|
205
311
|
};
|
|
206
312
|
return {
|
|
207
313
|
success: true,
|
|
208
|
-
data
|
|
314
|
+
data,
|
|
315
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
209
316
|
};
|
|
210
317
|
}
|
|
211
318
|
/**
|
|
@@ -414,6 +521,6 @@ function parse(input) {
|
|
|
414
521
|
};
|
|
415
522
|
}
|
|
416
523
|
//#endregion
|
|
417
|
-
export { flattenOverlays, normalizeTimestamps, parse, parseBaseline, parseComparison, parseEvidencePackage, parsePlan, parseResults, parseSystem };
|
|
524
|
+
export { flattenOverlays, normalizeSafSupplement, normalizeTimestamps, parse, parseBaseline, parseComparison, parseEvidencePackage, parsePlan, parseResults, parseSystem };
|
|
418
525
|
|
|
419
526
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["autoValidate"],"sources":["../typescript/flatten.ts","../typescript/index.ts"],"sourcesContent":["import type { HDFResults, EvaluatedBaseline, EvaluatedRequirement } from '@mitre/hdf-schema';\n\n// ── Public Types ────────────────────────────────────────────\n\nexport interface FlattenResult {\n results: HDFResults;\n metadata: FlattenMetadata;\n}\n\nexport interface FlattenMetadata {\n originalBaselineCount: number;\n flattenedBaselineCount: number;\n merges: BaselineMerge[];\n warnings: string[];\n}\n\nexport interface BaselineMerge {\n rootBaseline: string;\n absorbedBaselines: string[];\n controlsBefore: number;\n controlsAfter: number;\n pattern: 'deep' | 'wide' | 'hybrid';\n}\n\n// ── Internal Helpers ───────────────────────────────────────\n\n/** BFS from root, returns names in top-down order. Cycle-safe. */\nfunction collectTree(root: string, childrenMap: Map<string, string[]>): string[] {\n const order: string[] = [];\n const seen = new Set<string>();\n const queue = [root];\n while (queue.length > 0) {\n const name = queue.shift()!;\n if (seen.has(name)) continue;\n seen.add(name);\n order.push(name);\n for (const child of (childrenMap.get(name) || [])) {\n queue.push(child);\n }\n }\n return order;\n}\n\n/** Classify merge pattern based on tree shape */\nfunction detectPattern(root: string, childrenMap: Map<string, string[]>): 'deep' | 'wide' | 'hybrid' {\n const rootChildren = childrenMap.get(root) || [];\n if (rootChildren.length <= 1) {\n return 'deep';\n }\n for (const child of rootChildren) {\n if ((childrenMap.get(child) || []).length > 0) {\n return 'hybrid';\n }\n }\n return 'wide';\n}\n\n/** Merge incoming requirement fields onto existing */\nfunction mergeRequirement(\n existing: EvaluatedRequirement,\n incoming: EvaluatedRequirement\n): EvaluatedRequirement {\n const result: EvaluatedRequirement = { ...existing };\n\n // Impact: incoming always wins (required field, always present)\n result.impact = incoming.impact;\n\n // Results: keep whichever is non-empty (base has them, overlay doesn't)\n if (incoming.results && incoming.results.length > 0) {\n result.results = incoming.results;\n }\n\n // Code: incoming wins if non-empty\n if (incoming.code && incoming.code.trim() !== '') {\n result.code = incoming.code;\n }\n\n // Tags: shallow merge (incoming keys override)\n if (incoming.tags) {\n result.tags = { ...existing.tags, ...incoming.tags };\n }\n\n // Severity: incoming wins if present, else keep existing\n if (incoming.severity !== undefined) {\n result.severity = incoming.severity;\n }\n\n // EffectiveStatus: incoming wins only if it has results (otherwise its\n // effectiveStatus is a computed artifact from empty results, not intentional).\n // Overlays typically have empty results — the base has the real test results.\n if (incoming.effectiveStatus !== undefined && incoming.results && incoming.results.length > 0) {\n result.effectiveStatus = incoming.effectiveStatus;\n }\n\n // Descriptions: merge by label (incoming overrides same label)\n if (incoming.descriptions && incoming.descriptions.length > 0) {\n const descMap = new Map(\n (existing.descriptions || []).map(d => [d.label, d])\n );\n for (const d of incoming.descriptions) {\n descMap.set(d.label, d);\n }\n result.descriptions = [...descMap.values()];\n }\n\n return result;\n}\n\n/**\n * Resolve parentBaseline for a baseline.\n * InSpec parent_profile can use depends-name aliases (e.g., 'k8s' instead of\n * 'k8s-node-stig-baseline'). When the value isn't a direct profile name,\n * find who depends on this baseline — that's the actual parent.\n */\nfunction resolveParentBaseline(\n b: EvaluatedBaseline,\n byName: Map<string, EvaluatedBaseline>,\n allBaselines: EvaluatedBaseline[]\n): string | undefined {\n if (!b.parentBaseline) return undefined;\n if (byName.has(b.parentBaseline)) return b.parentBaseline;\n\n // Alias resolution: find the profile whose depends array includes this baseline\n for (const candidate of allBaselines) {\n if (candidate.depends?.some((d) => d.name === b.name)) {\n return candidate.name;\n }\n }\n return undefined; // orphan\n}\n\n// ── Public API ──────────────────────────────────────────────\n\n/**\n * Flatten overlay/wrapper baselines in an HDF Results document.\n *\n * Handles:\n * - Deep nesting (overlay chains with shared control IDs via parentBaseline)\n * - Wide nesting (wrapper profiles aggregating independent bases)\n * - Hybrid (both patterns in one document)\n *\n * @param results - Parsed HDF Results (from parseResults() or equivalent)\n * @returns FlattenResult with flattened data and merge metadata\n */\nexport function flattenOverlays(results: HDFResults): FlattenResult {\n const { baselines } = results;\n const warnings: string[] = [];\n const merges: BaselineMerge[] = [];\n\n if (!baselines || baselines.length === 0) {\n return {\n results: { ...results, baselines: [] },\n metadata: {\n originalBaselineCount: 0,\n flattenedBaselineCount: 0,\n merges: [],\n warnings: [],\n },\n };\n }\n\n // Index baselines by name\n const byName = new Map<string, EvaluatedBaseline>();\n for (const b of baselines) {\n if (byName.has(b.name)) {\n warnings.push(`Duplicate baseline name \"${b.name}\" — later entry overwrites earlier`);\n }\n byName.set(b.name, b);\n }\n\n // Resolve parentBaseline aliases and build parent map\n const resolvedParent = new Map<string, string | undefined>();\n for (const b of baselines) {\n const parent = resolveParentBaseline(b, byName, baselines);\n resolvedParent.set(b.name, parent);\n if (b.parentBaseline && !parent) {\n warnings.push(\n `Baseline \"${b.name}\" references nonexistent parent \"${b.parentBaseline}\"`\n );\n }\n }\n\n // Build parent → children adjacency using resolved parents\n const childrenMap = new Map<string, string[]>();\n for (const b of baselines) {\n const parent = resolvedParent.get(b.name);\n if (parent) {\n const list = childrenMap.get(parent) || [];\n list.push(b.name);\n childrenMap.set(parent, list);\n }\n }\n\n // Find roots: no resolved parent\n const roots: string[] = [];\n const visited = new Set<string>();\n\n for (const b of baselines) {\n if (!resolvedParent.get(b.name)) {\n roots.push(b.name);\n }\n }\n\n // Mark reachable from roots (iterative DFS to avoid stack overflow on deep trees)\n function markReachable(start: string): void {\n const stack = [start];\n while (stack.length > 0) {\n const name = stack.pop()!;\n if (visited.has(name)) continue;\n visited.add(name);\n const children = childrenMap.get(name);\n if (children) {\n for (const child of children) {\n stack.push(child);\n }\n }\n }\n }\n for (const r of roots) {\n markReachable(r);\n }\n\n // Detect cycles: unvisited baselines are in cycles\n for (const b of baselines) {\n if (!visited.has(b.name)) {\n warnings.push(`Circular parentBaseline detected involving \"${b.name}\"`);\n roots.push(b.name);\n markReachable(b.name);\n }\n }\n\n // Process each root tree\n const flatBaselines: EvaluatedBaseline[] = [];\n\n for (const rootName of roots) {\n const root = byName.get(rootName)!;\n const treeNames = collectTree(rootName, childrenMap);\n\n if (treeNames.length === 1) {\n // Standalone baseline — pass through unchanged (preserve depends)\n flatBaselines.push(root);\n continue;\n }\n\n // Bottom-up order: reverse top-down BFS\n const bottomUp = [...treeNames].reverse();\n\n // Merge requirements across the tree\n const merged = new Map<string, EvaluatedRequirement>();\n let controlsBefore = 0;\n const absorbed: string[] = [];\n\n for (const name of bottomUp) {\n const b = byName.get(name)!;\n controlsBefore += b.requirements.length;\n if (name !== rootName) {\n absorbed.push(name);\n }\n for (const req of b.requirements) {\n if (merged.has(req.id)) {\n merged.set(req.id, mergeRequirement(merged.get(req.id)!, req));\n } else {\n merged.set(req.id, { ...req });\n }\n }\n }\n\n const mergedReqs = [...merged.values()];\n const pattern = detectPattern(rootName, childrenMap);\n\n merges.push({\n rootBaseline: rootName,\n absorbedBaselines: absorbed,\n controlsBefore,\n controlsAfter: mergedReqs.length,\n pattern,\n });\n\n const out: EvaluatedBaseline = {\n ...root,\n requirements: mergedReqs,\n };\n delete out.parentBaseline;\n delete out.depends;\n flatBaselines.push(out);\n }\n\n return {\n results: { ...results, baselines: flatBaselines },\n metadata: {\n originalBaselineCount: baselines.length,\n flattenedBaselineCount: flatBaselines.length,\n merges,\n warnings,\n },\n };\n}\n","import type {\n HDFResults,\n HDFBaseline,\n HDFSystem,\n HDFPlan,\n HDFEvidencePackage,\n HDFComparison,\n} from '@mitre/hdf-schema';\nexport { flattenOverlays } from './flatten.js';\nexport type { FlattenResult, FlattenMetadata, BaselineMerge } from './flatten.js';\nimport {\n validateResults,\n validateBaseline,\n validateSystem,\n validatePlan,\n validateEvidencePackage,\n validateComparison,\n validate as autoValidate,\n} from '@mitre/hdf-validators';\n\n// JSON-quoted ISO 8601 timestamp with no trailing timezone — InSpec emits\n// these (e.g. \"2026-03-25T22:56:27.736808\"). ajv-formats requires RFC 3339\n// for `date-time` and rejects them.\nconst NO_TZ_TIMESTAMP_REGEX = /\"(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?)\"/g;\n\n/**\n * Append Z (treat as UTC) to bare ISO timestamps in a JSON string so they\n * pass schema validation. Exported so other workspace packages can use the\n * same regex instead of re-implementing it. Matches the Go side at\n * hdf-parsers/go/parsers.go.\n */\nexport function normalizeTimestamps(input: string): string {\n return input.replace(NO_TZ_TIMESTAMP_REGEX, '\"$1Z\"');\n}\n\n/**\n * Result of parsing operation\n */\nexport interface ParseResult<T> {\n success: boolean;\n data?: T;\n error?: string;\n type?: 'results' | 'baseline' | 'system' | 'plan' | 'evidencePackage' | 'comparison';\n}\n\n/**\n * Parse HDF Results document from string or bytes\n * @param input - JSON string or Uint8Array to parse\n * @returns ParseResult with parsed data or error\n */\nexport function parseResults(input: string | Uint8Array): ParseResult<HDFResults> {\n // Convert Uint8Array to string if needed\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n\n // Check for empty input\n if (jsonStr.trim().length === 0) {\n return {\n success: false,\n error: 'Input is empty'\n };\n }\n\n // Parse JSON\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return {\n success: false,\n error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}`\n };\n }\n\n // JSON.parse already rejects trailing garbage (it throws on the first\n // non-whitespace byte after the root value), so the catch above covers\n // that case. A prior length-compare heuristic here false-positived on\n // complex real-world inputs (e.g. `0.70` parsed as `0.7` would re-\n // serialize to a different length) — caught by the cross-language\n // parser parity test in typescript/parse-equivalence.test.ts.\n\n // Validate against schema\n const validationResult = validateResults(data);\n if (!validationResult.valid) {\n return {\n success: false,\n error: `Schema validation failed: ${validationResult.getErrorMessage()}`\n };\n }\n\n return {\n success: true,\n data: data as HDFResults\n };\n}\n\n/**\n * Parse HDF Baseline document from string or bytes\n * @param input - JSON string or Uint8Array to parse\n * @returns ParseResult with parsed data or error\n */\nexport function parseBaseline(input: string | Uint8Array): ParseResult<HDFBaseline> {\n // Convert Uint8Array to string if needed\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n\n // Check for empty input\n if (jsonStr.trim().length === 0) {\n return {\n success: false,\n error: 'Input is empty'\n };\n }\n\n // Parse JSON\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return {\n success: false,\n error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}`\n };\n }\n\n // Trailing garbage already caught by the JSON.parse catch above; see\n // parseResults for the full rationale.\n\n // Validate against schema\n const validationResult = validateBaseline(data);\n if (!validationResult.valid) {\n return {\n success: false,\n error: `Schema validation failed: ${validationResult.getErrorMessage()}`\n };\n }\n\n return {\n success: true,\n data: data as HDFBaseline\n };\n}\n\n/**\n * Parse HDF System document from string or bytes\n */\nexport function parseSystem(input: string | Uint8Array): ParseResult<HDFSystem> {\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n if (jsonStr.trim().length === 0) {\n return { success: false, error: 'Input is empty' };\n }\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return { success: false, error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` };\n }\n const validationResult = validateSystem(data);\n if (!validationResult.valid) {\n return { success: false, error: `Schema validation failed: ${validationResult.getErrorMessage()}` };\n }\n return { success: true, data: data as HDFSystem };\n}\n\n/**\n * Parse HDF Plan document from string or bytes\n */\nexport function parsePlan(input: string | Uint8Array): ParseResult<HDFPlan> {\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n if (jsonStr.trim().length === 0) {\n return { success: false, error: 'Input is empty' };\n }\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return { success: false, error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` };\n }\n const validationResult = validatePlan(data);\n if (!validationResult.valid) {\n return { success: false, error: `Schema validation failed: ${validationResult.getErrorMessage()}` };\n }\n return { success: true, data: data as HDFPlan };\n}\n\n/**\n * Parse HDF Evidence Package document from string or bytes\n */\nexport function parseEvidencePackage(input: string | Uint8Array): ParseResult<HDFEvidencePackage> {\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n if (jsonStr.trim().length === 0) {\n return { success: false, error: 'Input is empty' };\n }\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return { success: false, error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` };\n }\n const validationResult = validateEvidencePackage(data);\n if (!validationResult.valid) {\n return { success: false, error: `Schema validation failed: ${validationResult.getErrorMessage()}` };\n }\n return { success: true, data: data as HDFEvidencePackage };\n}\n\n/**\n * Parse HDF Comparison document from string or bytes\n */\nexport function parseComparison(input: string | Uint8Array): ParseResult<HDFComparison> {\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n if (jsonStr.trim().length === 0) {\n return { success: false, error: 'Input is empty' };\n }\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return { success: false, error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` };\n }\n const validationResult = validateComparison(data);\n if (!validationResult.valid) {\n return { success: false, error: `Schema validation failed: ${validationResult.getErrorMessage()}` };\n }\n return { success: true, data: data as HDFComparison };\n}\n\n/**\n * Parse HDF document with auto-detection of type\n * @param input - JSON string or Uint8Array to parse\n * @returns ParseResult with parsed data, type indicator, or error\n */\nexport function parse(\n input: string | Uint8Array,\n): ParseResult<HDFResults | HDFBaseline | HDFSystem | HDFPlan | HDFEvidencePackage | HDFComparison> {\n // Convert Uint8Array to string if needed\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n\n // Check for empty input\n if (jsonStr.trim().length === 0) {\n return {\n success: false,\n error: 'Input is empty'\n };\n }\n\n // Parse JSON\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return {\n success: false,\n error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}`\n };\n }\n\n // Trailing garbage already caught by the JSON.parse catch above; see\n // parseResults for the full rationale.\n\n // Auto-validate and detect type\n const validationResult = autoValidate(data);\n if (!validationResult.valid) {\n return {\n success: false,\n error: `Schema validation failed: ${validationResult.getErrorMessage()}`\n };\n }\n\n // Determine type based on structure\n if (typeof data === 'object' && data !== null) {\n const obj = data as Record<string, unknown>;\n\n // HDF Results has 'baselines' array at root\n if ('baselines' in obj) {\n return {\n success: true,\n data: data as HDFResults,\n type: 'results'\n };\n }\n\n // HDF Comparison has 'requirementDiffs' at root (unique discriminator)\n if ('requirementDiffs' in obj) {\n return { success: true, data: data as HDFComparison, type: 'comparison' };\n }\n\n // HDF Plan has 'assessments' at root\n if ('assessments' in obj) {\n return { success: true, data: data as HDFPlan, type: 'plan' };\n }\n\n // HDF Evidence Package has 'contents' at root\n if ('contents' in obj) {\n return { success: true, data: data as HDFEvidencePackage, type: 'evidencePackage' };\n }\n\n // HDF Baseline has 'name' and 'requirements' at root\n if ('name' in obj && 'requirements' in obj) {\n return {\n success: true,\n data: data as HDFBaseline,\n type: 'baseline'\n };\n }\n\n // HDF System has 'components' at root (Results' baselines check already ruled out)\n if ('components' in obj) {\n return { success: true, data: data as HDFSystem, type: 'system' };\n }\n }\n\n return {\n success: false,\n error: 'Unable to determine HDF document type'\n };\n}\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["autoValidate"],"sources":["../typescript/flatten.ts","../typescript/saf-supplement.ts","../typescript/index.ts"],"sourcesContent":["import type { HDFResults, EvaluatedBaseline, EvaluatedRequirement } from '@mitre/hdf-schema';\n\n// ── Public Types ────────────────────────────────────────────\n\nexport interface FlattenResult {\n results: HDFResults;\n metadata: FlattenMetadata;\n}\n\nexport interface FlattenMetadata {\n originalBaselineCount: number;\n flattenedBaselineCount: number;\n merges: BaselineMerge[];\n warnings: string[];\n}\n\nexport interface BaselineMerge {\n rootBaseline: string;\n absorbedBaselines: string[];\n controlsBefore: number;\n controlsAfter: number;\n pattern: 'deep' | 'wide' | 'hybrid';\n}\n\n// ── Internal Helpers ───────────────────────────────────────\n\n/** BFS from root, returns names in top-down order. Cycle-safe. */\nfunction collectTree(root: string, childrenMap: Map<string, string[]>): string[] {\n const order: string[] = [];\n const seen = new Set<string>();\n const queue = [root];\n while (queue.length > 0) {\n const name = queue.shift()!;\n if (seen.has(name)) continue;\n seen.add(name);\n order.push(name);\n for (const child of (childrenMap.get(name) || [])) {\n queue.push(child);\n }\n }\n return order;\n}\n\n/** Classify merge pattern based on tree shape */\nfunction detectPattern(root: string, childrenMap: Map<string, string[]>): 'deep' | 'wide' | 'hybrid' {\n const rootChildren = childrenMap.get(root) || [];\n if (rootChildren.length <= 1) {\n return 'deep';\n }\n for (const child of rootChildren) {\n if ((childrenMap.get(child) || []).length > 0) {\n return 'hybrid';\n }\n }\n return 'wide';\n}\n\n/** Merge incoming requirement fields onto existing */\nfunction mergeRequirement(\n existing: EvaluatedRequirement,\n incoming: EvaluatedRequirement\n): EvaluatedRequirement {\n const result: EvaluatedRequirement = { ...existing };\n\n // Impact: incoming always wins (required field, always present)\n result.impact = incoming.impact;\n\n // Results: keep whichever is non-empty (base has them, overlay doesn't)\n if (incoming.results && incoming.results.length > 0) {\n result.results = incoming.results;\n }\n\n // Code: incoming wins if non-empty\n if (incoming.code && incoming.code.trim() !== '') {\n result.code = incoming.code;\n }\n\n // Tags: shallow merge (incoming keys override)\n if (incoming.tags) {\n result.tags = { ...existing.tags, ...incoming.tags };\n }\n\n // Severity: incoming wins if present, else keep existing\n if (incoming.severity !== undefined) {\n result.severity = incoming.severity;\n }\n\n // EffectiveStatus: incoming wins only if it has results (otherwise its\n // effectiveStatus is a computed artifact from empty results, not intentional).\n // Overlays typically have empty results — the base has the real test results.\n if (incoming.effectiveStatus !== undefined && incoming.results && incoming.results.length > 0) {\n result.effectiveStatus = incoming.effectiveStatus;\n }\n\n // Descriptions: merge by label (incoming overrides same label)\n if (incoming.descriptions && incoming.descriptions.length > 0) {\n const descMap = new Map(\n (existing.descriptions || []).map(d => [d.label, d])\n );\n for (const d of incoming.descriptions) {\n descMap.set(d.label, d);\n }\n result.descriptions = [...descMap.values()];\n }\n\n return result;\n}\n\n/**\n * Resolve parentBaseline for a baseline.\n * InSpec parent_profile can use depends-name aliases (e.g., 'k8s' instead of\n * 'k8s-node-stig-baseline'). When the value isn't a direct profile name,\n * find who depends on this baseline — that's the actual parent.\n */\nfunction resolveParentBaseline(\n b: EvaluatedBaseline,\n byName: Map<string, EvaluatedBaseline>,\n allBaselines: EvaluatedBaseline[]\n): string | undefined {\n if (!b.parentBaseline) return undefined;\n if (byName.has(b.parentBaseline)) return b.parentBaseline;\n\n // Alias resolution: find the profile whose depends array includes this baseline\n for (const candidate of allBaselines) {\n if (candidate.depends?.some((d) => d.name === b.name)) {\n return candidate.name;\n }\n }\n return undefined; // orphan\n}\n\n// ── Public API ──────────────────────────────────────────────\n\n/**\n * Flatten overlay/wrapper baselines in an HDF Results document.\n *\n * Handles:\n * - Deep nesting (overlay chains with shared control IDs via parentBaseline)\n * - Wide nesting (wrapper profiles aggregating independent bases)\n * - Hybrid (both patterns in one document)\n *\n * @param results - Parsed HDF Results (from parseResults() or equivalent)\n * @returns FlattenResult with flattened data and merge metadata\n */\nexport function flattenOverlays(results: HDFResults): FlattenResult {\n const { baselines } = results;\n const warnings: string[] = [];\n const merges: BaselineMerge[] = [];\n\n if (!baselines || baselines.length === 0) {\n return {\n results: { ...results, baselines: [] },\n metadata: {\n originalBaselineCount: 0,\n flattenedBaselineCount: 0,\n merges: [],\n warnings: [],\n },\n };\n }\n\n // Index baselines by name\n const byName = new Map<string, EvaluatedBaseline>();\n for (const b of baselines) {\n if (byName.has(b.name)) {\n warnings.push(`Duplicate baseline name \"${b.name}\" — later entry overwrites earlier`);\n }\n byName.set(b.name, b);\n }\n\n // Resolve parentBaseline aliases and build parent map\n const resolvedParent = new Map<string, string | undefined>();\n for (const b of baselines) {\n const parent = resolveParentBaseline(b, byName, baselines);\n resolvedParent.set(b.name, parent);\n if (b.parentBaseline && !parent) {\n warnings.push(\n `Baseline \"${b.name}\" references nonexistent parent \"${b.parentBaseline}\"`\n );\n }\n }\n\n // Build parent → children adjacency using resolved parents\n const childrenMap = new Map<string, string[]>();\n for (const b of baselines) {\n const parent = resolvedParent.get(b.name);\n if (parent) {\n const list = childrenMap.get(parent) || [];\n list.push(b.name);\n childrenMap.set(parent, list);\n }\n }\n\n // Find roots: no resolved parent\n const roots: string[] = [];\n const visited = new Set<string>();\n\n for (const b of baselines) {\n if (!resolvedParent.get(b.name)) {\n roots.push(b.name);\n }\n }\n\n // Mark reachable from roots (iterative DFS to avoid stack overflow on deep trees)\n function markReachable(start: string): void {\n const stack = [start];\n while (stack.length > 0) {\n const name = stack.pop()!;\n if (visited.has(name)) continue;\n visited.add(name);\n const children = childrenMap.get(name);\n if (children) {\n for (const child of children) {\n stack.push(child);\n }\n }\n }\n }\n for (const r of roots) {\n markReachable(r);\n }\n\n // Detect cycles: unvisited baselines are in cycles\n for (const b of baselines) {\n if (!visited.has(b.name)) {\n warnings.push(`Circular parentBaseline detected involving \"${b.name}\"`);\n roots.push(b.name);\n markReachable(b.name);\n }\n }\n\n // Process each root tree\n const flatBaselines: EvaluatedBaseline[] = [];\n\n for (const rootName of roots) {\n const root = byName.get(rootName)!;\n const treeNames = collectTree(rootName, childrenMap);\n\n if (treeNames.length === 1) {\n // Standalone baseline — pass through unchanged (preserve depends)\n flatBaselines.push(root);\n continue;\n }\n\n // Bottom-up order: reverse top-down BFS\n const bottomUp = [...treeNames].reverse();\n\n // Merge requirements across the tree\n const merged = new Map<string, EvaluatedRequirement>();\n let controlsBefore = 0;\n const absorbed: string[] = [];\n\n for (const name of bottomUp) {\n const b = byName.get(name)!;\n controlsBefore += b.requirements.length;\n if (name !== rootName) {\n absorbed.push(name);\n }\n for (const req of b.requirements) {\n if (merged.has(req.id)) {\n merged.set(req.id, mergeRequirement(merged.get(req.id)!, req));\n } else {\n merged.set(req.id, { ...req });\n }\n }\n }\n\n const mergedReqs = [...merged.values()];\n const pattern = detectPattern(rootName, childrenMap);\n\n merges.push({\n rootBaseline: rootName,\n absorbedBaselines: absorbed,\n controlsBefore,\n controlsAfter: mergedReqs.length,\n pattern,\n });\n\n const out: EvaluatedBaseline = {\n ...root,\n requirements: mergedReqs,\n };\n delete out.parentBaseline;\n delete out.depends;\n flatBaselines.push(out);\n }\n\n return {\n results: { ...results, baselines: flatBaselines },\n metadata: {\n originalBaselineCount: baselines.length,\n flattenedBaselineCount: flatBaselines.length,\n merges,\n warnings,\n },\n };\n}\n","// Backwards-compatible normalization of legacy SAF-supplement top-level keys\n// (`target`, `passthrough`) into v3-native carriers, run before schema\n// validation. Mirrors the Go side at hdf-parsers/go/saf_supplement.go — the two\n// are pinned against a shared legacy-in/v3-out fixture pair.\n\nconst SAF_TARGET_DEPRECATION =\n \"deprecated: top-level 'target' (saf supplement target write) was normalized into components[]; emit a component directly — this compatibility shim will be removed in a future release\";\nconst SAF_PROVENANCE_DEPRECATION =\n \"deprecated: top-level 'passthrough' was normalized into extensions.passthrough; write provenance under extensions — this compatibility shim will be removed in a future release\";\n\n// v3 component/target types. Kept in sync with the schema's Target_Type enum; an\n// unknown type is left for the schema to reject rather than guessed.\nconst VALID_COMPONENT_TYPES = new Set([\n 'aiModel', 'application', 'artifact', 'cloudAccount', 'cloudResource',\n 'containerImage', 'containerInstance', 'containerPlatform', 'database',\n 'dataset', 'host', 'network', 'repository',\n]);\n\nexport interface SafNormalizeResult {\n /** The normalized JSON string (byte-identical to the input when nothing was rewritten). */\n output: string;\n /** One deprecation warning per rewritten legacy key. */\n warnings: string[];\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/**\n * Rewrite the legacy SAF-supplement top-level keys into v3-native carriers so a\n * SAF-produced document becomes valid v3 before schema validation: `target` → a\n * components[] entry (type validated; id → name and, for cloudAccount, accountId;\n * boundary → labels.boundary; merged into a matching existing component rather\n * than duplicated); `passthrough` → extensions.passthrough.\n *\n * Deliberately narrow: input that is not a JSON object, or carries neither legacy\n * key, is returned BYTE-IDENTICAL with no warnings. A target whose type is not a\n * valid component type is left in place (with a warning) for the schema to reject.\n */\nexport function normalizeSafSupplement(input: string): SafNormalizeResult {\n let doc: unknown;\n try {\n doc = JSON.parse(input);\n } catch {\n return { output: input, warnings: [] }; // not JSON — let the validator surface it\n }\n if (!isObject(doc) || (!('target' in doc) && !('passthrough' in doc))) {\n return { output: input, warnings: [] }; // no legacy keys — byte-identical\n }\n\n const warnings: string[] = [];\n\n if ('target' in doc) {\n if (rewriteTarget(doc)) {\n warnings.push(SAF_TARGET_DEPRECATION);\n } else {\n warnings.push(\n `${SAF_TARGET_DEPRECATION} (target.type is not a recognized component type; left for schema validation)`,\n );\n }\n }\n\n if ('passthrough' in doc) {\n rewritePassthrough(doc);\n warnings.push(SAF_PROVENANCE_DEPRECATION);\n }\n\n return { output: JSON.stringify(doc), warnings };\n}\n\n/** Lift a legacy top-level `target` object into components[]; returns false\n * (leaving `target` in place) when it is not an object or its type is invalid. */\nfunction rewriteTarget(doc: Record<string, unknown>): boolean {\n const tgt = doc.target;\n if (!isObject(tgt)) return false;\n const typ = typeof tgt.type === 'string' ? tgt.type : '';\n if (!VALID_COMPONENT_TYPES.has(typ)) return false;\n const id = typeof tgt.id === 'string' ? tgt.id : '';\n const boundary = typeof tgt.boundary === 'string' ? tgt.boundary : '';\n\n const comps: unknown[] = Array.isArray(doc.components) ? doc.components : [];\n\n let merged = false;\n for (const c of comps) {\n if (isObject(c) && c.name === id && c.type === typ) {\n applyBoundaryLabel(c, boundary);\n merged = true;\n break;\n }\n }\n if (!merged) {\n const c: Record<string, unknown> = { type: typ, name: id };\n if (typ === 'cloudAccount') c.accountId = id;\n applyBoundaryLabel(c, boundary);\n comps.push(c);\n }\n doc.components = comps;\n delete doc.target;\n return true;\n}\n\n/** Record the legacy target.boundary as a component label (the deferred\n * first-class-field decision — ADR-0015). No-op for an empty boundary. */\nfunction applyBoundaryLabel(c: Record<string, unknown>, boundary: string): void {\n if (boundary === '') return;\n const labels = isObject(c.labels) ? c.labels : {};\n if (!('boundary' in labels)) labels.boundary = boundary;\n c.labels = labels;\n}\n\n/** Move the legacy top-level `passthrough` under extensions.passthrough, merging\n * into any existing extensions without clobbering other keys. */\nfunction rewritePassthrough(doc: Record<string, unknown>): void {\n const ext = isObject(doc.extensions) ? doc.extensions : {};\n if (!('passthrough' in ext)) ext.passthrough = doc.passthrough;\n doc.extensions = ext;\n delete doc.passthrough;\n}\n","import type {\n HDFResults,\n HDFBaseline,\n HDFSystem,\n HDFPlan,\n HDFEvidencePackage,\n HDFComparison,\n} from '@mitre/hdf-schema';\nexport { flattenOverlays } from './flatten.js';\nexport type { FlattenResult, FlattenMetadata, BaselineMerge } from './flatten.js';\nimport { normalizeSafSupplement } from './saf-supplement.js';\nexport { normalizeSafSupplement } from './saf-supplement.js';\nexport type { SafNormalizeResult } from './saf-supplement.js';\nimport {\n validateResults,\n validateBaseline,\n validateSystem,\n validatePlan,\n validateEvidencePackage,\n validateComparison,\n validate as autoValidate,\n} from '@mitre/hdf-validators';\n\n// JSON-quoted ISO 8601 timestamp with no trailing timezone — InSpec emits\n// these (e.g. \"2026-03-25T22:56:27.736808\"). ajv-formats requires RFC 3339\n// for `date-time` and rejects them.\nconst NO_TZ_TIMESTAMP_REGEX = /\"(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?)\"/g;\n\n/**\n * Append Z (treat as UTC) to bare ISO timestamps in a JSON string so they\n * pass schema validation. Exported so other workspace packages can use the\n * same regex instead of re-implementing it. Matches the Go side at\n * hdf-parsers/go/parsers.go.\n */\nexport function normalizeTimestamps(input: string): string {\n return input.replace(NO_TZ_TIMESTAMP_REGEX, '\"$1Z\"');\n}\n\n/**\n * Result of parsing operation\n */\nexport interface ParseResult<T> {\n success: boolean;\n data?: T;\n error?: string;\n type?: 'results' | 'baseline' | 'system' | 'plan' | 'evidencePackage' | 'comparison';\n /** Non-fatal notices from pre-validation normalization (e.g. a legacy\n * SAF-supplement shape rewritten to v3-native); callers surface these. */\n warnings?: string[];\n}\n\n/**\n * Parse HDF Results document from string or bytes\n * @param input - JSON string or Uint8Array to parse\n * @returns ParseResult with parsed data or error\n */\nexport function parseResults(input: string | Uint8Array): ParseResult<HDFResults> {\n // Convert Uint8Array to string if needed\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n // Rewrite legacy SAF-supplement top-level keys (target/passthrough) into\n // v3-native carriers BEFORE validation, so a SAF-produced document is accepted\n // (ajv enforces unevaluatedProperties) with its attribution preserved. Sibling\n // to normalizeTimestamps.\n const { output: jsonStr, warnings } = normalizeSafSupplement(normalizeTimestamps(decoded));\n\n // Check for empty input\n if (jsonStr.trim().length === 0) {\n return {\n success: false,\n error: 'Input is empty'\n };\n }\n\n // Parse JSON\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return {\n success: false,\n error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}`\n };\n }\n\n // JSON.parse already rejects trailing garbage (it throws on the first\n // non-whitespace byte after the root value), so the catch above covers\n // that case. A prior length-compare heuristic here false-positived on\n // complex real-world inputs (e.g. `0.70` parsed as `0.7` would re-\n // serialize to a different length) — caught by the cross-language\n // parser parity test in typescript/parse-equivalence.test.ts.\n\n // Validate against schema\n const validationResult = validateResults(data);\n if (!validationResult.valid) {\n return {\n success: false,\n error: `Schema validation failed: ${validationResult.getErrorMessage()}`\n };\n }\n\n return {\n success: true,\n data: data as HDFResults,\n warnings: warnings.length > 0 ? warnings : undefined\n };\n}\n\n/**\n * Parse HDF Baseline document from string or bytes\n * @param input - JSON string or Uint8Array to parse\n * @returns ParseResult with parsed data or error\n */\nexport function parseBaseline(input: string | Uint8Array): ParseResult<HDFBaseline> {\n // Convert Uint8Array to string if needed\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n\n // Check for empty input\n if (jsonStr.trim().length === 0) {\n return {\n success: false,\n error: 'Input is empty'\n };\n }\n\n // Parse JSON\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return {\n success: false,\n error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}`\n };\n }\n\n // Trailing garbage already caught by the JSON.parse catch above; see\n // parseResults for the full rationale.\n\n // Validate against schema\n const validationResult = validateBaseline(data);\n if (!validationResult.valid) {\n return {\n success: false,\n error: `Schema validation failed: ${validationResult.getErrorMessage()}`\n };\n }\n\n return {\n success: true,\n data: data as HDFBaseline\n };\n}\n\n/**\n * Parse HDF System document from string or bytes\n */\nexport function parseSystem(input: string | Uint8Array): ParseResult<HDFSystem> {\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n if (jsonStr.trim().length === 0) {\n return { success: false, error: 'Input is empty' };\n }\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return { success: false, error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` };\n }\n const validationResult = validateSystem(data);\n if (!validationResult.valid) {\n return { success: false, error: `Schema validation failed: ${validationResult.getErrorMessage()}` };\n }\n return { success: true, data: data as HDFSystem };\n}\n\n/**\n * Parse HDF Plan document from string or bytes\n */\nexport function parsePlan(input: string | Uint8Array): ParseResult<HDFPlan> {\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n if (jsonStr.trim().length === 0) {\n return { success: false, error: 'Input is empty' };\n }\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return { success: false, error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` };\n }\n const validationResult = validatePlan(data);\n if (!validationResult.valid) {\n return { success: false, error: `Schema validation failed: ${validationResult.getErrorMessage()}` };\n }\n return { success: true, data: data as HDFPlan };\n}\n\n/**\n * Parse HDF Evidence Package document from string or bytes\n */\nexport function parseEvidencePackage(input: string | Uint8Array): ParseResult<HDFEvidencePackage> {\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n if (jsonStr.trim().length === 0) {\n return { success: false, error: 'Input is empty' };\n }\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return { success: false, error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` };\n }\n const validationResult = validateEvidencePackage(data);\n if (!validationResult.valid) {\n return { success: false, error: `Schema validation failed: ${validationResult.getErrorMessage()}` };\n }\n return { success: true, data: data as HDFEvidencePackage };\n}\n\n/**\n * Parse HDF Comparison document from string or bytes\n */\nexport function parseComparison(input: string | Uint8Array): ParseResult<HDFComparison> {\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n if (jsonStr.trim().length === 0) {\n return { success: false, error: 'Input is empty' };\n }\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return { success: false, error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` };\n }\n const validationResult = validateComparison(data);\n if (!validationResult.valid) {\n return { success: false, error: `Schema validation failed: ${validationResult.getErrorMessage()}` };\n }\n return { success: true, data: data as HDFComparison };\n}\n\n/**\n * Parse HDF document with auto-detection of type\n * @param input - JSON string or Uint8Array to parse\n * @returns ParseResult with parsed data, type indicator, or error\n */\nexport function parse(\n input: string | Uint8Array,\n): ParseResult<HDFResults | HDFBaseline | HDFSystem | HDFPlan | HDFEvidencePackage | HDFComparison> {\n // Convert Uint8Array to string if needed\n const decoded = typeof input === 'string' ? input : new TextDecoder().decode(input);\n const jsonStr = normalizeTimestamps(decoded);\n\n // Check for empty input\n if (jsonStr.trim().length === 0) {\n return {\n success: false,\n error: 'Input is empty'\n };\n }\n\n // Parse JSON\n let data: unknown;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n return {\n success: false,\n error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}`\n };\n }\n\n // Trailing garbage already caught by the JSON.parse catch above; see\n // parseResults for the full rationale.\n\n // Auto-validate and detect type\n const validationResult = autoValidate(data);\n if (!validationResult.valid) {\n return {\n success: false,\n error: `Schema validation failed: ${validationResult.getErrorMessage()}`\n };\n }\n\n // Determine type based on structure\n if (typeof data === 'object' && data !== null) {\n const obj = data as Record<string, unknown>;\n\n // HDF Results has 'baselines' array at root\n if ('baselines' in obj) {\n return {\n success: true,\n data: data as HDFResults,\n type: 'results'\n };\n }\n\n // HDF Comparison has 'requirementDiffs' at root (unique discriminator)\n if ('requirementDiffs' in obj) {\n return { success: true, data: data as HDFComparison, type: 'comparison' };\n }\n\n // HDF Plan has 'assessments' at root\n if ('assessments' in obj) {\n return { success: true, data: data as HDFPlan, type: 'plan' };\n }\n\n // HDF Evidence Package has 'contents' at root\n if ('contents' in obj) {\n return { success: true, data: data as HDFEvidencePackage, type: 'evidencePackage' };\n }\n\n // HDF Baseline has 'name' and 'requirements' at root\n if ('name' in obj && 'requirements' in obj) {\n return {\n success: true,\n data: data as HDFBaseline,\n type: 'baseline'\n };\n }\n\n // HDF System has 'components' at root (Results' baselines check already ruled out)\n if ('components' in obj) {\n return { success: true, data: data as HDFSystem, type: 'system' };\n }\n }\n\n return {\n success: false,\n error: 'Unable to determine HDF document type'\n };\n}\n\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mitre/hdf-parsers",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "Parse and load HDF documents with validation",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"author": "MITRE Corporation",
|
|
26
26
|
"license": "Apache-2.0",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@mitre/hdf-schema": "^3.
|
|
29
|
-
"@mitre/hdf-validators": "^3.
|
|
28
|
+
"@mitre/hdf-schema": "^3.7.0",
|
|
29
|
+
"@mitre/hdf-validators": "^3.7.0"
|
|
30
30
|
},
|
|
31
31
|
"engines": {
|
|
32
32
|
"node": ">=22.0.0"
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@stryker-mutator/core": "^9.5.1",
|
|
42
42
|
"@stryker-mutator/vitest-runner": "^9.5.1",
|
|
43
|
-
"@mitre/hdf-fixtures": "^3.
|
|
43
|
+
"@mitre/hdf-fixtures": "^3.7.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsdown",
|