FHIR Resource Access Audit v0.1 draft. Append-only ledger of which AI tool read which patient FHIR resource, when, under what consent. Bridges HL7 FHIR's
AuditEventresource type to the Kinetic Gain Protocol Suite's hash-chained audit-stream spine so a hospital's compliance team gets one verifiable record of AI access — across the EHR, the RAG index, and any downstream Decision Card-governed surface.
Part of the Kinetic Gain Protocol Suite.
Status: v0.1 draft. Schema at
schema/fhir-resource-access-event.schema.json, examples atexamples/, tiny in-browser verifier insrc/.
Three audit surfaces touch FHIR data when an AI tool is in play:
- The EHR (Epic, Oracle Health, Meditech) emits FHIR
AuditEventresources for each read againstPatient/Observation/DocumentReference/ etc. — but the event'sagent.whois usually a service account, not the AI tool the buyer's Decision Card actually authorized. - The AI tool itself (a RAG pipeline, a clinical-decision-support service, a tutor) logs which resources it ingested — but usually to its own private log shape that the buyer's GRC team can't replay.
- The Suite's audit-stream-py carries governance events (Decision Card drafted, policy bundle minted, reveal authorized) — but doesn't natively understand FHIR semantics.
This repo bridges them. It defines a single event shape that:
- Carries the FHIR
AuditEventsemantics (type, subtype, action, period, patient, agent) so a SIEM or a FHIR-aware auditor reads it natively. - Adds the Suite audit-stream invariants (canonical-JSON SHA-256,
prev_hash,decision_card_ref,tool_card_ref) so it appends cleanly to the same hash-chained log every other governance event lands on. - Names the AI tool by reference to its MCP Tool Card and the Decision Card that authorized the access — so an auditor can trace which buyer signature permitted this read.
The result: one ledger, FHIR-shaped, Suite-shaped, hash-chained, signable.
Every event is a single JSON object that conforms to schema/fhir-resource-access-event.schema.json. Required fields:
| Field | Type | Purpose |
|---|---|---|
event_id |
string |
UUID v7 or similar monotonic ID |
timestamp |
string (RFC 3339) |
When the access happened |
kind |
string (enum) |
fhir.resource.read · fhir.resource.search · fhir.resource.write · fhir.resource.export |
source |
string |
The system that emitted the event (e.g. epic-mychart-r4, rad-ai-chest-triage) |
patient_ref |
string |
FHIR Patient reference: Patient/<id> |
resource |
object |
The resource accessed: { type, id, version_id? } |
action |
string (enum) |
FHIR AuditEvent action codes: C · R · U · D · E (Create / Read / Update / Delete / Execute) |
outcome |
string (enum) |
0 (success) · 4 (minor failure) · 8 (serious failure) · 12 (major failure) per FHIR |
agent |
object |
The actor: { ai_tool_card_url, ai_decision_card_url, principal? } |
decision_card_ref |
string |
URL to the Decision Card that authorized this access |
prev_hash |
string (64-char hex) |
Hash of the previous event in the chain (or 64 zeros for the first event) |
hash |
string (64-char hex) |
Canonical-JSON SHA-256 of the event body excluding hash itself |
Optional fields documented in the schema include signature (ed25519 over the canonical body), network (source IP + protocol), purpose_of_use (FHIR purposeOfUse coded concept), and redaction_applied[] (which fields were tokenized per the Decision Card's vault contract before reaching the AI tool).
| File | Vertical | Scenario |
|---|---|---|
examples/rad-ai-reads-patient.json |
HealthTech | RadAI Chest Triage 4.2 reads Patient/12345 for triage scoring; tokens-only (vault contract applied) |
examples/rag-pipeline-ingests-documentreference.json |
HealthTech | A clinical RAG pipeline pulls a DocumentReference for indexing; rag-sentinel applied tokenization before the index write |
examples/three-event-chain.json |
HealthTech | A self-consistent 3-event chain demonstrating canonical-JSON SHA-256 chaining (use with the verifier) |
A full end-to-end Node.js reference implementation lives at fhir-resource-access-audit-reference. It reads from a FHIR R4 server (HAPI public test in live mode, fixtures in test mode), applies a HIPAA Safe-Harbor vault contract, emits Suite-compliant hash-chained events, and re-verifies its own output against this spec's JSON Schema in CI. Green CI there is evidence this spec is implementable end-to-end.
License: AGPL-3.0 (the spec is MIT; the reference implementation is AGPL-3.0).
The verifier in src/verify.mjs is a tiny pure-JS function that walks a chain and reports the first break. It mirrors the convention used by audit-stream-py's GET /verify so downstream tools agree on what "valid" means.
node src/verify.mjs examples/three-event-chain.json
# → Chain valid · 3 eventsIt also runs in the browser:
import { verifyChain, canonicalJSON, canonicalHash } from './src/verify.mjs';
const result = await verifyChain(events);
if (!result.valid) console.error('Chain broken at event #' + result.firstBreakAt);| Spec | Role |
|---|---|
| HL7 FHIR R4 — AuditEvent | The underlying clinical event model |
mcp-tool-card-spec |
agent.ai_tool_card_url references this |
ai-procurement-decision-spec (v0.3) |
decision_card_ref references this; data_vault_targets drives redaction_applied[] |
phi-vault-contract-profile |
When the buyer is a covered entity, this profile names which FHIR fields are vaulted |
audit-stream-py |
The hash-chained log these events append to |
clinical-ai-disclosure-spec |
The vendor disclosure that names which FHIR resource types the product reads |
Audit-stream readiness scaffolding for healthcare AI deployments. Buyers signing a Decision Card for a clinical AI vendor get a portable, FHIR-native, hash-chained record of access that an external auditor can replay. This does not establish HIPAA compliance, certify a vendor, or substitute for a covered entity's privacy + security program — per the standing public-language guardrail.
Spec text + JSON schemas + example documents: MIT. Reference verifier in src/: MIT.