@mitre/hdf-schema
JSON schemas and multi-language type definitions for Heimdall Data Format (HDF).
Overview
HDF is a standardized format for representing security assessment results. This package provides:
- JSON Schemas for validating HDF documents
- Generated types for TypeScript and Go
Installation
npm install @mitre/hdf-schemaSchema Types
Eight document types: seven covering the full security assessment lifecycle, plus a continuous-monitoring change-event stream.
HDF Results (hdf-results)
Assessment findings from running security checks against target systems. The primary output of converters. Contains evaluated baselines with requirement results, components (hosts, containers, cloud resources), status overrides with disposition tracking, and statistics.
HDF Baseline (hdf-baseline)
Security requirement definitions without results — the "what to check" document. Contains requirement metadata (title, descriptions, severity, impact), check/fix instructions, framework mappings (NIST, CCI), and dependency information.
HDF System (hdf-system)
Authorization boundary definition. Describes a system's components (with polymorphic types: host, container, cloud account, application, etc.), data flows between components, and control designations (common/hybrid/system-specific).
HDF Plan (hdf-plan)
Assessment plan linking baselines to system components. Defines what will be assessed, how, and by whom. References baselines, systems, and runner configurations.
HDF Amendments (hdf-amendments)
Standalone amendment documents containing waivers, attestations, POA&Ms, and other overrides. Applied to results via hdf amend apply to track adjudication decisions (false positives, risk adjustments, operational requirements).
HDF Evidence Package (hdf-evidence-package)
Bundles references to all documents needed for a compliance review — results, baselines, system, plan, and amendments — with checksums for integrity verification.
HDF Comparison (hdf-comparison)
Output of the diff engine. Structural comparison between two or more HDF documents showing requirement-level changes, status transitions, and field diffs.
HDF Requirement Change Event (hdf-requirement-change-event)
A continuous-monitoring event stream: one event per requirement whose posture changed between two results scans (new, absent, updated, fixed, regressed). Each event carries the full after-state, a thin before-state, and a per-key sequence, so a reconciled results document can be replayed from a seed. Produced by hdf events derive.
Usage
Importing Schemas
Schemas can be imported in two ways:
// Named exports from the barrel (all schemas + types available)
import { hdfResultsSchema, hdfBaselineSchema, hdfSystemSchema } from '@mitre/hdf-schema';
import type { HDFResults, HDFBaseline, HDFSystem, HDFPlan, HDFAmendments, HDFEvidencePackage, HDFComparison, HDFRequirementChangeEvent } from '@mitre/hdf-schema';
// Sub-path imports also work (all resolve to the same combined module)
import type { HDFResults } from '@mitre/hdf-schema/hdf-results';
import type { HDFBaseline } from '@mitre/hdf-schema/hdf-baseline';Helper functions (severity mapping, effective status computation):
import { severityToImpact, impactToSeverity, computeEffectiveStatus } from '@mitre/hdf-schema/helpers';Validating Documents (TypeScript/JavaScript)
import Ajv from 'ajv';
import { hdfResultsSchema } from '@mitre/hdf-schema';
const ajv = new Ajv({ strict: false });
const validate = ajv.compile(hdfResultsSchema);
const isValid = validate(myDocument);
if (!isValid) {
console.error(validate.errors);
}Using Generated Types (TypeScript)
import type { HDFResults, HDFBaseline } from '@mitre/hdf-schema';
function processResults(results: HDFResults) {
for (const baseline of results.baselines) {
for (const requirement of baseline.requirements) {
console.log(`${requirement.id}: ${requirement.results[0]?.status}`);
}
}
}Using Generated Types (Go)
import hdf "github.com/mitre/hdf-libs/hdf-schema/dist/go/v3"
func main() {
data := []byte(`{"baselines": [...]}`)
results, err := hdf.UnmarshalHDFResults(data)
if err != nil {
panic(err)
}
for _, baseline := range results.Baselines {
fmt.Printf("%s: %d requirements\n", baseline.Name, len(baseline.Requirements))
}
}Schema Files
| File | Description |
|---|---|
src/schemas/hdf-results.schema.json | Assessment findings (modular, uses $ref) |
src/schemas/hdf-baseline.schema.json | Requirement definitions without results |
src/schemas/hdf-system.schema.json | Authorization boundary, components, data flows |
src/schemas/hdf-plan.schema.json | Assessment plan linking baselines to components |
src/schemas/hdf-amendments.schema.json | Waivers, attestations, POA&Ms |
src/schemas/hdf-evidence-package.schema.json | Bundle of references to all documents |
src/schemas/hdf-comparison.schema.json | Differential analysis between assessments |
src/schemas/hdf-requirement-change-event.schema.json | Continuous-monitoring per-requirement change-event stream |
src/schemas/primitives/*.schema.json | Shared type definitions |
dist/schemas/*.schema.json | Bundled schemas (self-contained, all $refs inlined) |
Modular vs Bundled Schemas
Modular schemas (src/schemas/) use $ref to reference shared definitions from primitive files. Use these if your validator supports $ref resolution.
Bundled schemas (dist/schemas/) have all references inlined. Use these for tools that don't support $ref or for simpler integration.
Generated Types
After building, types are available in:
| Language | Location |
|---|---|
| TypeScript | dist/ts/hdf.ts (single combined file, all types deduplicated) |
| Go | dist/go/hdf.go (single combined file, all types deduplicated) |
Development
# Install dependencies
pnpm install
# Run tests
pnpm test
# Build everything (schemas + types)
pnpm build
# Build only bundled schemas
pnpm build:schemas
# Build only generated types
pnpm build:typesVersioning
This package has two version numbers that serve different purposes:
Package version (
package.jsonversion): Follows npm semver. Bumped on every release — bug fixes, new helpers, type generation improvements, dependency updates. This is what consumers see innpm install @mitre/hdf-schema@3.0.1.Schema version (
$idURL in each.schema.json): Identifies the schema structure itself. Only changes when the schema structure changes — new fields, removed fields, type changes, constraint changes. Example:https://mitre.github.io/hdf-libs/schemas/hdf-results/v3.1.0.
These versions are aligned at major boundaries (both are 3.x to signal this is the successor to the heimdall2 v2.x ecosystem) but can diverge at minor/patch levels. A package patch release (e.g., 3.0.1 → 3.0.2) that only fixes a converter bug or updates a helper function does not change the schema $id. A schema structural change (e.g., adding a new required field) bumps the schema version in the $id URL regardless of where the package version stands.
The $id URLs are also the canonical hosted location for each schema: https://mitre.github.io/hdf-libs/schemas/.
JSON Schema dialect
All schemas use JSON Schema draft/2020-12.
Hosted schema documentation
Interactive schema reference documentation is published at: https://mitre.github.io/hdf-libs/schemas/
What's new in v3.7.0
Milestone.title— optional single-line label. A short label on each POA&MMilestone, suitable where a consumer needs a title (for example an OSCAL POA&M remediation or task). It is optional and does not replacedescription, which remains the full milestone text; a consumer needing a title where none is supplied derives one. The value carries the project's single-line-label constraint —minLength: 1plus a pattern (OSCAL'sStringDatatype, spelled with explicit character classes so ECMA-262 and Go regexp engines agree) banning line breaks and leading/trailing whitespace.Evidence.datatightened.datanow requiresminLength: 1(an empty evidence body no longer validates), and whenencodingis exactlybase64(lowercase) the data must be bare base64 matching^[0-9A-Za-z+/]+={0,2}$(OSCAL'sBase64Datatype): nodata:URI prefix, URL, or line breaks. Tightening: a v3.6.x document with an emptydata, or with abase64-encoded value that carries adata:prefix or line breaks, now fails validation — strip the prefix/whitespace or correct the encoding label.- Compatibility.
Milestone.titleis additive and optional, so a v3.6.x document validates unchanged under v3.7.0. TheEvidence.datachange is a validation tightening, not a structural one: documents whose evidence bodies were already non-empty and (forbase64) bare validate cleanly; the rest must be corrected. A v3.7.0 document carryingMilestone.titlewill not validate against the v3.6.x schemas, which reject unevaluated properties; strip the field or validate against v3.7.0.
What's new in v3.6.0
preAmendmentChecksumon the Results root. OptionalChecksumrecording the document's hash as it stood immediately before the most recent amendment application, written byhdf amend apply. It covers the results file's raw bytes as read, not a canonical form, and records only the most recent application rather than accumulating. Distinct from the override-levelpreviousChecksum, which chains amendments to one another over a canonical form. This is the only structural change in v3.6.0; everything else below is description-level.previousChecksumsemantics stated precisely (description-only, onStandalone_Override,Status_Override, and the POA&M element) — each amendment's checksum is recorded by the next one, so an in-place edit is detectable only for an amendment that has a later one chained to it. The chain is not tamper-proof: the final amendment, the document envelope, deleted trailing amendments, and a wholesale recompute are outside what it can detect; usesignaturefor non-repudiation. The field is omitted (notnull) on the first amendment. This is the contracthdf amend verifyenforces.- Schema descriptions reflowed into paragraphs and the source files pretty-printed one value per line. Cosmetic in the source, but the bundled
dist/schemas/descriptions now carry paragraph breaks, which IDE tooltips render. computeEffectiveStatushelper delegates to the canonical status ladder in@mitre/hdf-utilities. Behavior change for@mitre/hdf-schema/helpersconsumers: the helper no longer returns a pre-seteffectiveStatusverbatim, and it now applies the governing non-expiredstatusOverridesentry and the error roll-up ahead of the impact-0notApplicableshort-circuit, matching the CLI and converters.@mitre/hdf-schema/testhdfsub-path export — test-only builders (req,baseline,doc,results,baselineDoc,override,amendments,system,plan,evidencePackage,changeEvent,comparison, and friends) that construct schema-valid documents for downstream test suites, with a Go counterpart atgithub.com/mitre/hdf-libs/hdf-schema/testhdf/go.- Compatibility. The one schema addition is optional, so v3.5.x documents validate unchanged under v3.6.0. A v3.6.0 document carrying
preAmendmentChecksumwill not validate against the v3.5.x schemas, which reject unevaluated properties; strip the field or validate against v3.6.0.
What's new in v3.5.0
hdf-requirement-change-eventdocument type — a new schema for the continuous-monitoring change-event stream: per-requirement events (new/absent/updated/fixed/regressed) with a full after-state, thin before-state, and per-key sequence, chained for deterministic replay from a seed. Produced byhdf events derive.External_Referenceprimitive +externalReferences[]wiring — a generalized, STIX-2.1-aligned reference (requiredsourceNameplus one ofexternalId/href/description, openrel/kind, optional lossless embeddeddocument) wired across the document types, including on the inlineStatus_Override. Backs the STIX CTI enrichment feature.Change_ReasongainsdispositionChangedandeffectiveImpactChanged— the diff engine's amendment-axis change reasons are now part of the comparison vocabulary.- POA&M
expiresAtis now required — a POA&M is a time-boxed acceptance of an open finding; the deadline is no longer optional. Breaking: previously-valid HDF documents with deadline-less POA&Ms now fail validation. Source a real remediation/vendor-fix date. - Compatibility. The additions are additive except the required POA&M
expiresAt; v3.4.x documents without deadline-less POA&Ms validate cleanly under v3.5.0. See CHANGELOG.
What's new in v3.4.0
- Generalized
boms[]on components — a singleboms[]array onBase_Componentcarries any Bill of Materials (SBOM,ai-model,dataset, or reserved futurebomType), each by passthrough (ref/document) or normalized shape. Breaking: replaces the formersbom/sbomRef/sbomFormattrio; a component may now carry several BOMs (e.g. an SBOM plus an ai-model BOM). Seeprimitives/bom.schema.json. aiModelanddatasetcomponent types — thin AI-subject components whose detail lives in an attached ai-model / dataset BOM.- Generic component
integrity[]— one array home for artifact/subject integrity (model weights/shards, dataset archive, container image, package bytes). Breaking: replaces the per-typeContainer_Image.digestandArtifact.checksumfields. - Host identity
hostname+domainonHost_Component— short OS-reported name and directory (AD/NetBIOS/LDAP) domain, kept distinct fromfqdn(ECShost.hostname/host.domainsemantics). agentidentity type onIdentity— provenance for AI-agent actors.blake3added to theHash_Algorithmenum.- Compatibility. Additive fields validate v3.3.x documents cleanly; the BOM/integrity field removals are the one breaking change — migrate
sbom/sbomRef/sbomFormattoboms[]and per-type digests tointegrity[]. See CHANGELOG.
What's new in v3.2.0
- Combined TypeScript output — all types are now generated into a single
dist/ts/hdf.tsvia quicktype combined mode. This eliminates the duplicateIdentitytype bug (same interface from different per-file outputs was not assignable). Sub-path exports (@mitre/hdf-schema/hdf-results, etc.) still work but all resolve to the same module. - Canonical type naming via
title— all generated enum names are now controlled by explicittitleproperties in the source schemas. Key renames:Copyright→TargetType,OwnerType→IdentityType,Status→MilestoneStatus,SbomFormat→SBOMFormat,PoamType→POAMType. - Deprecated aliases —
HdfResults,HdfBaseline, etc. are deprecated type aliases forHDFResults,HDFBaseline. They still compile but consumers should migrate to theHDF*naming. controlTypefield onRequirement_Core— optional enum (policy | procedure | technical | management | operational) aligning with NIST SP 800-53 / SP 800-53A categories.verificationMethodfield onRequirement_Core— optional enum (automated | manual-by-design | manual-pending-automation | hybrid) disambiguating the two cases that nullcodeoverloaded.applicabilityfield onRequirement_Core— optional enum (required | optional | advisory) providing a uniform expression for what FedRAMPCOREprops, FedRAMP 20xOptional:markers, CIS Implementation Groups, and CMMC sublevels each encode incompatibly today.- All schema fields are optional and additive. v3.1.x documents validate cleanly under v3.2.0.
What's new in v3.1.0
dispositionfield onEvaluatedRequirement— the type of the governing override or POAM (e.g.,waiver,falsePositive,riskAdjustment). Indicates why a requirement is in its current state.effectiveImpactfield onEvaluatedRequirement— the computed impact score (0.0–1.0) after applying the most recent non-expired impact override.Impact_Overridetype onStatus_OverrideandStandalone_Override— object with avaluefield (0.0–1.0). At least one ofstatusorimpactmust be set (enforced viaanyOf).Override_Typeexpansion — addedfalsePositive,riskAdjustment,operationalRequirement; removedexception(usewaiverwithstatus: "notApplicable"instead).vendorDependencyadded to POAM type enum.- Breaking: The
./schemas/<name>.schema.jsonsub-path export was removed. Use named imports from the barrel (import { hdfResultsSchema } from '@mitre/hdf-schema') instead.