Data protection and privacy model
One shared model, not each app, protects personal and financial columns. The privacy team picks the private columns. Each user group reads the matching copy.
The problem
The data holds personal and financial details, and privacy law applies. Not every user may see every field. Before this work, each table had one protected view, and it set only which rows a person could see. If a user could see a row, they saw every column in it.
Constraints
- Privacy law, and extra limits on financial data.
- Apps in production must keep working while the access model changes underneath them.
- Engineers must not be the ones who decide what counts as private.
What was built
Two checks on every request. A column check decides which columns a user sees. A row check decides which rows. The user sees only the cells where the two overlap. This page covers the columns. Hierarchical access covers the rows.
A list of private columns. The privacy team owns one list that names the private fields. Aggregated and anonymised data is public. Personal, financial and sales area details are private.
| What the copy shows | Public | Private |
|---|---|---|
| Aggregated data | ● | ● |
| Anonymised information | ● | ● |
| Personal details | ○ | ● |
| Financial details | ○ | ● |
| Sales area details | ○ | ● |
Two copies, one object. The pipeline uses the list to build two copies of each table. The private copy has every column. The public copy has no private columns. Each copy has its own row rules. One business object sits on both copies.
Public and private groups. Each user group is classed as public or private, and that class decides which copy its members read. Apps see one object and do not change.
Before: rows only
- 1Source table
- 2One protected viewRow rules only. A visible row shows every column.
- 3Business object
After: rows and columns
- 1List of private columnsOwned by the privacy team.
- 2Two copies of the tablePrivate: every column. Public: no private columns.
- 3Row rules on each copy
- 4One business objectReads the copy that matches the user group's class.
Key decisions
- Protect data in the model, not in each app. One place sets the rules, so there is one place to audit them.
- Privacy owns the privacy decision. The privacy team defines which columns are private, and only they can change the list. Engineering builds what the list says.
- Access as data, not code. Giving a user access means adding them to a group. Making a field private, or public again, is one change to the list and a rebuild. No app changes.
| Request | Who | How | Code change |
|---|---|---|---|
| Give a user public or private access | Support | Add the user to a public or private group | None |
| Make a column private, or public again | Privacy team | Update the list of private columns | None |
Where it is now
It was the first public and private column split for the whole organisation. The organisation is global, and teams in many countries reuse one central data model. So one split protects every team that builds on that model.