C.W.K.
Stream
Lesson 04 of 06 · published

PII, Compliance, and Access Control

~11 min · pii, security, compliance

Level 0Curious Reader
0 XP0/47 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

The professional minimum

Every production data engineer eventually deals with PII (personally identifiable information). The minimum bar is: know what's PII in your tables, control who can read it, log who reads it, and handle deletion requests when they come. The exact regulations differ by region (GDPR in the EU, CCPA in California, K-Personal Information Protection Act in Korea), but the underlying engineering shape is similar.

The four engineering controls

  • Tagging. Every column is tagged as PII / sensitive / public in a metadata catalog or in dbt's schema.yml.
  • Masking. Non-privileged users see hashed or redacted values; privileged users see the real values, and access is logged.
  • Row-level security. The same table can be filtered differently for different roles (each region's analyst sees only their region).
  • Right-to-be-forgotten propagation. When a user requests deletion, the deletion has to flow through every derived table. If you don't know where their data is, you can't honestly say it's deleted.

What every analyst should not be able to do

Bulk-export a table containing PII to a personal laptop. Production warehouses (Snowflake, BigQuery, Postgres with row-level security) all support policies that prevent this. The default for a new analyst account should be: read-only on aggregated marts, no PII, no export-to-CSV without an explicit approval workflow. Tightening permissions later is a thousand times harder than tightening them by default.

Code

PII tagging in dbt's schema.yml — meta tags travel with the model·yaml
version: 2

models:
  - name: dim_customers
    description: "Customer dimension. Contains PII."
    meta:
      contains_pii: true
      access_classification: restricted
    columns:
      - name: customer_id
        meta:
          pii: false
          column_classification: pseudonymous_id
      - name: email
        meta:
          pii: true
          column_classification: personal_contact
      - name: phone
        meta:
          pii: true
          column_classification: personal_contact
      - name: country
        meta:
          pii: false
          column_classification: demographic
PostgreSQL row-level security — the mechanism that enforces it·sql
ALTER TABLE fact_orders ENABLE ROW LEVEL SECURITY;

-- Region analysts see only their region
CREATE POLICY region_filter ON fact_orders
    FOR SELECT TO region_analyst_role
    USING (region = current_setting('app.current_region'));

-- Global admins see everything
CREATE POLICY admin_all ON fact_orders
    FOR ALL TO admin_role
    USING (true);

-- The application sets app.current_region per-session at connect time:
--   SET app.current_region = 'KR';

External links

Exercise

Inventory one production table you work with. List every column and tag each one PII / sensitive / public. For each PII column, write down (a) who in your org should be able to read the raw value, (b) what mechanism enforces that today, (c) whether that mechanism is in the warehouse or just in the BI tool. Most audits surface at least one gap.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.