@mitre/hdf-schema 3.5.1 → 3.6.0-rc.1

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/go/hdf.go CHANGED
@@ -263,11 +263,13 @@ type ExternalReference struct {
263
263
  // own when neither id nor href is available.
264
264
  Description *string `json:"description,omitempty"`
265
265
  // Optional lossless embedded copy of the referenced artifact — the raw STIX object, EPSS
266
- // record, advisory, or annotation payload — preserved verbatim. Composes with
267
- // `href`/`externalId` (which point at the artifact) and `checksum` (which ties the copy to
268
- // the source): a single entry can both point and embed. HDF stays payload-agnostic — the
269
- // content is carried untouched, never normalized into HDF fields — so this does not
270
- // duplicate the source ontology (e.g. STIX rides here unchanged).
266
+ // record, advisory, or annotation payload — preserved verbatim.
267
+ //
268
+ // Composes with `href`/`externalId` (which point at the artifact) and `checksum` (which
269
+ // ties the copy to the source): a single entry can both point and embed.
270
+ //
271
+ // HDF stays payload-agnostic — the content is carried untouched, never normalized into HDF
272
+ // fields — so this does not duplicate the source ontology (e.g. STIX rides here unchanged).
271
273
  Document map[string]interface{} `json:"document,omitempty"`
272
274
  // Identifier of the artifact within `sourceName` (e.g., 'CVE-2021-44228' for source 'cve',
273
275
  // 'T1059' for 'mitre-att&ck'). Cite by id without needing a URL. Together with `sourceName`
@@ -278,10 +280,15 @@ type ExternalReference struct {
278
280
  // `checksum`/`mediaType` apply only to a retrievable `href`.
279
281
  Href *string `json:"href,omitempty"`
280
282
  // Open token classifying the referenced/embedded payload, turning a bare reference into an
281
- // enrichment envelope. Deliberately open (like `sourceName`/`rel`), not a closed enum.
283
+ // enrichment envelope.
284
+ //
285
+ // Deliberately open (like `sourceName`/`rel`), not a closed enum.
286
+ //
282
287
  // Documented starter vocabulary: 'threat-intel' (STIX/CTI object), 'annotation' (human
283
288
  // triage note), 'exploitation' (EPSS/KEV signal carried as context), 'advisory'
284
- // (vendor/security advisory). Use the `x-` prefix for custom kinds.
289
+ // (vendor/security advisory).
290
+ //
291
+ // Use the `x-` prefix for custom kinds.
285
292
  Kind *string `json:"kind,omitempty"`
286
293
  // IANA media type of the referenced artifact when retrievable (RFC 6838), e.g.,
287
294
  // 'application/json'. Meaningful only with `href`.
@@ -306,13 +313,14 @@ type Identity struct {
306
313
  Description *string `json:"description,omitempty"`
307
314
  // The identifier value. Example: 'user@example.com', 'jdoe', 'automated-scanner-01'.
308
315
  Identifier string `json:"identifier"`
309
- // The type of identifier. Use 'email' for email addresses, 'username' for user accounts,
310
- // 'system' for deterministic non-interactive automation (CI jobs, cron, scanners), 'agent'
311
- // for an AI/LLM agent acting with autonomy — kept distinct from 'system' so auditors can
312
- // apply AI-specific scrutiny (e.g. 'an LLM proposed this' vs a deterministic job) and
313
- // satisfy AI-source disclosure under frameworks like the EU AI Act and NIST AI RMF,
314
- // 'simple' for basic string identifiers without additional classification, or 'other' for
315
- // custom identity systems.
316
+ // The type of identifier.
317
+ //
318
+ // Use 'email' for email addresses, 'username' for user accounts, 'system' for deterministic
319
+ // non-interactive automation (CI jobs, cron, scanners), 'agent' for an AI/LLM agent acting
320
+ // with autonomy — kept distinct from 'system' so auditors can apply AI-specific scrutiny
321
+ // (e.g. 'an LLM proposed this' vs a deterministic job) and satisfy AI-source disclosure
322
+ // under frameworks like the EU AI Act and NIST AI RMF, 'simple' for basic string
323
+ // identifiers without additional classification, or 'other' for custom identity systems.
316
324
  Type IdentityType `json:"type"`
317
325
  }
318
326
 
@@ -409,12 +417,17 @@ type EvaluatedRequirement struct {
409
417
  // POAMs apply.
410
418
  Disposition *OverrideType `json:"disposition,omitempty"`
411
419
  // Checksum of this requirement's resolved effective posture, for per-control change
412
- // detection in continuous monitoring. sha256 over the canonical JSON object with keys
413
- // status, impact, disposition (in that order), holding the resolved effective status,
414
- // resolved effective impact, and governing override type (null when nothing governs), with
415
- // override expiry anchored to the document timestamp. Flips exactly when the operative
416
- // status, impact, or disposition changes; stable under all other churn (result details,
417
- // timestamps, tags). Optional; stamped by tooling (hdf convert, hdf amend apply).
420
+ // detection in continuous monitoring.
421
+ //
422
+ // sha256 over the canonical JSON object with keys status, impact, disposition (in that
423
+ // order), holding the resolved effective status, resolved effective impact, and governing
424
+ // override type (null when nothing governs), with override expiry anchored to the document
425
+ // timestamp.
426
+ //
427
+ // Flips exactly when the operative status, impact, or disposition changes; stable under all
428
+ // other churn (result details, timestamps, tags).
429
+ //
430
+ // Optional; stamped by tooling (hdf convert, hdf amend apply).
418
431
  EffectiveChecksum *Checksum `json:"effectiveChecksum,omitempty"`
419
432
  // The current effective impact score (0.0–1.0) after applying the most recent non-expired
420
433
  // override with an impact field. Absent when no impact overrides apply; consumers should
@@ -456,10 +469,14 @@ type EvaluatedRequirement struct {
456
469
  Impact float64 `json:"impact"`
457
470
  // A set of tags - usually metadata like CCI, STIG ID, severity.
458
471
  Tags map[string]interface{} `json:"tags"`
459
- // Whether the requirement is mandatory within its baseline. Distinct from severity (risk
460
- // weight) and status (lifecycle state). Maps cleanly onto: FedRAMP rev5 OSCAL 'CORE' prop,
461
- // FedRAMP 20x inline 'Optional:' markers, CMMC sublevel rows, and CIS Implementation Group
462
- // memberships (IG1/IG2/IG3 may carry richer semantics; layer those onto props[]/tags{}).
472
+ // Whether the requirement is mandatory within its baseline.
473
+ //
474
+ // Distinct from severity (risk weight) and status (lifecycle state).
475
+ //
476
+ // Maps cleanly onto: FedRAMP rev5 OSCAL 'CORE' prop, FedRAMP 20x inline 'Optional:'
477
+ // markers, CMMC sublevel rows, and CIS Implementation Group memberships (IG1/IG2/IG3 may
478
+ // carry richer semantics; layer those onto props[]/tags{}).
479
+ //
463
480
  // Optional: when omitted, consumers should treat the requirement as 'required' by
464
481
  // convention.
465
482
  Applicability *Applicability `json:"applicability,omitempty"`
@@ -469,11 +486,15 @@ type EvaluatedRequirement struct {
469
486
  // underlying source code.
470
487
  Code *string `json:"code,omitempty"`
471
488
  // Classification of the control's nature, aligning with NIST SP 800-53 / SP 800-53A
472
- // categories. 'policy' = an authored governance statement; 'procedure' = a documented
473
- // process; 'technical' = an enforced technical configuration; 'management' = a
489
+ // categories.
490
+ //
491
+ // 'policy' = an authored governance statement; 'procedure' = a documented process;
492
+ // 'technical' = an enforced technical configuration; 'management' = a
474
493
  // programmatic/management activity; 'operational' = a recurring operational activity (e.g.
475
- // AT, IR, MA families). Optional: when omitted, consumers may infer heuristically from
476
- // family/id but should not assume a default.
494
+ // AT, IR, MA families).
495
+ //
496
+ // Optional: when omitted, consumers may infer heuristically from family/id but should not
497
+ // assume a default.
477
498
  ControlType *ControlType `json:"controlType,omitempty"`
478
499
  // Optional references to external artifacts relevant to this requirement (CTI/STIX
479
500
  // correlation, advisories, control/definition sources, or any URI-addressable artifact).
@@ -484,12 +505,17 @@ type EvaluatedRequirement struct {
484
505
  Refs []Reference `json:"refs,omitempty"`
485
506
  // The title - is nullable.
486
507
  Title *string `json:"title,omitempty"`
487
- // How this requirement is intended to be verified. Disambiguates the two cases that null
488
- // 'code' overloads: 'manual-by-design' (the requirement is statement-form and not amenable
489
- // to automation, e.g. FedRAMP 20x KSIs); 'manual-pending-automation' (automation could
490
- // exist but does not yet, e.g. a STIG rule lacking a fix). 'automated' = a check exists and
491
- // runs without operator action; 'hybrid' = part automated, part manual. Optional: when
492
- // omitted, consumers should not infer a default.
508
+ // How this requirement is intended to be verified.
509
+ //
510
+ // Disambiguates the two cases that null 'code' overloads: 'manual-by-design' (the
511
+ // requirement is statement-form and not amenable to automation, e.g. FedRAMP 20x KSIs);
512
+ // 'manual-pending-automation' (automation could exist but does not yet, e.g. a STIG rule
513
+ // lacking a fix).
514
+ //
515
+ // 'automated' = a check exists and runs without operator action; 'hybrid' = part automated,
516
+ // part manual.
517
+ //
518
+ // Optional: when omitted, consumers should not infer a default.
493
519
  VerificationMethod *VerificationMethodEnum `json:"verificationMethod,omitempty"`
494
520
  }
495
521
 
@@ -505,7 +531,7 @@ type AffectedPackage struct {
505
531
  // Optional CPE 2.3 URI identifying the affected product. Validated leniently: only the
506
532
  // 'cpe:2.3:' prefix and the part-type letter ('a' application, 'h' hardware, 'o' operating
507
533
  // system) are enforced here. Use `hdf-utilities.parseCpe` for full-grammar parsing.
508
- // Example: 'cpe:2.3:a:openssl:openssl:1.1.1k:*:*:*:*:*:*:*'.
534
+ // Example: `cpe:2.3:a:openssl:openssl:1.1.1k:*:*:*:*:*:*:*`.
509
535
  Cpe *string `json:"cpe,omitempty"`
510
536
  // The packaging ecosystem the package belongs to. Use 'generic' for hardware, firmware, or
511
537
  // anything outside the listed language/OS package managers.
@@ -517,11 +543,16 @@ type AffectedPackage struct {
517
543
  // The package name as published in its ecosystem. Examples: 'openssl' (rpm), 'lodash'
518
544
  // (npm), 'org.apache.logging.log4j:log4j-core' (maven, group:artifact).
519
545
  Name *string `json:"name,omitempty"`
520
- // Optional Package URL (PURL) identifying the affected package. Validated leniently: only
521
- // the 'pkg:TYPE/' scheme prefix is enforced here, where TYPE follows the PURL grammar (a
522
- // letter followed by letters, digits, '.', '+', or '-') and is matched case-insensitively
523
- // to mirror `hdf-utilities.parsePurl`'s accept-and-warn behavior. Use `parsePurl` for full
524
- // PURL parsing. Example: 'pkg:rpm/redhat/openssl@1.1.1k-7.el8_4?arch=x86_64'.
546
+ // Optional Package URL (PURL) identifying the affected package.
547
+ //
548
+ // Validated leniently: only the 'pkg:TYPE/' scheme prefix is enforced here, where TYPE
549
+ // follows the PURL grammar (a letter followed by letters, digits, '.', '+', or '-') and is
550
+ // matched case-insensitively to mirror `hdf-utilities.parsePurl`'s accept-and-warn
551
+ // behavior.
552
+ //
553
+ // Use `parsePurl` for full PURL parsing.
554
+ //
555
+ // Example: 'pkg:rpm/redhat/openssl@1.1.1k-7.el8_4?arch=x86_64'.
525
556
  Purl *string `json:"purl,omitempty"`
526
557
  // The exact version of the package that the vulnerability scanner observed. Use the
527
558
  // ecosystem's native version string verbatim (e.g., '1.1.1k-7.el8_4' for rpm, '4.17.20' for
@@ -543,11 +574,15 @@ type Cvss struct {
543
574
  // 'none' or 'critical' bands; map accordingly when populating.
544
575
  BaseSeverity *CVSSSeverity `json:"baseSeverity,omitempty"`
545
576
  // Optional Base metric group vector string as emitted by the source (e.g.,
546
- // 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H'). For CVSS 2.0 the version prefix is
547
- // omitted. Some vendor tools emit a final baseScore without the vector — in that case this
548
- // field is absent and the score cannot be recomputed or decomposed. The pattern accepts any
549
- // version-prefixed or prefix-less metric token sequence; semantic validity of individual
550
- // metrics is checked by hdf-utilities, not by the schema.
577
+ // 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H').
578
+ //
579
+ // For CVSS 2.0 the version prefix is omitted.
580
+ //
581
+ // Some vendor tools emit a final baseScore without the vector — in that case this field is
582
+ // absent and the score cannot be recomputed or decomposed.
583
+ //
584
+ // The pattern accepts any version-prefixed or prefix-less metric token sequence; semantic
585
+ // validity of individual metrics is checked by hdf-utilities, not by the schema.
551
586
  BaseVector *string `json:"baseVector,omitempty"`
552
587
  // Optional final score after combining Base + Threat + Environmental metrics. This is the
553
588
  // score consumers should treat as authoritative for risk decisions when present.
@@ -862,11 +897,16 @@ type Component struct {
862
897
  // System-specific overrides for baseline input values.
863
898
  InputOverrides []InputOverride `json:"inputOverrides,omitempty"`
864
899
  // Cryptographic integrity of this component's underlying artifact — model weights or
865
- // shards, dataset archive, container image, or package bytes. An array supports
866
- // multi-file/sharded artifacts. This is the single, generic home for artifact/subject
867
- // integrity across all component types (it replaced the former per-type Container_Image
868
- // digest and Artifact checksum fields). Distinct from BOM-document integrity (Bom.hashes[])
869
- // and from the document tamper-evidence Integrity type.
900
+ // shards, dataset archive, container image, or package bytes.
901
+ //
902
+ // An array supports multi-file/sharded artifacts.
903
+ //
904
+ // This is the single, generic home for artifact/subject integrity across all component
905
+ // types (it replaced the former per-type Container_Image digest and Artifact checksum
906
+ // fields).
907
+ //
908
+ // Distinct from BOM-document integrity (Bom.hashes[]) and from the document tamper-evidence
909
+ // Integrity type.
870
910
  Integrity []Checksum `json:"integrity,omitempty"`
871
911
  // Optional key-value labels for flexible grouping. Well-known keys: system, component,
872
912
  // environment, region, team. Values must be strings.
@@ -1290,19 +1330,22 @@ type StatisticBlock struct {
1290
1330
  // The security tool that produced the assessment data represented in this HDF file. Aligns with
1291
1331
  // SARIF, OSCAL, and CycloneDX terminology.
1292
1332
  type Tool struct {
1293
- // The named format of the source data, when it follows a recognized format specification
1294
- // with its own identity: an interchange format emitted by many tools ('SARIF', 'XCCDF',
1295
- // 'OSCAL') or one of several named output formats a single tool produces ('FVDL',
1296
- // 'exec-json', 'FPF'). Never a serialization structure — 'JSON', 'XML', and 'CSV' are
1297
- // encodings, not formats. Omit for a tool's native output: an absent format means the
1298
- // tool's own shape, and data arriving as a named format is converted by that format's
1299
- // converter, which sets this field alongside the producing tool's name.
1300
- Format *string `json:"format,omitempty"`
1301
- // The name of the security tool that produced the data. Examples: 'gosec', 'Semgrep',
1302
- // 'OpenSCAP', 'AWS Config', 'Nessus'. Omit if the tool cannot be identified.
1303
- Name *string `json:"name,omitempty"`
1304
- // Version of the source tool, if available in the tool's output. Example: '5.22.3'.
1305
- Version *string `json:"version,omitempty"`
1333
+ // The named format of the source data, when it follows a recognized format specification
1334
+ // with its own identity: an interchange format emitted by many tools ('SARIF', 'XCCDF',
1335
+ // 'OSCAL') or one of several named output formats a single tool produces ('FVDL',
1336
+ // 'exec-json', 'FPF').
1337
+ //
1338
+ // Never a serialization structure — 'JSON', 'XML', and 'CSV' are encodings, not formats.
1339
+ //
1340
+ // Omit for a tool's native output: an absent format means the tool's own shape, and data
1341
+ // arriving as a named format is converted by that format's converter, which sets this field
1342
+ // alongside the producing tool's name.
1343
+ Format *string `json:"format,omitempty"`
1344
+ // The name of the security tool that produced the data. Examples: 'gosec', 'Semgrep',
1345
+ // 'OpenSCAP', 'AWS Config', 'Nessus'. Omit if the tool cannot be identified.
1346
+ Name *string `json:"name,omitempty"`
1347
+ // Version of the source tool, if available in the tool's output. Example: '5.22.3'.
1348
+ Version *string `json:"version,omitempty"`
1306
1349
  }
1307
1350
 
1308
1351
  // Information on the set of requirements that can be assessed, including baseline metadata and
@@ -1368,10 +1411,14 @@ type BaselineRequirement struct {
1368
1411
  Impact float64 `json:"impact"`
1369
1412
  // A set of tags - usually metadata like CCI, STIG ID, severity.
1370
1413
  Tags map[string]interface{} `json:"tags"`
1371
- // Whether the requirement is mandatory within its baseline. Distinct from severity (risk
1372
- // weight) and status (lifecycle state). Maps cleanly onto: FedRAMP rev5 OSCAL 'CORE' prop,
1373
- // FedRAMP 20x inline 'Optional:' markers, CMMC sublevel rows, and CIS Implementation Group
1374
- // memberships (IG1/IG2/IG3 may carry richer semantics; layer those onto props[]/tags{}).
1414
+ // Whether the requirement is mandatory within its baseline.
1415
+ //
1416
+ // Distinct from severity (risk weight) and status (lifecycle state).
1417
+ //
1418
+ // Maps cleanly onto: FedRAMP rev5 OSCAL 'CORE' prop, FedRAMP 20x inline 'Optional:'
1419
+ // markers, CMMC sublevel rows, and CIS Implementation Group memberships (IG1/IG2/IG3 may
1420
+ // carry richer semantics; layer those onto props[]/tags{}).
1421
+ //
1375
1422
  // Optional: when omitted, consumers should treat the requirement as 'required' by
1376
1423
  // convention.
1377
1424
  Applicability *Applicability `json:"applicability,omitempty"`
@@ -1381,11 +1428,15 @@ type BaselineRequirement struct {
1381
1428
  // underlying source code.
1382
1429
  Code *string `json:"code,omitempty"`
1383
1430
  // Classification of the control's nature, aligning with NIST SP 800-53 / SP 800-53A
1384
- // categories. 'policy' = an authored governance statement; 'procedure' = a documented
1385
- // process; 'technical' = an enforced technical configuration; 'management' = a
1431
+ // categories.
1432
+ //
1433
+ // 'policy' = an authored governance statement; 'procedure' = a documented process;
1434
+ // 'technical' = an enforced technical configuration; 'management' = a
1386
1435
  // programmatic/management activity; 'operational' = a recurring operational activity (e.g.
1387
- // AT, IR, MA families). Optional: when omitted, consumers may infer heuristically from
1388
- // family/id but should not assume a default.
1436
+ // AT, IR, MA families).
1437
+ //
1438
+ // Optional: when omitted, consumers may infer heuristically from family/id but should not
1439
+ // assume a default.
1389
1440
  ControlType *ControlType `json:"controlType,omitempty"`
1390
1441
  // Optional references to external artifacts relevant to this requirement (CTI/STIX
1391
1442
  // correlation, advisories, control/definition sources, or any URI-addressable artifact).
@@ -1398,12 +1449,17 @@ type BaselineRequirement struct {
1398
1449
  SourceLocation *SourceLocation `json:"sourceLocation,omitempty"`
1399
1450
  // The title - is nullable.
1400
1451
  Title *string `json:"title,omitempty"`
1401
- // How this requirement is intended to be verified. Disambiguates the two cases that null
1402
- // 'code' overloads: 'manual-by-design' (the requirement is statement-form and not amenable
1403
- // to automation, e.g. FedRAMP 20x KSIs); 'manual-pending-automation' (automation could
1404
- // exist but does not yet, e.g. a STIG rule lacking a fix). 'automated' = a check exists and
1405
- // runs without operator action; 'hybrid' = part automated, part manual. Optional: when
1406
- // omitted, consumers should not infer a default.
1452
+ // How this requirement is intended to be verified.
1453
+ //
1454
+ // Disambiguates the two cases that null 'code' overloads: 'manual-by-design' (the
1455
+ // requirement is statement-form and not amenable to automation, e.g. FedRAMP 20x KSIs);
1456
+ // 'manual-pending-automation' (automation could exist but does not yet, e.g. a STIG rule
1457
+ // lacking a fix).
1458
+ //
1459
+ // 'automated' = a check exists and runs without operator action; 'hybrid' = part automated,
1460
+ // part manual.
1461
+ //
1462
+ // Optional: when omitted, consumers should not infer a default.
1407
1463
  VerificationMethod *VerificationMethodEnum `json:"verificationMethod,omitempty"`
1408
1464
  }
1409
1465
 
@@ -1957,22 +2013,27 @@ type HDFAmendments struct {
1957
2013
  // branches gated on 'type': when type is 'operationalRequirement', neither 'status' nor 'impact'
1958
2014
  // may be set — the override records accepted risk without changing the finding
1959
2015
  // (documentation-only). For all other types, at least one of 'status' or 'impact' must be set. This
1960
- // rule aligns with: (1) OSCAL Assessment Results — finding.target.status and
2016
+ // rule aligns with: - OSCAL Assessment Results — finding.target.status and
1961
2017
  // finding.associated-risk[].facet[] are separate axes
1962
- // (https://pages.nist.gov/OSCAL/learn/concepts/layer/assessment/assessment-results/); (2) FedRAMP
2018
+ // (https://pages.nist.gov/OSCAL/learn/concepts/layer/assessment/assessment-results/) - FedRAMP
1963
2019
  // deviation request types — Risk Adjustment changes impact only, Operational Requirement documents
1964
2020
  // acceptance only, False Positive changes status
1965
- // (https://www.ignyteplatform.com/blog/fedramp/fedramp-deviation-requests-submit/); (3) NIST SP
1966
- // 800-37 RMF — risk response (accept/mitigate/transfer) is a separate step from control assessment
1967
- // status (https://csrc.nist.gov/pubs/sp/800/37/r2/final).
2021
+ // (https://www.ignyteplatform.com/blog/fedramp/fedramp-deviation-requests-submit/) - NIST SP 800-37
2022
+ // RMF — risk response (accept/mitigate/transfer) is a separate step from control assessment status
2023
+ // (https://csrc.nist.gov/pubs/sp/800/37/r2/final).
1968
2024
  type StandaloneOverride struct {
1969
2025
  // Software packages this amendment is scoped to, distinct from componentRef (which scopes
1970
- // to an HDF-internal Component by UUID). Use when the source amendment format references
1971
- // packages by purl/cpe/name+version — e.g., VEX `affects[]` / `products[]`, OSCAL POA&M
1972
- // `subjects[]`, FedRAMP component-aware amendments. Symmetric with
1973
- // Evaluated_Requirement.affectedPackages, which scopes findings to the same package
1974
- // vocabulary. When omitted, the amendment applies system-wide (or only to componentRef when
1975
- // that is set).
2026
+ // to an HDF-internal Component by UUID).
2027
+ //
2028
+ // Use when the source amendment format references packages by purl/cpe/name+version — e.g.,
2029
+ // VEX `affects[]` / `products[]`, OSCAL POA&M `subjects[]`, FedRAMP component-aware
2030
+ // amendments.
2031
+ //
2032
+ // Symmetric with Evaluated_Requirement.affectedPackages, which scopes findings to the same
2033
+ // package vocabulary.
2034
+ //
2035
+ // When omitted, the amendment applies system-wide (or only to componentRef when that is
2036
+ // set).
1976
2037
  AffectedPackages []AffectedPackage `json:"affectedPackages,omitempty"`
1977
2038
  // When this amendment was applied. ISO 8601 format.
1978
2039
  AppliedAt time.Time `json:"appliedAt"`
@@ -2199,10 +2260,12 @@ type HDFRequirementChangeEvent struct {
2199
2260
  EventID string `json:"eventId"`
2200
2261
  // The effectiveChecksum of the entity state this event supersedes, forming a per-key hash
2201
2262
  // chain: a mismatch or gap against stored state is detectable, letting a consumer mark the
2202
- // key unverified instead of serving stale posture. Null at chain start (no prior state,
2203
- // e.g. a new entity or the first event after a seed). The chain provides tamper/gap
2204
- // evidence given a trusted head; completeness is anchored out-of-band by periodic
2205
- // re-centering rescans.
2263
+ // key unverified instead of serving stale posture.
2264
+ //
2265
+ // Null at chain start (no prior state, e.g. a new entity or the first event after a seed).
2266
+ //
2267
+ // The chain provides tamper/gap evidence given a trusted head; completeness is anchored
2268
+ // out-of-band by periodic re-centering rescans.
2206
2269
  PriorChecksum interface{} `json:"priorChecksum"`
2207
2270
  // The versioned schema $id this event validates against, so events self-describe on
2208
2271
  // heterogeneous streams. Recommended on every wire event.
@@ -2223,13 +2286,14 @@ type HDFRequirementChangeEvent struct {
2223
2286
  Timestamp time.Time `json:"timestamp"`
2224
2287
  }
2225
2288
 
2226
- // The type of identifier. Use 'email' for email addresses, 'username' for user accounts,
2227
- // 'system' for deterministic non-interactive automation (CI jobs, cron, scanners), 'agent'
2228
- // for an AI/LLM agent acting with autonomy — kept distinct from 'system' so auditors can
2229
- // apply AI-specific scrutiny (e.g. 'an LLM proposed this' vs a deterministic job) and
2230
- // satisfy AI-source disclosure under frameworks like the EU AI Act and NIST AI RMF,
2231
- // 'simple' for basic string identifiers without additional classification, or 'other' for
2232
- // custom identity systems.
2289
+ // The type of identifier.
2290
+ //
2291
+ // Use 'email' for email addresses, 'username' for user accounts, 'system' for deterministic
2292
+ // non-interactive automation (CI jobs, cron, scanners), 'agent' for an AI/LLM agent acting
2293
+ // with autonomy — kept distinct from 'system' so auditors can apply AI-specific scrutiny
2294
+ // (e.g. 'an LLM proposed this' vs a deterministic job) and satisfy AI-source disclosure
2295
+ // under frameworks like the EU AI Act and NIST AI RMF, 'simple' for basic string
2296
+ // identifiers without additional classification, or 'other' for custom identity systems.
2233
2297
  type IdentityType string
2234
2298
 
2235
2299
  const (
@@ -2298,10 +2362,14 @@ const (
2298
2362
  RPM Ecosystem = "rpm"
2299
2363
  )
2300
2364
 
2301
- // Whether the requirement is mandatory within its baseline. Distinct from severity (risk
2302
- // weight) and status (lifecycle state). Maps cleanly onto: FedRAMP rev5 OSCAL 'CORE' prop,
2303
- // FedRAMP 20x inline 'Optional:' markers, CMMC sublevel rows, and CIS Implementation Group
2304
- // memberships (IG1/IG2/IG3 may carry richer semantics; layer those onto props[]/tags{}).
2365
+ // Whether the requirement is mandatory within its baseline.
2366
+ //
2367
+ // Distinct from severity (risk weight) and status (lifecycle state).
2368
+ //
2369
+ // Maps cleanly onto: FedRAMP rev5 OSCAL 'CORE' prop, FedRAMP 20x inline 'Optional:'
2370
+ // markers, CMMC sublevel rows, and CIS Implementation Group memberships (IG1/IG2/IG3 may
2371
+ // carry richer semantics; layer those onto props[]/tags{}).
2372
+ //
2305
2373
  // Optional: when omitted, consumers should treat the requirement as 'required' by
2306
2374
  // convention.
2307
2375
  type Applicability string
@@ -2313,11 +2381,15 @@ const (
2313
2381
  )
2314
2382
 
2315
2383
  // Classification of the control's nature, aligning with NIST SP 800-53 / SP 800-53A
2316
- // categories. 'policy' = an authored governance statement; 'procedure' = a documented
2317
- // process; 'technical' = an enforced technical configuration; 'management' = a
2384
+ // categories.
2385
+ //
2386
+ // 'policy' = an authored governance statement; 'procedure' = a documented process;
2387
+ // 'technical' = an enforced technical configuration; 'management' = a
2318
2388
  // programmatic/management activity; 'operational' = a recurring operational activity (e.g.
2319
- // AT, IR, MA families). Optional: when omitted, consumers may infer heuristically from
2320
- // family/id but should not assume a default.
2389
+ // AT, IR, MA families).
2390
+ //
2391
+ // Optional: when omitted, consumers may infer heuristically from family/id but should not
2392
+ // assume a default.
2321
2393
  type ControlType string
2322
2394
 
2323
2395
  const (
@@ -2352,19 +2424,19 @@ const (
2352
2424
  The40 Version = "4.0"
2353
2425
  )
2354
2426
 
2355
- // The type of amendment, aligned with FedRAMP deviation request categories. 'waiver': risk accepted
2356
- // by Authorizing Official. 'attestation': manually verified by assessor. 'poam': remediation
2357
- // tracked (no status change). 'inherited': control provided by another component or system.
2358
- // 'falsePositive': scanner incorrectly identified a finding — for compliance scans (STIG, CIS), the
2359
- // check actually passes, so status is typically set to 'passed'; for vulnerability scans (CVE,
2360
- // SCA), the flagged vulnerability does not apply to this system, so status is typically set to
2361
- // 'notApplicable'. The disposition field on the requirement distinguishes false positives from
2362
- // genuinely not-applicable findings. 'riskAdjustment': impact score adjusted based on environmental
2363
- // context (FedRAMP Risk Adjustment); does not change pass/fail status, only impact via the impact
2364
- // field. 'operationalRequirement': deviation required by operational constraints (FedRAMP
2365
- // Operational Requirement); the finding cannot be remediated because the system requires the
2366
- // affected functionality. Remains an open risk. Migration note: 'exception' was removed in v3.1.0 —
2367
- // use 'waiver' with status 'notApplicable' instead.
2427
+ // The type of amendment, aligned with FedRAMP deviation request categories. - 'waiver': risk
2428
+ // accepted by Authorizing Official. - 'attestation': manually verified by assessor. - 'poam':
2429
+ // remediation tracked (no status change). - 'inherited': control provided by another component or
2430
+ // system. - 'falsePositive': scanner incorrectly identified a finding — for compliance scans (STIG,
2431
+ // CIS), the check actually passes, so status is typically set to 'passed'; for vulnerability scans
2432
+ // (CVE, SCA), the flagged vulnerability does not apply to this system, so status is typically set
2433
+ // to 'notApplicable'. The disposition field on the requirement distinguishes false positives from
2434
+ // genuinely not-applicable findings. - 'riskAdjustment': impact score adjusted based on
2435
+ // environmental context (FedRAMP Risk Adjustment); does not change pass/fail status, only impact
2436
+ // via the impact field. - 'operationalRequirement': deviation required by operational constraints
2437
+ // (FedRAMP Operational Requirement); the finding cannot be remediated because the system requires
2438
+ // the affected functionality. Remains an open risk. Migration note: 'exception' was removed in
2439
+ // v3.1.0 — use 'waiver' with status 'notApplicable' instead.
2368
2440
  type OverrideType string
2369
2441
 
2370
2442
  const (
package/dist/helpers.js CHANGED
@@ -229,36 +229,26 @@ export function createCvss(version, options = {}) {
229
229
  // @mitre/hdf-schema/helpers still get these functions.
230
230
  export { severityToImpact, impactToSeverity } from '@mitre/hdf-utilities';
231
231
 
232
- import { worstStatus } from '@mitre/hdf-utilities';
232
+ import { computeEffectiveStatus as canonicalComputeEffectiveStatus } from '@mitre/hdf-utilities';
233
233
 
234
234
  /**
235
- * Compute the effective status of a requirement from its results and impact.
236
- *
237
- * When effectiveStatus is already set on the requirement, returns it directly.
238
- * Otherwise derives status using standard HDF/InSpec precedence:
239
- * 1. effectiveStatus already set → return it
240
- * 2. impact === 0 → notApplicable
241
- * 3. No results → notReviewed
242
- * 4. Worst-wins roll-up of results via the canonical shared ordering
243
- * (error > failed > passed > notApplicable > notReviewed)
235
+ * Compute the effective status of a requirement — delegates to the canonical
236
+ * ladder in @mitre/hdf-utilities (see status-determination.md): governing
237
+ * non-expired override → error roll-up → impact-0 notApplicable → worst-wins
238
+ * roll-up. The stored effectiveStatus field is never read (output cache).
244
239
  *
245
240
  * @param {import('../dist/ts/hdf-results.js').EvaluatedRequirement} requirement
246
241
  * @returns {import('../dist/ts/hdf-results.js').ResultStatus}
247
242
  */
248
243
  export function computeEffectiveStatus(requirement) {
249
- if (requirement.effectiveStatus) {
250
- return requirement.effectiveStatus;
251
- }
252
-
253
- if (requirement.impact === 0) {
254
- return 'notApplicable';
255
- }
256
-
257
- // Worst-wins roll-up via the canonical shared ordering (error > failed >
258
- // passed > notApplicable > notReviewed); empty results -> notReviewed.
259
- // NOTE: unlike the full effective-status computation in @mitre/hdf-utilities,
260
- // this helper deliberately honors an already-set effectiveStatus first (its
261
- // documented back-compat contract) and does not consult statusOverrides.
262
- const results = requirement.results ?? [];
263
- return worstStatus(results.map((result) => result.status));
244
+ const stamp = (v) => (v instanceof Date ? v.toISOString() : typeof v === 'string' && v !== '' ? v : undefined);
245
+ return canonicalComputeEffectiveStatus({
246
+ impact: requirement.impact,
247
+ resultStatuses: (requirement.results ?? []).map((result) => result?.status),
248
+ overrides: (requirement.statusOverrides ?? []).map((override) => ({
249
+ status: override.status || undefined,
250
+ appliedAt: stamp(override.appliedAt),
251
+ expiresAt: stamp(override.expiresAt),
252
+ })),
253
+ });
264
254
  }