SMART Permission Tickets
0.1.0 - ci-build

SMART Permission Tickets, published by . This guide is not an authorized publication; it is the continuous build for version 0.1.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/jmandel/smart-permission-tickets-wip/ and changes regularly. See the Directory of published versions

Proposal 005: Sensitive Data Profile

Status: Experimental profile draft for discussion Author: Josh Mandel Date: May 27, 2026 (rev. June 2026)

Summary

This proposal defines an experimental Permission Ticket profile for communicating sensitivity-category handling, in two pieces that live on opposite sides of the access constraint border:

  • sensitivity_withhold — an access constraint: do not send data in these categories. A limit, so it fails closed: a Data Holder that cannot enforce it rejects the ticket rather than silently letting the authorizing person down.
  • sensitivity_release_authorized — a top-level profile claim: the issuer attests that these categories are within the authorization scope, subject to Data Holder policy and law. A fact, so it degrades gracefully: a Data Holder that does not recognize it falls back to its own sensitivity gates and releases less.

This profile lives outside the base specification deliberately: it lays out the shape of sensitive-data handling ahead of what base APIs can do today. The base kernel carries only what every conforming Data Holder can enforce now; this profile models where sensitive-data management needs to go, so issuers, EHRs, and trust frameworks build toward one shape instead of inventing several.

Motivation

Three parties need these rules:

  • The patient, through the issuer, restricting clients. "Share my record with this app, but not my substance-use history." The patient's withholding choice is captured once, at the issuer, and travels in the ticket to every Data Holder — that is the core permission-ticket pattern applied to the data patients care most about.
  • The recipient, minimizing its own intake. A client not prepared to handle a category — and wanting to avoid the special obligations that come with it — can ask that the category never be sent.
  • The patient, unlocking access. Today, when API policies filter restricted categories, there is often no field a patient can check to let their own data flow. A release authorization is the signal that could change that: the issuer attests the patient's authorization covers the category, and the Data Holder decides under its own policy and law.

Two Directions, Different Properties

The two pieces carry different trust and enforcement properties, and the split encodes them structurally:

  • Withholding can be honored without trusting the issuer (a request to send less cannot expand access) and tolerates conservative enforcement — when classification is uncertain, withhold more. But a withholding rule the Data Holder cannot evaluate at all is a broken promise to the patient, which is why it is an access constraint: unrecognized or unenforceable means the ticket is rejected.
  • Release authorization rests on the issuer's authorization ceremony and requires the Data Holder to trust that ceremony for sensitive categories specifically. It cannot be enforced conservatively in either direction: under-release defeats the patient's intent, over-release is a breach. Trust frameworks adopting this profile SHOULD define which issuers may assert release authorization, for which categories, and what ceremony and evidence stand behind it. A Data Holder that does not implement it ignores it — the patient gets the conservative default instead of no data at all. Issuers SHOULD say so when capturing the authorization: the unlock may not be honored everywhere.

Wherever both match the same data, withholding wins. That is not a special rule of this profile: a constraint always bounds what a fact can unlock, by the base constraint algebra.

Profile Identifier

Item Value
Profile URI https://smarthealthit.org/permission-ticket-profile/sensitivity-policy-v1
Constraint sensitivity_withhold, a member of access
Profile claim sensitivity_release_authorized, a top-level claim
Applies to Ticket types or trust-framework profiles that explicitly incorporate this profile

This profile does not define a new ticket_type. It is a composable profile that a ticket-type profile may incorporate, defining which code systems and local mappings are acceptable for that use case. A ticket carrying sensitivity_withhold beyond its type's required constraint set is rejected by servers that do not enforce it — the standard consequence, and the desired one.

Shapes

Both pieces share one shape:

Field Type Description
codes Coding[] Sensitivity categories, as FHIR codings.
unlisted boolean When true, the rule also covers locally classified sensitive data named in neither piece. Defaults to false: unlisted sensitive data follows local policy.

At least one of a non-empty codes or unlisted: true SHALL be present in each piece used. Setting unlisted: true on sensitivity_release_authorized is the broadest mode; it SHOULD only be used when the incorporating ticket-type profile or trust framework permits it and the issuer's ceremony covers all locally classified sensitive data not otherwise withheld.

Each coding is a FHIR Coding:

{
  "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
  "code": "ETH",
  "display": "substance abuse information sensitivity"
}

Example: Withhold a Category

The patient told the issuer not to share substance-use data with this app. Other sensitivity categories follow local policy:

"access": {
  "smart_scopes": [ "patient/Observation.rs" ],
  "sensitivity_withhold": {
    "codes": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
        "code": "ETH",
        "display": "substance abuse information sensitivity"
      }
    ]
  }
}

Example: Authorize One Category, Withhold Other Sensitive Data

The patient authorized sharing HIV-related information; other locally classified sensitive data stays back:

{
  "sensitivity_release_authorized": {
    "codes": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
        "code": "HIV",
        "display": "HIV/AIDS information sensitivity"
      }
    ]
  },
  "access": {
    "smart_scopes": [ "patient/Observation.rs" ],
    "sensitivity_withhold": { "unlisted": true }
  }
}

Release authorization does not force disclosure. It means the issuer attests this category is not outside the ticket's authorization scope. The Data Holder still applies local law, local policy, patient matching, and technical enforceability checks.

Example: Recipient Data Minimization

A client doing routine medication reconciliation asks never to receive anything the Data Holder classifies as sensitive:

"access": {
  "smart_scopes": [ "patient/MedicationRequest.rs" ],
  "sensitivity_withhold": { "unlisted": true }
}

Vocabulary Starting Points

This profile uses FHIR Coding values and expects ticket-type profiles to constrain the supported vocabularies. Starting points include:

These codes identify categories. They do not by themselves define what data falls into a category at a given Data Holder; that mapping is profile-specific, trust-framework-specific, and local.

sensitivity_withhold: Constraint Definition

sensitivity_withhold is an access constraint, so its definition follows the four-section constraint template. (sensitivity_release_authorized is a profile claim, not a constraint; its rules follow in the next section and are not bound by the template.) Neither piece broadens any access constraint, client registration, or what law permits.

Shape and validity

The wire shape is the shared shape above: a non-empty codes array, unlisted: true, or both. The issuer determines the value from its withholding records, and SHALL:

  • Use code systems permitted by the incorporating ticket-type profile or trust framework.
  • Record the provenance of each withholding — patient-requested, client-requested, issuer-imposed, or framework-imposed.
  • Apply the withholding decision to everything that could reveal what was withheld, including issuance-time artifacts such as endpoint hints (see Proposal 003).
  • Avoid placing supporting sensitive documents directly in the ticket unless the incorporating profile explicitly requires that evidence.

For the authorizing party

The constraint encodes a withholding choice an authorization screen can state plainly — "share my record with this app, but not my substance-use history." Because a request to send less can never expand access, it is honored without trusting the issuer, and it is enforced conservatively: where classification is uncertain, more is withheld, not less.

For the client

The client can rely on withheld categories never arriving, and a recipient not prepared to handle a category can use the constraint to keep it out of its own intake. A client must not treat a response as the complete record: it may be lawfully incomplete because data was withheld. The profile does not reveal whether withheld sensitive data exists, so a category's absence is not evidence either way.

For the Data Holder

A Data Holder implementing the constraint SHALL:

  1. Withhold data matching a sensitivity_withhold coding unconditionally. When unlisted: true, also withhold all locally classified sensitive data, except data covered by sensitivity_release_authorized and permitted under that claim's rule below.
  2. When classification is uncertain, enforce withholding conservatively (withhold more); never resolve uncertainty in favor of release.
  3. If the withholding rule cannot be enforced at all, reject with invalid_grant — the base rule for access constraints, restated. A Data Holder that does not implement this profile therefore rejects any ticket carrying sensitivity_withhold, an unrecognized access member.
  4. Not reveal whether withheld sensitive data exists; error descriptions and audit entries SHALL NOT create that disclosure.

Enforcement is determinate against the Data Holder's own facts. The Data Holder MAY match sensitivity categories — for both withholding and release authorization — through FHIR security labels on returned resources, local classifications mapped to the profile-supported coding system, or encounter, department, service-line, order, diagnosis, note-type, or patient-level classifications when local policy treats those as equivalent to the listed category. Ticket-type profiles that incorporate this profile SHOULD define which code systems and local mappings are in scope.

sensitivity_release_authorized: Profile Claim

sensitivity_release_authorized is a top-level profile claim, not an access constraint: an issuer attestation that the named categories are within the authorization scope. It operates on the Data Holder's own sensitivity gates — it can satisfy a local rule that conditions release on patient authorization, but it cannot override a rule that does not accept ticket-borne authorization, and it broadens nothing on its own.

A Data Holder implementing this profile treats data covered by sensitivity_release_authorized as within the ticket's authorization scope, releasing only if Data Holder policy, law, patient matching, and technical constraints permit; it never resolves classification uncertainty in favor of release. A Data Holder that does not implement the profile ignores the claim — an unrecognized top-level claim — and applies its conservative default. Issuers SHALL retain the authorization-ceremony evidence behind each release authorization.

Relationship to Trust Frameworks

Trust frameworks or ticket-type profiles incorporating this profile should define:

  • Which issuers and ticket types may carry these rules, and separately, which may assert release authorization (the higher-trust direction).
  • Which code systems and codes are accepted.
  • What patient or requester authorization ceremony is required before an issuer may populate sensitivity_release_authorized.
  • Whether withholding rules may be client-requested, patient-requested, issuer-imposed, or trust-framework-imposed.
  • What evidence the issuer must retain, and how responders may audit issuer compliance.
  • How local mappings from EHR classifications to profile codes are validated or documented.

Open Questions

Open Question (OQ-5D): Release Authorization Prerequisites. What authorization UX, classification precision, and trust-framework rules does a Data Holder need before honoring sensitivity_release_authorized for a category like 42 CFR Part 2 data, and who certifies that an issuer's ceremony meets the bar?