Skip to content

Healthcare Consent Management

**Cross-industry · Patient-controlled access · Emergency override**

Overview

Healthcare Consent Management

Cross-industry · Patient-controlled access · Emergency override

The problem

A patient’s medical records span 10+ systems: primary care, specialists, hospitals, labs, insurers, pharmacies, mental health. Every access requires consent, but the current reality:

  • Paper consents at each provider office. Unscannable, uncorrelated.
  • Platform-locked portals (Epic MyChart, Cerner HealtheLife, etc.), each siloed.
  • HIPAA retroactively punishes wrongful access but doesn’t prevent it at time-of-access. Breaches happen regularly.
  • Emergency access is ad-hoc: an ER doctor needing records for an unconscious patient either bypasses controls (“glass break” override) or waits hours for phone-based consent.
  • Revocation is fictional. A patient “revokes” consent with a practice; the practice keeps local copies; other providers don’t learn of the revocation.
  • Referral chains are opaque. Primary → specialist → lab is a chain of trust the patient implicitly grants but can’t easily model.

The right model: the patient is the principal; access is time-bounded, explicit consent from the patient; emergency override exists via a patient-selected guardian quorum; every access is auditable on a tamper-evident log.

Why Quidnug fits

Consent management is a trust graph: patient trusts doctor A for a specific purpose for a specific period. Guardians can override for emergencies with time-lock. Revocation propagates.

ProblemQuidnug primitive
”Patient X consents to Dr. Y accessing…”Signed TRUST edge with validUntil
”Emergency access when patient unconscious”GuardianRecovery with short delay
”Revoke access across all providers”Trust-edge update, push-gossiped
”Audit trail of who saw what”Event stream per access
”Specialist referral trust”Transitive trust through referring doctor
”Patient’s signing key lost”Guardian recovery (spouse, chosen POA)

High-level architecture

Patient ("patient-alice-123")
as quid with Guardian Set:
{spouse, adult-child, primary-care-doc,
chosen-healthcare-proxy}
threshold: 2 (2 of 4 for emergency access)
requireGuardianRotation: false (allow normal
updates by patient)
┌───────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
trust edges for trust edges for Event stream:
specific providers domain inheritance [consent granted,
record accessed,
consent revoked,
emergency override]

Data model

Patient as quid

{
"quidId":"patient-alice-123",
"homeDomain":"healthcare.consent.us",
"attributes":{
"patientID":"<internal hash>",
"dateOfBirth":"HASH:<sha256 of DOB+nonce>",
"healthcareProxy":"adult-child-bob-456"
}
}

Patient PII is kept minimal on-chain. Rich data stays in provider systems; Quidnug tracks consent and access.

Patient’s guardian set

{
"guardians":[
{"quid":"spouse-carol","weight":1},
{"quid":"adult-child-bob","weight":1},
{"quid":"primary-care-doc-dr-smith","weight":1},
{"quid":"healthcare-proxy-advance-directive","weight":2}
],
"threshold":2,
"recoveryDelay":900000000000, /* 15 minutes, short for emergencies */
"requireGuardianRotation":false
}

Short recovery delay (15 min) balances emergency need with basic veto window. Patient can increase (e.g., 24h) for non-life-threatening scenarios.

Terminal window
# Patient grants Dr. Jones access to their records for 90 days
curl -X POST $NODE/api/trust -d '{
"truster":"patient-alice-123",
"trustee":"dr-jones-cardiology",
"trustLevel":0.9,
"domain":"healthcare.records.access",
"nonce":47,
"validUntil":<now + 90d>,
"description":"Cardiac consultation; full record access"
}'

Provider’s system queries Quidnug for consent before each access. A query returns trust level + validity; provider proceeds only if both are acceptable.

Access as event

{
"type":"EVENT",
"subjectId":"patient-alice-123",
"subjectType":"QUID",
"eventType":"record.accessed",
"payload":{
"accessor":"dr-jones-cardiology",
"consentTxId":"<ID of trust transaction>",
"accessType":"clinical-notes",
"accessedAt":1713400000,
"purpose":"follow-up appointment prep"
},
"signature":"<Dr. Jones's sig>"
}

Every access logged. Patient (or regulator) can query their own stream to see who accessed what.

Emergency override flow

Patient arrives unconscious at ER. ER doctor needs records. No direct consent available.

1. ER doctor (dr-er-cooper) requests emergency access.
2. Dr. Cooper submits a guardian-recovery-init:
subjectQuid: patient-alice-123
fromEpoch: current
toEpoch: current + 1 (new "emergency-access" epoch)
newPublicKey: <ephemeral key for this emergency session>
guardianSigs: [primary-care-doc signature + healthcare-proxy]
(2 signatures from guardians met threshold)
3. Recovery delay: 15 minutes. Patient (or spouse) could veto
if this is a hostile takeover. In practice, patient is
unconscious → no veto → delay elapses.
4. Commit: ER gets access with an "emergency" trust edge
scoped to the hospital for 24 hours.
5. Event stream records the emergency access with full
context. Patient sees it upon recovery.

For a genuine life-threatening situation requiring access in seconds not minutes, providers have “break-glass” procedures separately, Quidnug records the override event for post-hoc audit, not gatekeeping time-critical care.

Referral chain (transitive trust)

Primary care (Dr. Smith) refers patient to specialist (Dr. Jones). Specialist refers to lab (Lab Corp).

Patient ──0.9──► Dr. Smith (primary care, longstanding)
Dr. Smith ──0.9──► Dr. Jones (trusted cardiologist)
Dr. Jones ──0.8──► Lab Corp (usual lab)
Patient's transitive trust in Lab Corp = 0.9 × 0.9 × 0.8 = 0.648

Patient’s app can preconfigure: “accept transitive access through my PCP up to 3 hops, max trust decay 0.6”. The app automatically grants access when the chain meets threshold.

Patient revokes access:

Terminal window
# Update trust edge to 0 (or expire it)
curl -X POST $NODE/api/trust -d '{
"truster":"patient-alice-123",
"trustee":"dr-jones-cardiology",
"trustLevel":0.0,
"domain":"healthcare.records.access",
"nonce":48,
"description":"Ending care; revoking access"
}'

Push gossip propagates revocation within seconds. Every provider node that queries for consent sees 0 trust → denies future access.

Sub-domain granularity

Different record types → different access rules:

healthcare.records.access.full (everything)
healthcare.records.access.prescriptions (only Rx)
healthcare.records.access.imaging (only imaging)
healthcare.records.access.mental-health (highly restricted)

Patient can grant Dr. Jones full access but grant the pharmacy only prescriptions.

Key Quidnug features

  • Signed trust edges with validUntil, consent as time-bounded grant.
  • Guardian recovery with short delay, emergency override with audit trail.
  • Event streams, every access logged.
  • Push gossip, revocation propagates fast.
  • Domain hierarchy, sub-scope consents.
  • Transitive trust, referral chains modeled cleanly.
  • GuardianResignation (QDP-0006), guardian lifecycle (spouse divorce, proxy decline).

Value delivered

DimensionBeforeWith Quidnug
Consent portabilityPer-platform, siloedSingle source of truth across all providers
Time-bounded consentRarely enforcedvalidUntil enforced cryptographically
Revocation speedDays to weeksSeconds
Emergency access”Break glass” uncontrolledGuardian-recovery with 15-min time-lock + audit
Audit trailPer-provider, fragmentedSingle event stream per patient
GranularityWhole-recordSub-domain (prescriptions vs. imaging vs. etc.)
Patient controlLimited by platform UIOwn quid + own guardian set
Compliance reportingManual extractionDeterministic chain replay

What’s in this folder

Runnable POC

Full end-to-end demo at examples/healthcare-consent-management/:

  • consent_evaluate.py, pure decision logic: direct consent, transitive referrals, revocation, emergency guardian-quorum override.
  • consent_evaluate_test.py, 16 pytest cases.
  • demo.py, seven-step end-to-end flow: register patient + providers + guardians, grant and log direct access, demonstrate transitive referral, revoke, then run an emergency override with quorum and show denial without quorum.
Terminal window
cd examples/healthcare-consent-management
python demo.py

Implementation

Concrete API calls, pseudocode, signing shape.

Implementation: Healthcare Consent Management

1. Patient onboarding

Terminal window
# Patient creates quid
curl -X POST $NODE/api/identities -d '{
"quidId":"patient-alice-123",
"name":"Alice (pseudonymous ID)",
"homeDomain":"healthcare.consent.us",
"creator":"patient-alice-123","updateNonce":1
}'
# Patient installs guardian set for emergency override
curl -X POST $NODE/api/v2/guardian/set-update -d '{
"subjectQuid":"patient-alice-123",
"newSet":{
"guardians":[
{"quid":"spouse-carol","weight":1,"epoch":0},
{"quid":"adult-child-bob","weight":1,"epoch":0},
{"quid":"primary-care-dr-smith","weight":1,"epoch":0},
{"quid":"healthcare-proxy-legal-doc","weight":2,"epoch":0}
],
"threshold":2,
"recoveryDelay":900000000000, /* 15 min */
"requireGuardianRotation":false
},
"anchorNonce":1,"validFrom":<now>,
"primarySignature":{"keyEpoch":0,"signature":"<patient sig>"},
"newGuardianConsents":[
{"guardianQuid":"spouse-carol","keyEpoch":0,"signature":"<sig>"},
{"guardianQuid":"adult-child-bob","keyEpoch":0,"signature":"<sig>"},
{"guardianQuid":"primary-care-dr-smith","keyEpoch":0,"signature":"<sig>"},
{"guardianQuid":"healthcare-proxy-legal-doc","keyEpoch":0,"signature":"<sig>"}
]
}'
Terminal window
# Patient grants Dr. Jones cardiology full-record access for 90 days
curl -X POST $NODE/api/trust -d '{
"truster":"patient-alice-123",
"trustee":"dr-jones-cardiology",
"trustLevel":0.9,
"domain":"healthcare.records.access",
"nonce":47,
"validUntil":<now + 90d>,
"description":"Cardiac consultation series Q2 2026"
}'
# Sub-domain granular consent for pharmacy (Rx only)
curl -X POST $NODE/api/trust -d '{
"truster":"patient-alice-123",
"trustee":"cvs-pharmacy-lincoln-park",
"trustLevel":0.9,
"domain":"healthcare.records.access.prescriptions",
"nonce":48,
"validUntil":<now + 365d>
}'

3. Provider access check

Before accessing records, provider’s system queries:

func (p *Provider) CanAccess(ctx context.Context, patientID string, recordType string) (bool, error) {
domain := "healthcare.records.access"
if recordType != "" {
domain = fmt.Sprintf("healthcare.records.access.%s", recordType)
}
trust, err := p.client.GetTrust(ctx, patientID, p.quid, domain, &GetTrustOptions{
MaxDepth: 3, // Allow referral chain up to 3 hops
})
if err != nil {
return false, err
}
if trust.TrustLevel < 0.5 {
return false, nil // Insufficient trust
}
// Check validity, GetTrust returns active edges only, but
// verify the most recent edge hasn't expired.
return trust.TrustLevel > 0, nil
}
func (p *Provider) LogAccess(ctx context.Context, patientID string, access AccessDetails) error {
event := map[string]interface{}{
"subjectId": patientID,
"subjectType": "QUID",
"eventType": "record.accessed",
"payload": map[string]interface{}{
"accessor": p.quid,
"consentTxId": access.ConsentRef,
"accessType": access.RecordType,
"accessedAt": time.Now().Unix(),
"purpose": access.Purpose,
},
"creator": p.quid,
"signature": p.sign(/* canonical */),
}
return p.submitEvent(ctx, event)
}

4. Emergency override (unconscious patient)

Terminal window
# ER submits emergency guardian recovery
curl -X POST $NODE/api/v2/guardian/recovery/init -d '{
"kind":"guardian_recovery_init",
"subjectQuid":"patient-alice-123",
"fromEpoch":0,
"toEpoch":1,
"newPublicKey":"<ephemeral ER key>",
"minNextNonce":1,
"maxAcceptedOldNonce":100, /* don'\''t invalidate prior consent */
"anchorNonce":<next>,
"validFrom":<now>,
"guardianSigs":[
{"guardianQuid":"primary-care-dr-smith","keyEpoch":0,"signature":"<sig>"},
{"guardianQuid":"healthcare-proxy-legal-doc","keyEpoch":0,"signature":"<sig>"}
]
}'

With guardian threshold 2 met, recovery is pending. 15-minute delay. If no veto, auto-commit by any party or explicit commit by ER:

Terminal window
curl -X POST $NODE/api/v2/guardian/recovery/commit -d '{
"kind":"guardian_recovery_commit",
"subjectQuid":"patient-alice-123",
"recoveryAnchorHash":"<hash>",
"anchorNonce":<next>,
"validFrom":<now>,
"committerQuid":"er-system-dr-cooper",
"committerSig":"<sig>"
}'

After commit, an emergency trust edge is auto-created for the ER with a 24-hour window:

Terminal window
curl -X POST $NODE/api/trust -d '{
"truster":"patient-alice-123", /* now signed by new emergency key */
"trustee":"hospital-er-central",
"trustLevel":0.9,
"domain":"healthcare.records.access",
"nonce":99,
"validUntil":<now + 24h>,
"description":"Emergency access via guardian quorum; unconscious patient"
}'

5. Patient reviews emergency access afterward

After recovery, patient queries their stream:

Terminal window
curl "$NODE/api/v1/events/QUID/patient-alice-123" | jq '.data[] | select(.eventType == "record.accessed")'

Shows exactly who accessed records during their unconscious period. Patient sees the guardian-recovery event, understands it as emergency override, and either retroactively approves or files a dispute.

Terminal window
# Update trust edge to 0
curl -X POST $NODE/api/trust -d '{
"truster":"patient-alice-123",
"trustee":"dr-jones-cardiology",
"trustLevel":0.0,
"domain":"healthcare.records.access",
"nonce":50,
"description":"Discontinued care"
}'

Push gossip within seconds; all providers querying for consent see trust=0 and deny.

7. Referral (transitive access)

Patient ──0.9──► Dr. Smith (primary care)
Dr. Smith ──0.85──► Dr. Jones (cardiology specialist, referred)
Dr. Jones ──0.8──► Lab-Corp (ordering labs)

Lab-Corp queries Quidnug for trust from patient: traverses Patient → Smith → Jones → Lab-Corp. Computed trust: 0.9 × 0.85 × 0.8 = 0.612. Above 0.5 threshold → access granted.

Patient preconfigures their app: “auto-accept through primary care up to 3 hops with trust ≥ 0.5”. The app stays out of the clinical flow except for exceptions.

8. Testing

func TestHealthcare_DirectConsent(t *testing.T) {
// Patient grants Dr. Jones
// Dr. Jones can access; Dr. Lee (no consent) cannot
}
func TestHealthcare_ConsentExpiresAfterValidUntil(t *testing.T) {
// Consent issued for 1 hour
// After expiry, provider access denied
}
func TestHealthcare_EmergencyOverride(t *testing.T) {
// 2-of-4 guardians initiate
// 15-min delay elapses with no veto
// ER system gets emergency trust edge
// Access logged in patient's event stream
}
func TestHealthcare_PatientVetoesEmergencyOverride(t *testing.T) {
// Guardian recovery initiated
// Patient (or another guardian) vetoes before time-lock
// No ER access granted
}
func TestHealthcare_RevocationPropagates(t *testing.T) {
// Set trust; gossip to 3-node network
// Revoke; verify all nodes see revocation
// Provider access denied across network
}

Where to go next

Threat model

Adversaries, assumed capabilities, mitigations.

Threat Model: Healthcare Consent Management

Assets

  1. Patient medical data, sensitive and regulated.
  2. Consent integrity, the cryptographic record of who was granted what.
  3. Access audit trail, tamper-evident log.
  4. Patient’s signing key, represents the patient; compromise enables unauthorized consent grants.

Attackers

AttackerCapabilityGoal
Curious insiderProvider employee with valid accessLookup records unauthorized
Compromised providerValid provider signing keyAccess records without consent
Malicious guardianPatient’s named guardian, bad intentForce emergency access
Patient compromisePatient’s key stolenGrant unauthorized access
ExternalNo credentialsExploration / theft

Threats

T1. Unauthorized provider access

Attack. Provider tries to access records without patient consent.

Mitigation.

  • Provider’s system checks trust before access; trust=0 or expired → deny.
  • Every access attempt generates a signed event. False claims that “patient consented” are contradicted by the chain.

Residual risk. A provider with valid consent for record type A accessing record type B (sub-domain scoping helps).

T2. Guardian collusion for emergency access

Attack. Spouse + adult child collude to gain access to records the patient doesn’t want them to see.

Mitigation.

  • 15-minute veto window. Patient or another guardian can intercede.
  • Event stream records the access; patient sees it after.
  • Guardian structure is patient-chosen; they can revoke problem guardians via GuardianResignation (QDP-0006).

Residual risk. If patient is truly incapacitated and two guardians collude, access happens. Mitigation is choosing guardians carefully and reviewing them periodically.

T3. Compromised patient key

Attack. Patient’s signing key stolen; attacker grants themselves access.

Mitigation.

  • Guardian recovery lets patient (via other channels) rotate.
  • Providers observing recent rotations re-evaluate trust edges issued by the old-epoch key.
  • Anchor nonces prevent replay.

T4. Revocation delay exploit

Attack. Patient revokes consent; attacker accesses records before revocation propagates.

Mitigation.

  • Push gossip (QDP-0005), revocation reaches all providers within seconds. Small window, but non-zero.
  • Provider’s system should query Quidnug at time-of-access, not rely on cached trust.

Residual risk. Very narrow window (seconds).

T5. Emergency override abuse

Attack. Provider fakes emergency to trigger override.

Mitigation.

  • 2 guardian signatures required. Provider alone can’t initiate.
  • Guardians who falsely sign emergency claims are accountable, their signatures are on-chain.
  • Audit by regulators trivially surfaces “who requested emergency access in circumstances that weren’t actually emergency”.

T6. HIPAA / regulatory compliance

Concern. Is Quidnug’s event log HIPAA-compliant?

Response.

  • PHI is NOT on Quidnug directly. Only consent and access events.
  • Consent and access logs ARE PHI under some interpretations (they reveal care patterns).
  • Deployment best practice: Quidnug events stored on consortium chain; patient-linked metadata encrypted.
  • This is a regulatory implementation concern, not a protocol gap.

T7. De-anonymization

Attack. Attacker correlates consent events to identify patients.

Mitigation.

  • Use pseudonymous quids. Patient’s real identity is kept off-chain.
  • Domain scoping + restrictive event visibility.
  • Real-world identity resolution requires the patient or their provider’s cooperation.

Attack. Attacker replays a valid old consent grant after patient has revoked.

Mitigation.

  • Anchor nonces on trust transactions. Revocation is a higher-nonce transaction; replay of the old grant has a stale nonce and is rejected.

Not defended against

  1. Physical record theft. Paper records, USB drives with exports. Not a Quidnug concern.
  2. Provider’s internal access controls. Quidnug says “yes you can access”. Which employee at the provider actually reads the file is the provider’s access-control problem.
  3. Consent-under-duress. Patient signs consent under pressure. The protocol records consent validly; the legality is a real-world matter.

References