The 6 Categories of Specification Drift: How Tessara Classifies Non-Conformance

The 6 Categories of Specification Drift

Every time an API deployment ships, there is a chance the live behavior has diverged from the specification it is certified against. In regulated healthcare APIs — governed by CMS-0057-F, CMS-9115-F, and the Implementation Guides published by HL7 — that divergence is not a bug class. It is a compliance event.

Tessara’s Conformance Comparator classifies every structural divergence into one of six categories. The taxonomy is specification-anchored: we compare the live API’s structural contract against the published Implementation Guide baseline, not against prior observed behavior.

How we detect drift

Tessara’s pipeline produces two SHA-256 Merkle hash trees:

  1. Spec Baseline Hash Set (SBHS) — derived from the published IG (for example hl7.fhir.us.carin-bb@2.1.0). Computed once per IG version and frozen.
  2. Observed Hash Set (OHS) — derived from the target API’s CapabilityStatement and, where applicable, declared profile snapshots.

Both trees canonicalize their source JSON under RFC 8785 JCS before hashing, which guarantees byte-identical inputs produce byte-identical hashes regardless of key order or whitespace.

If the root hashes match, the API is conformant — the comparison completes in O(1). If they differ, the Comparator descends the Merkle tree, exploring only subtrees where parent hashes diverge (O(log n)). Every divergence is classified into one of the six categories below.

Category 1 — Mandatory Element Removal (CRITICAL)

Trigger: An element flagged mustSupport: true with min >= 1 in the spec is absent from the observed structure.

Example: Coverage.subscriberId is mandatory under CARIN Blue Button. The API no longer declares it in CapabilityStatement and does not return it in sample resource instances.

Why it matters: Downstream apps relying on the IG contract will fail to parse responses. Patient Access clients break silently. This is the category that most directly maps to a CMS or OCR finding.

Category 2 — Type or Cardinality Change (CRITICAL / HIGH)

Trigger: A required element’s type, min, or max differs between spec and observed.

Example: Patient.identifier declared as 1..* in US Core but observed as 0..1, or Claim.created declared as dateTime but observed as date.

Why it matters: Type-level drift corrupts deserialization across every client that validates against the IG. Cardinality drift is worse — it permits the API to return shapes the spec explicitly forbids.

Category 3 — Structural Extension (INFO)

Trigger: The observed structure contains elements not present in the spec, via extensions, profiles, or custom fields.

Example: A payer adds an _priorAuthorizationStatus extension on ExplanationOfBenefit that is not declared in the advertised profile.

Why it matters: Informational by default. Structural extensions are how the FHIR ecosystem evolves. But unannounced extensions create audit surface: they represent data the payer is emitting that has not been reviewed for privacy, conformance, or specification alignment. Tessara records them for the audit trail without raising severity.

Category 4 — Authorization Deviation (HIGH)

Trigger: The observed security scheme — grant types, scopes, token endpoint auth methods, or SMART capabilities — differs from what the IG requires.

Example: The spec requires private_key_jwt for Backend Services; the /.well-known/smart-configuration endpoint only advertises client_secret_basic.

Why it matters: Authorization drift is the category regulators notice fastest, because it affects whether a third-party app can legally access the API at all. SMART App Launch compliance is a gatekeeper for both CMS-0057-F and the 21st Century Cures information-blocking provisions.

Category 5 — Endpoint Behavioral Change (MEDIUM)

Trigger: The structural declaration matches the spec, but the endpoint’s runtime behavior has shifted — for example, a required search parameter is accepted but ignored.

Example: Practitioner?name= is advertised as a supported search parameter, but queries with it return the same results as queries without it.

Why it matters: This is the category most easily missed by schema-only validators. Tessara detects it during Tier 1 and Tier 2 probes by cross-checking declared capabilities against minimal, non-data-bearing functional probes.

Category 6 — Specification Version Mismatch (HIGH)

Trigger: The API’s self-reported FHIR version (fhirVersion in CapabilityStatement, or the IG version declared in profile references) does not match the mandated baseline.

Example: The payer certifies against CARIN Blue Button 2.1.0 but the production metadata endpoint declares CARIN Blue Button 1.2.0.

Why it matters: Spec-version drift means every downstream conformance test is validating against the wrong contract. It is almost always the result of a staged rollout that never completed.

Severity is determined by category, not by scoring

Each drift finding Tessara emits carries the severity associated with its category: CRITICAL, HIGH, MEDIUM, or INFO. We do not score findings on a points system, and we do not weight by “production environment” or “user-facing endpoint” heuristics. The severity comes from the regulatory provision the drift implicates — which is encoded in Tessara’s Regulatory Provision Index (RPI) and attached to every verdict.

This is a deliberate choice. A Category 1 finding on Coverage.subscriberId in a sandbox is the same finding as in production — the spec contract is the same, the regulatory exposure is the same, and the fix is the same. Priority is determined by the customer’s deployment context; severity is determined by the specification.

The evidence chain

Every classified drift becomes a DriftFinding attached to a signed ComplianceVerdict. Verdicts are Ed25519-signed and hash-linked to the prior verdict for the same API. An auditor replaying the chain can verify, byte-for-byte, which drifts were present at any point in history, and can prove the history has not been edited since.


Read the full product overview at /product, or browse the CLI reference.