The Regional Manager Who Sees Too Much
prod.sales.orders holds 640 million rows across six regions and includes customer_email, customer_phone, and national_id. Two groups need access. apac_sales (about 400 analysts) must see only region = 'APAC' rows and must never see national_id. global_finance (12 people) needs all six regions with real emails and phones, but still no national_id. Three existing dashboards are published to apac_sales and are owned by the service principal sp_reporting; they query the table directly. Procurement has forbidden re-pointing those dashboards to new object names until next quarter. A new Genie space for apac_sales will also be built on this table. Audit has asked for a written statement of how enforcement works and who can bypass it.
1. Choose between separate regional tables, dynamic views, and Unity Catalog row filters plus column masks. Justify the choice given the constraints, and give the concrete enforcement definitions and grants.
Read the worked answer
Row filters and column masks on the table itself. The deciding constraint is that three dashboards cannot be re-pointed this quarter: filters and masks attach to prod.sales.orders, so every existing consumer - dashboards, notebooks, ad hoc SQL, and any table-level view layered on top - inherits enforcement without changing a single object name. Dynamic views would enforce correctly but require re-pointing, which procurement has blocked. Six regional copies would triplicate maintenance, multiply storage, and create a drift risk where a row moves region and appears in two or zero tables.
Row filter (predicate appended to every read of the table):
CREATE FUNCTION prod.sales.apac_or_finance()
RETURNS BOOLEAN
RETURN is_account_group_member('global_finance') OR region = 'APAC';
ALTER TABLE prod.sales.orders SET ROW FILTER prod.sales.apac_or_finance ON ();
Column mask on national_id (returns a placeholder for everyone, including finance, since finance is also barred):
CREATE FUNCTION prod.sales.mask_national_id(v STRING)
RETURNS STRING
RETURN CASE WHEN is_account_group_member('pii_break_glass') THEN v ELSE '***' END;
ALTER TABLE prod.sales.orders ALTER COLUMN national_id SET MASK prod.sales.mask_national_id;
Leave email and phone unmasked: apac_sales already sees them for APAC rows per the requirement, and masking them would break the finance workflow for no stated benefit.
Grants: GRANT USAGE ON CATALOG prod, GRANT USAGE ON SCHEMA prod.sales, and GRANT SELECT ON TABLE prod.sales.orders to both apac_sales and global_finance. Do not grant MODIFY, and do not grant ownership to either group - ownership lets a user alter or drop the filter and mask, which is the bypass path audit is asking about.
The bypass question, stated honestly: only the table owner, a user with MANAGE on the object, and a metastore/catalog admin can replace or remove the filter and mask or read underneath them. Also check whether sp_reporting is exempted by the filter function; if the global dashboards are meant to show all regions, add it to a named exemption group rather than leaving it accidentally over-permissioned. Confirm by testing as a member of each group before rollout whether the groups additionally need EXECUTE on the two functions in your workspace, since that requirement varies by setup.
2. What breaks or surprises people after this lands, and how do you validate it? Include the Genie space and the service principal.
Read the worked answer
The service principal is the most likely surprise. sp_reporting owns the dashboards and is subject to the same row filter as everyone else unless explicitly exempted. If those three dashboards are the APAC-only ones, an APAC-only result is exactly right and nothing breaks. If any of them is a global view that happens to be published to apac_sales, it will silently lose five regions - numbers change, no error is raised. Enumerate what sp_reporting is used for before deployment and decide the exemption deliberately, in writing.
Silent under-reporting is the general risk. A row filter does not error; it returns fewer rows. Any user who totals a column and compares to a previously saved figure will see a discrepancy. The mitigation is a short notice to apac_sales explaining that totals are now APAC-scoped, plus a reconciliation query for finance run as a global_finance member.
Genie executes its generated SQL using the asking user's Unity Catalog permissions, so an apac_sales member gets APAC rows and a masked national_id automatically - no separate configuration is required for enforcement. Two things to verify by actually signing in as an apac_sales member: (a) row counts returned by a Genie-built query match a direct SQL query, and (b) any space-level sample values or previews Genie displays for tables do not show unmasked national_id values. Also expect Genie answer quality to change, because it now sees a smaller, region-skewed slice when it inspects data to draft SQL; instructions in the space should state that the space is APAC-scoped so it does not build region breakdowns that always return one row.
Validation checklist: sign in as an apac_sales member and run SELECT region, count(*) FROM prod.sales.orders GROUP BY 1 - expect one row. Run SELECT national_id FROM ... LIMIT 5 - expect asterisks. Repeat as a global_finance member - expect six regions and asterisks. Attempt ALTER TABLE ... DROP ROW FILTER as a non-owner - expect a permission error. Then re-open each of the three dashboards and compare one tile's total against the pre-change value for APAC only.