PABCD Initiative Documentation Hub pabcd_initiative codexclaw cli-jaw

Data Governance — PII, Masking, Compliance

Source: dev-data/references/governance.md

Data Governance — PII, Masking, Compliance

Last reviewed: 2026-07-02

Security and privacy patterns for production data pipelines.

---

PII Masking Techniques

TechniqueReversibleUse Case
PseudonymizationYes (with mapping)Analytics needing re-identification
AnonymizationNoPublic datasets, research
Dynamic maskingN/A (query-time)Production DBs with mixed access levels
Static maskingNoNon-production environments (dev/QA)
TokenizationYes (separate vault)Payment data (PCI-DSS), SSNs

Rule: Always use static masking for non-production environments. Never copy production PII to dev/staging.

---

GDPR Engineering Patterns

Right to Erasure (Article 17)

User deletion request
→ Soft delete in application DB
→ Batch purge job (after grace period)
→ Propagate to all downstream stores:
  ├── Data warehouse (DELETE or partition drop)
  ├── Data lake (Delta Lake/Iceberg row-level delete)
  ├── Search indices (Elasticsearch delete-by-query)
  ├── Caches (Redis DEL)
  └── Backups (mark for purge at next rotation)
  • Check consent flags before processing PII columns
  • Different processing paths per consent level
  • Store consent as versioned events (not mutable flags)

Data Subject Access Request (DSAR)

  • Build export endpoint that collects all user data across systems
  • Format: JSON or CSV per GDPR Article 20 (data portability)
  • Automate where possible — manual DSAR handling doesn't scale

---

CCPA Additions

CCPA RequirementDifference from GDPREngineering Pattern
Right to opt-out of saleNo GDPR equivalentBoolean do_not_sell flag on user profile; filter in data sharing pipelines
Financial incentive disclosureNo GDPR equivalentMetadata on loyalty/discount programs linked to data collection
12-month lookbackGDPR has no fixed windowRetain deletion request logs for 12 months

---

Row-Level Security (RLS)

Access Control Hierarchy:
├── Table-level: Can this role access this table?
├── Column-level: Which columns visible? (mask PII)
├── Row-level: Which rows visible? (filter by org_id)
└── Cell-level: Dynamic masking per field per role

PostgreSQL RLS example:

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY org_isolation ON orders
    USING (org_id = current_setting('app.current_org_id')::int);

Snowflake dynamic masking:

CREATE MASKING POLICY email_mask AS (val STRING) RETURNS STRING ->
  CASE
    WHEN CURRENT_ROLE() IN ('ADMIN', 'DATA_STEWARD') THEN val
    ELSE REGEXP_REPLACE(val, '.+@', '***@')
  END;

---

Data Retention Policy

TierRetentionStorageAccess Pattern
Hot0-90 daysPrimary warehouseReal-time queries
Warm90 days - 2 yearsArchive tables / cold storageOccasional queries
Cold2-7 yearsObject storage (S3/GCS) ParquetCompliance/audit only
PurgeBeyond retentionPermanently deletedN/A

Automate tiering with lifecycle policies. Tag tables with retention_days and data_classification metadata.