NENA i3-Aligned CHE Evidence Graph
- Jon Whirledge
- Oct 16
- 3 min read
Every 911 call tells a story — from the first ring to the final report. The CHE Evidence Graph captures that story in real time, recording each call-handling event as a verifiable entry on the 911 Trust Ledger. By anchoring cryptographic proofs of call logs, audio recordings, and operator actions to a shared, permissioned blockchain, PSAPs can demonstrate integrity, compliance, and trust without exposing sensitive data.
The result is a transparent, tamper-evident record of every call — aligning with NENA i3 and EIDO standards while preserving privacy and operational control.
Why it matters
Call Handling Equipment (CHE) sits at the heart of every emergency response. It captures the moment a 911 call is received, answered, transferred, and closed. But until now, the digital trail behind those events lived in separate systems — vulnerable to deletion, error, or dispute.
The CHE Evidence Graph creates an immutable chain of custody for every call event. Each time a call changes state — from initiated to answered, on hold, transferred, or released — the CHE writes a signed record to the 911 Trust Ledger. The underlying data never leaves the PSAP; only a cryptographic fingerprint (hash) and essential metadata are published on-chain.
How It Works
Event-based Ledgering – Each call event becomes a blockchain transaction containing timestamp, call state, agent ID, and hash of off-chain artifacts (audio, logs, transcripts).
Privacy by Design – No personal data or audio is ever stored on-chain. Proofs of existence and integrity replace raw content.
Interoperable Schema – The event model extends the NENA i3 and EIDO standards, allowing CHE vendors and PSAPs to integrate without custom mapping.
Audit Ready – Every call can be reconstructed as a verified timeline — from call initiation to closure and retention action — without relying on a single vendor’s database.
Example Call Lifecycle
CallInitiated → CallAnswered → CallUpdated* → CallReleased
↘ RecordingCaptured → RetentionAction
CHE Evidence Event — Field Catalog
A) Identity & Linking (core)
event_id (UUID)
event_type (CallInitiated | CallAnswered | CallUpdated | CallReleased | RecordingCaptured | Transfer | Conference | Hold | Resume | Abandon | Error)
prev_event_id (UUID)
call_id (CHE logical CallID; stable across transfers/holds)
sip_call_id (raw SIP Call-ID header)
conversation_id (for multi-leg continuity, if CHE supports)
incident_id (optional; populated once linked to CAD)
B) Timestamps & Sequence
ts (event creation time, UTC ISO-8601 with ms)
che_rx_ts (CHE first-seen time)
che_tx_ts (CHE emit time, if different)
seq (monotonic per call_id)
C) Parties & Roles (PII-minimized)
agent_id (CHE operator ID or position)
agent_station_id (console/position)
caller_id_hash (hash of ANI/From; never raw)
callback_number_hash (hash)
service_urn (e.g., urn:service:sos.police)
language (detected/selected; BCP-47)
accessibility_mode (TTY | RTT | TCC | VRS | None)
origin_type (wireless | wireline | VoIP | NGCS | i3-text)
D) Media & QoS
media_types (audio | text | video array)
codec (e.g., PCM16, G711u)
jitter_ms_avg, packet_loss_pct_avg, rtt_ms_avg (if available)
recording_policy (on | off | selective)
E) Location (i3/PIDF-LO friendly, minimized)
location_source (HELD | PIDF-LO | LIS | Manual | None)
location_method (civic | geo | hybrid)
location_hash (hash of PIDF-LO or civic/geo blob)
dispatchable_location_hash (hash if derived)
life_cycle (received | validated | updated)
confidence (0–100; optional)
F) Routing Context (read-only in CHE, but useful)
esrp_id (if known)
route_reason (default | policy | overflow | transfer-in)
psap_id (target PSAP identifier)
G) Call State & Controls
call_state (Ringing | InProgress | OnHold | Transferred | Conferenced | Released | Abandoned | Error)
hold_reason (if hold)
transfer_type (blind | consult | supervised)
bridge_id (for conferences)
duration_ms (for terminal states)
H) Artifacts (off-chain references)
Each event can point to zero or more artifacts:
artifacts[]: {
type: "che-log | audio | rtt-transcript | screen-recording | policy-snapshot",
hash: "sha256:…",
uri: "che://… | recorder://…",
retention_class: "90d_audio | 2y_logs | casefile",
size: <bytes>,
segment: { index: 1, start_ts: “…”, end_ts: “…” } // for audio/text chunks
}
I) Security & Provenance
issuer (system identity, e.g., CHE-PSAP01)
issuer_cert_chain_id (reference to PKI chain)
signature (detached or JOSE over canonical payload)
schema_version (e.g., che.v1.2)
software_version (CHE version/build)
J) Policy, Privacy, and Audit
privacy_profile_id (which fields were suppressed/hardened)
retention_profile_id (applied at creation time)
redaction_of_event_id (if this event supersedes/redacts prior)
notes_hash (hash of any free-text notes captured in CHE)
policy_refs (array of policy IDs cited for this event)
Event Types & Their Expected Fields
CallInitiated
Must: A, B, C(partial), D(partial), E(partial), F(partial), GArtifacts: che-logNotes: include origin_type, media_types, service_urn if present in INVITE.
CallAnswered
Must: A, B, C(agent), G(state=InProgress)Nice: D(QoS baseline), E(life_cycle=received), H(optional audio segment start)Artifacts: che-log
CallUpdated (repeatable)
Use for location updates, language, accessibility, notes:Must: A, B, GPlus one or more of: C(language/accessibility), D(QoS deltas), E(updated location), H(additional audio/rtt-transcript)Artifacts: che-log, optional rtt-transcript
RecordingCaptured (can be emitted by recorder but linked here)
Must: A, B, H(artifact type=audio with segment info)Nice: D(codec)Notes: if recorder is a separate system, issuer = recorder, but keep call_id.
Hold / Resume
Must: A, B, G(with reason for hold)Artifacts: che-log
Transfer
Must: A, B, G(state=Transferred), F(route_reason=transfer-out), target_psap_idNice: transfer_type, consult_agent_id (if supervised)
Conference
Must: A, B, G(state=Conferenced), bridge_idArtifacts: che-log
Abandon
Must: A, B, G(state=Abandoned)Artifacts: che-log
CallReleased
Must: A, B, G(state=Released), duration_msArtifacts: che-log
Error
Must: A, B, error_code, error_detail_hashArtifacts: diagnostics log

Comments