Security

Patient data stays in your environment.

Clinical Extract runs inside your environment and exports only the variables your protocol approved, to storage you control.

Clinical Extract has read-only access, and no PHI is sent to us.

1 The data path

The data path runs inside your environment.

Patient data moves on one path: from your EHR to Clinical Extract to your study folder. Clinical Extract runs on your server or in your cloud tenant, next to the EHR it reads, and the NDJSON files, study.csv and data-dictionary.json land in storage you control. Only Clinical Extract software comes in, and we never receive patient data.

The data pathA dashed boundary labelled your environment. Your EHR, with its certified bulk FHIR API (ONC §170.315(g)(10)), sits on the boundary; inside it are Clinical Extract, on your server or cloud tenant, and the study folder in your storage. Clinical Extract sends requests to the EHR: POST to the token endpoint with a JWT signed RS384, GET Group/{cohort-id}/$export, then the status URL and the file URLs. The token carries read scopes only: system/Patient.read, system/Group.read, system/Encounter.read, system/Condition.read, system/Observation.read, system/MedicationRequest.read and system/Procedure.read. Patient data, highlighted, runs on one path inside your environment: NDJSON from the EHR into Clinical Extract, then study.csv and data-dictionary.json into the study folder. The private signing key stays in your key store. Releases sit outside the boundary: software goes in as release source, built into a container in your environment, and no data comes back out.YOUR ENVIRONMENTYour EHRcertified bulk FHIR API§170.315(g)(10)Clinical Extractyour server orcloud tenantStudy folderyour storage,your access controlsREQUESTSPOST {token endpoint}GET /Group/{cohort-id}/$exportGET {status-url}, {file-url}patient data, NDJSONREAD SCOPES ON THE TOKENsystem/Patient.readsystem/Group.readsystem/Encounter.readsystem/Condition.readsystem/Observation.readsystem/MedicationRequest.readsystem/Procedure.readstudy.csvdata-dictionary.jsonprivate key: your key storeJWT signed RS384Releasesno data outsoftware inrelease source, built in your environment
The data pathA dashed boundary labelled your environment. Your EHR, with its certified bulk FHIR API (ONC §170.315(g)(10)), sits on the boundary; inside it are Clinical Extract, on your server or cloud tenant, and the study folder in your storage. Clinical Extract sends requests to the EHR: POST to the token endpoint with a JWT signed RS384, GET Group/{cohort-id}/$export, then the status URL and the file URLs. The token carries read scopes only: system/Patient.read, system/Group.read, system/Encounter.read, system/Condition.read, system/Observation.read, system/MedicationRequest.read and system/Procedure.read. Patient data, highlighted, runs on one path inside your environment: NDJSON from the EHR into Clinical Extract, then study.csv and data-dictionary.json into the study folder. The private signing key stays in your key store. Releases sit outside the boundary: software goes in as release source, built into a container in your environment, and no data comes back out.YOUR ENVIRONMENTYour EHRcertified bulk FHIR APIClinical Extractyour server or cloud tenantsigning key in your key storeStudy folderyour storage,your access controlsREQUESTSPOST {token endpoint}GET /Group/{cohort-id}/$exportGET {status-url}, {file-url}patient data, NDJSONREAD SCOPES ON THE TOKENsystem/Patient.readsystem/Group.readsystem/Encounter.readsystem/Condition.readsystem/Observation.readsystem/MedicationRequest.readsystem/Procedure.readstudy.csvdata-dictionary.jsonReleasesno data outsoftware inrelease source
Figure 1. The data path. Patient data moves on one path, from your EHR to Clinical Extract to your study folder, all inside your environment. The token Clinical Extract presents carries read scopes only.

2 Scopes

Read-only scopes, one per resource type.

The token Clinical Extract presents carries one read scope per resource type the study reads and system/Group.read for the cohort. Those scopes allow read and search only. The export starts from the study cohort's Group and reaches the cohort's members only. Each study's token carries the resource types its protocol names, and a study that reads no medications carries no medication scope.

Read-only scopesA ruled table of the scopes on Clinical Extract’s access token, one row per FHIR resource type, each with its SMART v1 scope, its SMART v2 equivalent and the five v2 permissions create, read, update, delete and search, of which read and search are granted on every row. Patient: system/Patient.read, system/Patient.rs, birth date, administrative gender and the MRN identifier. Group, highlighted: system/Group.read, system/Group.rs, the study cohort’s member list, the starting point of Group/{cohort-id}/$export. Encounter: visit dates, class and type. Condition: diagnoses coded in ICD-10-CM and SNOMED CT, with onset dates. Observation: labs, vital signs, staging and biomarkers coded in LOINC, such as 16112-5, estrogen receptor status. MedicationRequest: ordered agents coded in RxNorm. Procedure: surgery and radiation coded in CPT and SNOMED CT. A key reads: filled dot granted, open dot not granted; c create, r read, u update, d delete, s search. Below, the token request, abridged: POST to the token endpoint with Content-Type application/x-www-form-urlencoded and the body grant_type=client_credentials, scope listing the system read scopes, one per row, client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer and client_assertion, a JWT signed RS384 that expires at most five minutes after it is issued.Resource typeScope, SMART v1SMART v2What the study readsPatientsystem/Patient.readsystem/Patient.rsbirth date, administrativegender, MRN identifierGroupsystem/Group.readsystem/Group.rsthe study cohort’s member list,where the export startsEncountersystem/Encounter.readsystem/Encounter.rsvisit dates, class and typeConditionsystem/Condition.readsystem/Condition.rsdiagnoses, ICD-10-CM and SNOMEDCT, with onset datesObservationsystem/Observation.readsystem/Observation.rslabs, vitals, staging, biomarkersin LOINC (16112-5, ER status)MedicationRequestsystem/MedicationRequest.readsystem/MedicationRequest.rsordered agents, RxNormProceduresystem/Procedure.readsystem/Procedure.rssurgery and radiation, CPT andSNOMED CTcrudsgrantednot grantedc creater readu updated deletes searchTOKEN REQUEST, ABRIDGEDPOST {token endpoint}Content-Type: application/x-www-form-urlencodedgrant_type=client_credentials&scope=system/Patient.read system/Group.read ... one per row above&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=eyJhbGciOiJSUzM4NCIs...  JWT signed RS384, exp at most 5 minutes out
Read-only scopesA ruled table of the scopes on Clinical Extract’s access token, one row per FHIR resource type, each with its SMART v1 scope, its SMART v2 equivalent and the five v2 permissions create, read, update, delete and search, of which read and search are granted on every row. Patient: system/Patient.read, system/Patient.rs, birth date, administrative gender and the MRN identifier. Group, highlighted: system/Group.read, system/Group.rs, the study cohort’s member list, the starting point of Group/{cohort-id}/$export. Encounter: visit dates, class and type. Condition: diagnoses coded in ICD-10-CM and SNOMED CT, with onset dates. Observation: labs, vital signs, staging and biomarkers coded in LOINC, such as 16112-5, estrogen receptor status. MedicationRequest: ordered agents coded in RxNorm. Procedure: surgery and radiation coded in CPT and SNOMED CT. A key reads: filled dot granted, open dot not granted; c create, r read, u update, d delete, s search. Below, the token request, abridged: POST to the token endpoint with Content-Type application/x-www-form-urlencoded and the body grant_type=client_credentials, scope listing the system read scopes, one per row, client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer and client_assertion, a JWT signed RS384 that expires at most five minutes after it is issued.Scope, SMART v1 and v2crudsPatientsystem/Patient.readv2 system/Patient.rsbirth date, administrative gender, MRNidentifierGroupsystem/Group.readv2 system/Group.rsthe study cohort’s member list, where theexport startsEncountersystem/Encounter.readv2 system/Encounter.rsvisit dates, class and typeConditionsystem/Condition.readv2 system/Condition.rsdiagnoses, ICD-10-CM and SNOMED CT, withonset datesObservationsystem/Observation.readv2 system/Observation.rslabs, vitals, staging, biomarkers in LOINC(16112-5, ER status)MedicationRequestsystem/MedicationRequest.readv2 system/MedicationRequest.rsordered agents, RxNormProceduresystem/Procedure.readv2 system/Procedure.rssurgery and radiation, CPT and SNOMED CTgrantednot grantedc creater readu updated deletes searchTOKEN REQUEST, ABRIDGEDPOST {token endpoint}grant_type=client_credentials&scope=system/Patient.read ...&client_assertion_type=urn:ietf:params:oauth:  client-assertion-type:jwt-bearer&client_assertion=eyJhbGciOiJSUzM4NCIs...JWT signed RS384, exp at most 5 minutes out
Figure 2. Read-only scopes. Clinical Extract’s token carries one read scope per resource type the study reads, including the cohort’s Group, with read and search permissions only. The export starts from the study cohort’s Group and reaches the cohort’s members only. The rows show an oncology study; each study’s token carries the resource types its protocol names.

3 Minimum necessary

How the export enforces minimum necessary.

The Privacy Rule's minimum necessary standard (45 CFR 164.502(b)) asks a covered entity to limit protected health information to what the purpose needs. Clinical Extract enforces it at three levels in the export itself: the Group scopes the patients to the cohort, _type scopes the resource types, and the approved variable list scopes the columns. A variable the protocol did not approve never reaches study.csv, and the data dictionary records which variables did. The dictionary also drives the informatics team's release step.

Your privacy office reviews the deployment like any other in-house system, with the data path in Figure 1 and the scopes in Figure 2. For the agreements HIPAA asks of vendors, our checklist for business associate agreements is the reference.

A limited data set (45 CFR 164.514(e)) is one variable list: dates and geography kept, direct identifiers out. A fully identified extract under an IRB waiver is another. The dictionary is the record of which one you exported. A review preparatory to research needs only counts: the cohort builder returns the count before any record moves.

4 Your controls

What runs where in your environment.

Your compute
We install one container on your server or cloud tenant, built from the release source with the Dockerfile. It runs under your access controls. Health check at /healthz, version at /api/version.
Your key store
The RSA private key as a read-only mounted file or an injected secret; the public key at the JWKS URL Clinical Extract serves, the one path an EHR vendor fetches.
Your storage
The NDJSON, study.csv and data-dictionary.json in a study folder under your access controls; nothing is sent anywhere else.
Your log
Each run step, token request and JWKS fetch is written to the server log in your environment, size-rotated, yours to keep.
Your front door
The dashboard sits behind your reverse proxy's authentication or the built-in login; only the JWKS path is public. Deployment in your environment has the settings.
Outbound only to the EHR
Clinical Extract's outbound calls go to your EHR alone, over HTTPS on port 443: the token endpoint, the Group kickoff, the status URL, each file URL.

5 Questions

Questions about security

Is the export read-only?

The token Clinical Extract presents carries one system/<Resource>.read scope per resource type the study reads, plus system/Group.read for the cohort. Those scopes allow read and search only, so Clinical Extract cannot create or change a record.

Where is the private key?

In your key store: a file mounted read-only into the container, or a secret your platform injects. It signs the JWT for every token request and never leaves your environment; the EHR holds only the public key, at the JWKS URL Clinical Extract serves or as an uploaded certificate.

What does minimum necessary mean for a study export?

Three limits, applied in the export itself: the Group scopes the patients to the cohort, _type scopes the resource types the protocol reads, and the approved variable list scopes the columns. A variable the protocol did not approve never reaches study.csv.

Who can see the study folder?

Whoever your access controls allow. The NDJSON, study.csv and data-dictionary.json land on the server or cloud tenant you run Clinical Extract on, under your own storage, identity and audit controls.

Next

See Clinical Extract run on one of your studies.

Tell us which EHR you run and what the study or registry needs. We reply within one business day to set a meeting time.

Request a demo