LifeCare.ID® Developer Docs Public

Concepts

Everything you need to reason about a LifeCare.ID integration. If you read one page before coding, read this one.


Decentralized identifiers (DIDs)

Every person on the network is identified by a DID — a stable, resolvable identifier that is not an email, a username, or a phone number, and is not owned by any application.

A DID document looks like this:

{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:web:node0.example:u:9f2a1c4d8b3e0f57",
  "verificationMethod": [{
    "id": "did:web:node0.example:u:9f2a1c4d8b3e0f57#key-1",
    "type": "JsonWebKey2020",
    "controller": "did:web:node0.example:u:9f2a1c4d8b3e0f57",
    "publicKeyJwk": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" }
  }],
  "authentication": ["…#key-1"],
  "assertionMethod": ["…#key-1"],
  "service": [
    { "id": "#uma",     "type": "UMAAuthorization", "serviceEndpoint": ".../v1/token" },
    { "id": "#consent", "type": "ConsentService",   "serviceEndpoint": ".../v1/consent" },
    { "id": "#rev",     "type": "RevocationList2020","serviceEndpoint": ".../v1/revocation/{id}" }
  ]
}

The service block is how a generic agent discovers where to ask for a token, manage consent, and check revocation for a given identity.


Key custody — the device holds the key

The user's private signing key (P-256) never leaves their device. It is generated and stored in the platform secure element (Apple Secure Enclave, Android Keystore) and exercised through a FIDO2 / WebAuthn passkey, biometric-gated.

LifeCare.ID is the DID authority, not the key holder: it derives the DID, publishes the DID document, hosts the revocation registry, and coordinates recovery — but it can never sign as the user. This means:


Identity recovery

Because there is no password, recovery rotates the user to a new device key while keeping the same DID (so their consents and data survive):

Recovery is an end-user / operator concern; your app does not implement it, but should expect that a user's verification key can change over the DID's lifetime (always resolve the DID document fresh when verifying signatures).


The authorization server (AS)

The AS is the consent + token engine. Its implementation base is D-001: a lean, standards-shaped custom service (chosen over Medplum and Keycloak+UMA for arm64 fit and minimal lock-in). It speaks two standards-aligned patterns:

These are two different tokens for two different jobs — don't conflate them:

Token Issued by Means Presented to
Session / access token (lcs_…) POST /token (federation) "this session belongs to DID X" LifeCare.ID (e.g. the panel API)
Data-access token / RPT (lc_…) POST /v1/token (UMA) "bearer may read scope S for purpose P" the data source / resource server

Scopes — data categories, never values

Consent is expressed over scopes, which name categories of data, never the data itself. The MVP vocabulary:

cgm · daily · labs · body_composition · recovery · activity

The vocabulary is shared through the published contract; resource holders and the AS agree on it. Requesting cgm says "I want continuous-glucose data"; it never carries a glucose value. See Scopes & consent.


Every grant produces two things at once:

  1. A plain-language ledger entry the user can read ("ProForta can read your cgm, daily data until 2026-09-14. Purpose: weekly synthesis.").
  2. A machine-readable consent receipt — ISO/IEC TS 27560:2023-shaped, DID-signed, with a W3C DPV purpose term — for controllers and auditors.

Consent is purpose-bound: a grant authorizes a scope for a declared purpose. A token only issues against a grant whose purpose matches the request, so the same scope can be granted to two consumers for two purposes without collision.


The ledger — hash-chained, tamper-evident

Every event — grant, token issuance, data access, revocation — is appended to a per-subject, hash-chained, append-only ledger. Each entry hashes the previous one, so any tampering is detectable: the ledger read returns a chain_valid flag. This is the audit trail the user sees in the consent panel, and it is exportable. Resource holders are expected to record each access here ( POST /v1/access/record) — this is what makes data use auditable end to end.


Revocation — fast and public

Revocation is one tap for the user. The targets:

Resource servers and token validators check the registry / introspection endpoint, so a revoked grant stops working everywhere quickly. See Authorization & tokens.


The zero-PHI invariant (binding on you too)

LifeCare.ID never receives, caches, relays, or logs a health-data value — and no field of any request or response you send it may carry one. Scopes name categories; purposes are short declared strings; free text must not smuggle values. Raw data flows directly between the data source and your app, never through LifeCare.ID. This is both the platform's guarantee and your contractual obligation — see Security & compliance.


Glossary

Term Meaning
DID Decentralized identifier; the user's stable, resolvable identity
DID document Public record of a DID's keys + service endpoints
RP / relying party An app that authenticates users via LifeCare.ID
AS Authorization server — LifeCare.ID's consent + token engine
PKCE Proof Key for Code Exchange; secures the OAuth code flow
UMA User-Managed Access; the pattern for purpose-bound data tokens
RPT Requesting Party Token; the data-access token from /v1/token
DPV W3C Data Privacy Vocabulary; types the purpose of a grant
Receipt ISO 27560-shaped, signed record of a consent grant
Ledger Hash-chained, append-only audit trail per DID
Trust partner The human anchor that approves identity recovery
Scope A data category (e.g. cgm) — never a data value