Design field-level and record-level access controls for a business application where each customer configures their own rules.
Show the full answer Hide the answer
Where enforcement must live
At the data layer, not in application code. Application-level filtering means every query author must remember the rule, every new access path is a potential bypass, and a reporting tool connecting directly sees everything. Policy attached to the table applies regardless of how the data is reached.
The design
- Row policies as predicates evaluated against the session's identity and attributes, so the same query returns different rows per user without the query knowing.
- Column policies as masking rather than removal where possible, since a missing column breaks queries while a masked value degrades gracefully — but mask consistently, because a value visible in one view and masked in another is a leak.
- Policy defined once and applied to every access path: application, reporting, export, API, ad-hoc SQL.
- Tenant configuration within platform-set boundaries. Tenants configure their own restrictions; they cannot configure away isolation or audit.
- Deny by default, with access granted through explicit policy.
What has to be watched
Aggregate leakage. A user forbidden from seeing individual salary records can frequently infer them from a small-group average. Row-level security does not address this — it needs minimum group sizes on aggregates, which is a separate control people forget exists.
Performance. Predicates evaluated per row can prevent index use and change query plans dramatically. Test with realistic policy complexity, because a policy that is correct and makes reports take four minutes will be disabled.
Policy testing. Access rules need a test suite like any other logic — assertions that specific personas see specific rows — or a refactor silently widens access with no failure anywhere.