commvita
Connected care platform
Information Governance

Who owns the data, who controls it, and how access is granted, protected & rescinded

A demo reference for the three IG roles — data subject, data controller, data processor — who can see special-category (Article 9) data, and exactly where each control lives in the commvita platform, following a single record from access granted to access rescinded by policy — all on one immutable, intelligent audit.

Live vs demonstrated: Live — real, API-backed platform logic (wired end-to-end today) Demonstrated — representative control surface with seeded data / illustrative UI mock-up

The three roles

UK GDPR / Data Protection Act 2018 define who does what. The subject holds the rights; the controller holds the accountability and the decisions; the processor only ever acts on the controller's instructions.

Data subject

The person the record is about — the patient (or a staff member)

Not a party to the processing contract. The law gives them rights: to be informed, to access (SAR, Art.15), rectify, erase, restrict, port (Art.20) and object — plus the National Data Opt-Out for secondary use.

Where in commvita Patient Portal privacy tab · Art.15 SAR export in the /legitimate-access-log · FHIR PHR download · "query this access" view.

Data controller

The provider — NHS trust · GP practice · ICB · local authority

Decides why and how (Art.4(7)). Holds the lawful basis (Art.6 + Art.9(2)(h) for health), keeps the Art.30 record of processing, runs DPIAs, answers subject rights and reports breaches to the ICO within 72h.

Where in commvita /ig-hub (DSPT · DPIA · 72h breach · Caldicott 8) · /ig-spine policy-as-code · Patient Data Control (Art.30 flows).

Data processor

The platform / hosting supplier acting for the controller

Processes only on the controller's documented instructions, never for its own purposes (Art.4(8)). Bound by an Art.28 contract; sub-processors need authorisation. Decide your own purpose and you become a controller.

Where in commvita /supplier-ig-assurance (DSPT/DTAC + DPA register) · /dspa-manager (Art.26 joint-controller agreements).

9 Who can see special-category data

Under UK GDPR Article 9, health, sex life & orientation, ethnicity, genetics, biometrics, religion, trade-union membership and political opinion are special-category data — in a care record, almost everything clinical qualifies. It carries an extra layer of control on top of the access chain below.

Only roles with a lawful Article 9 condition

Access needs an Art.9 condition — for direct care that is Art.9(2)(h) (provision of health/social care). The 18-role × 16-domain RBAC matrix decides which clinical domains a role reaches, and effective_role() takes the role only from an explicit assignment — never inferred.

/rbac · RBAC MatrixUK GDPR Art.9(2)(h)

Field-level control — minimum necessary

Policy-as-code binds role → field, so even inside a record a professional sees only the special-category fields their purpose needs (Caldicott Principle 4 / Art.5(1)(c)). The executive oversight role is deliberately excluded from unrestricted scope — seniority is not blanket access.

/ig-spine · Purpose & Legal Basis

The most sensitive domains are gated further

Genomics requires an explicit genomics_access grant; sexual-health / GUM records are handled as Art.9 special category with their own confidentiality; sensitive mental-health notes can be break-glass-only. And every Art.9 action requires a fresh step-up re-authentication — a standing session is not enough.

/auth/reauthbreak-glass policy

Granted, and rescinded, the same way as any access

Granted by an explicit role + Art.9 purpose + scope (plus the specific grant for genomics/GUM). Rescinded by the same policy levers as everything else — self-expiring delegations/groups filtered by effective_scope(), consent withdrawal or opt-out propagated via FHIR Consent R4, and token revocation. Secondary use of special-category data adds the Caldicott Guardian gate, honours the National Data Opt-Out, and for research relies on Art.9(2)(j) with Art.89 safeguards.

effective_scope()/consent-hub · /shcr-opt-out/ig-spine · Caldicott Queue
Every special-category access is logged. There is no route to read Art.9 data that does not write an entry to the immutable audit described below — and the patient can see who looked and "query this access".

🔎 Scoped patient search — you can only find who you should

Access control starts at the very first keystroke. You cannot search your way to a record you have no basis to see — the smart patient search is constrained by scope, role and jurisdiction before a single name is returned. ● Live

1

The search is organisation-scoped

The smart patient search (the PatientPicker used across the platform) filters by your organisation scope — the union of your own practice/trust ODS codes plus any team-lead delegations and user-group memberships (effective_scope()), exactly as the patient list does. A GP-practice receptionist scoped to one practice only matches that practice's patients; an empty scope returns nothing (never "everyone"); only an explicitly-assigned UNRESTRICTED role searches across organisations.

GET /patients/searcheffective_scope()Patient.ods_code ∈ orgs
2

Special-category records need a clinical basis

A receptionist (read_only) is blocked from special-category recordssexual-health and Mental Health Act data require a clinical role (require_min_role), returning 403 for reception/admin roles. Those sensitive records sit behind a clinical basis, never behind a demographic search: finding the person is not the same as opening their Art.9 data.

/sexual-health/episodes/mha-recordsrequire_min_role · Art.9
3

And it's isolated to your jurisdiction

Search is also bounded by jurisdiction — an England user never matches a Crown Dependency, Ireland or any other jurisdiction's patients — and every match resolves through the same immutable audit as any other access.

Patient.jurisdiction_idjurisdiction isolation
Scope + role + jurisdiction constrain the first keystroke. A GP receptionist sees only their own practice's patients and cannot reach sexual-health or mental-health special-category data at all — enforced server-side (/patients/search is org-scoped; the Art.9 reads are role-gated), not merely hidden in the UI.

A How a controller grants access to a subject's record

Access is never a single switch — it is a chain, and every link must be satisfied before a professional sees a record. Each link is a real control in the platform.

1

Establish a lawful purpose

The controller fixes why — a lawful basis (Art.6) plus a special-category condition (Art.9(2)(h), provision of care). This is encoded as policy-as-code: purpose → dataset, role → field.

/ig-spine · Purpose & Legal BasisUK GDPR Art.6/9
2

Put the processor under contract & assurance

Before any data is touched, an Art.28 Data Processing Agreement binds the processor to instructions-only use, security (Art.32) and deletion at end. The processor evidences DSPT / DTAC assurance first.

/supplier-ig-assurance/dspa-managerArt.28 · DSPT 2024/25 · DTAC
3

Assign a role — least privilege

A role decides which of 16 data domains the person can reach (18-role hierarchy read_only→…→superadmin). Role comes only from an explicit assignment — effective_role() never infers it.

/rbac · RBAC Matrixeffective_role()
4

Bind organisational scope

effective_scope() computes the ODS org codes a user may see — the union of their own org, any team-lead delegations (UserDelegation) and user-group memberships (UserGroup, scope-only, never a role). Stamped into the token at login as _org_codes. You see your population, not the database.

/rbac/user-groups/rbac/delegations/rbac/users/{id}/effective-access
5

Require a legitimate relationship

Role + scope let you reach a cohort; opening an individual record needs a care reason. Each access is justified and logged; out-of-area, bulk or cross-ICS access raises an anomaly alert.

/legitimate-access-logFHIR R4 AuditEvent
6

Open a short-lived, revocable session

Access rides a 60-minute JWT carrying a unique JTI. Special-category (Art.9) actions require a step-up re-authentication (/auth/reauth). Nothing is a standing key.

Data Security ArchitectureJTI · TOKEN_TTL 60m

Secondary (non-direct-care) use adds a gate: the request routes to the Caldicott Guardian queue for approval, and the National Data Opt-Out is enforced — before any access is granted.

B How that access is protected while it is live

Granting is not the end — the access is continuously constrained, watched and evidenced.

Least privilege & data minimisation

Role × domain matrix caps what; org scope caps whose. Data minimisation is enforced by design (Caldicott Principle 4 / Art.5(1)(c)) — e.g. the executive oversight role is deliberately excluded from unrestricted scope.

Caldicott gate & opt-out enforcement

Non-direct-care access is held for Caldicott Guardian decision (CaldicottDecision, principles applied recorded); the National Data Opt-Out blocks secondary use of an opted-out patient's confidential data.

/ig-spine · Caldicott Guardian Queue

Break-glass — allowed, but heavily audited

Emergency override exists (e.g. break-glass-only mental-health notes) but every use is justified, logged, notifiable and challengeable by the patient or IG.

/shcr-opt-out · Override Log

Immutable, tamper-evident audit

Access and account events are written to append-only SHA-256 hash-chained (WORM) logs that the server re-verifies on every read — a broken chain shows a tamper banner. There is no update or delete endpoint.

/login-audit/ig-spine · WORM auditGET /auth/login-audit

Transparency to the subject

Non-controller access triggers controller notification and a patient "query this access" view (Caldicott Principle 8); the subject can pull an Art.15 SAR of who accessed their record.

/ig-spine · Cross-Controller Transparency/legitimate-access-log

C How access is rescinded — by policy, not by memory

The important part: access ends automatically when the policy that justified it lapses. No administrator has to remember to switch it off.

Time-boxed grants that self-expire

Delegations and group memberships carry an expires_at. effective_scope() filters expired grants at authentication time — the moment a grant lapses the associated org scope simply stops resolving, so the record falls out of view with no manual step.

UserDelegation.expires_atUserGroup.expires_ateffective_scope()

Lapse recorded to the tamper-evident chain

A lapse is written once (lapse_recorded) to the hash-chained account log, and renewal requires an explicit re-attestation — access can't quietly persist or silently re-elevate. Role and group changes are logged the same way.

LoginAuditEvent chainPATCH /rbac/user-groups/{id}

Consent withdrawal & opt-out propagate

The subject withdrawing consent (Art.7) in the /consent-hub, or opting out in /shcr-opt-out, updates a FHIR Consent R4 record that propagates — removing sharing at source, including partial category-level opt-outs.

FHIR R4 ConsentNational Data Opt-Out

Session & token revocation

A live session is killed immediately: the JTI denylist revokes the token, /auth/logout ends it, and an admin can force-logout any session from the Security Console. The 60-minute TTL caps residual exposure.

JTI denylistSecurity Console · Terminate

Challenge & revoke an access after the fact

A patient or IG reviewer can challenge a recorded access or a break-glass override; the workflow can restrict or revoke it, with the decision written to the immutable log.

/shcr-opt-out · challenge/revoke/legitimate-access-log · challenges
The principle: access is protected and rescinded by policy — time-boxed grants filtered at every login, consent/opt-out that propagates at source, and revocation that is immediate and audited. Removing access is a data-driven consequence of an expired or withdrawn authorisation, not a manual clean-up task someone might forget.

The immutable, intelligent audit — how it's driven

Every event above — grant, access, special-category read, expiry, extension, revocation — lands in one place: an immutable, tamper-evident log that doesn't just record what happened, it watches for what shouldn't and drives a response.

Immutable by construction (WORM)

Audit rows are append-only and SHA-256 hash-chained — each row's prev_hash → row_hash links to the one before it. The server re-verifies the whole chain on every read and shows a tamper-evidence banner if a link is broken. There is no update or delete endpoint — an entry cannot be quietly altered or removed, on any log (Login Audit, IG Spine, commvita Sign, Policy-to-Process).

/login-audit/ig-spine · WORM auditprev_hash → row_hash

It captures who, what, when — and where from

Each event records the username, action and result, plus the source IP + X-Forwarded-For chain, the country logged in from, the device / user-agent and the jurisdiction — enough to reconstruct exactly how an access happened, and to spot when it looks wrong.

LoginAuditEventGDPR Art.5(1)(f)/30

Out-of-hours & anomaly detection

The audit is rule-driven: access outside expected hours or from an unusual location is flagged, and the Legitimate Relationship Log surfaces out-of-area, bulk and cross-ICS patterns with investigate / dismiss / DPO-flag workflows — so "why was this record opened at 03:00 from another region?" is a question the system asks, not one you have to go looking for.

/legitimate-access-log · Anomaly AlertsSecurity Console

Cross-setting safety-netting — the GP is told

When a patient's record is opened in another direct-care setting — a hospital, out-of-hours or NHS 111 clinician — a safety-netting alert is sent to the registered GP practice. It is gated on encounter / ADT corroboration (a real clinical contact, not a stray click), kept minimum-necessary, deduplicated and rate-limited, and the acknowledgement is itself audited. This is Caldicott Principle 8 in action — the duty to share for care, made visible to the patient's home team.

/ig-spine · Clinical Trigger AlertEPR Hub ADT · NHS 111

Clinical-workflow-aware & transparent to the patient

The Security Console adds clinical-workflow-aware anomaly detection and Article 9 special-category monitoring, with a GDPR Art.33 72-hour ICO breach countdown. And the subject can see who accessed their record and "query this access" — pulling an Art.15 SAR. Every alert is acknowledgeable, and the acknowledgement is written back to the immutable chain: the audit records the response, not just the event.

/security-console/ig-spine · Cross-Controller Transparency

Where each control lives in commvita

Subjectrights → Controllergrants via A · protects via B · rescinds via C → Processor
IG conceptModuleRouteModel / APIStandard
Purpose & legal basis (policy-as-code)Confidential-IG Spine/ig-spinepurpose→dataset · role→fieldUK GDPR Art.6/9
Controller accountabilityIG Hub · Patient Data Control/ig-hubDPIA · Art.30 flows · 72h breachDSPT 2024/25 · Caldicott 8
Processor contract & assuranceSupplier IG Assurance/supplier-ig-assuranceDPA / contract registerArt.28 · DSPT · DTAC
Joint-controller sharingDSPA Manager/dspa-managerDSPA lifecycle · signatoriesArt.26 · NHS DSPA template
Role — what you can reachRBAC · RBAC Matrix/rbaceffective_role() · /rbac/matrix18 roles × 16 domains
Scope — whose recordsRBAC · Groups & Delegations/rbac/user-groupseffective_scope() · UserGroup · UserDelegation (expires_at)ODS · Caldicott P4 / Art.5(1)(c)
Legitimate relationshipLegitimate Relationship Log/legitimate-access-logaccess log · anomaly alerts · Art.15 SARDSPT · GDPR Art.30/15
Caldicott gate (secondary use)Confidential-IG Spine/ig-spineCaldicottDecisionCaldicott 8 · National Data Opt-Out
Consent & withdrawalConsent Hub · Shared Care Opt-Out/consent-hub · /shcr-opt-outFHIR Consent R4 · override logGDPR Art.7 · FHIR R4 Consent
Session & token controlData Security Architecture · Security Console/security-architectureJTI denylist · /auth/logout · /auth/reauthGDPR Art.32 · NCSC
Special-category (Art.9) controlConfidential-IG Spine · RBAC/ig-spine · /rbacrole→field policy-as-code · genomics_access · /auth/reauthUK GDPR Art.9(2)(h)/(j)
Scoped patient search (org · role · jurisdiction)Patient search · PatientPickerGET /patients/searcheffective_scope() org filter · Art.9 reads role-gated (/mha-records, /sexual-health)UK GDPR Art.5(1)(c)/9 · Caldicott P4
Immutable audit (grant/protect/rescind)Login Audit · IG Spine WORM/login-auditSHA-256 hash chain · GET /auth/login-auditGDPR Art.5(1)(f) · DSPT
Intelligent audit (OOH · anomaly · GP alert)Legitimate Relationship Log · IG Spine · Security Console/legitimate-access-log · /ig-spineanomaly alerts · Clinical Trigger Alert (ADT/111) · Art.9 monitoringCaldicott 8 · GDPR Art.33
UK GDPR · Data Protection Act 2018Caldicott 8 PrinciplesDSPT 2024/25 National Data Opt-OutFHIR R4 AuditEvent / Provenance / ConsentNon-SaMD IG control surface
© 2026 Commvita Digital Health Solutions Ltd. All rights reserved.