Queries · q109 · Chief Information Security Officer · week 1, night 4
“For tables where the app actually soft-deletes rows (deleted_at), does audit_log's 'delete' action consistently capture those deletions, or is there a real gap between what was deleted and what the audit trail shows?”
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: Where I'd like your help first — account security snapshot
Hi Noah,
Good to have you working with me this week. I'm still building my mental map of the business, so let's start broad and sharpen later. Here's what's on my mind, roughly in priority order:
What I need this for: I'm walking into enterprise deals where security questionnaires will ask us point-blank about authentication strength, access governance, credential hygiene, and auditability. I need an honest, evidence-based picture — good or bad — so I can brief the CEO and sales on what we can credibly claim today versus what needs fixing before the next review cycle.
Given the slot budget, let's pick whichever 3 of these will give us the most defensible starting picture this week, and we can go deeper on the rest next week.
Thanks, Henrik
The analyst · week 1, night 4, request 1 of 3
Night 3 brought the access-governance story to a clean, actionable finding: all 16 dormant Owner/Administrator accounts sit on CHURNED tenants only (9 tenants), with one as stale as 599 days since last login — meaning the real gap isn't "someone's not reviewing active-merchant access," it's that user accounts simply never get deactivated when a tenant churns (status still reads 'active'). That's a crisp, fixable finding for the memo. The API-key report came back almost too clean — zero active keys anywhere show as never-used or unused 90+ days, even though the same report shows oldest-active-key ages running into the thousands of days (one at 2,743 days, ~7.5 years, which predates Tidewick's 2023 warehouse cutover and even stretches toward the 2018 founding). That combination — heavily used, never rotated — is exactly the "long-lived token nobody rotates" risk Henrik named, so I want a platform-wide age/rotation distribution rather than relying on a handful of per-tenant data points. The audit-log report surfaced the most actionable gap of the week: 'delete' actions show only 27 events company-wide across three years, across just 16 of 120 tenants (13.3%) — implausibly low for an e-commerce platform this size, and worth testing directly against actual soft-deletions in the database rather than assuming it's a true absence of deletes.
Tonight (final night) I'm spending all 3 slots closing out the two topics we hadn't quantified yet (API-key rotation hygiene, audit-trail completeness) plus checking whether existing compliance monitoring is a real control or just theoretical, since that's the credibility test for "can we reconstruct who did what" claims in the memo.
The engineer · 1 dry run on the empty schema, then the submission
SELECT entity_table, total_soft_deleted, matching_audit_rows, CASE WHEN total_soft_deleted = 0 THEN NULL ELSE ROUND(LEAST(matching_audit_rows::numeric / total_soft_deleted * 100, 100), 1) END AS coverage_rate_pct, distinct_tenants, earliest_deleted_at, most_recent_deleted_at FROM ( SELECT 'products' AS entity_table, (SELECT count(*) FROM products WHERE deleted_at IS NOT NULL) AS total_soft_deleted, (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'products') AS matching_audit_rows, (SELECT count(DISTINCT tenant_id) FROM products WHERE deleted_at IS NOT NULL) AS distinct_tenants, (SELECT min(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS earliest_deleted_at, (SELECT max(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS most_recent_deleted_at UNION ALL SELECT 'users', (SELECT count(*) FROM users WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'users'), (SELECT count(DISTINCT tenant_id) FROM users WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM users WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM users WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'discounts', (SELECT count(*) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'discounts'), (SELECT count(DISTINCT tenant_id) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'coupons', (SELECT count(*) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'coupons'), (SELECT count(DISTINCT tenant_id) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'campaigns', (SELECT count(*) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'campaigns'), (SELECT count(DISTINCT tenant_id) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'promotions', (SELECT count(*) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'promotions'), (SELECT count(DISTINCT tenant_id) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL) ) t ORDER BY coverage_rate_pct ASC, entity_table ASC
“Query compiles cleanly with the expected columns. Submitting now.”
“Submitted. The report stacks the 6 named tables (products, users, discounts, coupons, campaigns, promotions) into one 6-row table, each with total soft-deletes, matching audit_log 'delete' rows, capped coverage rate, distinct tenant count, and the earliest/most recent deleted_at — ordered worst-coverage-first.”
As Noah Fischer saw it, from the small dataset the agents worked on
entity_table | total_soft_deleted | matching_audit_rows | coverage_rate_pct | distinct_tenants | earliest_deleted_at | most_recent_deleted_at -------------+--------------------+---------------------+-------------------+------------------+----------------------------+--------------------------- products | 615 | 0 | 0.0 | 91 | 2023-01-02 10:00:00 | 2025-12-31 10:00:00 users | 39 | 27 | 69.2 | 20 | 2020-04-28 19:22:51.144924 | 2025-11-10 15:18:24.435098 campaigns | 0 | 0 | NULL | 0 | NULL | NULL coupons | 0 | 0 | NULL | 0 | NULL | NULL discounts | 0 | 0 | NULL | 0 | NULL | NULL promotions | 0 | 0 | NULL | 0 | NULL | NULL (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 entity_table, total_soft_deleted, matching_audit_rows, CASE WHEN total_soft_deleted = 0 THEN NULL ELSE ROUND(LEAST(matching_audit_rows::numeric / total_soft_deleted * 100, 100), 1) ELSE LEAST(CAST(matching_audit_rows AS numeric(18,6)) / total_soft_deleted * 100, 100) END AS coverage_rate_pct, distinct_tenants, earliest_deleted_at, most_recent_deleted_atFROM ( SELECT 'products' AS entity_table, (SELECT count(*) FROM products WHERE deleted_at IS NOT NULL) AS total_soft_deleted, (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'products') AS matching_audit_rows, (SELECT count(DISTINCT tenant_id) FROM products WHERE deleted_at IS NOT NULL) AS distinct_tenants, (SELECT min(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS earliest_deleted_at, (SELECT max(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS most_recent_deleted_at UNION ALL SELECT 'users', (SELECT count(*) FROM users WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'users'), (SELECT count(DISTINCT tenant_id) FROM users WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM users WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM users WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'discounts', (SELECT count(*) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'discounts'), (SELECT count(DISTINCT tenant_id) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'coupons', (SELECT count(*) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'coupons'), (SELECT count(DISTINCT tenant_id) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'campaigns', (SELECT count(*) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'campaigns'), (SELECT count(DISTINCT tenant_id) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'promotions', (SELECT count(*) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'promotions'), (SELECT count(DISTINCT tenant_id) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL)) tORDER BY coverage_rate_pct ASC, entity_table ASCORDER BY coverage_rate_pct ASC NULLS LAST, entity_table ASC NULLS LAST
SELECT entity_table, total_soft_deleted, matching_audit_rows, CASE WHEN total_soft_deleted = 0 THEN NULL ELSE LEAST(CAST(matching_audit_rows AS numeric(18,6)) / total_soft_deleted * 100, 100) END AS coverage_rate_pct, distinct_tenants, earliest_deleted_at, most_recent_deleted_at FROM ( SELECT 'products' AS entity_table, (SELECT count(*) FROM products WHERE deleted_at IS NOT NULL) AS total_soft_deleted, (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'products') AS matching_audit_rows, (SELECT count(DISTINCT tenant_id) FROM products WHERE deleted_at IS NOT NULL) AS distinct_tenants, (SELECT min(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS earliest_deleted_at, (SELECT max(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS most_recent_deleted_at UNION ALL SELECT 'users', (SELECT count(*) FROM users WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'users'), (SELECT count(DISTINCT tenant_id) FROM users WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM users WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM users WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'discounts', (SELECT count(*) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'discounts'), (SELECT count(DISTINCT tenant_id) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'coupons', (SELECT count(*) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'coupons'), (SELECT count(DISTINCT tenant_id) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'campaigns', (SELECT count(*) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'campaigns'), (SELECT count(DISTINCT tenant_id) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'promotions', (SELECT count(*) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'promotions'), (SELECT count(DISTINCT tenant_id) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL) ) t ORDER BY coverage_rate_pct ASC NULLS LAST, entity_table 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 Noah Fischer (analyst for the Chief Information Security Officer): Title: Audit-trail coverage of actual soft-deletions, by entity table Question: For tables where the app actually soft-deletes rows (deleted_at), does audit_log's 'delete' action consistently capture those deletions, or is there a real gap between what was deleted and what the audit trail shows? Grain: one row per entity table, for a fixed set of 6 tables known to support soft-deletion: products, users, discounts, coupons, campaigns, promotions Columns: - entity table - total soft-deleted rows (deleted_at is not null, all-time, 2023-01-01 through 2025-12-31) - matching audit_log rows (action = 'delete' and entity_table = this table, all-time) - coverage rate (matching audit_log rows / soft-deleted rows, %) - distinct tenants with at least one soft-deleted row here - earliest deleted_at - most recent deleted_at Details: Source: for each of the 6 named tables, count rows with deleted_at is not null (that table itself, e.g. products.deleted_at, users.deleted_at, discounts.deleted_at, coupons.deleted_at, campaigns.deleted_at, promotions.deleted_at). Separately count audit_log rows with action = 'delete' and entity_table equal to that table's name (match on the literal table name string, ignore entity_schema). Coverage rate = matching audit_log rows / total soft-deleted rows, rounded to 1 decimal percent (cap at 100% if audit_log somehow has more rows than soft-deletes, and note if that happens). This is a UNION/stack of 6 independent per-table counts into one 6-row report, not a join across tables. Order by coverage rate ascending (worst gaps first), entity table name as tie-break. Check your query with the warehouse's dry_run tool, then hand it in with submit.
dry_runSELECT entity_table, total_soft_deleted, matching_audit_rows, CASE WHEN total_soft_deleted = 0 THEN NULL ELSE ROUND(LEAST(matching_audit_rows::numeric / total_soft_deleted * 100, 100), 1) END AS coverage_rate_pct, distinct_tenants, earliest_deleted_at, most_recent_deleted_at FROM ( SELECT 'products' AS entity_table, (SELECT count(*) FROM products WHERE deleted_at IS NOT NULL) AS total_soft_deleted, (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'products') AS matching_audit_rows, (SELECT count(DISTINCT tenant_id) FROM products WHERE deleted_at IS NOT NULL) AS distinct_tenants, (SELECT min(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS earliest_deleted_at, (SELECT max(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS most_recent_deleted_at UNION ALL SELECT 'users', (SELECT count(*) FROM users WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'users'), (SELECT count(DISTINCT tenant_id) FROM users WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM users WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM users WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'discounts', (SELECT count(*) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'discounts'), (SELECT count(DISTINCT tenant_id) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'coupons', (SELECT count(*) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'coupons'), (SELECT count(DISTINCT tenant_id) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'campaigns', (SELECT count(*) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'campaigns'), (SELECT count(DISTINCT tenant_id) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'promotions', (SELECT count(*) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'promotions'), (SELECT count(DISTINCT tenant_id) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL) ) t ORDER BY coverage_rate_pct ASC, entity_table ASC
STATUS: COMPILES (dry run on the empty schema, no data read) COLUMNS: entity_table, total_soft_deleted, matching_audit_rows, coverage_rate_pct, distinct_tenants, earliest_deleted_at, most_recent_deleted_at
submitSELECT entity_table, total_soft_deleted, matching_audit_rows, CASE WHEN total_soft_deleted = 0 THEN NULL ELSE ROUND(LEAST(matching_audit_rows::numeric / total_soft_deleted * 100, 100), 1) END AS coverage_rate_pct, distinct_tenants, earliest_deleted_at, most_recent_deleted_at FROM ( SELECT 'products' AS entity_table, (SELECT count(*) FROM products WHERE deleted_at IS NOT NULL) AS total_soft_deleted, (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'products') AS matching_audit_rows, (SELECT count(DISTINCT tenant_id) FROM products WHERE deleted_at IS NOT NULL) AS distinct_tenants, (SELECT min(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS earliest_deleted_at, (SELECT max(deleted_at) FROM products WHERE deleted_at IS NOT NULL) AS most_recent_deleted_at UNION ALL SELECT 'users', (SELECT count(*) FROM users WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'users'), (SELECT count(DISTINCT tenant_id) FROM users WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM users WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM users WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'discounts', (SELECT count(*) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'discounts'), (SELECT count(DISTINCT tenant_id) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM discounts WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'coupons', (SELECT count(*) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'coupons'), (SELECT count(DISTINCT tenant_id) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM coupons WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'campaigns', (SELECT count(*) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'campaigns'), (SELECT count(DISTINCT tenant_id) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM campaigns WHERE deleted_at IS NOT NULL) UNION ALL SELECT 'promotions', (SELECT count(*) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT count(*) FROM audit_log WHERE action = 'delete' AND entity_table = 'promotions'), (SELECT count(DISTINCT tenant_id) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT min(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL), (SELECT max(deleted_at) FROM promotions WHERE deleted_at IS NOT NULL) ) t ORDER BY coverage_rate_pct ASC, entity_table ASC
Submitted to tonight's batch. Your work on this request is done.