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
sensitivity_withhold: Constraint Definitionsensitivity_release_authorized: Profile Claim| Status: Experimental profile draft for discussion | Author: Josh Mandel | Date: May 27, 2026 (rev. June 2026) |
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.
Three parties need these rules:
The two pieces carry different trust and enforcement properties, and the split encodes them structurally:
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.
| 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.
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"
}
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"
}
]
}
}
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.
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 }
}
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 Definitionsensitivity_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.
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:
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.
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.
A Data Holder implementing the constraint SHALL:
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.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.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 Claimsensitivity_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.
Trust frameworks or ticket-type profiles incorporating this profile should define:
sensitivity_release_authorized.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_authorizedfor a category like 42 CFR Part 2 data, and who certifies that an issuer's ceremony meets the bar?