@mitre/hdf-validators 2.0.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/LICENSE.md ADDED
@@ -0,0 +1,55 @@
1
+ # License
2
+
3
+ Copyright © 2025 The MITRE Corporation.
4
+
5
+ Approved for Public Release; Distribution Unlimited. Case Number 18-3678.
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License"); you may
8
+ not use this file except in compliance with the License. You may obtain a
9
+ copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+ License for the specific language governing permissions and limitations
17
+ under the License.
18
+
19
+ ## Redistribution Terms
20
+
21
+ Redistribution and use in source and binary forms, with or without
22
+ modification, are permitted provided that the following conditions are
23
+ met:
24
+
25
+ - Redistributions of source code must retain the above copyright/digital
26
+ rights legend, this list of conditions and the following Notice.
27
+ - Redistributions in binary form must reproduce the above
28
+ copyright/digital rights legend, this list of conditions and the
29
+ following Notice in the documentation and/or other materials provided
30
+ with the distribution.
31
+ - Neither the name of The MITRE Corporation nor the names of its contributors
32
+ may be used to endorse or promote products derived from this software
33
+ without specific prior written permission.
34
+
35
+ ## Notice
36
+
37
+ The MITRE Corporation grants permission to reproduce, distribute, modify, and
38
+ otherwise use this software to the extent permitted by the licensed terms
39
+ provided in the LICENSE file included with this project.
40
+
41
+ This software was produced by The MITRE Corporation for the U.S. Government
42
+ under contract. As such the U.S. Government has certain use and data
43
+ rights in this software. No use other than those granted to the U.S.
44
+ Government, or to those acting on behalf of the U.S. Government, under
45
+ these contract arrangements is authorized without the express written
46
+ permission of The MITRE Corporation.
47
+
48
+ Some files in this codebase were generated by generative AI, under the
49
+ direction and review of The MITRE Corporation employees, for the purpose of
50
+ development efficiency. All AI-generated code functionality was validated
51
+ by standard quality and assurance testing.
52
+
53
+ For further information, please contact The MITRE Corporation,
54
+ Contracts Management Office, 7515 Colshire Drive, McLean, VA 22102-7539,
55
+ (703) 983-6000.
package/README.md ADDED
@@ -0,0 +1,385 @@
1
+ # @mitre/hdf-validators
2
+
3
+ JSON Schema validation for Heimdall Data Format (HDF) documents. Validates HDF Results and Baselines against the official HDF schemas to ensure structural correctness and data integrity.
4
+
5
+ ## Scope and Responsibilities
6
+
7
+ **hdf-validators** provides schema-based validation:
8
+ - Validate HDF Results documents against the HDF Results schema
9
+ - Validate HDF Baseline documents against the HDF Baseline schema
10
+ - Detailed error reporting with field-level validation messages
11
+ - Support for both TypeScript and Go implementations
12
+
13
+ ### hdf-validators vs. hdf-utilities
14
+
15
+ | hdf-validators | hdf-utilities |
16
+ |----------------|---------------|
17
+ | HDF schema validation | Format syntax validation |
18
+ | "Is this valid HDF?" | "Is this valid JSON/XML/CSV?" |
19
+ | "Does baselines exist and is it an array?" | "Can this string be parsed as JSON?" |
20
+ | Validates structure and types | Validates syntax only |
21
+ | HDF-specific semantic rules | Generic format handling |
22
+
23
+ **Example:**
24
+ - `isValidJSON('{"foo": "bar"}')` → `true` (utilities - just checks JSON syntax)
25
+ - `validateResults({foo: 'bar'})` → `false`, missing baselines field (validators - checks HDF schema)
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install @mitre/hdf-validators
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ### TypeScript
36
+
37
+ ```typescript
38
+ import { validateResults, validateBaseline } from '@mitre/hdf-validators';
39
+
40
+ // Validate HDF Results
41
+ const hdfResults = {
42
+ baselines: [{
43
+ name: 'My Baseline',
44
+ checksum: { algorithm: 'sha256', value: 'abc123' },
45
+ requirements: [{
46
+ id: 'REQ-001',
47
+ descriptions: [{ label: 'default', data: 'Test requirement' }],
48
+ impact: 0.7,
49
+ tags: { nist: ['AC-1'] },
50
+ results: [{
51
+ status: 'passed',
52
+ codeDesc: 'Control check',
53
+ startTime: '2025-01-01T00:00:00Z'
54
+ }]
55
+ }]
56
+ }],
57
+ targets: [],
58
+ statistics: {}
59
+ };
60
+
61
+ const result = validateResults(hdfResults);
62
+
63
+ if (result.valid) {
64
+ console.log('✓ Valid HDF Results document');
65
+ } else {
66
+ console.error('✗ Validation failed:');
67
+ console.error(result.getErrorMessage());
68
+
69
+ // Or access individual errors
70
+ result.errors.forEach(error => {
71
+ console.error(` ${error.field}: ${error.message}`);
72
+ });
73
+ }
74
+ ```
75
+
76
+ ```typescript
77
+ // Validate HDF Baseline
78
+ const hdfBaseline = {
79
+ name: 'Security Baseline',
80
+ title: 'Example Security Baseline',
81
+ version: '1.0.0',
82
+ checksum: { algorithm: 'sha256', value: 'def456' },
83
+ requirements: [{
84
+ id: 'REQ-001',
85
+ title: 'Access Control',
86
+ descriptions: [{ label: 'default', data: 'Requirement description' }],
87
+ impact: 0.7,
88
+ tags: { nist: ['AC-1', 'AC-2'] }
89
+ }]
90
+ };
91
+
92
+ const baselineResult = validateBaseline(hdfBaseline);
93
+
94
+ if (!baselineResult.valid) {
95
+ console.error('Validation errors:', baselineResult.errors);
96
+ }
97
+ ```
98
+
99
+ ```typescript
100
+ // Auto-detect document type
101
+ import { validate } from '@mitre/hdf-validators';
102
+
103
+ const autoResult = validate(someHdfDocument);
104
+ // Automatically determines if it's Results or Baseline and validates accordingly
105
+ ```
106
+
107
+ ### Go
108
+
109
+ ```go
110
+ package main
111
+
112
+ import (
113
+ "encoding/json"
114
+ "fmt"
115
+ "os"
116
+
117
+ validators "github.com/mitre/hdf-validators/go"
118
+ )
119
+
120
+ func main() {
121
+ // Read HDF file
122
+ data, err := os.ReadFile("results.json")
123
+ if err != nil {
124
+ panic(err)
125
+ }
126
+
127
+ // Validate HDF Results
128
+ result := validators.ValidateResults(data)
129
+
130
+ if result.Valid {
131
+ fmt.Println("✓ Valid HDF Results document")
132
+ } else {
133
+ fmt.Println("✗ Validation failed:")
134
+ fmt.Println(result.Error())
135
+
136
+ // Access individual errors
137
+ for _, e := range result.Errors {
138
+ fmt.Printf(" %s: %s\n", e.Field, e.Description)
139
+ }
140
+ os.Exit(1)
141
+ }
142
+ }
143
+ ```
144
+
145
+ ```go
146
+ // Validate HDF Baseline
147
+ result := validators.ValidateBaseline(baselineData)
148
+
149
+ // Use custom schema directory (for development/testing)
150
+ validators.SetSchemaDir("./custom-schemas")
151
+ result = validators.ValidateResults(data) // Will use schemas from custom directory
152
+
153
+ // Reset to embedded schemas
154
+ validators.SetSchemaDir("")
155
+ ```
156
+
157
+ ## API Reference
158
+
159
+ ### TypeScript
160
+
161
+ #### `validateResults(data: unknown): ValidationResult`
162
+
163
+ Validate data against the HDF Results schema.
164
+
165
+ - **Parameters:**
166
+ - `data` - JavaScript object to validate
167
+ - **Returns:** `ValidationResult` with validation status and errors
168
+
169
+ #### `validateBaseline(data: unknown): ValidationResult`
170
+
171
+ Validate data against the HDF Baseline schema.
172
+
173
+ - **Parameters:**
174
+ - `data` - JavaScript object to validate
175
+ - **Returns:** `ValidationResult` with validation status and errors
176
+
177
+ #### `validate(data: unknown): ValidationResult`
178
+
179
+ Auto-detect document type and validate.
180
+
181
+ - **Parameters:**
182
+ - `data` - JavaScript object to validate
183
+ - **Returns:** `ValidationResult` with validation status and errors
184
+
185
+ #### `ValidationResult`
186
+
187
+ ```typescript
188
+ interface ValidationResult {
189
+ valid: boolean; // True if validation passed
190
+ errors: ValidationError[]; // Array of validation errors (empty if valid)
191
+ getErrorMessage(): string; // Formatted error message
192
+ }
193
+ ```
194
+
195
+ #### `ValidationError`
196
+
197
+ ```typescript
198
+ interface ValidationError {
199
+ field: string; // JSON path to the field with error
200
+ message: string; // Description of the validation error
201
+ value?: unknown; // The invalid value (optional)
202
+ }
203
+ ```
204
+
205
+ ### Go
206
+
207
+ #### `ValidateResults(data []byte) ValidationResult`
208
+
209
+ Validate JSON bytes against the HDF Results schema.
210
+
211
+ - **Parameters:**
212
+ - `data` - JSON bytes to validate
213
+ - **Returns:** `ValidationResult` with validation status and errors
214
+
215
+ #### `ValidateBaseline(data []byte) ValidationResult`
216
+
217
+ Validate JSON bytes against the HDF Baseline schema.
218
+
219
+ - **Parameters:**
220
+ - `data` - JSON bytes to validate
221
+ - **Returns:** `ValidationResult` with validation status and errors
222
+
223
+ #### `Validate(data []byte, schemaType SchemaType) ValidationResult`
224
+
225
+ Validate JSON bytes against specified schema type.
226
+
227
+ - **Parameters:**
228
+ - `data` - JSON bytes to validate
229
+ - `schemaType` - `TypeResults` or `TypeBaseline`
230
+ - **Returns:** `ValidationResult` with validation status and errors
231
+
232
+ #### `SetSchemaDir(dir string)`
233
+
234
+ Configure package to load schemas from a directory instead of embedded schemas.
235
+
236
+ - **Parameters:**
237
+ - `dir` - Directory path (empty string to revert to embedded schemas)
238
+
239
+ #### `GetSchemaDir() string`
240
+
241
+ Get the current schema directory (empty if using embedded schemas).
242
+
243
+ - **Returns:** Current schema directory path
244
+
245
+ #### `ValidationResult`
246
+
247
+ ```go
248
+ type ValidationResult struct {
249
+ Valid bool `json:"valid"` // True if validation passed
250
+ Errors []ValidationError `json:"errors"` // Validation errors (empty if valid)
251
+ }
252
+
253
+ func (r ValidationResult) Error() string // Formatted error message
254
+ ```
255
+
256
+ #### `ValidationError`
257
+
258
+ ```go
259
+ type ValidationError struct {
260
+ Field string `json:"field"` // JSON path to invalid field
261
+ Description string `json:"description"` // Error description
262
+ Value any `json:"value"` // Invalid value (optional)
263
+ }
264
+ ```
265
+
266
+ ## Common Validation Errors
267
+
268
+ ### Missing Required Fields
269
+
270
+ ```
271
+ baselines: is required
272
+ ```
273
+
274
+ HDF Results must have a `baselines` array.
275
+
276
+ ### Invalid Field Types
277
+
278
+ ```
279
+ baselines: must be array
280
+ baselines[0].name: is required
281
+ ```
282
+
283
+ The `name` field is required for each baseline.
284
+
285
+ ### Invalid Enum Values
286
+
287
+ ```
288
+ results[0].status: must be equal to one of the allowed values
289
+ ```
290
+
291
+ Result status must be one of: `passed`, `failed`, `error`, `skipped`, `not_applicable`, `not_reviewed`.
292
+
293
+ ### Invalid Numeric Ranges
294
+
295
+ ```
296
+ impact: must be >= 0 and <= 1
297
+ ```
298
+
299
+ Impact scores must be between 0.0 and 1.0.
300
+
301
+ ## Use Cases
302
+
303
+ ### Converter Output Validation
304
+
305
+ Validate that your converter produces valid HDF:
306
+
307
+ ```typescript
308
+ import { convertNessusToHdf } from '@mitre/hdf-converters';
309
+ import { validateResults } from '@mitre/hdf-validators';
310
+
311
+ const hdf = convertNessusToHdf(nessusXml);
312
+ const result = validateResults(JSON.parse(hdf));
313
+
314
+ if (!result.valid) {
315
+ throw new Error(`Invalid HDF output: ${result.getErrorMessage()}`);
316
+ }
317
+ ```
318
+
319
+ ### Pre-Upload Validation
320
+
321
+ Validate HDF before uploading to Heimdall:
322
+
323
+ ```typescript
324
+ const hdfData = JSON.parse(fs.readFileSync('scan-results.json', 'utf-8'));
325
+ const result = validateResults(hdfData);
326
+
327
+ if (result.valid) {
328
+ uploadToHeimdall(hdfData);
329
+ } else {
330
+ console.error('Cannot upload invalid HDF:', result.getErrorMessage());
331
+ }
332
+ ```
333
+
334
+ ### CI/CD Pipeline Validation
335
+
336
+ ```bash
337
+ # Validate HDF file in CI
338
+ hdf validate results.json
339
+
340
+ # Exit code 0 if valid, non-zero if invalid
341
+ if hdf validate scan.json --quiet; then
342
+ echo "✓ HDF validation passed"
343
+ else
344
+ echo "✗ HDF validation failed"
345
+ exit 1
346
+ fi
347
+ ```
348
+
349
+ ## Development
350
+
351
+ ```bash
352
+ # Install dependencies
353
+ pnpm install
354
+
355
+ # Run TypeScript tests
356
+ pnpm test:ts
357
+
358
+ # Run Go tests
359
+ pnpm test:go
360
+
361
+ # Run all tests
362
+ pnpm test
363
+
364
+ # Run tests with coverage
365
+ pnpm test:coverage
366
+
367
+ # Build TypeScript package
368
+ pnpm build
369
+
370
+ # Lint code
371
+ pnpm lint
372
+ ```
373
+
374
+ ## Test Coverage
375
+
376
+ Both TypeScript and Go implementations maintain **>95% test coverage** with comprehensive validation tests covering:
377
+ - Valid HDF Results and Baseline documents
378
+ - Invalid documents (missing fields, wrong types, invalid values)
379
+ - Error message formatting
380
+ - Custom schema directory loading (Go)
381
+ - Integration tests with real HDF fixtures
382
+
383
+ ## License
384
+
385
+ Apache-2.0 © MITRE Corporation
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Validation error details
3
+ */
4
+ export interface ValidationError {
5
+ field: string;
6
+ message: string;
7
+ value?: unknown;
8
+ }
9
+ /**
10
+ * Result of schema validation
11
+ */
12
+ export interface ValidationResult {
13
+ valid: boolean;
14
+ errors: ValidationError[];
15
+ getErrorMessage(): string;
16
+ }
17
+ /**
18
+ * Validate HDF Results document against schema
19
+ */
20
+ export declare function validateResults(data: unknown): ValidationResult;
21
+ /**
22
+ * Validate HDF Baseline document against schema
23
+ */
24
+ export declare function validateBaseline(data: unknown): ValidationResult;
25
+ /**
26
+ * Validate HDF Comparison document against schema
27
+ */
28
+ export declare function validateComparison(data: unknown): ValidationResult;
29
+ /**
30
+ * Validate HDF System document against schema
31
+ */
32
+ export declare function validateSystem(data: unknown): ValidationResult;
33
+ /**
34
+ * Validate HDF Plan document against schema
35
+ */
36
+ export declare function validatePlan(data: unknown): ValidationResult;
37
+ /**
38
+ * Validate HDF Amendments document against schema
39
+ */
40
+ export declare function validateAmendments(data: unknown): ValidationResult;
41
+ /**
42
+ * Validate HDF Evidence Package document against schema
43
+ */
44
+ export declare function validateEvidencePackage(data: unknown): ValidationResult;
45
+ /**
46
+ * Validate HDF document (auto-detect type based on structure)
47
+ */
48
+ export declare function validate(data: unknown): ValidationResult;
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../typescript/index.ts"],"names":[],"mappings":"AA0BA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,eAAe,IAAI,MAAM,CAAC;CAC3B;AAuKD;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAG/D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAGhE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAGlE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAG9D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAG5D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAGlE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAGvE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAoDxD"}
package/dist/index.js ADDED
@@ -0,0 +1,266 @@
1
+ import Ajv from 'ajv';
2
+ import addFormats from 'ajv-formats';
3
+ // Import all schemas (bare JSON imports — bundled by Vite via noExternal config)
4
+ import hdfResultsSchema from '@mitre/hdf-schema/schemas/hdf-results.schema.json';
5
+ import hdfBaselineSchema from '@mitre/hdf-schema/schemas/hdf-baseline.schema.json';
6
+ import hdfComparisonSchema from '@mitre/hdf-schema/schemas/hdf-comparison.schema.json';
7
+ import hdfSystemSchema from '@mitre/hdf-schema/schemas/hdf-system.schema.json';
8
+ import hdfPlanSchema from '@mitre/hdf-schema/schemas/hdf-plan.schema.json';
9
+ import hdfAmendmentsSchema from '@mitre/hdf-schema/schemas/hdf-amendments.schema.json';
10
+ import hdfEvidencePackageSchema from '@mitre/hdf-schema/schemas/hdf-evidence-package.schema.json';
11
+ import commonSchema from '@mitre/hdf-schema/schemas/primitives/common.schema.json';
12
+ import extensionsSchema from '@mitre/hdf-schema/schemas/primitives/extensions.schema.json';
13
+ import platformSchema from '@mitre/hdf-schema/schemas/primitives/platform.schema.json';
14
+ import resultSchema from '@mitre/hdf-schema/schemas/primitives/result.schema.json';
15
+ import runnerSchema from '@mitre/hdf-schema/schemas/primitives/runner.schema.json';
16
+ import statisticsSchema from '@mitre/hdf-schema/schemas/primitives/statistics.schema.json';
17
+ import targetSchema from '@mitre/hdf-schema/schemas/primitives/target.schema.json';
18
+ import parameterSchema from '@mitre/hdf-schema/schemas/primitives/parameter.schema.json';
19
+ import systemSchema from '@mitre/hdf-schema/schemas/primitives/system.schema.json';
20
+ import planSchema from '@mitre/hdf-schema/schemas/primitives/plan.schema.json';
21
+ import amendmentsSchema from '@mitre/hdf-schema/schemas/primitives/amendments.schema.json';
22
+ import comparisonSchema from '@mitre/hdf-schema/schemas/primitives/comparison.schema.json';
23
+ import componentSchema from '@mitre/hdf-schema/schemas/primitives/component.schema.json';
24
+ import dataFlowSchema from '@mitre/hdf-schema/schemas/primitives/data-flow.schema.json';
25
+ /**
26
+ * Create and configure Ajv instance with all HDF schemas
27
+ */
28
+ function createValidator() {
29
+ const ajv = new Ajv({
30
+ allErrors: true,
31
+ verbose: true,
32
+ strict: false,
33
+ validateFormats: true,
34
+ validateSchema: false // Skip meta-schema validation for performance
35
+ });
36
+ // Add format validators (date-time, uri, etc.)
37
+ addFormats(ajv);
38
+ // Add all primitive schemas so they can be referenced
39
+ ajv.addSchema(commonSchema);
40
+ ajv.addSchema(platformSchema);
41
+ ajv.addSchema(resultSchema);
42
+ ajv.addSchema(runnerSchema);
43
+ ajv.addSchema(statisticsSchema);
44
+ ajv.addSchema(targetSchema);
45
+ ajv.addSchema(parameterSchema);
46
+ ajv.addSchema(amendmentsSchema); // before extensions (extensions $refs amendments Override_Type)
47
+ ajv.addSchema(extensionsSchema);
48
+ ajv.addSchema(systemSchema);
49
+ ajv.addSchema(planSchema);
50
+ ajv.addSchema(comparisonSchema);
51
+ ajv.addSchema(componentSchema);
52
+ ajv.addSchema(dataFlowSchema);
53
+ return ajv;
54
+ }
55
+ // Singleton Ajv instance
56
+ const ajv = createValidator();
57
+ // Compile schemas once (lazy initialization)
58
+ let resultsValidator = null;
59
+ let baselineValidator = null;
60
+ let comparisonValidator = null;
61
+ let systemValidator = null;
62
+ let planValidator = null;
63
+ let amendmentsValidator = null;
64
+ let evidencePackageValidator = null;
65
+ function getResultsValidator() {
66
+ if (!resultsValidator) {
67
+ resultsValidator = ajv.compile(hdfResultsSchema);
68
+ }
69
+ return resultsValidator;
70
+ }
71
+ function getBaselineValidator() {
72
+ if (!baselineValidator) {
73
+ baselineValidator = ajv.compile(hdfBaselineSchema);
74
+ }
75
+ return baselineValidator;
76
+ }
77
+ function getComparisonValidator() {
78
+ if (!comparisonValidator) {
79
+ comparisonValidator = ajv.compile(hdfComparisonSchema);
80
+ }
81
+ return comparisonValidator;
82
+ }
83
+ function getSystemValidator() {
84
+ if (!systemValidator) {
85
+ systemValidator = ajv.compile(hdfSystemSchema);
86
+ }
87
+ return systemValidator;
88
+ }
89
+ function getPlanValidator() {
90
+ if (!planValidator) {
91
+ planValidator = ajv.compile(hdfPlanSchema);
92
+ }
93
+ return planValidator;
94
+ }
95
+ function getAmendmentsValidator() {
96
+ if (!amendmentsValidator) {
97
+ amendmentsValidator = ajv.compile(hdfAmendmentsSchema);
98
+ }
99
+ return amendmentsValidator;
100
+ }
101
+ function getEvidencePackageValidator() {
102
+ if (!evidencePackageValidator) {
103
+ evidencePackageValidator = ajv.compile(hdfEvidencePackageSchema);
104
+ }
105
+ return evidencePackageValidator;
106
+ }
107
+ /**
108
+ * Convert Ajv errors to ValidationError format
109
+ */
110
+ function formatErrors(errors) {
111
+ if (!errors || errors.length === 0) {
112
+ return [];
113
+ }
114
+ return errors.map(err => {
115
+ // Clean up field path (remove leading slash, use dot notation)
116
+ let field = err.instancePath
117
+ .replace(/^\//, '')
118
+ .replace(/\//g, '.');
119
+ // If field is empty, use the data path from the error
120
+ if (!field && err.schemaPath) {
121
+ const pathParts = err.schemaPath.split('/');
122
+ field = pathParts[pathParts.length - 1] || '(root)';
123
+ }
124
+ // Build message
125
+ let message = err.message || 'validation failed';
126
+ if (err.params) {
127
+ // Add parameter info for more context
128
+ if ('missingProperty' in err.params) {
129
+ field = field ? `${field}.${err.params.missingProperty}` : err.params.missingProperty;
130
+ message = 'is required';
131
+ }
132
+ else if ('additionalProperty' in err.params) {
133
+ field = field ? `${field}.${err.params.additionalProperty}` : err.params.additionalProperty;
134
+ message = 'is not allowed';
135
+ }
136
+ else if ('limit' in err.params) {
137
+ message = `${message} (limit: ${err.params.limit})`;
138
+ }
139
+ }
140
+ return {
141
+ field: field || '(root)',
142
+ message,
143
+ value: err.data
144
+ };
145
+ });
146
+ }
147
+ /**
148
+ * Create ValidationResult from validator output
149
+ */
150
+ function createResult(validator, data) {
151
+ const valid = validator(data);
152
+ const errors = formatErrors(validator.errors);
153
+ return {
154
+ valid: valid === true,
155
+ errors,
156
+ getErrorMessage() {
157
+ if (this.valid) {
158
+ return '';
159
+ }
160
+ return this.errors
161
+ .map(e => {
162
+ if (e.field === '(root)') {
163
+ return e.message;
164
+ }
165
+ return `${e.field}: ${e.message}`;
166
+ })
167
+ .join('; ');
168
+ }
169
+ };
170
+ }
171
+ /**
172
+ * Validate HDF Results document against schema
173
+ */
174
+ export function validateResults(data) {
175
+ const validator = getResultsValidator();
176
+ return createResult(validator, data);
177
+ }
178
+ /**
179
+ * Validate HDF Baseline document against schema
180
+ */
181
+ export function validateBaseline(data) {
182
+ const validator = getBaselineValidator();
183
+ return createResult(validator, data);
184
+ }
185
+ /**
186
+ * Validate HDF Comparison document against schema
187
+ */
188
+ export function validateComparison(data) {
189
+ const validator = getComparisonValidator();
190
+ return createResult(validator, data);
191
+ }
192
+ /**
193
+ * Validate HDF System document against schema
194
+ */
195
+ export function validateSystem(data) {
196
+ const validator = getSystemValidator();
197
+ return createResult(validator, data);
198
+ }
199
+ /**
200
+ * Validate HDF Plan document against schema
201
+ */
202
+ export function validatePlan(data) {
203
+ const validator = getPlanValidator();
204
+ return createResult(validator, data);
205
+ }
206
+ /**
207
+ * Validate HDF Amendments document against schema
208
+ */
209
+ export function validateAmendments(data) {
210
+ const validator = getAmendmentsValidator();
211
+ return createResult(validator, data);
212
+ }
213
+ /**
214
+ * Validate HDF Evidence Package document against schema
215
+ */
216
+ export function validateEvidencePackage(data) {
217
+ const validator = getEvidencePackageValidator();
218
+ return createResult(validator, data);
219
+ }
220
+ /**
221
+ * Validate HDF document (auto-detect type based on structure)
222
+ */
223
+ export function validate(data) {
224
+ if (typeof data === 'object' && data !== null) {
225
+ const obj = data;
226
+ // HDF Results has 'baselines' array at root
227
+ if ('baselines' in obj) {
228
+ return validateResults(data);
229
+ }
230
+ // HDF Baseline has 'name' and 'requirements' at root
231
+ if ('name' in obj && 'requirements' in obj) {
232
+ return validateBaseline(data);
233
+ }
234
+ // HDF System has 'name' and 'components' at root
235
+ if ('name' in obj && 'components' in obj) {
236
+ return validateSystem(data);
237
+ }
238
+ // HDF Plan has 'name' and 'assessments' at root
239
+ if ('name' in obj && 'assessments' in obj) {
240
+ return validatePlan(data);
241
+ }
242
+ // HDF Amendments has 'name' and 'overrides' at root
243
+ if ('name' in obj && 'overrides' in obj) {
244
+ return validateAmendments(data);
245
+ }
246
+ // HDF Comparison has 'mode' and 'sources' at root
247
+ if ('mode' in obj && 'sources' in obj) {
248
+ return validateComparison(data);
249
+ }
250
+ // HDF Evidence Package has 'name' and 'contents' at root
251
+ if ('name' in obj && 'contents' in obj) {
252
+ return validateEvidencePackage(data);
253
+ }
254
+ }
255
+ // Cannot determine type, try results first (most common)
256
+ const resultsResult = validateResults(data);
257
+ if (resultsResult.valid) {
258
+ return resultsResult;
259
+ }
260
+ const baselineResult = validateBaseline(data);
261
+ if (baselineResult.valid) {
262
+ return baselineResult;
263
+ }
264
+ return resultsResult;
265
+ }
266
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../typescript/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@mitre/hdf-validators",
3
+ "version": "2.0.0",
4
+ "description": "JSON Schema validation for HDF documents (Results and Baselines)",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "development": "./typescript/index.ts",
14
+ "import": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/mitre/hdf-libs.git",
24
+ "directory": "hdf-validators"
25
+ },
26
+ "author": "MITRE Corporation",
27
+ "license": "Apache-2.0",
28
+ "dependencies": {
29
+ "ajv": "^8.17.1",
30
+ "ajv-formats": "^3.0.1",
31
+ "@mitre/hdf-schema": "2.0.0"
32
+ },
33
+ "engines": {
34
+ "node": ">=20.0.0"
35
+ },
36
+ "keywords": [
37
+ "hdf",
38
+ "heimdall",
39
+ "validation",
40
+ "json-schema"
41
+ ],
42
+ "devDependencies": {
43
+ "@stryker-mutator/core": "^9.5.1",
44
+ "@stryker-mutator/vitest-runner": "^9.5.1"
45
+ },
46
+ "scripts": {
47
+ "build": "pnpm clean && tsc",
48
+ "clean": "rimraf dist",
49
+ "test": "pnpm run test:ts && pnpm run test:go",
50
+ "test:ts": "vitest run",
51
+ "test:go": "cd go && go test ./...",
52
+ "test:watch": "vitest",
53
+ "test:coverage": "vitest run --coverage",
54
+ "type-check": "tsc --noEmit",
55
+ "lint": "eslint typescript",
56
+ "lint:fix": "eslint typescript --fix"
57
+ }
58
+ }