Coho Health: Classifying PHI, Enforcing Partner RLS, and Keeping EU Data in the EU
Coho Health Administrators processes claims for 3.2 million members across the US, Canada and the EU. Power BI datasets contain member IDs, claim amounts and diagnosis codes classified as PHI. Six hundred internal users and 40 external partner organizations access shared reports through B2B guest accounts. Last quarter an analyst published a dataset to a public web link for two days before it was noticed. The security team wants automatic classification of sensitive columns, end-to-end lineage from Synapse to report, row-level restriction so each partner sees only its own members, and a block on exporting raw PHI to Excel or CSV while still allowing summarized exports. The EU regulator requires that EU member data never be processed on US-based capacity, and auditors want evidence of who queried which dataset.
1. Design the classification, lineage and exfiltration controls, and explain how each would have prevented the public-link incident.
Read the worked answer
Classification and lineage
- Register the Synapse workspace, the ADLS Gen2 account and the Power BI tenant as Purview sources. Add custom regex classifications for member ID and ICD-10 patterns on top of the system classifiers.
- Apply a sensitivity label such as Confidential-PHI in Purview. With label inheritance enabled in the tenant, the label flows to the dataset and reports and appears in the lineage view.
- Lineage then runs Synapse table to dataset to report, which answers the auditor question of where a column came from.
Why the incident happened
- Publishing to web is a tenant-level capability, not a per-user mistake. The fix is disabling Publish to web for everyone except a named security group, or disabling it entirely.
- Alert on the PublishedToWeb operation in the Microsoft 365 audit log so a two-day exposure becomes a two-minute one.
Exfiltration controls
- Turn off Export data for the PHI security group at the tenant level, and apply a Purview DLP policy for Power BI that detects PHI patterns in datasets.
- Use the label's encryption and content-marking settings so any file that does escape is protected and traceable.
Evidence
- Keep the unified audit log and Power BI activity logs exported to a Log Analytics workspace with retention beyond the regulatory minimum.
2. Design row-level security so each of the 40 partner organizations sees only its own members through B2B guest accounts. What breaks in practice and how do you test it?
Read the worked answer
Model design
- Build a mapping table in the warehouse: PartnerOrgId to MemberId, plus a PartnerUser table mapping guest identity to PartnerOrgId. Import both.
- Create one dynamic role on DimMember:
DimMember[PartnerOrgId] = LOOKUPVALUE(PartnerUser[OrgId], PartnerUser[UserPrincipalName], USERPRINCIPALNAME()) - Single-direction relationships only. Bidirectional filters combined with RLS are a classic source of leakage and of slow queries.
What breaks in practice
- B2B guest UPNs are not plain email addresses; they look like
name_partner.com#EXT#@tenant.onmicrosoft.com. Matching on email silently returns blank rows or, worse, all rows if the measure falls back to a default. Store the exact UPN format, or use a custom security attribute as the join key. - Partners with staff turnover need the mapping table refreshed; group-based roles reduce that maintenance but require governance of the groups.
Testing
- Use View as role for each partner, and also test with a real guest account because View as role does not exercise the B2B identity format.
- Run a DAX query as the role and compare row counts against the partner's expected member count.
- Add a negative test: a user with no mapping row must see zero rows, not everything.
3. How do you satisfy the EU data-residency requirement while keeping a single reporting experience, and what design choices would silently violate it?
Read the worked answer
Compliant design
- Put the EU workspace on Premium capacity located in West Europe, or use Multi-Geo if the tenant is on a SKU that supports it. Multi-Geo stores dataset metadata and executes queries in the assigned region, so EU data is processed in the EU.
- Assign the EU workspace explicitly to the EU capacity. Capacity assignment, not workspace naming, is what determines processing location.
- Keep any on-premises data gateway for EU sources in an EU region, and register the EU Purview data map in the same geography.
Silent violations to avoid
- A composite model or a linked dataset that pulls the EU dataset into a US-hosted model. Processing follows the model that owns the table, so cross-capacity composition can move EU data. Block it by policy and by not granting Build permission across regions.
- A US workspace report bound to the EU dataset is generally acceptable because the query executes in the EU, but the strictest reading is to duplicate the dataset per region and publish separate apps.
- Export to a US-hosted lake or a shared Excel file on US storage defeats the control entirely; pair the residency rule with the export restrictions from the previous task.
Trade-off
Duplicating datasets doubles refresh cost. If the EU population is a small slice, filter the EU dataset at source and accept the duplication rather than sharing one model across regions.