Queries · q119 · Data Protection Officer · week 1, night 3
“What retention rules actually exist across entity tables, collapsing the one-row-per-tenant duplication, so I can see real coverage and variation?”
Fictional people at a fictional company, each played by a language-model agent. Who they are and what they are told
The manager, at the start of week 1
Subject: A few starting questions on privacy & data handling
Hi Priyanka,
Welcome aboard, and thank you for taking these on this week. As I get oriented, here's what I'd like to understand first. Given the slot constraints, please treat these as priorities in order — if only three fit this week, start from the top and we'll pick up the rest next week.
For now, could you scope the first request for me? I'd like to see it broken down in a way that shows me trend over the last several months, not just a single total — I want to catch whether we're improving or falling behind.
Let me know if any of these need to be split further once you see what the data looks like.
Thanks, Ines
The analyst · week 1, night 3, request 2 of 3
Report 1's big finding: all 3 of the long-overdue DSARs are status='rejected' yet have completed_at = NULL — my original monthly report (night 1) treated 'completed_at IS NULL' as the sole "still open" signal, which may be wrongly counting rejected (i.e., actually-decided) requests as backlog. Before I hand Ines a number, I need to know whether 'rejected' is a systemic gap (completed_at never set on rejections) or an isolated failure on these 3 — that reshapes the whole answer to her question 1, so it's the top priority tonight. Report 3 (retention policy inventory) was dominated by one audit_log policy repeated per tenant and got truncated at 50 of 720 rows before showing any other entity_table — I need a properly aggregated view of what policies actually exist before I can check reality against them (item 4). With only this night and one more left, I'm also opening item 5 (legal holds) tonight since it looks like a single, self-contained report I can likely close in one shot, leaving night 4 free for the retention actual-vs-policy comparison and any remaining loose ends.
The engineer · 1 dry run on the empty schema, then the submission
SELECT t0.entity_schema AS entity_schema, t0.entity_table AS entity_table, t0.retention_days AS retention_days, t0.action_on_expiry AS action_on_expiry, COUNT(DISTINCT t0.tenant_id) AS tenant_count, COALESCE(SUM(CASE WHEN t0.is_active THEN 1 ELSE 0 END), 0) AS active_count, COALESCE(SUM(CASE WHEN t0.last_run_at IS NULL THEN 1 ELSE 0 END), 0) AS never_run_count FROM retention_policies t0 GROUP BY t0.entity_schema, t0.entity_table, t0.retention_days, t0.action_on_expiry ORDER BY t0.entity_table ASC, tenant_count DESC, t0.entity_schema ASC, t0.retention_days ASC, t0.action_on_expiry ASC
“Query compiles cleanly. Submitting.”
“Submitted. The report groups retention_policies by (entity_schema, entity_table, retention_days, action_on_expiry), with tenant_count as the distinct tenant count per combination, and active_count / never_run_count as row-level counts within that combination — flagged in the note since a tenant's active/last_run status could vary even when the days/action match.”
As Priyanka Desai saw it, from the small dataset the agents worked on
entity_schema | entity_table | retention_days | action_on_expiry | tenant_count | active_count | never_run_count --------------+----------------------+----------------+------------------+--------------+--------------+---------------- audit | audit_log | 730 | archive | 120 | 120 | 9 comms | email_log | 730 | delete | 120 | 0 | 120 analytics | events | 1095 | delete | 120 | 120 | 9 ops | job_runs | 90 | delete | 120 | 120 | 9 analytics | page_views | 1095 | delete | 120 | 120 | 9 ops | system_health_checks | 35 | delete | 120 | 120 | 9 (6 rows)
The memo and the queries that followed; links found by title, so inferred
Later queries that build on this report:
It builds on:
Changed only where the benchmark needs the same result on every system
SELECT t0.entity_schema AS entity_schema, t0.entity_table AS entity_table, t0.retention_days AS retention_days, t0.action_on_expiry AS action_on_expiry, COUNT(DISTINCT t0.tenant_id) AS tenant_count, COALESCE(SUM(CASE WHEN t0.is_active THEN 1 ELSE 0 END), 0) AS active_count, COALESCE(SUM(CASE WHEN t0.last_run_at IS NULL THEN 1 ELSE 0 END), 0) AS never_run_countFROM retention_policies t0GROUP BY t0.entity_schema, t0.entity_table, t0.retention_days, t0.action_on_expiryORDER BY t0.entity_table ASC, tenant_count DESC, t0.entity_schema ASC, t0.retention_days ASC, t0.action_on_expiry ASC t0.entity_table ASC NULLS LAST, tenant_count DESC NULLS FIRST, t0.entity_schema ASC NULLS LAST, t0.retention_days ASC NULLS LAST, t0.action_on_expiry ASC NULLS LAST
SELECT t0.entity_schema AS entity_schema, t0.entity_table AS entity_table, t0.retention_days AS retention_days, t0.action_on_expiry AS action_on_expiry, COUNT(DISTINCT t0.tenant_id) AS tenant_count, COALESCE(SUM(CASE WHEN t0.is_active THEN 1 ELSE 0 END), 0) AS active_count, COALESCE(SUM(CASE WHEN t0.last_run_at IS NULL THEN 1 ELSE 0 END), 0) AS never_run_count FROM retention_policies t0 GROUP BY t0.entity_schema, t0.entity_table, t0.retention_days, t0.action_on_expiry ORDER BY t0.entity_table ASC NULLS LAST, tenant_count DESC NULLS FIRST, t0.entity_schema ASC NULLS LAST, t0.retention_days ASC NULLS LAST, t0.action_on_expiry ASC NULLS LAST
The agents' own records, as the role play wrote them; only the personal data of the person who ran it is redacted
Report request from Priyanka Desai (analyst for the Data Protection Officer): Title: Retention policy landscape: distinct rules by entity table Question: What retention rules actually exist across entity tables, collapsing the one-row-per-tenant duplication, so I can see real coverage and variation? Grain: one row per distinct combination of (entity_schema, entity_table, retention_days, action_on_expiry) Columns: - entity schema - entity table - retention days - action on expiry - tenant count using this exact combination - active count (is_active = true) - never-run count (last_run_at is null) Details: Source: retention_policies. Group by (entity_schema, entity_table, retention_days, action_on_expiry) instead of listing one row per tenant, since last night's report showed the same audit_log/730/archive combination repeated across ~120 tenants and got truncated before reaching other entity tables. This should surface every entity table that has a policy (likely a handful: audit_log, access_log, data_exports, consent_records, etc.) and flag any table where retention_days or action_on_expiry varies across tenants. Order by entity_table, then tenant_count descending. Check your query with the warehouse's dry_run tool, then hand it in with submit.
dry_runSELECT t0.entity_schema AS entity_schema, t0.entity_table AS entity_table, t0.retention_days AS retention_days, t0.action_on_expiry AS action_on_expiry, COUNT(DISTINCT t0.tenant_id) AS tenant_count, COALESCE(SUM(CASE WHEN t0.is_active THEN 1 ELSE 0 END), 0) AS active_count, COALESCE(SUM(CASE WHEN t0.last_run_at IS NULL THEN 1 ELSE 0 END), 0) AS never_run_count FROM retention_policies t0 GROUP BY t0.entity_schema, t0.entity_table, t0.retention_days, t0.action_on_expiry ORDER BY t0.entity_table ASC, tenant_count DESC, t0.entity_schema ASC, t0.retention_days ASC, t0.action_on_expiry ASC
STATUS: COMPILES (dry run on the empty schema, no data read) COLUMNS: entity_schema, entity_table, retention_days, action_on_expiry, tenant_count, active_count, never_run_count
submitSELECT t0.entity_schema AS entity_schema, t0.entity_table AS entity_table, t0.retention_days AS retention_days, t0.action_on_expiry AS action_on_expiry, COUNT(DISTINCT t0.tenant_id) AS tenant_count, COALESCE(SUM(CASE WHEN t0.is_active THEN 1 ELSE 0 END), 0) AS active_count, COALESCE(SUM(CASE WHEN t0.last_run_at IS NULL THEN 1 ELSE 0 END), 0) AS never_run_count FROM retention_policies t0 GROUP BY t0.entity_schema, t0.entity_table, t0.retention_days, t0.action_on_expiry ORDER BY t0.entity_table ASC, tenant_count DESC, t0.entity_schema ASC, t0.retention_days ASC, t0.action_on_expiry ASC
Submitted to tonight's batch. Your work on this request is done.