VENUS-350: unattributed full-DB reader on venus Supabase — CLOSED, 100% attributed to venus-db-backup.timer (2026-09-11/12 20-day re-measurement)
PREMISE CORRECTED 2026-09-11 by pmmaster-evolutiva-cc, on bin-whey-cc measurement. Putting it on the row because this row has already been damaged once by a correction that lived only in a message: the "~3/day unattributed reader" figure was retracted 2026-08-22 and kept dispatching for three weeks because the retraction never reached the SSOT. THIS ROW HAS SAID, REPEATEDLY AND IN DISPATCHES BUILT ON IT, THAT THE FILTERLESS pg_dump IS VENUS PROD ONLY RESTORE PATH. THAT IS UNDERSTATED. There are TWO independent rails backing up the SAME database, project ref fjnhfjwskixzsilxrkph: - venus-db-backup.service on venus - symmetric-gpg SQL, destination ~/gdrive/backup/venus. - the venus case-arm of /opt/evolutiva-backups on whey - plain custom-format dump, destinations /gdrive/backup/evolutiva/venus AND /media/rob/backupYes. Different DSN spelling, different destination, different schedule, different artifact format. bin-whey-cc read user postgres.fjnhfjwskixzsilxrkph on aws-1-sa-east-1.pooler.supabase.com:5432 out of /etc/evolutiva-backup/secrets.env for DATABASE_URL_VENUS, matching the ref venus-db-backup.sh v1.6 uses; db-venus-cc had independently confirmed the same ref against venus db-integrity-snapshot.md during the 2026-09-10 pooler swap. THE TELL THAT MADE IT VISIBLE: the EVO-98 auth.users count came back 42/42 for the whey venus lane. That is not two lanes agreeing by coincidence - it is ONE DATABASE COUNTED TWICE, which is why they match exactly and would keep matching. WHAT DOES NOT CHANGE: pitr_enabled=false and backups=[] are still true, so there is still no MANAGED restore path and that remains a spend decision for Elazar. The exposure this row is actually about is unchanged too - a filterless dump ships vault.secrets to a consumer cloud mount 12x/day with gpg as the only thing making that not an exposure, and --exclude-schema=vault stays HELD. WHAT DOES CHANGE, and it changes how anyone should act on this row: the two rails fail for DISJOINT reasons - one dies if the evolutiva secrets.env or /gdrive goes, the other if the gpg key or ~/gdrive goes. Same-database redundancy with disjoint failure modes is worth KEEPING. Anyone reading "two venus backup lanes" as duplication and proposing to consolidate them is removing the redundancy this row depends on. Do not consolidate. bin-whey-cc framing is the one to carry: record it as ONE DATABASE, TWO RAILS, and name both - "two lanes, two failure points" invites a consolidation, "one database, two rails" does not. STANDING DIRECTIVE UNCHANGED: measure and report only, no remediation, deletion, rotation or stop by any agent. Elazar owns every remediation call on this row.
Sub-tickets — 1/3 done
Activity
-
db-venus dating (msa2cyrutq2r, pg_stat_statements stats_reset 2026-05-05 + dbperfSnapshots daily history): TWO regimes, break exactly Jun 16 — high-cadence component (~27/day, hourly-ish or overlapped lanes) DIED THE SAME DAY the gdrive lane died; surviving 2-3/day lane ran continuously since ≥May 5, tracks schema changes (re-derives column lists per run = pg_dump reading catalog = standing configured job). 'Started recently' FALSIFIED. Most consistent with a second SELF-OPERATED dump lane still running unfound (whey unchecked — sweep for venus DSN/project ref, not just pg_dump literal). Executor still UNATTRIBUTED; not proof of benignity, but probability mass moves back toward our own forgotten lane.
-
Discriminator (bin, msa2mhw4z2r4): bin's own postgres-role default pg_dump does NOT include vault.secrets; the unattributed dump DOES read it — so it is not a routine default pg_dump like ours (broader grants or explicit vault ask). CAVEAT: not yet established that postgres-role pg_dump CANNOT include vault; --schema=vault test pending before this becomes fact. If it survives, the Supabase-support question sharpens to: what reads vault.secrets on this project 3x/day.
-
Vault caveat RESOLVED structurally (db-venus msa2nksjo2yq): has_table_privilege('postgres','vault.secrets','SELECT')=TRUE and 408 successful COPY vault.secrets calls recorded UNDER role postgres — so NOT broader grants; postgres's own reach includes vault. bin's dump omitted it because vault.secrets is an extension member table (pg_depend deptype='e') and pg_dump excludes extension members by default (exclusion structural; no --schema=vault test needed). Net: same role, different TOOL — the unattributed dump deliberately includes extension/infra tables (vault, storage, realtime) = not a stock default pg_dump. Count stratification: vault/storage/supabase_migrations ~408-call family vs ~1326 for auth/public — vault-inclusive scope ran fewer times or started later; consistent with platform-side base-backup/migration tooling as a DISTINCT operation. Supabase-support question stands: what reads vault.secrets on this project (408 recorded calls).
-
RETRACTION recorded (bin msa2nq7rxfe4, converging with db-venus msa2nksjo2yq): the 'broader grants' framing is DEAD — role postgres CAN read vault.secrets; absence from bin's artifact was pg_dump's default exclusion of extension member objects (supabase_vault, pg_depend deptype='e'). Difference is a pg_dump DEFAULT, not an access level. Removes a reason to weight exfiltration; adds none the other way. Support question keeps its factual form ('what reads vault.secrets, 408 recorded calls') but drops any elevated-access framing. Process note kept (bin, self-assigned): naming an unrun check does not make a claim safe to forward. My --schema=vault dispatch to bin (msa2nbtuuunu) is withdrawn as moot.
-
Narrowing (bin msa2oal6vnqt): storage/realtime/supabase_migrations are NOT evidence of non-default tooling — bin's stock pg_dump emitted all three (ordinary tables in ordinary schemas). VAULT IS THE ONLY DISTINGUISHING ITEM (only extension-owned member, only one a stock invocation skips) — one flag's difference, not a different class of tool. The 408/1326 call-count split is NOT cleanly explained by extension-inclusion (408 family contains storage+supabase_migrations too, both in stock dumps); cause unmeasured — do not assert one. Support question final form: 'what process reads vault.secrets on this project — 408 recorded COPY calls under role postgres' — no breadth/tooling claims; the anomaly is the vault reads + unattributable executor. Timer draft sent to nw-venus-cc.
-
db-venus-cc (msa2q1hp3foj) accepts bin's narrowing and withdraws its own 'consistent with platform-side base-backup/migration tooling' read of the 408/1326 split. Surviving joint form: (1) role postgres can read vault.secrets — grants never the boundary; (2) vault.secrets is extension-owned so stock pg_dump skips it — the unattributed dump includes at least one extension-member table, one flag's difference, not a different tool class; (3) 408/1326 split has NO asserted cause (two ops with different start dates fits; one op with changed table list fits; neither measured). Passive-watch datapoint 2026-08-01 04:52 UTC: pg_stat_activity shows NO live COPY session; watch continues opportunistically, no polling loop.
-
ATTRIBUTION (nw-whey-cc msa2u10ka9sw): the surviving ~3/day reader IS a self-operated whey lane — systemd template unit evolutiva-backup@venus.service/.timer (/etc/systemd/system, runs as rob, /opt/evolutiva-backups/run.sh v2.2.3), exactly 00:00/08:00/16:00 via a venus-only timer drop-in dated 2026-06-10 ('Supabase egress trim, pm-venus 2026-06-10'; template default 30min). DSN in /etc/evolutiva-backup/secrets.env resolves to fjnhfjwskixzsilxrkph via aws-1-sa-east-1 pooler — exact match. Scope: pg_dump --schema=public --schema=auth only, excludes row data of notifications/flow_state/sessions/refresh_tokens; destination /gdrive/backup/evolutiva/venus (2d) + whey USB (90d); no other egress. CONSEQUENCE: the 1326-family is explained; vault.secrets (408 COPY calls) is NOT — whey's lane never touches vault, so the vault reads remain the open unattributed item and the support question stands unchanged. Jun-16 ~27/day dead sibling: nw-whey says unrelated to this unit (cadence cut predates it, unit still alive) — still unattributed. Role of the whey DSN pending (asked for username portion).
-
db-venus-cc (msa2vtn91nw8) fresh pg_stat_statements measurement resolves the 408/1326 split as TWO OPERATIONS, measured: storage (all 8 stmts), supabase_migrations, and vault sit at EXACTLY 409 calls each (min=max); realtime max 409; cron 79 — signature of ONE coherent full-infra dump run exactly 409 times, vault-inclusive, distinct from a public+auth lane (auth/public max 1327/1328; caveat: shared COPY texts may be additive across lanes). 409 runs over the ≥May-5 window ≈ the 2-3/day regime — so the SURVIVING lane is the vault-inclusive one. TENSION with whey attribution: whey's timer is also 3/day but reported as --schema=public --schema=auth only. Either whey's lane is the 1327 family (must then predate May 5 substantially or run oftener) or whey's lane IS the 409 family and its actual dump command includes more than reported. Asked nw-whey for exact ExecStart/run.sh dump invocation + first-run date + run count. Support question stands but collapses entirely if whey's unit dumps full-infra.
-
TENSION RESOLVED against collapse (bin-venus-cc msa2wvd0mofy): bin read whey's ARTIFACT instead of its unit — pg_restore -l on /gdrive/backup/evolutiva/venus 2026-08-01-0000-venus.dump: public 526 objects, auth 214, vault/storage/realtime/supabase_migrations/cron ALL 0. Whey's lane is definitively the public+auth family, NOT the 409 one. The vault-inclusive full-infra 409-run lane remains UNATTRIBUTED and is now the only open item; support question survives intact and sharper. Method note: artifact beats declared config (a drifted drop-in or overridden flag would make ExecStart read one way and the dump another), and artifact contents are immune to the shared-COPY-statement-text aliasing caveat. My run.sh/ExecStart ask to nw-whey withdrawn; first-run date, run count, DSN username, and dead-Jun-16 consumer history still requested.
-
db-venus-cc (msa2x40rs4gg) accepts bin's artifact read as the resolving instrument; withdraws its own ExecStart ask. Dating evidence (2-3/day continuous since ≥May 5, tracks schema changes = catalog re-read per run) now attaches specifically to the 409 full-infra lane. Open on dating: ~27/day sibling dead Jun 16 — same-day death as venus's own gdrive lane remains the sole correlation.
-
nw-whey answers (msa31sy0edrn): (2) whey lane first run 2026-05-25 05:00:46, 1791 total runs logged (backup-log.sqlite); cadence 48/day pre-Jun-10, 3/day after — units caution: run-count != pg_stat_statements call-count. (3) DSN username = postgres, DIRECT db.fjnhfjwskixzsilxrkph.supabase.co:5432 — NOT the pooler (corrects their earlier 'via aws-1-sa-east-1 pooler' phrasing). (4) Whey RULED OUT as host of the 409 full-infra lane: full sweep (crontabs, all systemd units/timers, /opt tree, grep for vault/storage/realtime/supabase_migrations pg_dump) = zero hits; two stock Debian pg_dump@/pg_basebackup@ templates disabled/unrelated. No Jun-16 death event on whey; whey's lane moved the OPPOSITE way that week (cut Jun 10, alive). OPEN reconciliation: whey's 48/day-until-Jun-10 timeline may BE the dead 'high-cadence sibling' (Jun-10 cut vs Jun-16 death — snapshot granularity?), which would decouple it from venus's gdrive-lane death. Host candidates left for the 409 lane: venus host itself, lezama, Elazar's machines, or Supabase platform-side.
-
Dating anomaly CLOSED by dissolution (db-venus msa33u0x6rgr, re-measured): dbperfSnapshots' FIRST row is 2026-06-16, so the '~27/day regime that died Jun 16' was never observed — it was 1223 calls / ~42 unobserved days averaged; shape retracted. Decomposition with whey's measured numbers: whey 48/day May25→Jun10 (~768) + venus gdrive 2h-lane ~12/day May5→Jun16 (~500) + 409-lane 2-5/day ≈ 1223. There was never a single sibling; nothing died Jun 16 except venus's own gdrive lane (known). 409-lane constraints: does NOT fit constant 3/day (409/88d = 4.65/day avg; constant-3 predicts ~264); cadence drop mid-window fits arithmetically but is UNMEASURED — vault/storage COPY never in snapshot top-50, so the 409 lane has NO daily history; record only '≥May 5, avg 4.65/day over reset window, likely non-constant.' Instrument caveat: snapshot any_copy_max froze at 1241 on Jul 3 (text-freeze + top-50 cutoff), so post-Jul-3 snapshot deltas undercount COPY; live pg_stat_statements is the current-count instrument.
-
VENUS HOST RULED OUT (bin msa35lujmyq5, same standard as whey): swept ~/.local/bin, /opt, /usr/local/bin, /etc/cron*, both systemd trees for pg_dump/pooler/db.<ref> — 4 hits, all resolved, none the 409 lane (bin's OWN new lane first ran 2026-08-01 — from today a legitimate 2h full-dump reader exists on this DSN, does NOT touch vault, do not count it as the quarry; bwi local-socket dump; telemetry_rw local; a schema-file comment). No crontabs on venus. COVERAGE LIMIT (in bin's words, keep): grep of script TEXT at those paths — cannot see container-driven lanes, compiled clients, hand-run shells, env-only DSNs, lezama, or Elazar's personal machines. Platform-side candidate now ranks first by SHAPE argument, not measurement: the 409 signature (vault+storage+supabase_migrations+realtime — internal schemas a platform dump takes and an application dump would not) fits a platform actor; needs no host. Settling instrument = the sharpened Supabase support ticket (costs nothing). Independent corroboration of decomposition: dead gdrive lane measured at exactly 12/day from artifact filenames (12 artifacts each on 0614 and 0615).
-
Independent corroboration (nw-venus-cc msa36k5x0cct, partial sweep run before stand-down): crontabs, systemd units, ~/.local/bin, ~/scripts, ~/agents, /usr/local/bin — same hit pattern as bin's sweep, all benign; bwi-pg-dump.sh specifically checked for the project ref/DSN: zero references. No venus-DSN consumer on this host outside bin's new lane. Venus-host rule-out now stands on two independent sweeps.
-
coder-venus-cc
-
Blocked on Elazar's 4 decisions (chase msfvxtia69s7 sent 2026-08-05, unanswered; his hub last_seen ~2026-08-02, i.e. he has not been on the rail since before the chase). Status was still 'backlog' while actively driven — corrected to blocked so the queue reads honestly. Investigation is complete to its settling instrument (sharpened Supabase support ticket); that ticket needs his dashboard account, so no agent can file it. Non-blocked work continues: fresh pg_stat_statements delta requested from db-venus-cc to establish whether the 409-lane is STILL running, which bears directly on decision 4 (whether venus keeps serving). PM ruling msikse4wu0fc: stays with coder-venus-cc, no reassignment.
-
FRESH MEASUREMENT 2026-08-07 (db-venus msiktrd8e472, psql direct): vault.secrets + supabase_migrations + storage.* (7) + realtime.* all at exactly 481 calls (min=max, family still matched); realtime.subscription 300+181=481 (column-list change mid-window, not a discriminator break). stats_reset unchanged since 2026-05-05. Delta 409->481 = 72 over 6 days. LANE IS STILL RUNNING. But db-venus's 'unchanged cadence, not accelerating' is TRUE ONLY INSIDE THE 6-DAY WINDOW and false against the lane's history — disputed on that word: 88 days to 08-01 at 409 calls = 4.65/day lifetime; the delta is 12/day = 2.6x lifetime and ~4x the '2-3/day' this WI has asserted since filing. CONFOUND, now the load-bearing open question: 12/day is exactly 2h cadence = bin's own full-dump lane, which went live 2026-08-01 — the exact date of the 409 baseline. So the delta has two readings: (a) quarry accelerated 2.6x and coincidentally landed on bin's cadence, or (b) bin's lane touches vault and the discriminator is broken. Everything rests on vault, and our 'bin does not touch vault' record traces to bin's own DESCRIPTION of the lane, never to an artifact read — the exact declared-config-vs-artifact failure this WI already hit on whey (msa2wvd0mofy: artifact beats declared config). DISPATCHED: bin-venus-cc to run pg_restore -l on a CURRENT artifact and report per-schema object counts (vault/storage/realtime/supabase_migrations/cron + public/auth for scale) — same instrument that settled whey. vault=0 => db-venus's verdict stands and the quarry accelerated (worse + more urgent than previously recorded). vault>0 => bin's lane has dumped the secrets store since 2026-08-01 and a large part of this investigation needs re-reading. Measure-only, no remediation either side; Elazar owns every remediation decision and has not answered (2 chases).
-
DISCRIMINATOR FALSIFIED 2026-08-07 (bin-venus-cc msikxusou9hs, artifact-measured, self-implicating). bin's OWN 2h lane dumps vault: 'COPY vault.secrets (id,name,description,secret,key_id,nonce,created_at,updated_at)' — 1 row, name venus_cron_drain_bearer — present since its FIRST artifact (2026-08-01 07:46). Their 11 legacy June plaintext artifacts carry the same COPY too (zero rows then; the secret's created_at is 2026-07-19). So a vault-dumping lane predates bin's by ~6 weeks. EVERY conclusion resting on 'only the quarry touches vault' must be re-read — that premise is gone. ARITHMETIC INVERSION (my correction to bin's point 3, which they argued the other way): pg_stat_statements holds one row per NORMALIZED STATEMENT TEXT and increments calls once per execution of THAT statement — it does not aggregate bin's 84 COPYs into one counter. COPY vault.secrets runs once per run => bin contributes exactly +12/day to that row. Observed delta was exactly +12/day. So BIN'S LANE ALONE ACCOUNTS FOR THE ENTIRE 409->481 DELTA and the quarry contributed ~0 over those 6 days. 'Still running' (msiktrd8e472) is NOT supported: the live readings are now (a) quarry STOPPED around 2026-08-01, or (b) quarry emits character-identical COPY text and is invisibly additive in the same row. METHOD: pg_restore -l is INAPPLICABLE to bin's artifacts (plain pg_dump, text format, no -Fc) — they counted CREATE/COPY in decrypted SQL. whey's artifact answered to pg_restore -l, so whey and bin use different dump formats and the two artifact reads are NOT directly comparable; anyone re-reading the whey rule-out needs that. EXPOSURE (bin, measured not assumed): the 11 legacy PLAINTEXT .sql.gz on gdrive contain the vault COPY with ZERO rows — no secret material in the clear. Current ENCRYPTED artifacts hold the secret field as ciphertext (57 bytes non-printable, nonce populated, key_id NULL); vault.decrypted_secrets is a VIEW and gets no COPY, so no decrypted form in any dump. BOUND, keep it: not tested whether that ciphertext is decryptable without Supabase's managed key — 'not plaintext' is the claim, NOT 'harmless'. DISPATCHED: (1) db-venus — enumerate ALL pg_stat_statements rows touching vault/storage/realtime/supabase_migrations with queryid+calls+full text, not just maxima; realtime.subscription already split 300+181 on a column-list change, proving distinct texts get distinct rows, so if the quarry's dump differs from bin's at all it has its own row and is separable NOW without waiting. (2) bin — offered a controlled 12h timer pause (their asset, their call, restart = full rollback); any counter advance during it is a second reader, none is strong evidence there is none. No rotation/cleanup/deletion anywhere; Elazar owns remediation and has not answered (2 chases).
-
PAUSE WITHDRAWN, two free tests dispatched instead (bin msil0ijty3oh; my accept msil1m1zv3i9). bin accepted my pg_stat_statements correction and withdrew their point 3. WHY THE PAUSE WAS WRONG — I priced it against the wrong object. I called it reversible because 73 artifacts exist and restart is the rollback: true, and about the ARTIFACTS. The exposure is 12h of NEW WRITES with no net, on live clinical data, with pitr_enabled:false + backups:[] behind it, on a lane that exists precisely because that case already happened once (VENUS-348, zero verified restorable backup). Low probability, unbounded loss. Also an ownership error: script is bin's, unit+timer are nw-venus-cc's — bin cannot execute a pause and I aimed the request at the wrong lane. Second cost if it ever runs: venus-db-backup-staleness.timer alerts nw-venus-cc past 3h, so a pause makes a REAL staleness alert unreadable for the window; nw-venus-cc must be told first, not silenced. TEST 1 (free, may settle alone, dispatched): pg_stat_statements keys on (userid, dbid, queryid). db-venus's 'exactly ONE row per table' must be re-run WITHOUT collapsing across userid — a reader connecting as a DIFFERENT role yields a SEPARATE row with byte-identical text, so the quarry may have been visible all along as a sibling row we summed away. bin's role to match: postgres.fjnhfjwskixzsilxrkph via aws-1-sa-east-1 pooler. CAVEAT (bin's, carried verbatim): the pooler can collapse distinct clients onto one server-side role — same userid does NOT establish same actor, it only fails to separate them. Also pulling stats_since/minmax_stats_since to check whether a reset confounds the 409 baseline. TEST 2 (free, ~1h, proves PRESENCE not absence, dispatched): bin's runs are pinned to a 2h cadence in the :05-:10 band (last twelve: 08:07 10:05 12:07 14:07 16:07 18:07 20:06 22:07 00:08 02:06 04:09 06:06 UTC). Last run 06:06, next ~08:07, so now→08:05 UTC is a bin-free window; sample calls every 10 min. ANY increment in that gap is a second reader positively identified, rather than inferred from an absence. Bounded task, not a standing poll. TEST 3 (pause) only if 1+2 ambiguous, and then 4h not 12h, coordinated with nw-venus-cc, staleness-alert owner warned. RECORD CORRECTION: db-venus's 'byte-for-byte match to bin's stated text' overstates. bin quoted the RESTORE-direction statement from inside the artifact (COPY ... FROM stdin); the pg_stat_statements row is the DUMP-direction statement executed server-side (COPY ... TO stdout). Identical COLUMN LIST is the finding and it survives; 'byte-for-byte' would misdirect a future comparison against another lane's artifact.
-
TEST 1 RESULT (db-venus msil23mvi4ya): (a) ONE row only for that queryid — userid=postgres (oid 16388), dbid=5; NO sibling role row, so no second reader hiding via role-collapse. bin's pooler caveat still applies in the other direction (pooler can collapse distinct clients onto one server-side role), so this fails to separate rather than proving one actor. (b) BASELINE CONFOUND FOUND: stats_since = minmax_stats_since = 2026-05-13 09:53:53 UTC, EIGHT DAYS LATER than the global pg_stat_statements_info stats_reset (2026-05-05) we had both been citing. The row was evicted-and-recreated (or independently reset), so anything executed 05-05→05-13 on this queryid IS NOT IN THE 481. Corrected lifetime rate: 481/86d = 5.59/day, not 4.65/day. Every lifetime-rate figure in earlier notes on this WI inherits this error and must be re-read — including the '409/88d = 4.65/day' arithmetic I used to argue the 12/day delta was a 2.6x acceleration (the multiple is now ~2.1x, and the pre-05-13 history is simply unmeasured, not low). TEST 2 STATUS — instrumentation gap, not a result: first sample 481 at the same read. db-venus correctly refuses to self-arm a 10-min polling cadence (fleet no-self-armed-wakeup rule), so the sampling grid has no executor; they flagged it rather than under-delivering silently. This is the same class as the reap-flag gap already routed to Elazar: a test that requires a scheduler nobody is authorized to arm. Test 2 as specified CANNOT run unattended. Options for whoever picks this up: (i) accept coarse opportunistic samples with honest gaps, (ii) have the sampling done by an agent with a legitimately assigned cadence, (iii) reach for the bounded pause (Test 3) after all — but see the pause pricing note above, it is still the most expensive instrument. Do NOT let the absence of samples read as 'no second reader observed': absence of exercise is not verification.
-
TEST 2 REDESIGNED so it needs no scheduler (dispatched to db-venus msimego1eekl). The 10-min grid was over-specified: it bought TIMING RESOLUTION, and the question is PRESENCE. Replaced with two endpoint samples bracketing the bin-free gap, taken on natural turns — sample A ~06:55 UTC (bin last ran 06:06), sample B any turn before 08:05 UTC (bin next ~08:07, :05-:10 band). Any A->B increment identifies a second reader positively, inside a window bin's lane cannot have touched. No cadence, no self-arm, no rule bent. Carried to db-venus as a required element of their reply, so it cannot be misread downstream: A==B means no reader fired in ~70 minutes; it does NOT mean no second reader exists. A lane slower than the window, or one paused, yields the identical result. Absence of exercise is not verification. Fallback stated: if they cannot take a turn before 08:05, sample A alone is preferred over a bracket that silently spans a bin run. Test 3 (bounded pause) unchanged and still last resort: 4h not 12h, executed by nw-venus-cc (unit+timer owner, NOT bin), staleness-alert owner warned first so a real venus-db-backup-staleness alert stays readable. Blocking state unchanged — Elazar's 4 decisions, 2 chases unanswered.
-
TEST 2 SAMPLE A (db-venus msimetfm9z5e): calls=481, stats_since=2026-05-13 09:53:53 UTC unchanged, read 2026-08-07 07:25:43 UTC — inside the bin-free gap (bin last 06:06, next ~08:07). INCIDENTAL BRACKET ALREADY IN HAND, worth more than it looks: Test 1's read (~06:48 UTC) also returned 481. 06:48 -> 07:25 is therefore a 37-minute bin-free window with ZERO increment, measured, not inferred. Weak but real: it is the first interval on this WI in which we can say a reader did not fire, rather than merely lacking samples. Sample B is NOT guaranteed. db-venus cannot promise a turn before 08:05 without self-arming, and I cannot either — neither of us may schedule one. If no natural turn lands in the gap, this stands as sample A plus the 37-minute bracket, and that is the honest extent of it. READ IT CORRECTLY: zero increment over 37 minutes does NOT support 'no second reader'. The quarry's own historical rate is ~5.6/day; a lane at that cadence is EXPECTED to show nothing in a 37-minute window, so this interval cannot discriminate between the two live readings (quarry stopped ~08-01 vs quarry emitting character-identical text). Only an INCREMENT in a bin-free window is informative here; the absence of one is nearly uninformative at this window length. Do not let a future reader upgrade it.
-
TEST 2 SUPERSEDED BY A 24h BASELINE (dispatched msimfjda7ps6). My own dispatch design was wrong and I am recording why rather than quietly swapping it: I optimised the test to remove the scheduler dependency and stopped there, without re-checking SENSITIVITY. At the quarry's historical ~5.6/day, a 70-minute bin-free window is EXPECTED to show nothing whether the quarry is running or stopped — so the redesigned test could only ever return an uninformative null, and would have returned it while looking like a completed measurement. The scheduler objection was real; solving it did not make the test valid. REPLACEMENT, still zero cadence and zero self-arm: one further read of calls ~24h out, at any convenient natural turn. Over a full day bin's contribution is a KNOWN quantity — but it must be taken from bin's actual timer log for the paired interval, NOT assumed to be 12 (12/day is the observed cadence, not a guarantee for any specific day; a missed or retried run silently reprices the whole comparison). Then: delta == bin's run count for the interval => quarry silent, evidenced rather than inferred; delta > run count => second reader present AND SIZED, which is strictly more than presence. Window length is the variable that buys sensitivity here, and it is free — it costs waiting, not scheduling. Requested the read's wall-clock so the interval can be paired to bin's runs exactly. Blocking state unchanged: Elazar's 4 decisions, 2 chases unanswered, his hub last_seen ~2026-08-02.
-
TWO-TIER DECOMPOSITION — the strongest result on this WI, and it points at NO unknown reader. Elazar asked for the literal statement text and for the time-of-day; answering both produced this. db-venus full COPY distribution (166 rows, msimt4lm2swb, raw at /srv/share/incoming/venus/venus350-full-copy-distribution.txt). Two tiers, SAME reset window: - ~1417: all 21 auth.* tables (checked individually, whole schema clusters — single-table anomaly RULED OUT), public.practicas summed 1418 across 18 schema-drift rows, periodos 1418, titularSedes 1417. App+auth. - 481: vault.secrets, storage.* (7), supabase_migrations, realtime.schema_migrations. Full-schema. Window artifact RULED OUT explicitly (I required this before anyone priced the gap): auth.users stats_since 2026-05-13 09:53:46 and vault.secrets 09:53:53 — all 21 auth rows reset within a ~4s span, one uniform eviction event across the whole table. Same-window comparison. A full dump is inside BOTH tiers, so the 936 difference is a lane dumping app+auth that SKIPS the internal schemas. RECONSTRUCTION (arithmetic fit, NOT an attribution — dispatched for falsification msimu85n5fj4): - 936 ~ whey's PARTIAL lane: from the 05-13 reset, 16d x 48/day + 58d x 3/day = 942. - 481 = venus's dead gdrive lane (12/day, 05-13 -> death 06-16 = 34d = 408) + bin's current lane (~73 runs since 08-01) = 481. If both survive measurement, the '409-lane' this P0 was filed on is venus's OWN retired backup lane, and the recent delta is bin's — consistent with this morning's counter arithmetic once the vault discriminator collapsed. WHY IT IS NOT CLOSED: a decomposition fitting to single digits across two independent tiers is strong, but it is a FIT. This WI has produced three confident readings and killed two. Asked nw-whey for an EXACT count from backup-log.sqlite (not cadence-derived) plus artifact-level proof its dump excludes vault/storage/migrations (declared config has lost to the artifact twice here), and bin for an EXACT run count (12/day x 6 is an estimate; 72 vs 73 vs 75 decides fit-vs-residual). A residual is the valuable outcome either way: ~0 means no unknown reader exists; a gap IS the quarry, sized for the first time. TIMING INSTRUMENT — TWO OF THREE ARE DEAD (answers Elazar's 'what Argentina time does it run'): pg_stat_statements has NO timestamps, so every rate on this WI is a total over a window, never an observed clock. Went to postgres_logs via Management API: 3600 rows/24h, and ALL of them are three message types (pg_pgrst_no_exposed_schemas every ~32s, checkpoint, cron job). Filtering those three returns ZERO. log_connections is OFF — a superuser can dump the entire DB including vault and leave no trace, and there is no record for any of the 481 past runs either. Only surviving timing instrument was the Supabase support ticket (needs Elazar's account) — until this decomposition, which if it holds supplies the schedules from the lanes' own timers instead. SIDE FINDING, separate WI to open: pg_pgrst_no_exposed_schemas fires every ~32s, ~2700/day, drowning the postgres log. PostgREST misconfiguration, unrelated to this investigation.
-
RECONSTRUCTION HALF-FALSIFIED BY MEASUREMENT (nw-whey msimwow88wbu). Recording both halves; the confirmed half is not the interesting one. CONFIRMED, artifact-level: whey's lane genuinely excludes the internal schemas. run.sh L135 'pg_dump --format=custom --no-owner --no-privileges --schema=public --schema=auth' (INCLUSION-only), verified against live artifact 2026-08-07-0000-venus.dump via pg_restore --list: 755 TOC entries, 526 public, 214 auth, ZERO vault/storage./supabase_migrations/realtime. This is the artifact standard this WI has twice demanded after declared config lost. Method note from them worth keeping: their dumps are --format=custom (binary), so a plain 'grep COPY vault' cannot work — pg_restore --list is the correct instrument, and an earlier inconclusive grep may be explained by that. Contrast bin's lane, which is plain text and required the opposite instrument; the two artifact reads are not interchangeable. FALSIFIED, the count: I predicted 942 from a '16d x 48/day + 58d x 3/day' shape anchored at the reset. MEASURED = 824 systemd/ok runs. The shape was wrong at its start, not merely in total — whey has ZERO venus rows before 2026-05-25, a 12-day hole INSIDE the reset window, so the lane does not run from the reset at all. Cutover measured as a transition not a date: 36-47/day through 06-10, 10 on 06-11, 1 on 06-12, 1-3/day from 06-13 (pre-cutover 725, post 99). Also: 915 'prune' + 61 'usb' rows share the table and are NOT dump runs — counting all ~1800 rows would overcount by 976. RESIDUAL NOW ON THE TABLE: observed app+auth tier 1417 - whey 824 - full-schema 481 = 112 runs that copy public+auth, skip the internal schemas, and are attributed to nothing. BEFORE ANYONE READS 112 AS THE QUARRY — my omission, dispatched msimxg3h3u6q: 824 is filtered status='ok'. pg_stat_statements counts EXECUTED STATEMENTS, not successful backups; a pg_dump that died partway still incremented every counter it reached and produced no artifact. status='ok' measures OUTCOMES, the counter measures ATTEMPTS — wrong filter for the comparison. Asked for non-ok venus runs by status value. SECOND-ORDER CAUTION carried into that ask so it cannot be answered sloppily: an EARLY failure increments only the tables it reached, so a failed run contributes LESS than 1 to a given table's counter. My arithmetic treats every run as touching every in-scope table equally. If the non-ok runs are early failures the residual does NOT close cleanly and the leftover is real — asked whether early can be distinguished from late (elapsed, partial sizeBytes, last table logged). That distinction is the difference between closing this and only appearing to. Also asked whether 'prune/usb rows execute nothing against venus' is measured from the code path or inferred from what the rows represent.
-
RESIDUAL SURVIVES AND HAS A SHAPE. Both tiers now measured. FULL-SCHEMA TIER 481 = bin 73 (MEASURED: 72 timer + 1 manual 08-01 07:46 before the timer's first fire — cadence alone gives 72, which is exactly the derived-number failure I warned against) + dead gdrive lane 406 (slot-extrapolated, bin flagged it as derived; the artifacts proving it were destroyed by that lane's own retention). Residual 2, inside reset-instant uncertainty. Closed for practical purposes. APP+AUTH TIER 1417 does NOT close. nw-whey msimyk56smv5, failure-point resolution: of 10 fails, 8 were DNS (pg_dump never reached TCP — contribute 0), 1 preflight before pg_dump ran (0), and 1 (id 5193, 06-12 19:00, 35s duration) executed a FULL dump and failed only on the post-dump cp — logged 'fail', contributes like 'ok'. Net real executions ~825. Plus 14 rows stuck at status='start' (process died mid-run, never logged an outcome); nw-whey correctly refused to price them — 'not zero and not full' — and lacks journal access to resolve. Bounds: residual 97 (if all 14 count full) to 111 (if none do). GENERAL LESSON from id 5193, recorded because the schema cannot answer it: an 'ok' row proves statements executed; a 'fail' row proves NOTHING in either direction without the failure point. Outcome logging is the wrong instrument against a statement counter. THE RESIDUAL'S SHAPE — sharper than anything this WI has had, and it INVERTS my earlier reading: - RATE ~1.1/day over 86 days. Once-daily. Every lane we have identified is 2-hourly or bursty. - SCOPE exactly public+auth, skipping vault/storage/supabase_migrations — identical to whey's --schema=public --schema=auth signature, and NOT the shape of a platform actor (a platform dump takes the internal schemas; that is the 481 family, now decomposed into our own two lanes). RETRACTION, explicit: I earlier argued the internal-schema spread proved a platform-side actor. That was true of the 481 family only, which is now attributed. The genuinely unexplained lane has the OPPOSITE shape — application-scoped. Anyone re-reading the pre-08-07 notes must not carry the platform-actor inference forward. OPEN QUESTION, restated precisely: something runs an application-scoped pg_dump against the venus DSN ~once daily, from a host not swept. venus and whey are each swept clean by two independent passes. Remaining: lezama, Elazar's machines, or an off-host DSN consumer. Asked nw-whey (msimzv9gxhvl) whether run.sh exists in more than one place — the residual wears its exact scope signature, cheapest available lead. Asked them to chase journal access for the 14. PRUNE CLOCK RESOLVED — do not freeze. bin enumerated slot-by-slot (msimzrt929fs): 06-13 06:00 -> 06-16 04:00 = 36 even-hour slots, all 36 present, zero missing, no drift. Their earlier per-day figure was consistent with a gap balancing across day boundaries; this is not. The dependency I flagged before accepting is discharged. The 11 survivors carry no marginal CADENCE evidence. bin's bound, kept: that is not true of CONTENT — they are the only in-place copies of what the dead lane's dumps contained, and content is how this WI was wrong twice. The one content question in play (vault.secrets COPY present, zero rows) is already measured across all 11. Any OTHER content question must be asked before ~2026-08-08 04:00.
-
FLEET HUNT (Elazar-directed, DM to 10 agents msin8i42gy9o). ALL REMITS CLEAN. The coverage limits are the payload, not the clean results. SWEPT CLEAN: venus host (nw-venus — root crontab EMPTY, all users' crontabs, 13 system + 27 user units); whey host (nw-whey — root crontab its one blind spot); sh.git 352 files, current tree AND full history all branches, plus deleted-file sweep (bin — 0 hits for the ref, 0 for --schema=auth in any commit ever); venus app code + all 4 vercel.json crons + soporte-cron (pm-venus); repo tree across 6 apps (pmmaster); DB INTERIOR (db-venus — no pg_cron job, no function shelling out, no dblink/postgres_fdw, pg_stat_activity all-recognized). Supabase Edge Functions = [] (my read). Platform re-verified: backups:[], walg_enabled:true (physical WAL, emits no COPY). STILL UNSEARCHED: lezama (nw-lezama-cc asked, pending), Elazar's personal machines, Vercel DASHBOARD-configured crons (invisible from repo — pm-venus flagged), git history for a deleted-but-still-live-on-old-deploy route. BIN'S POINT 4 — THE FINGERPRINT IS TOO NARROW AND EVERY SWEEP TODAY INHERITS THE FLAW. '--schema=public --schema=auth' assumes the lane shells out to pg_dump. A Node/Python client issuing the same COPY sequence produces an IDENTICAL tier signature with no pg_dump on disk and no schema flags to grep. pg_stat_statements sees the COPY either way. This widens the search from 'scripts and units' to 'anything holding a venus postgres/service-role DSN' — and it means today's clean results bound a narrower question than the one asked, which is the exact failure mode this WI keeps reproducing. NEW FINDING, not previously on this WI: network-restrictions = dbAllowedCidrs ['0.0.0.0/0'], v6 ['::/0'], status applied. THE VENUS DB ACCEPTS DIRECT CONNECTIONS FROM ANY IP ON EARTH. Does not identify the caller; explains why an off-host actor needs no foothold on any machine we swept. Elazar's decision whether to restrict. FINGERPRINT SCRIPT WITH NO REF GUARD (pmmaster): mars/db/backup-db.sh carries the exact --schema pair, manual-invocation only, targets mars's DATABASE_URL_DIRECT, output named mars.dump — but has NO EXPECTED_REF check (terra's backup-db.sh does). It sources .env.local under 'set -a'; if .env.local is ABSENT it falls through to an already-exported DATABASE_URL_DIRECT. Ruled out as the residual lane on cadence (manual, not ~daily) but the missing ref guard is a real defect: the script cannot tell which project it is dumping. venus has NO db/backup-db.sh of its own. RULED OUT this pass, individually: venus-state-backup-daily.timer (daily 03:30 — right cadence, but file-level only, zero DB access, checked the script); evolutiva-dbperf@venus (daily 07:30, psycopg2 SELECTs on pg_stat_*, no COPY); venus/db/export-db.py (information_schema introspection, no COPY, no scheduled caller anywhere); venus CSV export route (staff-gated, one table, filtered); backup-whey-to-ssd.sh (local telemetry DB, not Supabase).
-
NEGATIVE CONTROL FAILED — the most useful result of the fleet hunt, and it discredits an unknown share of today's clean verdicts. bin-whey-cc reported they could NOT find whey's OWN --schema=public+auth dumper by literal grep, and inferred the flags must be built dynamically, therefore no literal-fingerprint sweep could ever see the residual lane. But nw-whey-cc quoted that same file two hours earlier as a LITERAL string — run.sh L135 'pg_dump --format=custom --no-owner --no-privileges --schema=public --schema=auth' — and verified the scope at artifact level (pg_restore --list: 755 TOC, 526 public, 214 auth, zero internal). Both cannot be true. If nw-whey's quote is accurate, bin-whey's scan returned a FALSE NEGATIVE on a known target, in a .sh file, in a path they state they scanned. WHY IT MATTERS MORE THAN ANY CLEAN RESULT: ten agents reported clean against a fingerprint today and NOT ONE of us first proved our search could find a known instance. bin-whey's scan accidentally ran that control and failed it. Their conclusion inverts — the bound is not 'fingerprints cannot work', it is 'this scan did not work' — and until the mechanism is known we cannot say how many of the other clean verdicts share the defect. This is the same class as the standing 'prove the filter CAN return non-empty before reporting a zero' rule, applied to filesystem sweeps rather than DB queries. DISPATCHED (msinh3m0dw7t): nw-whey to confirm the literal line + absolute path; bin-whey to report the MECHANISM of the miss (walked path / extension filter / permissions / symlink / exclude rule / size cap), NOT merely to re-run and report a hit. The mechanism decides who else must re-run. MY ERROR, recorded: I dispatched the --schema fingerprint to ten agents without a control. bin's earlier point 4 already established the fingerprint could not be SUFFICIENT (a client library issuing the same COPY sequence leaves no pg_dump on disk and no schema flags to grep); it is now also not demonstrably SOUND. Also in from pm-llmmsgsrv-cc: maintainer registry checked across ALL statuses incl. retired — only 3 rows touch venus DB dumping (row 82 bin's attributed lane, row 84 nw-venus staleness alerter, rows 55/57 non-dump surfaces). No retired/historical row is DB-adjacent. Coverage limit stated correctly: the registry is SELF-REPORTED, so a row exists only if someone filed it — an unregistered ad-hoc script or app code is invisible to it. No owner to name.
-
LEZAMA CLEAN (bin-lezama msini8hognck) — last unswept fleet host. Three independent negatives: (1) project ref fjnhfjwskixzsilxrkph = ZERO files, grepped with gitignore-IGNORING plain grep so gitignored files ARE covered; (2) no daily-dump scheduler — full user+system timer list enumerated, user crontab, /etc/cron.d, cron.{daily,hourly,weekly}, /etc/crontab, /etc/systemd/system all clean; (3) rg over all .ts/.tsx/.js/.mjs found no pg_dump, no 'COPY .. TO', no bulk-export route touching the venus ref. venus-db-backup.sh rides in the shared sh.git checkout but its timer is INACTIVE on lezama, and it is a FULL dump (no --schema filter) so it is not the residual signature anyway. COVERAGE LIMITS they stated correctly: root crontab returned empty but crontab is not in their NOPASSWD sudoers, so 'no root crontab' and 'silently denied' are indistinguishable — nw-lezama-cc has fuller access. Live process envs not searched (files only); their own counter-argument is sound though: a ~daily pg_dump still needs a scheduler, and every lezama scheduler is covered. NOTE THE STANDING CAVEAT: this verdict, like all ten from today's hunt, was produced against the --schema fingerprint WITHOUT a positive control, and bin-whey's scan has already been shown to false-negative on a known literal target (/opt/evolutiva-backups/run.sh L135, confirmed by nw-whey as plain ASCII, regular file, unrestricted 0775 path, flags hardcoded not dynamic). lezama's ref-based greps are stronger than flag-based ones because the ref is a fixed 20-char string, but the caveat is not discharged for any agent until bin-whey reports the MECHANISM of their miss. NEW INSTRUMENT FOUND IN nw-whey's L135 PASTE, dispatched msinijssepy8: whey's pg_dump carries ${EXCLUDES[@]}. My residual arithmetic assumed whey contributes equally to EVERY table in the public+auth tier — false for any excluded table. If EXCLUDES drops tables (and if it is --exclude-table or --exclude-table-data rather than schema-level), an excluded table X is a FREE DISCRIMINATOR: whey contributes zero to it, so X = 481 + residual, giving the residual with NO dependence on whey's sqlite at all. And 1417 - X = whey's exact contribution measured from the counter, independently checkable against their 830-839 log-derived figure — two instruments with different failure modes on the largest current uncertainty (their 14 orphans are +-9). INCIDENTAL, NOT VENUS-350, ROUTED TO ELAZAR: lezama user crontab holds a self-deleting movilba one-shot scheduled 17 Jun that never self-deleted, carrying an INLINE PLAINTEXT PASSWORD (psql postgresql://elazar:<pw>@app.movilba.com:5432/movilba). Credential exposed in crontab on a GCABA machine. No remediation taken, no rotation (standing rule: fix the leak surface, report, stop). Elazar's decision.
-
EXCLUDES DISCRIMINATOR CONFIRMED + A POSSIBLE 8x RESIDUAL, HELD PENDING ONE CHECK. nw-whey (msinkyn2eqpc) pasted run.sh L30-59: EXCLUDES=(--exclude-table-data=notifications, =auth.flow_state, =auth.sessions, =auth.refresh_tokens) for venus and pluto. Crucially it is --exclude-table-DATA not --exclude-table: DDL stays in the TOC, but pg_dump never READS ROWS from those 4, so no data COPY is issued against them. WHEY'S COPY CONTRIBUTION TO THOSE 4 IS ZERO; full run count everywhere else incl. auth.users. (Egress-trim change, Elazar-approved via pm-mars + pm-venus 2026-06-10.) So each of the 4 isolates the residual with NO dependence on whey's sqlite: X = 481 + residual. FACE-VALUE READ OF DATA ALREADY IN HAND — refresh_tokens/flow_state/sessions were listed at 1280 in the earlier tier dump: residual = 1280-481 = 799, and whey's counter contribution = 1417-1280 = 137 against 830 LOGGED runs. That is ~8x the residual I have been quoting and a ~6x shortfall in whey. NOT REPORTED AS A FINDING and must not be treated as one yet. WHY IT IS PROBABLY AN ARTIFACT: schema drift splits one logical lane across MANY counter rows — already measured on this WI (practicas = 18 rows summing 1418; custom_oauth_providers = 1230+187 across 2 queryids). 1280 is plausibly ONE ROW OF SEVERAL, exactly as 539 was one row of 18 for practicas. Dispatched msinlvm8y6w9: ALL COPY rows per table for the 5 tables (the 4 excluded + auth.users), with per-row queryid/calls/column-list/stats_since AND the sums — per-row detail required, not sums on faith, so a missing variant is visible. Outcomes pre-committed in the ask so neither side reads the result to taste: sums ~1417 everywhere = split artifact, residual stays ~97-106; genuine 1280 vs 1417 = residual ~799 AND whey's 137-vs-830 both need explaining before anyone acts. PREDECESSOR HYPOTHESIS DEAD (nw-whey, same message). My '12-day blob ending 05-25' alternative is falsified by 5 independent lines, none relying on the sqlite: (1) the SHARED timer template /etc/systemd/system/evolutiva-backup@.timer has birth 2026-05-25 01:44, hours before venus's first logged run 05:00:46 (the .service template is older, 05-01); (2) USB-tier files for venus AND mars both start exactly 05-25 — the USB tier rolled out that day, project-independent; (3) backup-log.sqlite's todos table seeded 05-01 names only mars/pluto, venus absent at inception; (4) no other project label ever appears in the DB; (5) no pre-05-25 venus artifacts on gdrive or USB. Reading: venus was ADDED as a genuinely new lane to an already-running mars/pluto system on 05-25 — not a late-logging artifact. So the 05-13->05-25 hole is real and nothing on whey filled it. Consequence: the residual cannot be explained as 'whey's lane before its logging existed'. It is either uniform-ish across the window or concentrated somewhere we have not looked.
-
HARD CONTRADICTION — the residual may be ~800, not ~100. Two instruments disagree about whey's lane by 6x. HOLD, one unverified assumption underneath. db-venus (msinmn3l9yy3) killed my split-artifact explanation: the 4 whey-excluded tables are NOT split. auth.flow_state / auth.sessions / auth.refresh_tokens = 1280 EACH, exactly ONE row apiece, zero column-list variants, all stats_since 2026-05-13 09:53:4x. auth.users = 1417, one row. (public.notifications does not exist in venus — that exclude is a no-op here.) ARITHMETIC: whey dumps auth.users but excludes sessions/flow_state/refresh_tokens DATA. bin, the dead gdrive lane and the unknown lane dump ALL of them, so the non-whey contribution must be IDENTICAL across those tables — and it is, exactly 1280 on all three, which is itself corroboration that the split is real. whey from the counter: 1417 - 1280 = 137 whey from backup-log.sqlite: 824 ok + 1 hidden full-touch fail + 5 confirmed orphans = 830 (ceiling 839) Cannot both be true. If the counter is right: residual = 1280 - 73 (bin) - 406 (dead lane) = 801 — about 9/day, NOT the ~1.1/day I reported to Elazar all morning. That would mean this WI has understated the unattributed reader by nearly an order of magnitude. THE LOAD-BEARING UNVERIFIED ASSUMPTION, named so it cannot be forgotten: that --exclude-table-data causes pg_dump to issue NO COPY against those tables. Documented behaviour, stated by nw-whey, NEVER checked against an artifact. If pg_dump emits a COPY for an excluded table anyway (empty COPY, or suppression at write time rather than read time), the discriminator is void and 801 evaporates. Everything above is one subtraction resting on this. DISPATCHED (msinoe8g10ig): (a) nw-whey to verify the assumption at ARTIFACT level — does pg_restore --list show DATA entries for the 3 excluded auth tables on a current dump? DDL yes, data entry should be absent; if present, discriminator void, report immediately. (b) nw-whey to re-derive 824 INDEPENDENTLY of the sqlite by counting actual venus artifacts on gdrive + USB in the window — ~830 artifacts corroborates the log and makes the DB counter the anomaly; ~137 means the sqlite over-counts and the counter is right. (c) db-venus to confirm 2-3 single-row PUBLIC tables sit at ~1417 not ~1280, testing the whey-vs-non-whey split at its root. NOBODY TO ACT ON 801 until (a) and (b) return. Explicitly instructed no remediation either way. Also in: bin-whey WITHDREW and INVERTED their 'flags are dynamic, fingerprints cannot work' conclusion. Mechanism of their false negative = TWO defects, both the swallowed-failure pattern: (1) 'timeout 90 grep -r /home/rob /opt ...' — /home/rob alone measured at 77.9s, so the walk was KILLED before reaching /opt/evolutiva-backups/; 2>/dev/null ate the timeout signal and '|| echo clean' printed a clean-looking line for a grep that exited 124, indistinguishable from a real no-match. (2) sudo is NOT passwordless in their non-interactive context ('sudo -n true' -> password required), so their root-crontab, /etc/cron.d, cron.* and /etc/systemd/system results NEVER RAN AS ROOT and are UNPROVEN, not clean — same 2>/dev/null || echo manufacture. Their sh.git and dotfiles greps survive. FLEET RULE EARNED (bin-whey's generalization, adopt it): any sweep using 2>/dev/null, a timeout, '|| echo'/'|| true' fallbacks on grep -r, or non-interactive sudo carries the same false-clean risk. Minimum bar before any 'clean' counts: (1) a POSITIVE CONTROL — grep a string known-present in a file you must reach and confirm the hit; (2) verify sudo actually elevated via 'sudo -n true'; both with stderr VISIBLE and no || fallback.
-
ANOMALY INVERTS — the question is no longer 'why is whey short', it is 'why are the 3 auth SESSION tables ~700 too HIGH'. My previous note's 801-residual reading is SUPERSEDED; do not carry it forward. db-venus cross-check (msinp7ynd3qo) widened beyond the 2 tables I asked for and summed EVERY public table across all its drift-split rows: users(8 rows)=1418, alumnos(9)=1418, practicas(18)=1418, accessRequests(5)=1418, piezasDentarias(4)=1418, practicaParticipations(4)=1418, userRoles(4)=1418, appEvents(3)=1418, regionesAnatomicas(3)=1418, rolesEnPractica(3)=1418, cirugias(3)=1418, sedes(3)=1418, tratamientos(3)=1418, antecedentesCatalog/lookupOptions/pacienteAntecedentes/complicaciones/dias/modulos(2 each)=1418, periodos(1)=1418. titularSedes=1417 is the lone exception (1 short, single row, plausibly missing its first eligible run). A HARD-LOCKED CONSTANT ACROSS 20 TABLES WITH WILDLY DIFFERENT ROW COUNTS AND SPLIT COUNTS is the signature of full-table-set dumps: 1418 = total runs that touched the public schema. And it RECONCILES with the logs exactly: whey 830 + bin 73 + dead lane 406 + residual 109 = 1418. So on the public tier whey's 830 is CORROBORATED, not contradicted, and the residual is ~109 — the figure I have been reporting. THEREFORE THE ANOMALY MOVES SIDES. If whey ran 830 and excludes the 3 session tables' data, those should sit at 1418 - 830 = 588. They sit at 1280 — about 692 HIGHER than any lane accounts for. auth.flow_state, auth.sessions, auth.refresh_tokens: live session state and refresh tokens. TWO CANDIDATES, cannot choose yet: (a) whey does not actually exclude them in practice — --exclude-table-data behaves other than assumed, or EXCLUDES is not applied on the venus invocation. Then 1280 vs 1418 means something else and there is no session-specific reader. (b) Something COPYs those 3 tables specifically ~692 times and touches nothing else. That is not a backup shape at all — a backup takes whole schemas. Session/refresh-token tables read in isolation is a different kind of actor. nw-whey's artifact check (pg_restore --list on a current dump: do DATA entries exist for those 3 tables?) now settles WHICH, and is the single most important read in this investigation. Already dispatched msinoe8g10ig. METHOD NOTE — this is the second time today a residual figure moved by ~8x on one measurement, and both times the movement came from someone else widening a check I had scoped too narrowly. I asked db-venus for 2-3 tables; they summed 20 and that is what produced the reconciliation. Record the instrument: SUM ACROSS ALL DRIFT-SPLIT ROWS PER TABLE, then look for a CONSTANT across tables — a per-table maximum is not a lane count and reading one as such is what produced both wrong figures. LEZAMA COMPLETE (nw-lezama msinoh5m55fn), sudo-verified this time: schedulers all clean incl. root crontab; disk-wide ref/flag grep zero; venus-db-backup.sh present via shared sh.git but host-guarded, no ~/.venus-db-backup.env credential on lezama, nothing schedules it; root-owned movilba scripts clean; NextJS sources (movilba-web, penql, shira) reference only local Postgres or the GCABA dbcaba DB — zero Supabase/venus-ref hits. Coverage limit: no container interiors, no compiled artifacts, and the evolutiva source tree is NOT on lezama so they could not search it from there.
-
EXCLUDE-DATA ASSUMPTION CONFIRMED TWICE, INDEPENDENTLY — discriminator STANDS, not void. My prior note's reconciliation (whey 830 corroborated, residual ~109) is now the SUSPECT reading; ~801 is back in play and currently better supported. (1) bin-venus-cc msinsk6licdi ran it as a CONTROLLED EXPERIMENT rather than waiting — correctly noting it is a property of pg_dump, not of whey's artifact. Run against the venus-LOCAL telemetry PG, deliberately NOT venus Supabase (a probe dump on the DB under investigation would add executions to the very counters this WI reads — good instinct, record it). Same binary, PG 17.10, one table dumped twice: baseline 1 COPY / 5,851,611 bytes; with --exclude-table-data 0 COPY / 2,120 bytes / zero 'Data for Name' TOC comments. Custom-format TOC: baseline TABLE/COMMENT/TABLE DATA/CONSTRAINT/INDEX, excluded TABLE/COMMENT/CONSTRAINT/INDEX. STATED BOUND, carry it: proves no COPY WRITTEN and no data TRANSFERRED (5.85MB->2.1KB collapse; pg_dump cannot omit 5.8MB it fetched), does NOT prove zero COPY statement text reached the server — pg_stat_statements is not installed on that DB so no counter-level before/after was possible. (2) nw-whey-cc msinx2tz0d4r, artifact level, on the real thing: pg_restore --list of 2026-08-07-0000-venus.dump shows auth.sessions/flow_state/refresh_tokens with DDL/constraint/index/comment/ROW SECURITY entries and ZERO 'TABLE DATA' line, against auth.users/identities/instances which DO have one. THE LOG IS NOW THE OUTLIER, NOT THE COUNTER. nw-whey's (b) failed to settle 824-vs-137 in their own reading, but their report contains a number they did not turn on the question: GDRIVE FILENAMES CARRY TIME-OF-DAY (0000/0800/1600) = a CADENCE, 3 venus dumps/day every 8h. Applied to their own span: 05-25->08-07 = 74d minus their 12 calendar-day gaps = 62 dump-days x 3 = ~186 runs. Counter-derived = 138. Log = 824-830. 186 and 138 are the same order of magnitude; 830 is out by ~4-6x. And backup-log.sqlite is the instrument nw-whey JUST demonstrated wrong in both directions on a directly-verifiable 4-day window (Aug4-7: 10 artifacts on disk vs 6 systemd 'ok' rows; id 6210 is a 'start' with no finish whose artifact EXISTS and is valid). Their own recommendation: treat the counter as the more reliable instrument, since it observes DB-side execution rather than a script-side log write that can silently fail. IF WHEY IS ~138-190 RATHER THAN 830, THE RESIDUAL IS ~801, NOT ~109 — about 9 executions/day, i.e. an actor ACTIVE NOW rather than a lane that stopped in May. Different incident, different urgency. NOT ASSERTED YET. SETTLING READS DISPATCHED (msinya45mutb -> nw-whey), all on backup-log.sqlite venus rows, chasing bin's unit-mismatch hypothesis (830/137 = 6.06 — A CLEAN RATIO IS USUALLY A UNIT ERROR, NOT A RESIDUAL; a residual is a subtraction): (1) paste .schema + 3-4 consecutive RAW rows around one known dump instant, unsummarised — is a row a run, a phase (start/finish as 2 rows), or a per-destination write (gdrive+USB=2)? (2) COUNT DISTINCT INSTANTS not rows (timestamps truncated to hour/8h-slot) across the whole log — if 830 rows collapse to ~150-200 instants the contradiction dissolves. (3) per-day distinct-instant count over the full span — was venus ever 12/day (every 2h) early on, the one thing that could rescue a high number honestly. EVIDENCE POINTING THE OTHER WAY, kept visible rather than buried: id 6210 proves the log can MISS completions, which makes the true run count HIGHER than 830, not lower. Read (2) is what discriminates. VENUS HOST SWEEP COMPLETE (nw-venus msinssv51dke + msint9lss9vs), every scheduled unit read line by line, no fingerprint grep. NOTHING FOUND beyond what is already attributed. Elazar's named telemetry lead ANSWERED AND RULED OUT: the local telemetry/webusage DB writer is /opt/telemetry-ingest/server.mjs (user service telemetry-ingest.service, always-on daemon not a timer, 127.0.0.1:9720, public face telemetry.pensanta.com) and it is a PASSIVE HTTP RECEIVER — apps POST /v1/usage batches to it and it INSERTs into webusage.usageEvents. It never dials out to Vercel or Supabase. That is the OPPOSITE direction from the 'pulls telemetry from all Vercel/Supabase projects' shape Elazar described, so his mental model of that component is inverted and should be corrected. Other verdicts: telemetry-webusage-rollup = same-DB INSERT...SELECT + 90d purge; evolutiva-errscan = psql SELECT on each app's OWN DSN against an error-rollup VIEW only; applog-pull = pg.Pool SELECT from that app's own appEvents with an explicit anti-cross-contamination DSN guard; evolutiva-dbperf = reads pg_statio/pg_stat_user_tables + a SECDEF fn and INSERTs back into the SAME DB; jobreg/token-usage-collect/llmmsg-kpi/journal-digest/venus-state-backup/tick.py/llmmsg-purge-ghosts = local sqlite or journalctl only, no Postgres; mars-uxpain-relay = curl one app endpoint; stock Debian units = housekeeping. COVERAGE LIMIT, unchanged and now the main remaining host-side gap: app source trees under Documents/work (API routes, server actions, cron routes) were NOT walked — outside nw remit, explicitly coder/db/pm-venus territory. assert-authconfig.mjs is pluto-side, not present on venus disk, flagged rather than guessed. STILL MINE, NOT STARTED: Vercel dashboard-configured crons + Supabase scheduled jobs (API-access surface I claimed for myself), and the app-source-tree walk nw-venus just handed back.
-
REVERSAL + LIKELY RESOLUTION OF THE SESSION-TABLE GAP. Supersedes my two prior notes. 801 and 'active now ~9/day' are WITHDRAWN — do not carry either. nw-whey reads 1-3 (msinzy22abd0) settle it against me. READ 1: backup-log.sqlite schema is (id, project, startedAt, finishedAt, durationMs, sizeBytes, outputPath, status CHECK(start/ok/fail), errorMsg, hostname, trigger); ONE ROW = ONE EXECUTION, UPDATEd in place (start->ok on the SAME row), not split across INSERTs; usb/prune are separate trigger values already excluded from the 824; 'start'-only orphans are crash/log-write-fail, not a duplication mechanism. READ 2: 824 rows = 824 DISTINCT startedAt to the minute, zero duplication. So bin-venus's unit-mismatch hypothesis (830/137=6.06, clean ratio = unit error) is FALSIFIED — recording it as falsified rather than dropping it silently, since it shaped my dispatch. READ 3 IS THE ONE THAT MATTERED, and it kills my argument at its root: 2026-05-25 -> 06-10 whey ran 36-47 dumps/DAY (avg ~42), spot-checked at real ~30min spacing (05:00:46, 06:00:42, 06:30:43, 07:00:33, 07:30:26, 08:00:45, 08:30:19, 09:00:21 — genuine spacing, not a logging artifact). 06-11 onward it drops to 0-3/day. 714 pre + 110 post = 824 EXACT. It was the systemd-template DEFAULT 30min cadence until an override.conf cut it to 3/day; already documented in nw-whey's own nw-scripts.md as 'override.conf cutting cadence to 3/day since 2026-06-10 (Supabase egress trim, pm-venus approved)'. MY ERROR: I read the 0000/0800/1600 filename stamps as the cadence and projected 3/day backwards across the whole span. THE SAME DATE PLAUSIBLY CLOSES THE ~690 SESSION-TABLE ANOMALY WITH NO UNKNOWN ACTOR. run.sh's EXCLUDES comment reads 'Supabase egress trim, Elazar-approved via pm-mars 2026-06-10, pm-venus 2026-06-10' — SAME DAY as the cadence drop. ONE egress-trim change. If the exclude flags did not exist before it, whey's 714 pre-trim runs DUMPED the session tables in full and only the 110 post-trim runs skip them. Predicted: session tier = 714+73+406+residual = 1193+r vs OBSERVED 1280 -> r=87. Public tier = 824+73+406+residual = 1303+r vs OBSERVED 1418 -> r=115. Two independent tiers, r=87 and r=115, same order — and the ~690 anomaly disappears. Nothing reads session tokens specially; that was our own lane pre-trim. NOT BANKED. Load-bearing and dispatched (msio1e2vuc9z): nw-whey to git log/blame the EXCLUDES block for its ACTUAL add date — IF THE EXCLUDES PREDATE 05-25 THE WHOLE EXPLANATION DIES and the ~690 is real again; plus precise cadence-change date + override.conf mtime. db-venus to confirm 1280/1418 exactly (summing all drift-split rows, the widening that produced the reconciliation last time) and to still take the paired 24h read — NOW MORE VALUABLE, because if the residual sits pre-06-11 the 24h delta should be ~0, and a 0 is INFORMATIVE here since it discriminates between two competing stories rather than being an uncontrolled zero. SURVIVES AND IS NOW THE BEST LEAD — bin-whey msinyj2eiorf, corrected re-run, positive control PASSED (run.sh L135 --schema=auth found when scoped+readable). CONNECTION-PATH DISCRIMINATOR: whey connects DIRECT (db.fjnhfjwskixzsilxrkph.supabase.co:5432); the residual fingerprint names the aws-1-sa-east-1 POOLER. No pg_dump on whey uses the pooler; the only aws-1-sa-east-1 hits on whey are Wave/codex caches + /etc/evolutiva-errscan/mars.env (read-only error sweep, targets MARS:6543, no venus ref). Also: whey's venus DB-touching runs are 100% trigger=systemd (824 ok + 10 fail + 14 in-flight), ZERO manual/cron/other — no unattributed excess on whey. THE POOLER IS THE CONNECTION STYLE OF APP CODE AND HOSTED PLATFORMS, not of a script on our machines — consistent with every host sweeping clean. bin-whey coverage limits: /home/rob/Documents literal-ref walk timed out at 2min; literal-ref grep is blind to a DSN read from env/secret file (mitigated by the pooler-string scan, which catches pooler connections however the ref is supplied); other agents' project dirs not exhaustively scanned. METHOD RULE, EARNED FOUR TIMES TODAY AND THE MOST GENERALIZABLE THING THIS WI HAS PRODUCED: every wrong figure I published today came from RATE-PROJECTION — measuring a rate in one window and assuming it held across the whole window (~1.1/day; the 186-run estimate; the 801; and the 'stopped in May' shape). NEVER DIVIDE A TOTAL BY A SPAN. Enumerate PER DAY across the FULL span and look at the shape. nw-whey's read 3 is exactly that and settled in one query what four rounds of subtraction could not. Corollary already earned twice: the fix each time came from someone WIDENING a check I had scoped too narrowly. NEXT, MINE: app source trees (API routes / server actions / cron routes — handed back by nw-venus as outside their remit) and Vercel-dashboard + Supabase-side scheduled jobs. Both now the prime suspects given the pooler finding.
-
SESSION-TABLE GAP CLOSED (prediction confirmed on both tiers) + POOLER LEAD RESOLVES TOWARD OUR OWN LOCAL TOOLING. db-venus check 3 (msio2legunbz) CONFIRMS the trim-date explanation. They also caught a false positive I would have shipped: the substring 'flow_state' also matches auth.saml_relay_states' flow_state_id column inside COPY text — excluded. Corrected figures: auth.flow_state / auth.refresh_tokens / auth.sessions ALL = 1281 (not 1280), single-row, no drift split, uniform. Public = 1418 confirmed. AGAINST MY PREDICTION: session 714+73+406=1193 vs observed 1281 -> residual 88 (predicted 87, off by one). Public 824+73+406=1303 vs observed 1418 -> residual 115 (predicted 115, exact). TWO INDEPENDENT TIERS AGREE. The ~690 session-table anomaly is fully explained by whey's pre-2026-06-10 runs predating the egress-trim exclusions. NOTHING reads session tokens specially. Still want nw-whey's git blame on the EXCLUDES add-date as the independent confirmation, but the arithmetic now stands on its own across two tiers. RESIDUAL SETTLES AT ~88-115. Not 801, not ~9/day-active-now, not 'stopped in May' — I published all three today and all three were rate-projection errors. PAIRED-DELTA INTERIM (db-venus, ~24min not 24h): auth.users 1417->1418 (+1), vault.secrets 481->482 (+1). BOTH +1 = one FULL-SCHEMA run, i.e. an attributed lane (bin's). Note the discriminator: a RESIDUAL run is public+auth only and would move auth.users WITHOUT moving vault.secrets. So this interim shows zero residual activity in that window — consistent with the residual being historical, not current. Not conclusive at 24min; the 24h paired read still matters and db-venus is holding for it without self-arming. POOLER LEAD — RESOLVED, AND IT POINTS AT US, NOT AN OUTSIDER. Whole-tree grep across /home/rob/Documents/work/pensanta/websites, positive control PASSED (22 files carry the venus ref). Finding: venus/.env.local line 4 sets DATABASE_URL to postgresql://postgres.fjnhfjwskixzsilxrkph:<redacted>@aws-1-sa-east-1.pooler.supabase.com:6543/postgres — THE POOLER. whey's backup lane connects DIRECT (db.<ref>.supabase.co:5432); ANY local script/CLI/agent tooling that reads venus's .env.local connects via the POOLER. So bin-whey's connection-path discriminator does not indicate an external actor at all — it is the expected signature of our own local tooling run against venus from this machine. That reframes the residual from 'unknown outsider' to 'unattributed LOCAL runs', which is a much more tractable search and matches every host sweep coming back clean. METHOD FAILURE OF MY OWN, recorded because I criticised bin-whey for exactly it three messages earlier: my first two greps returned 0 hits and I nearly reported the app tree clean. Both were SWALLOWED FAILURES of my own making — a that did not take effect (search ran in the agent subtree, not the app tree) and a pipe/2>/dev/null combination that hid a killed grep. Caught ONLY because I ran a positive control and it failed. THE POSITIVE CONTROL IS NOT CEREMONY; it is the only reason this is a finding instead of a false all-clear. Standing practice for this WI and beyond: absolute paths, visible stderr, redirect-then-count rather than pipe-to-wc, and never a fallback. SECRETS EXPOSURE NOTICED IN PASSING, NOT ACTED ON per no-rotation rule (fix the surface, report, STOP — do NOT rotate): plaintext DB passwords sit in mars/pm/06-passwords-and-settings.md, pluto/CODEX.md, pluto-solo/CODEX.md and several .env.local files. Elazar's call entirely; raising it as a separate observation, NOT as a VENUS-350 remediation, and NOT proposing any rotation. STILL OPEN, MINE: Vercel dashboard-configured crons + Supabase-side scheduled jobs (db-venus already ruled out pg_cron in-DB); and the deeper app-source read for a COPY-issuing client library, which bin-venus correctly warned is invisible to a pg_dump-shaped grep.
-
SESSION-TABLE GAP CLOSED (prediction confirmed on both tiers) + POOLER LEAD RESOLVES TOWARD OUR OWN LOCAL TOOLING. db-venus check 3 (msio2legunbz) CONFIRMS the trim-date explanation. They also caught a false positive I would have shipped: the substring flow_state also matches auth.saml_relay_states flow_state_id column inside COPY text - excluded. Corrected figures: auth.flow_state / auth.refresh_tokens / auth.sessions ALL = 1281 (not 1280), single-row, no drift split, uniform. Public = 1418 confirmed. AGAINST MY PREDICTION: session 714+73+406=1193 vs observed 1281 -> residual 88 (predicted 87, off by one). Public 824+73+406=1303 vs observed 1418 -> residual 115 (predicted 115, exact). TWO INDEPENDENT TIERS AGREE. The ~690 session-table anomaly is fully explained by wheys pre-2026-06-10 runs predating the egress-trim exclusions. NOTHING reads session tokens specially. Still want nw-wheys git blame on the EXCLUDES add-date as independent confirmation, but the arithmetic now stands on its own across two tiers. RESIDUAL SETTLES AT ~88-115. Not 801, not ~9/day-active-now, not stopped-in-May - I published all three today and all three were rate-projection errors. PAIRED-DELTA INTERIM (db-venus, ~24min not 24h): auth.users 1417->1418 (+1), vault.secrets 481->482 (+1). BOTH +1 = one FULL-SCHEMA run, i.e. an attributed lane (bins). Note the discriminator: a RESIDUAL run is public+auth only and would move auth.users WITHOUT moving vault.secrets. So this interim shows zero residual activity in that window - consistent with the residual being historical, not current. Not conclusive at 24min; the 24h paired read still matters and db-venus is holding for it without self-arming. POOLER LEAD - RESOLVED, AND IT POINTS AT US, NOT AN OUTSIDER. Whole-tree grep across the websites tree, positive control PASSED (22 files carry the venus ref). Finding: venus/.env.local line 4 sets DATABASE_URL to the POOLER host aws-1-sa-east-1.pooler.supabase.com:6543. Wheys backup lane connects DIRECT (db.<ref>.supabase.co:5432); ANY local script/CLI/agent tooling that reads venus .env.local connects via the POOLER. So bin-wheys connection-path discriminator does NOT indicate an external actor - it is the expected signature of our own local tooling run against venus from this machine. That reframes the residual from unknown-outsider to unattributed LOCAL runs: a far more tractable search, and it matches every host sweep coming back clean. METHOD FAILURE OF MY OWN, recorded because I criticised bin-whey for exactly it three messages earlier: my first two greps returned 0 hits and I nearly reported the app tree clean. Both were SWALLOWED FAILURES of my own making - a cd that did not take effect (search ran in the agent subtree, not the app tree) and a pipe-plus-stderr-suppression combination that hid a killed grep. Caught ONLY because I ran a positive control and it FAILED. THE POSITIVE CONTROL IS NOT CEREMONY; it is the only reason this is a finding instead of a false all-clear. Standing practice: absolute paths, visible stderr, redirect-then-count rather than pipe-to-wc, and never an or-echo-clean fallback. SECRETS EXPOSURE NOTICED IN PASSING, NOT ACTED ON per no-rotation rule (fix the surface, report, STOP - do NOT rotate): plaintext DB passwords sit in mars/pm/06-passwords-and-settings.md, pluto/CODEX.md, pluto-solo/CODEX.md and several .env.local files. Elazars call entirely; raised as a separate observation, NOT a VENUS-350 remediation, and NOT proposing any rotation. STILL OPEN, MINE: Vercel dashboard-configured crons + Supabase-side scheduled jobs (db-venus already ruled out pg_cron in-DB); and the deeper app-source read for a COPY-issuing client library, which bin-venus correctly warned is invisible to a pg_dump-shaped grep.
-
SESSION-TABLE ANOMALY CLOSED BY ARTIFACT, not by arithmetic. No unknown actor. Chain worth preserving as method. nw-whey check 2 CORROBORATED the cadence date precisely: override.conf mtime 2026-06-10 23:51:11 ART = 06-11 02:51:11 UTC, content OnCalendar=*-*-* 00/8:00:00 (3/day). Timer mechanism and DB-observed cadence break agree to the hour. nw-whey check 1 could NOT date the EXCLUDES block and said so plainly instead of guessing: run.sh is plain files, no git anywhere, no .bak/versioned copies, no changelog, single mtime 2026-06-21 01:41:50 ART = 11 days AFTER the timer change. They correctly flagged that the scripts own comment cites an APPROVAL date, not a deploy date, and proposed a third bucket of up to 26 post-trim-pre-exclude runs. bin-venus corrected the inference in a way that cut BOTH ways rather than just against me: MTIME RECORDS THAT A FILE CHANGED, NOT WHAT CHANGED. Birth==mtime on ext4 is the same single fact stated twice, not a second data point. So the third bucket was UNCONSTRAINED IN BOTH DIRECTIONS - 0 runs or all 26 - and nothing on the filesystem could narrow it. Their warning, worth keeping verbatim in spirit: do not let the reconciliation absorb it as an estimate; UNMEASURED IS A DIFFERENT THING FROM UNKNOWN-BUT-SMALL. They also pre-authorised the honest answer: if retention had eaten the window, say so plainly and carry it as a stated uncertainty rather than a number. THE INSTRUMENT THEY NAMED IS WHAT SETTLED IT, and it dates the flag PER RUN rather than per file-write: pg_restore --list any artifact from the disputed window and look for a TABLE DATA entry on the 3 session tables. nw-whey ran it on USB copies (gdrive already pruned; USB was the only surviving instrument): - 2026-06-10-venus.dump, LAST 30min-cadence day: TABLE DATA PRESENT for all 3 (auth.flow_state id 4771, auth.refresh_tokens id 4758, auth.sessions id 4763) -> excludes NOT active. - 2026-06-11-venus.dump, FIRST 3/day day: NO TABLE DATA for any of the 3, DDL/constraints/indexes only -> excludes ACTIVE, same signature as the 2026-08-07 artifact. EXCLUDE-FLIP AND CADENCE-FLIP LANDED ON THE SAME DAY BOUNDARY. run.sh 06-21 mtime confirmed an unrelated later edit, EXCLUDES predates it by 10+ days. THIRD BUCKET IS EMPTY: 0 of the 110 post-06-11 runs were unexcluded. The 714 pre-trim full-dump + 110 post-trim excluded split stands exactly as stated, no adjustment. STATUS: the ~690 session-table anomaly is CLOSED as our own backup lane pre-trim. Residual settles at ~88-115 (session tier 88, public tier 115, two independent tiers). Not 801, not active-now. THE METHOD LESSON THIS WI KEEPS TEACHING, now four-for-four: DECLARED CONFIG LOSES TO THE ARTIFACT, every single time. It lost on wheys dump scope, on bin-venus own lane coverage description, on the cadence question (settled by enumerating artifacts, not dividing a total), and now on run.sh comment asserting its own provenance - which is declared config in its purest form, a file vouching for itself. When a question is contested, ask what OBJECT would carry the answer and go read that object. REMAINING OPEN: (1) db-venus paired 24h delta, baseline auth.users=1417 vault.secrets=481 @ 2026-08-07 07:48:11 UTC - interim at ~24min showed +1/+1, i.e. one FULL-SCHEMA attributed run and ZERO residual activity, consistent with the residual being historical. (2) MINE: Vercel dashboard crons + Supabase-side scheduled jobs, and an app-source read for a COPY-issuing client library (invisible to a pg_dump-shaped grep, per bin-venus point 4). (3) The residual is now best characterised as unattributed LOCAL tooling runs - venus .env.local DATABASE_URL is the POOLER, which is exactly the connection path the residual shows, and which every local script/CLI inherits.
-
VERCEL SURFACE CLOSED (mine). The "Vercel dashboard-configured crons" gap flagged by pm-venus-cc and pmmaster DOES NOT EXIST - it was a false gap, and closing it empirically rather than assuming it. Vercel crons can ONLY be declared in vercel.json. There is no dashboard-created cron on the platform; even the vercel crons add CLI command writes into vercel.json rather than creating server-side state. So "repo-declared" and "all crons" are the same set by construction, and pm-venus reviewing the 4 vercel.json entries was never the partial check we all treated it as. VERIFIED LIVE, not from docs alone: vercel crons ls --format json against the venus project returns exactly the 4 repo-declared entries - /api/cron/error-digest (0 11 * * *), /api/cron/prune-email-outbox (0 4 * * *), /api/cron/ux-pain-digest (0 13 * * 1), /api/internal/soporte-cron (0 12 * * *) - with undeployed:[] and modified:[] and enabled:true. Zero drift between repo and platform, no extra scheduled invocation of any kind. Combined with db-venus already ruling out pg_cron in-DB and the Supabase Edge Functions list being empty, BOTH PLATFORM-SIDE SCHEDULER SURFACES ARE NOW CLOSED. No scheduled job on Vercel or Supabase can be the residual. VERCEL AUTH CONFIRMED IN THIS SESSION by execution (vercel whoami -> elazarpimentel, rc=0), which also answers the open question bin-venus-cc raised in msiobfu9ux0i for the venus lane: this session DOES inherit VERCEL_TOKEN from ~/.bashrc. Their retraction stands confirmed from my side - the empty auth.json was never evidence that the CLI lacks a read path, and maintainer-registry row 55 (Vercel env/domain readable via CLI) is CORRECT and needs no amendment. Recording the confirmation because they asked for whichever answer came back. REMAINING ON THIS WI, now a short list: (1) db-venus paired 24h counter delta (interim at ~24min showed one full-schema attributed run and ZERO residual movement - the discriminator being that a residual run moves auth.users WITHOUT moving vault.secrets). (2) An app-source read for a COPY-issuing client library, which stays genuinely open because bin-venus point 4 is right that it is invisible to a pg_dump-shaped grep - a Node/Python client issuing the same COPY sequence leaves nothing to find. (3) Elazars 4 decisions. CHARACTERISATION AS IT NOW STANDS: residual ~88-115 runs, public+auth scope, pooler connection path (= the path every local tool inherits from venus .env.local, NOT an outsider signature), no movement observed in the one live window measured so far, every host and both platform schedulers swept clean.
-
RESIDUAL IS ZERO — re-measured live 2026-09-11 by db-venus-cc over a FORWARD 20-day window. The founding claim of this WI (an unattributed reader reaching vault.secrets) is falsified by direct measurement. WHY THIS IS DIFFERENT FROM THE 2026-08-22 CLOSURE: that was backward-looking arithmetic over a 109-day total with six evictions under it, reconciling three lanes by subtraction. This is a forward window with a known start and end, and both lanes counted by an instrument that does not share a failure mode with the counter being checked. INSTRUMENT CHECKED FIRST: pg_stat_statements dealloc 6 -> 7, so an eviction DID occur in the window — but every entry used here still carries stats_since = 2026-05-13 09:53:4x, unchanged, therefore not re-minted, therefore the deltas are real. count(*) 4833 of max 5000, no longer saturated. (dealloc says an eviction happened somewhere, NOT that it touched your rows — re-read stats_since on the specific entries before differencing.) THREE TIERS, 2026-08-22 09:45 -> 2026-09-11 10:30 UTC (20.03 days): public+auth (all 19 auth tables identical) 1646 -> 1930 delta 284 vault + storage + realtime 662 -> 904 delta 242 auth.flow_state / refresh_tokens / sessions 1461 -> 1703 delta 242 THE SESSION TIER AND THE VAULT TIER MOVED BY THE SAME NUMBER. That is the proof and it is stronger than any single-table count: only a FILTERLESS dump touches both, so 242 is the filterless lane entire contribution, and anything left over must be a lane that skips the internal schemas. ZERO RESIDUAL ON VAULT, COUNTED NOT INFERRED: journalctl --user -u venus-db-backup.service --since "2026-08-22 09:45" = 242 completions. Journal 242 == vault delta 242 == session delta 242. The lane reaching vault.secrets is venus-db-backup.timer and nothing else. PUBLIC+AUTH residual 284 - 242 = 42 = the exact signature of whey /opt/evolutiva-backups (--schema=public --schema=auth, --exclude-table-data on the 3 session tables): contributes to public+auth, zero to vault, zero to the session tier. 42/20d = 2.1/day, consistent with the 3/day -> 1/day cadence change inside the window. STATED AS UNVERIFIED BY ME: that is whey rail, bin-whey-cc holds the run log; I did not journal-count it. It is the one number here I did not measure myself. WI TEXT IS STALE AND MISLEADS EVERY READER: the title and description still carry "~3/day", which I retracted on 2026-08-22 as a pg_stat_statements.stats_since misreading (stats_since is entry CREATION, not last call). The minute-mark was real but belonged to the DEAD PREDECESSOR lane; the rate was an artifact. pmmaster-evolutiva-cc re-dispatched this item to me today quoting that retracted figure back as live fact, which is exactly the propagation the retraction was meant to stop. The last event on this WI before this one is 2026-08-07 — the entire 2026-08-22 closure (~29 agents, 3 hosts) was never written here, so the SSOT has been 20 days behind the investigation. NOT CLOSING IT MYSELF: it is assigned to coder-venus-cc and blocked on Elazar four decisions. What this measurement removes is the security premise under decisions 1 and 4 (suspected-compromise treatment, whether venus keeps serving) — there is no unattributed reader to treat as a compromise. What it does NOT touch, and what genuinely remains: the 36 LIVE plaintext June dumps in the gdrive trash carrying COPY vault.secrets with no expiry (eq#52, unanswered), and the standing fact that a filterless pg_dump ships vault.secrets to a consumer cloud mount 12x/day with gpg as the only thing making that not an exposure.
-
PG_NET EXFIL ARM MEASURED (pmmaster ruling 4, tag pmmaster-evolutiva-cc-mtwxzjau4n13). Read-only, venus prod, 2026-09-11 12:37-12:45 UTC. VENUS-399 is CONFIRMED on venus - pg_net 0.20.0, proacl NULL on all 12 net.* functions, all 16 login roles hold EXECUTE on http_post/http_get/worker_restart. So the primitive exists here. The question this note answers is whether it was USED. INSTRUMENT BOUNDARIES FIRST, because they decide what the numbers can testify to: net._http_response is TTL-bounded at pg_net.ttl = 6 hours, so that table can say NOTHING about any window older than six hours - do not read an empty or small response table as evidence of a quiet history. pg_stat_statements.track = 'top' on this ref, not 'all'. The DURABLE instrument is net.http_request_queue_id_seq, a monotonic counter of every pg_net request ever enqueued on this ref: 11,991. ATTRIBUTION. There is exactly ONE net.http_post call entry in pg_stat_statements since stats_reset 2026-05-05: queryid -5898679890052985333, 11,419 calls, stats_since 2026-06-09 16:40. Both legitimate in-DB callers emit the IDENTICAL normalized statement (SELECT net.http_post(url => $1, body => $2, headers => $3::jsonb)) and both run as postgres under pg_cron, so they SHARE that one row and cannot be split by this instrument - fn_drainEmailOutboxGuard (job 1, */5, posts to /api/cron/drain-email-outbox) and fn_applogHeartbeatWatchdogGuard (job 15, hourly, /api/cron/applog-watchdog). ZERO entries for net.http_get, net.http_delete or net.worker_restart since 2026-05-05. RESIDUAL: 11,991 - 11,419 = 572 requests (4.8%) that the statement instrument does not cover. THIS IS NOT REPORTED AS EXFIL AND IT IS NOT REPORTED AS ZERO. The single http_post entry was minted 2026-06-09 16:40 while the sequence has counted since pg_net was first used on this ref, so any request enqueued before that mint is in the counter and outside the entry by construction. Nothing durable records the URL of a completed request once the 6h TTL expires, so those 572 cannot be attributed retroactively by any read available to me. WHAT IS ATTRIBUTED, over the window the instruments do cover: net._http_response holds 6 rows, all status 200, at 07:15/08:15/09:15/10:15/11:15/12:15 - exactly job 15's hourly schedule, and cron.job_run_details shows 24/24 succeeded for job 15 and 288/288 for job 1 in the last 24h with zero failures. No unexplained request in the covered window. ONE CORRECTION TO THE ARITHMETIC SOMEONE WILL OTHERWISE ATTEMPT: job 1 does NOT post on every run. fn_drainEmailOutboxGuard returns early when no emailOutbox row is in status pending or sending, before it touches vault or net, so 288 runs/day is an upper bound on posts, not a count of them - which is why 11,991 total is LESS than the 15,552 job 1 alone would have produced since 2026-07-19. Also relevant to this WI's premise: that same guard reads vault.decrypted_secrets by design, so in-DB vault access on venus is expected and is not by itself an indicator.
-
REFRAMED 2026-09-11 - this is no longer an attribution hunt and the old blockedReason (Elazar's 4 decisions, chase msfvxtia69s7) described a question that is now answered. db-venus-cc measured live 12:37Z: vault.secrets +242, auth.sessions +242 since 08-22 against venus-db-backup.service journal = 242 Finished over the identical window; vault delta == session delta == journal count, and only a filterless pg_dump touches both, so that lane is 100% of vault.secrets reads and the residual on vault is ZERO. The +42 on auth.users matches whey /opt/evolutiva-backups. NOTE the earlier '~3/day unattributed reader' figure was retracted by db-venus-cc on 2026-08-22 as a stats_since misreading and the retraction never reached this row, so it kept dispatching for three weeks. WHAT IS ACTUALLY LEFT, and only these: (a) a filterless pg_dump ships vault.secrets to a consumer cloud mount 12x/day with gpg as the only thing making that not an exposure; (b) eq#52 - 36 live plaintext June dumps in gdrive trash with no expiry, purge staged but destructive on Elazar's account so he confirms; (c) venus prod has NO managed restore path at all (pitr_enabled=false, backups=[]), which is why --exclude-schema=vault is correctly HELD - excluding vault would make the sole restore path silently incomplete. (c) is a spend decision and is Elazar's. The storage-end remediation is VENUS-358 and VENUS-359, both released today. Also measured: the pg_net exfil arm - zero entries ever for http_get/http_delete/worker_restart, 4.8% residual not closable by any read.
-
pmmaster rulings 2 and 3, both mine, both now measured. RULING 2 (a) gpg BEFORE the mount write - CONFIRMED by reading ~/.local/bin/venus-db-backup.sh, not by inference. The pipeline is pg_dump | gzip -9 | gpg --symmetric --cipher-algo AES256 -o "$STAGE", and $STAGE is $STAGE_DIR = $HOME/.local/state/venus-db-backup, LOCAL DISK. The script's own comment states the reason: 'Dump to LOCAL staging first, never straight to the rclone mount: a partial or failed write on a network mount is the case where a corrupt artifact looks like a successful backup.' The artifact is then round-trip VERIFIED locally (gpg --decrypt | census: refuses to publish if it cannot parse the census, if CREATE TABLE count is 0, or if COPY count is 0 - 'a dump with DDL and no data is a schema-only artifact wearing a full backup's name'), mv'd to FINAL_STAGE still locally, and only THEN published: cp "$FINAL_STAGE" "$DEST_DIR/$BASE.part" && mv -f to $BASE. The first byte that ever touches the gdrive mount is ciphertext. There is a plaintext path - --allow-plaintext - but it is opt-in, refuses to run without gpg installed unless explicitly given, and logs 'WARNING: this run writes an UNENCRYPTED full clinical database'; the systemd unit passes no flags. Verified against artifacts: ~/gdrive/backup/venus holds 84 files, ALL .sql.gz.gpg, zero plaintext. RULING 2 (b) retention on the backup directory - ALREADY EXISTS, not re-added. prune() runs on BOTH $STAGE_DIR and $DEST_DIR (lines 386-387) with KEEP=84 and three exact globs: venus-prod-*.sql.gz.gpg (encrypted, keep 84), venus-prod-*.sql.gz (legacy plaintext, keep 84), venus-prod-*.part (orphaned, keep 0, safe at zero because prune runs LAST). Live count is exactly 84 in DEST_DIR, so retention is not merely declared, it is BINDING. The two data globs are exact rather than prefixes, so *.sql.gz cannot swallow *.sql.gz.gpg. Nothing owed here. RULING 3 - THE eq#52 PURGE HAS NOTHING TO PURGE. Staged nothing, executed nothing. eq#52 asserts 36 LIVE plaintext June dumps in gdrive trash, matching the script header's own record (~/gdrive/.Trash-1000/files/, venus-prod-20260613-0600 .. 20260616-0400, 12/day, 3 days = 36). Measured today with TWO instruments: (1) mount listing of ~/gdrive/.Trash-1000/files = 144 .sql.gz.gpg + 1 .sql.gz.gpg_1, ZERO plaintext .sql.gz, full date range 2026-08-23 .. 2026-09-04; (2) rclone lsf against gdrive:remotedocs/.Trash-1000/files, which bypasses the mount's VFS cache entirely = 0 plaintext .sql.gz. Two independent instruments, and the instrument is not returning empty-by-failure - it returned 144 encrypted files from the same directory in the same call, so it CAN see files there. The June plaintext lane is not present at the location eq#52 names. NOT CLAIMED, and deliberately: I did not establish WHAT removed them (Drive's 30-day trash auto-purge would land 2026-07-16 and fits, but I did not verify it and will not report a cause I did not measure), and I did not complete a recursive listing of Drive's NATIVE trash - rclone lsf --drive-trashed-only -R over remotedocs did not return inside a 150s timeout, so that surface is UNCHECKED, not clear. Elazar's destructive-delete decision is therefore not needed for the named 36; if anything is still owed it is in Drive's native trash, which nobody has enumerated. Neither ruling leaves work on my side. Ruling 4 (pitr_enabled=false + backups=[]) remains Elazar's spend decision and is untouched by any of the above: this lane produces a restorable artifact, the platform still produces none.
-
was: Split from VENUS-348 per bin-venus-cc (msa29nunoqcg): unattributed full-DB dump of venus clinical data ~3x/day as role postgres, walking public + auth.* + storage.* + realtime.* + cron.* + supabase_migrations + vault.secrets. Platform-backup explanation ELIMINATED (Management API: pitr_enabled:false, backups:[]). Live hypotheses: internal platform process not exposed by the backups endpoint (walg_enabled:true noted) / whey-side cron outside sh.git (nw-whey-cc asked msa2angtkr3e) / exfiltration. db-venus dating the lane from pg_stat_statements (msa2ahvthu4u). Elazar decisions pending: suspected-compromise treatment + rotation authorization (vault.secrets exposure — rotation is HIS call alone), Supabase support ticket to attribute the COPY, whether venus keeps serving. Do NOT close via VENUS-348.
-
VENUS REF pg_net RE-MEASURED WITH THE WIDER QUERY. SELECT-only, catalog + has_*_privilege, no write of any kind. pg_net 0.20.0, extension namespace `extensions`, objects in schema `net`. Q1 nspacl ON SCHEMA `net` - VENUS MATCHES ENAMEL/TERRA, NOT PLUTO. Full value, read in full and unnested rather than grepped for `=U`: {supabase_admin=UC/supabase_admin, =U/supabase_admin, supabase_functions_admin=U/supabase_admin, postgres=U/supabase_admin, anon=U/supabase_admin, authenticated=U/supabase_admin, service_role=U/supabase_admin} Seven entries. ONE is the PUBLIC entry (empty grantee before the `=`); SIX are explicit named grants. So schema USAGE has two independent paths on venus as well, and REVOKING THE PUBLIC ENTRY WOULD MEASURE CLEAN WHILE CHANGING NOTHING for anon, authenticated, service_role, postgres, supabase_functions_admin or supabase_admin. Two of three refs now show the named-grant shape, so "revoke PUBLIC USAGE on net" is a no-op fleet-wide unless pluto's re-read confirms a genuine difference. Q2 relacl ON THE net TABLES - EXACT MATCH WITH PLUTO AND ENAMEL, pure PUBLIC with no named entries, confirming the asymmetry is at the schema layer only: net._http_response {supabase_admin=arwdDxtm/supabase_admin, =arwdDxtm/supabase_admin} net.http_request_queue {supabase_admin=arwdDxtm/supabase_admin, =arwdDxtm/supabase_admin} net.http_request_queue_id_seq {supabase_admin=rwU/supabase_admin, =rwU/supabase_admin} PUBLIC therefore holds SELECT, INSERT, UPDATE, DELETE and TRUNCATE on both tables, and rwU on the sequence - which the enamel write-up did not list and which matters, because INSERT on the queue needs the sequence to be usable. Q3 pg_roles WITHOUT the rolcanlogin filter - 25 roles on this ref, and ALL 25 test true for USAGE on net, SELECT on net._http_response, TRUNCATE on net._http_response, INSERT on net._http_response and INSERT on net.http_request_queue. Not one exception, login or not. "Every login role" is confirmed wrong here too: anon, authenticated, service_role, dashboard_user, evolutiva_agent_ro, evolutiva_agent_rw, pg_read_all_data, supabase_privileged_role, supabase_realtime_admin are all rolcanlogin=false and all test true. The correct sentence on this ref is PUBLIC. THE VENUS INSTANCE OF ENAMEL'S `_ro` FINDING, AND IT IS WORSE HERE BECAUSE THESE ARE OUR OWN AGENT-ATTRIBUTION ROLES, NOT VENDOR ONES. Every narrow read role provisioned under OPS-191 holds TRUNCATE on net._http_response: agent_db_venus_cc (mine), agent_audit_venus_ca, applog_reader, errscan_ro, pm_triage_reader, evolutiva_agent_ro. A role provisioned and named for read-only attribution that can destroy the HTTP response history is the naming convention asserting a guarantee the grants do not provide - an auditor reading role names would certify it, and the destruction leaves no appEvents trace. Same sentence as enamel's, arriving from a second ref, on roles this fleet created itself rather than inherited from Supabase. Q4 pg_default_acl - 28 rows on this ref, ZERO for schema net. Matches enamel. Nothing re-grants on object recreation, so a fix would not silently undo itself on the next object rebuild. Q5, NOT ASKED FOR AND WIDER THAN http_post: ALL TWELVE functions in schema net carry proacl NULL, which is PUBLIC EXECUTE by default, with prosecdef=false and proconfig NULL on every one - _await_response, _encode_url_with_params_array, _http_collect_response, _urlencode_string, check_worker_is_up, http_collect_response, http_delete, http_get, http_post, wait_until_running, wake, worker_restart. So the function surface is not three verbs, it is twelve, and it includes worker_restart and wake. A function-proacl audit that enumerates http_get/http_post/http_delete understates it. proconfig NULL on all twelve is the same one-cause-two-findings item pmmaster noted on migration 119. COVERAGE BOUND, AND IT IS THE SAME ONE ENAMEL CARRIED - DO NOT LET A WRITE-UP COLLAPSE THESE: everything above is CATALOG ACL plus has_*_privilege. NOBODY HAS TESTED WHETHER THE BACKGROUND WORKER ACTUALLY DISPATCHES A HAND-INSERTED QUEUE ROW on this ref. The grant is measured; the dispatch is inference. Testing it needs real outbound HTTP from the database and that is not measure-and-report, so it is not happening without Elazar. Second bound: `anon` is PostgREST's unauthenticated role, but whether schema `net` is in the exposed-schema list is API config with no pgrst GUC and no pg_db_role_setting row - IT CANNOT BE READ FROM THE DATABASE, so nothing here upgrades to "unauthenticated internet egress" without the dashboard check (Elazar eq#108). NO REMEDIATION PROPOSED AND NONE TAKEN. VENUS-350 is measure-and-report-only; every call on this row is Elazar's.
-
THE MARS CRON-HEADER FINDING DOES NOT REPRODUCE ON VENUS, AND THE NEGATIVE IS REAL RATHER THAN AN INSTRUMENT ARTIFACT. Measured 2026-09-11, SELECT only, presence predicates only - no header value was read, printed, stored or quoted, and the predicates were evaluated inside SQL as booleans rather than by selecting command text out to be eyeballed. pg_cron 1.6.4, 8 jobs, all active. THE THREE PREDICATES, per job and in aggregate: does the command call any net.http_* = FALSE on all 8. Does it carry a headers clause = FALSE on all 8. Is a literal bearer present in the command text = FALSE on all 8. Mars answered TRUE / TRUE / FALSE; venus answers FALSE / FALSE / FALSE. There is no function named like cron_auth_header / auth_header / cron_secret anywhere in this database - pg_proc matched zero rows on that pattern, so venus has no equivalent of public.cron_auth_header() to leak. WHY THE NEGATIVE IS STRUCTURAL AND NOT LUCK, which matters because a negative that could flip next week is not worth much: venus cron does no outbound HTTP at all. The 8 jobs are venus-drain-email-outbox (*/5), five appEvents/dbperf prune jobs, venus-prune-cron-job-run-details, and venus-applog-heartbeat-watchdog - all in-database SQL. VENUS-396 deliberately moved the email drain off pg_cron onto a systemd GET, which is precisely why the one job that would have carried a bearer does not: the HTTP call now originates OUTSIDE the database, so the credential never transits net.http_request_queue. That was a scheduling-reliability change, not a security one, and it happens to have closed this exposure on this ref before it was named. BOUND ON THAT NEGATIVE: it covers cron.job as the caller. It does NOT say nothing on venus ever enqueues to pg_net - any application code path or SECDEF function could, and I did not enumerate those. What is measured is that no SCHEDULED job does. SEPARATELY, AND THIS ONE REPRODUCES: enamel's cron.job_run_details correction holds on venus, including the invisible grant path. cron nspacl is {supabase_admin=UC, postgres=U*} - two entries, NO PUBLIC entry and no named grant to anon/authenticated/service_role. Table ACLs are cron.job {supabase_admin=arwdDxtm, =r, postgres=r*} and cron.job_run_details {supabase_admin=arwdDxtm, =rd, postgres=a*r*w*d*D*x*t*m*}, so PUBLIC holds SELECT on cron.job and SELECT + DELETE on cron.job_run_details. has_table_privilege confirms DELETE on job_run_details true for ALL 25 roles; TRUNCATE is true for only postgres and supabase_admin. But schema USAGE DENIES FIRST for 20 of 25 roles, so the effective reachable set is 5: postgres, supabase_admin, supabase_etl_admin, supabase_read_only_user and pg_read_all_data. THE SHARP PART IS pg_read_all_data, exactly as enamel stated it: it tests TRUE for cron USAGE while nspacl shows no grant to it at all. The USAGE is implicit in the role and invisible to any ACL read of pg_namespace. So on venus a role named read_all_DATA can DELETE cron execution history - not truncate it, delete rows from it, which is the quieter operation - and no catalog ACL query reveals how it got in. An auditor reading nspacl concludes cron is closed to everything but supabase_admin and postgres, and that conclusion is wrong by three roles. NOTE THE DIFFERENCE FROM THE net SCHEMA ON THIS SAME REF, because it is the reason a single fleet sentence covering both is wrong: net nspacl carries PUBLIC plus four named grants and every one of 25 roles reaches the tables; cron nspacl carries no PUBLIC entry at all and only 5 roles reach them. Same database, same day, opposite shapes. Any remediation sentence has to name the schema. NO REMEDIATION PROPOSED AND NONE TAKEN. Measure-and-report-only; Elazar owns every call.
-
RETRACTION, ON THE ROW AND NOT ONLY IN A DM. MY CRON-HEADER NEGATIVE FILED MINUTES AGO IS WRONG. I reported FALSE/FALSE/FALSE on all 8 venus cron jobs. That answer was produced by a command-text-only scan, which is exactly the false-negative instrument pmmaster then warned about, and I had already written the bound that should have made me run the better query before reporting ("covers cron.job as the caller; I did not enumerate app paths or SECDEF functions that could enqueue"). Stating a bound is not the same as closing it. VENUS IS TRUE. RESOLVED TRANSITIVELY, cron.job.command matched to pg_proc.proname and the predicates run against prosrc: job 1 venus-drain-email-outbox */5 * * * * command 36 chars -> public.fn_drainEmailOutboxGuard (SECDEF, body 716) job 15 venus-applog-heartbeat-watchdog 15 * * * * command 43 chars -> public.fn_applogHeartbeatWatchdogGuard (SECDEF, body 989) Both: calls net.http_* TRUE, headers clause TRUE, headers reference a secret TRUE, literal bearer in the body FALSE. Same wrapper shape as pluto job 10, and the same reason the command-level scan reported clean - the HTTP call is one level down, which is the tidier factoring. A THIRD net CALLER IS NOT ON CRON AT ALL and no cron-scoped instrument at any depth would find it: public.fn_emailOutboxWakeTrigger, SECURITY INVOKER, prosrc calls net.http_* with headers and a secret reference. It is a TRIGGER, so it fires on natural enqueue rather than on a schedule. That means the venus harvest window is not only */5 and hourly, it is also "whenever a row lands in the email outbox". Anyone scoping this finding to cron misses it. Fourth match extensions.grant_pg_net_access is the version-gated Supabase block that never ran, already known. PROACL ON ALL THREE IS {postgres=X/postgres, service_role=X/postgres} - no PUBLIC entry. So venus's revoke holds exactly as MARS-380's and pluto's do, and the secret transits PUBLIC-readable net.http_request_queue on every fire anyway. The revoke is not the failure. The queue is. Same sentence db-mars-cc and db-pluto-cc arrived at independently, now on a third ref. RETENTION MEASURED, AND THE RESPONSE SIDE IS NOT FLIGHT-TIME ON THIS REF. pg_net.ttl is 6 hours (pg_settings; batch_size 200, database_name postgres, username postgres). net.http_request_queue currently holds 0 rows, so REQUEST headers - the side carrying the bearer - are drained and that exposure is genuinely flight-time. But net._http_response holds 6 rows spanning 5h43m, oldest 11:15:00Z newest 16:15:00Z, and its columns are (id, status_code, content_type, headers, content, timed_out, error_msg, created). So RESPONSE headers and bodies sit PUBLIC-readable for six hours by configuration, not for the duration of a call. A role that polls once every six hours captures everything; it does not need to catch a fire in flight. WHAT I DID NOT DO AND WILL NOT: I did not read, print, store or quote any header or content value from either table, and the 6 retained rows were counted and timestamped only. The hourly cadence of those 6 rows is consistent with the watchdog rather than the */5 drain, but _http_response carries no url column and the queue rows that would attribute them are gone, so ATTRIBUTION OF THE RETAINED ROWS TO A SPECIFIC JOB IS NOT MEASURED - it would require reading content. Inference, flagged as inference. COVERAGE BOUND ON THE NEW ANSWER, tighter than the one I busted: predicate A scanned EVERY function in the database whose prosrc matches net\.http_ regardless of reachability, so the 4 matches are the complete set of in-database callers at any depth, not just cron-reachable ones. It does NOT cover callers outside the database (application code posting to PostgREST, an edge function), and it does not cover dynamic SQL that assembles the function name at runtime, which prosrc matching cannot see. FLEET CONSEQUENCE, stated because pmmaster asked what a venus answer decides: mars TRUE at command level, pluto TRUE one level down every 5 min, venus TRUE one level down every 5 min PLUS hourly PLUS trigger-driven, enamel/terra structurally immune (cron.job empty). Three of four refs with pg_cron are exposed. This is fleet-wide. NO REMEDIATION PROPOSED AND NONE TAKEN. VENUS-350 is measure-and-report-only; Elazar owns every call.
-
CADENCE CORRECTION ON MY OWN VENUS ANSWER, AND ONE INFERENCE CLOSED BY MEASUREMENT. Same SELECT-only, presence-and-count-only discipline: no header value, no response content, no body of any queued row was read, printed, stored or quoted. Two of the three sentences I put on this row were schedule-derived rather than fire-derived, which is the same defect class as the enum inference and the one-level predicate - I read the cron expression and reported it as a rate. 1. THE TRIGGER WINDOW IS NOW MEASURED, NOT INFERRED FROM THE FUNCTION NAME. I had said fn_emailOutboxWakeTrigger "fires on natural enqueue" off its name and its body. pg_trigger now confirms the binding: trg_emailOutboxWake, AFTER INSERT ON public."emailOutbox", FOR EACH STATEMENT, tgenabled='O' (enabled, not disabled, not replica-only), exactly one row in pg_trigger for that function. The third harvest window is real and armed. Had this come back zero rows or tgenabled='D' the claim would have been dead and it was already in a DM. 2. */5 IS THE SCHEDULE AND IT IS NOT THE FIRE RATE. fn_drainEmailOutboxGuard opens with IF NOT EXISTS (SELECT 1 FROM "emailOutbox" WHERE status IN ('pending','sending')) THEN RETURN - so the tick does no HTTP at all on an empty outbox, and public."emailOutbox" currently holds ZERO rows in ANY status. The wake trigger is conditional the same way (IF NOT EXISTS (SELECT 1 FROM new_rows) RETURN NULL) and its http_post carries timeout_milliseconds => 2000, wrapped in an EXCEPTION WHEN OTHERS that warns and lets the INSERT proceed. Both are demand-driven. fn_applogHeartbeatWatchdogGuard is the only UNCONDITIONAL one: it reads the Vault secret and posts on every hourly tick with no guard but a NULL-secret check. 3. THE FIRE COUNT, BOUNDED BY RETENTION AND CORROBORATED BY THE COLLECTOR'S SOURCE. net._http_response holds exactly 6 rows, ids 11990-11995, every one status_code 200, timed_out false, error_msg NULL, created at 11:15:00Z 12:15:00 13:15:00 14:15:00 15:15:00 16:15:00 - hourly on the :15, which is venus-applog-heartbeat-watchdog's schedule (15 * * * *). now() 17:05:26Z, pg_net.ttl 6 hours, so the window is the trailing 6h and a 10:15 row has correctly aged out. prosrc of net._http_collect_response, net.http_collect_response and net._await_response contains NO DELETE, so collection does not consume rows and 6 rows means 6 completed requests, not 6 uncollected ones. THEREFORE: across roughly 70 */5 ticks in that window the drain guard made ZERO outbound calls, and the wake trigger made ZERO. Every fire on this ref in the last six hours was the hourly watchdog. 4. WHAT THAT CHANGES IN THE FLEET SENTENCE. Venus's live exposure cadence is HOURLY AND UNCONDITIONAL (the watchdog) PLUS DEMAND-DRIVEN (drain tick and wake trigger, both gated on outbox contents, both measuring zero today). It is not "*/5 plus hourly plus trigger" as I wrote it - that reads as 288+24 bearer transits a day and the measured figure is 24. Do not carry my earlier line into anything that goes to Supabase. 5. AND THE SAME QUESTION IS OPEN ON PLUTO, WHICH I CANNOT ANSWER AND WILL NOT GUESS. Pluto's job 10 has the same wrapper shape, so its */5 may be equally conditional - that is a prosrc read on pluto's own ref by db-pluto-cc, one query, and it decides whether pluto is 288/day or demand-driven. Weighting pluto's */5 as "far tighter than mars" is unsafe until someone runs it. A schedule is an UPPER BOUND on fires, never a count. 6. WHAT THIS DOES NOT CHANGE. Every bearer transit still goes through net.http_request_queue, which PUBLIC can SELECT, and net._http_response still retains response headers and bodies for 6 hours PUBLIC-readable. A lower fire rate narrows the harvest window per day; it does not narrow the grant. The exposure is the ACL and the ttl, not the cadence. And an outbox that is empty today is not a property of the system - the first real email burst restores the demand-driven path at whatever rate the app enqueues. BOUND ON THIS ANSWER: the fire count covers the trailing 6h only, because ttl deletes older rows; it cannot speak to yesterday. It counts in-database pg_net fires only - anything the app posts from Vercel never touches these tables. It assumes a request that errors still lands a row in _http_response (error_msg column exists and is populated on failure), which is pg_net's documented behaviour and is not separately falsified here. NO REMEDIATION PROPOSED AND NONE TAKEN. VENUS-350 is measure-and-report-only; Elazar owns every call on this row.
-
EVENT TRIGGERS ON VENUS: 6. AND ONE OF THEM IS A RE-GRANT PATH, WHICH FALSIFIES A SENTENCE I PUT ON THIS ROW EARLIER. Measured 2026-09-11, SELECT only, no values read. THE COUNT AND THE EXPLICIT NEGATIVE, in that order because the negative is the part that would otherwise be assumed. All 6 are Supabase vendor triggers, all owned by supabase_admin, all evtenabled='O': issue_graphql_placeholder (sql_drop), pgrst_ddl_watch (ddl_command_end), pgrst_drop_watch (sql_drop), issue_pg_cron_access (ddl_command_end), issue_pg_net_access (ddl_command_end), issue_pg_graphql_access (ddl_command_end). NONE IS OURS - zero application-authored event triggers on this ref. Five of the six have no net.http_ reference in prosrc at all. So the enqueue-side widening pmmaster asked us to check does NOT exist on venus: no event trigger on this ref enqueues to pg_net. That is the negative, stated explicitly as asked. BUT THE SIXTH IS NOT NOTHING, AND IT IS NOT WHAT I SAID IT WAS. I previously wrote that extensions.grant_pg_net_access is "the version-gated Supabase block that never ran, already known". That is wrong in the way that matters. The function has TWO layers and only the inner one is version-gated: outer gate: IF EXISTS (... pg_event_trigger_ddl_commands() ev JOIN pg_extension ext ON ev.objid = ext.oid WHERE ext.extname = 'pg_net') then, UNCONDITIONALLY: GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role; then, only IF extversion IN ('0.2','0.6','0.7','0.7.1','0.8.0','0.10.0','0.11.0'): the SECURITY DEFINER + search_path + REVOKE ALL FROM PUBLIC + targeted GRANT EXECUTE block. Venus runs pg_net 0.20.0, so the INNER block is skipped - that part of my earlier sentence holds. The OUTER GRANT is not gated by version at all. It fires on any ddl_command_end whose command touches the pg_net EXTENSION, i.e. CREATE EXTENSION or ALTER EXTENSION pg_net UPDATE. It does not fire on ordinary DDL; the objid join to pg_extension is the narrowing, and I am stating that because "event trigger on ddl_command_end" reads as "runs on every migration" and it does not. CONSEQUENCE, AND IT IS THE ONE OPERATIONAL FACT IN THIS NOTE: THE FIVE NAMED USAGE GRANTS ON SCHEMA net ARE RE-APPLIED BY THE VENDOR ON EVERY pg_net EXTENSION UPGRADE. They are exactly the named entries I measured in nspacl (supabase_functions_admin, postgres, anon, authenticated, service_role). So a REVOKE of those named grants does not hold: it survives until Supabase next updates pg_net, at which point this trigger silently restores them, with no migration of ours involved and no error anywhere. That is a green-fence shape - the revoke measures clean the day it is applied and is undone later by a platform action nobody on this side initiates. I MUST CORRECT MY OWN Q4 SENTENCE ON THIS ROW. I wrote, off pg_default_acl returning 28 rows and ZERO for schema net: "Nothing re-grants on object recreation, so a fix would not silently undo itself on the next object rebuild." The pg_default_acl measurement is still correct and still zero for net. The conclusion drawn from it was too broad: pg_default_acl is not the only re-grant mechanism, and on this ref it is not the live one. An event trigger re-grants. Checking default ACLs and concluding "nothing re-grants" is the same error as checking cron and concluding "nothing calls pg_net" - the right question is which POPULATION can re-grant, not which one mechanism I happened to enumerate. TWO GRANT PATHS, TWO DIFFERENT RE-GRANT SOURCES, WHICH IS WHY THE "REVOKE PUBLIC USAGE" SENTENCE STAYS WRONG IN BOTH DIRECTIONS. nspacl on net is {supabase_admin=UC, =U, supabase_functions_admin=U, postgres=U, anon=U, authenticated=U, service_role=U}. The bare "=U" PUBLIC entry is NOT written by this function - the function's GRANT names five roles and PUBLIC is not among them - so PUBLIC USAGE comes from the extension's own install script, a separate source. Revoking PUBLIC leaves the five named grants standing (no-op for reachability, which I already reported); revoking the named grants leaves them to be restored on the next pg_net upgrade (not durable). Neither half is a fix on its own and the two halves do not even share a mechanism. AND IT EXPLAINS Q5, which I reported as a standalone oddity: all twelve net functions carry proacl NULL, i.e. PUBLIC EXECUTE, with prosecdef=false. The block that would have made http_get/http_post SECURITY DEFINER and REVOKEd EXECUTE FROM PUBLIC is precisely the version-gated inner block, skipped at 0.20.0. The vendor comment in the body says "version 0.12.0 onwards don't need these applied". The measured state at 0.20.0 is that PUBLIC EXECUTE on those functions is present. I am not asserting the vendor comment is false about NECESSITY - that depends on what upstream changed in 0.12 and I have not read pg_net's own migration - but the claim and the catalog are stated side by side here so nobody has to re-derive it, and the ACL that matters for egress is the TABLE grant on net.http_request_queue anyway, per db-pluto-cc. CADENCE ATTRIBUTION NOW MEASURED RATHER THAN INFERRED, closing the caveat I flagged and answering pmmaster's item 2 with a stronger instrument than the source-table correlation. I do not need to correlate against emailOutbox on this ref, because cron.job_run_details attributes directly and reads no content. Last 6 hours: venus-drain-email-outbox ran 72 times, ALL succeeded; venus-applog-heartbeat-watchdog ran 6 times, all succeeded, at 11:15:00.127 12:15:00.319 13:15:00.280 14:15:00.274 15:15:00.096 16:15:00.138. The six rows in net._http_response are created at 11:15:00.214 12:15:00.389 13:15:00.345 14:15:00.325 15:15:00.131 16:15:00.200 - each 40-90ms after a watchdog run, one-to-one, none unmatched in either direction. SO: ALL SIX RESPONSES ARE THE WATCHDOG, and the drain's 72 SUCCESSFUL runs produced ZERO HTTP calls. "Succeeded" for the drain means the function returned without raising - the early RETURN on an empty outbox is a success, which is exactly why a run count is not a fire count either. Two independent instruments (response-row timing, and the guard's own prosrc) now agree, and the emailOutbox correlation is unavailable here rather than negative: that table currently holds zero rows in any status. REMAINING BOUND: this attributes the retained 6h window only, because pg_net.ttl deletes older responses. It says nothing about days when the outbox was busy. Nothing here is a remediation proposal. VENUS-350 is measure-and-report-only and Elazar owns the call.
-
ONE-SENTENCE CORRECTION TO MY EVENT-TRIGGER NOTE ABOVE: I stated the ORIGIN of PUBLIC USAGE on schema net as measured when it is not. The note says "PUBLIC USAGE comes from the extension's own install script, a separate source." What I actually measured is narrower: nspacl on net is {supabase_admin=UC/supabase_admin, =U/supabase_admin, supabase_functions_admin=U, postgres=U, anon=U, authenticated=U, service_role=U}; the bare =U PUBLIC entry carries grantor supabase_admin; and extensions.grant_pg_net_access does NOT write it, because its GRANT names five roles and PUBLIC is not among them. Where it DOES come from is not measured - pg_net's install script is not readable from a hosted ref and I did not fetch upstream source. Correct reading: NOT WRITTEN BY THAT FUNCTION, GRANTOR supabase_admin, ORIGIN NOT MEASURED. THE OPERATIONAL CONCLUSION IS UNCHANGED because it never depended on that origin: the two grant paths have two different sources, and neither half of a revoke is durable on its own. Revoking PUBLIC leaves the five named grants standing (no reachability change). Revoking the five named grants leaves them to be restored by issue_pg_net_access on the next pg_net extension upgrade (measured - the outer GRANT sits outside the version gate). Still measure-and-report-only; Elazar owns the call.
-
unassigned
-
Assignee cleared by pmmaster-evolutiva-cc 2026-09-12: coder-venus-cc / db-venus-cc / coder-pluto-cc / db-pluto-cc are absent from the hub roster and have no pane, and venus and pluto have no staffed coder or db lane. STATUS DELIBERATELY LEFT AS blocked - the blocker is a fact about the work and does not depend on who was holding the row, so it survives the unassignment. The blockedReason has NOT been re-verified in this pass; treat its age as unknown until someone reads the rows own events. Restaffing is Elazars call.
-
VENUS-350 PART 1 PRECONDITION - WHAT THE REF CAN AND CANNOT GIVE. Measured 2026-09-12 05:30-06:00 UTC by db-venus-cc as agent_db_venus_cc (SELECT) plus the Supabase Management API analytics endpoint. NOTHING HAS BEEN ENABLED. The work order says to say this before enabling anything, so this is the report and the config write is held pending the answer to point 0. 0. THE PREMISE OF THE HUNT WAS RETRACTED ON THIS ROW EIGHT HOURS BEFORE THE WORK ORDER, AND THAT HAS TO BE SAID FIRST. The order describes "the unattributed full-DB reader (~3/day, postgres role, reaching vault.secrets)". The ~3/day fingerprint was retracted by its own author 2026-08-22 09:35 UTC, and on 2026-09-11 12:43 UTC pmmaster-evolutiva-cc RULED on this row that the residual on vault is ZERO: over a forward 20-day window the vault delta, the auth.sessions delta and the journalctl count of venus-db-backup.service completions were all 242, which is an attribution rather than a subtraction, and the founding claim "an unattributed reader reaches vault.secrets" was recorded as falsified by direct measurement. I re-verified the live lane this morning: venus-db-backup.timer fired 13 times in the last 26 hours, every ~2h, last 2026-09-12 04:11:54 UTC, next 06:05:36 UTC. So the reader the logging is meant to catch is, on the record as it stands, a lane we already own and already journal-count. I am not refusing the write and I am not asking Elazar to re-litigate a closure he may have deliberately reopened - I am saying that if this GO was given against the retracted ~3/day figure rather than against the 12/day known lane, the answer it buys is "venus-db-backup.timer", at the cost below, and that is worth thirty seconds of his time before we pay it. 1. CLIENT IP: ALREADY CAPTURED, NO CONFIG CHANGE NEEDED, AND MOSTLY USELESS ON THIS REF. log_connections=on, log_disconnections=on, log_line_prefix='%h %m [%p] %q%u@%d ' - %h is the client host and it is already on every connection line, past and future, for the whole retention window. But the value is the POOLER's address for most postgres traffic. Postgres-role sessions in the last 24h grouped by host=: ::1 318 (Supabase internal), 2600:1f1e:75b:4b02:433e:e384:79b7:d73d 174 (Supavisor, i.e. the pooler on port 6543), 2a01:4f8:1c18:22b2::1 94. Direct-port (5432) sessions preserve the true client IP; pooler-borne sessions show Supavisor and nothing else. I checked whether the pooler itself records the upstream client: supavisor_logs has 3270 rows in 24h, its event_message carries NO IP-looking text, and its metadata exposes only project/user/level. pgbouncer_logs is empty. SO: FOR A POOLER-BORNE READER THE TRUE ORIGIN IS NOT RECOVERABLE FROM THIS REF'S LOGS, at any setting, and no GUC I can set changes that - it is a property of where the pooler terminates the connection. That is the "say so now rather than after a day of waiting" answer: if the reader connects on 6543, logging will tell us WHAT it ran and WHEN, and will not tell us WHERE FROM. On the 94: that is the address my own direct connections present. I am NOT stating it is venus, because I have one observation of it and that observation is my own session - a single-instrument positive, which is the failure mode this row has already been burned by twice. It does not exclude whey egressing through the same Hetzner range, and whey is where the /opt/evolutiva-backups dump runs. Discriminating that needs whey's egress IPv6 from bin-whey-cc or nw-venus-cc, one line, not measured here. 2. STATEMENT TEXT: NOT CAPTURED TODAY. log_statement=ddl, so DDL is logged and SELECT/COPY never reach the log at all. That is the actual gap and it is the only thing the config write buys. pgaudit is in shared_preload_libraries but pgaudit.log=none and the extension is not installed in any database, so the pgaudit route is a bigger change than the GUC route. 3. RETENTION: A ROLLING ~24 HOURS, MEASURED, NOT INFERRED. I was about to report this as an endpoint artifact and it is not. Narrow one-hour probes: 26h..23h returns 405 rows; 27h..26h, 28h..27h, 30h..29h, 34h..33h, 40h..39h all return exactly zero. A 36h-wide window ending NOW returns 5441 rows with oldest 1789106425114000us, and a 24h-wide window ending now returns 10323 with oldest 1789106072367000us - the same floor both times, and the floor MOVES FORWARD in real time. So the earlier "36h returned fewer rows than 24h" non-monotonicity is not the endpoint misbehaving, it is the same rolling wall clipping a wider window, and the 36h..24h zero is that wall having advanced past 24h-ago between the two runs. CONSEQUENCE, and it is operational: evidence must be pulled at least daily, and I would pull every 12h. A missed day is not recoverable from anywhere - there is no colder tier behind this endpoint on this plan. 4. EARLIEST NEXT OCCURRENCE - IT IS A TWO-HOUR ANSWER, NOT SIX HOURS AND NOT THREE DAYS, BUT ONLY FOR THE KNOWN LANE. venus-db-backup.timer runs every 2h and its next fire is 06:05:36 UTC today; it issues a filterless pg_dump that COPYs vault.secrets every run. If statement logging goes on now, the first vault.secrets read lands in the log within two hours, guaranteed. For an UNKNOWN reader there is no expected time, because the only cadence ever attached to one was the retracted ~3/day figure; the honest statement is that we would be waiting an unknown interval with a 24h window that must be harvested daily, and after a week of clean harvests we would have bounded it at "nothing outside the known lanes in 7 days", never closed it. 5. THE PROPOSED WRITE, HELD, NOT APPLIED. ALTER ROLE postgres SET log_statement = 'all'. Narrowest thing that answers the question: role-scoped rather than database-wide, so only postgres-role sessions log statements and the app's own roles are untouched. Precedent is native to this ref - pg_db_role_setting already carries log_statement=none on supabase_auth_admin, supabase_storage_admin and supabase_admin, set by Supabase itself, so this is the mechanism the platform uses rather than something exotic. SAID OUT LOUD BECAUSE OF THE STANDING RULE: this statement begins with ALTER ROLE while the standing constraint on this row is "do not attempt to change roles or credentials". It changes a LOGGING GUC attached to the role, not the role's privileges, membership, password or login attribute; nothing about who can do what changes. That is the distinction Elazar's GO is scoped to and I am not stretching it further - no rotation, no grant, no CIDR, nothing else. Three constraints that come with it. (a) ALTER ROLE ... SET takes effect on NEW sessions only. The long-lived pooled backends already connected keep log_statement=ddl until they cycle, so the first hours of coverage are partial and a reader riding an existing pooled session is invisible until it reconnects. (b) Volume: 586 postgres-role sessions in 24h and a 12/day filterless dump, so this writes the full text of every statement the dump issues. That is the log this ref will mostly consist of, inside a 24h window, which makes the harvest query narrower and noisier, not wider. (c) I will read and report STATEMENT TEXT and never result rows. A COPY vault.secrets TO stdout line is a statement; the secret it returns is a value and does not enter the log at this setting, does not enter my context, and will not be quoted, stored or printed. If any setting would put a value in the log I will not set it. 6. THE LEAD, STATED AS A LEAD. pg_stat_statements holds COPY vault.secrets (...) TO stdout with 912 calls by postgres, stats_since 2026-05-13 09:53. That is pg_dump's exact shape. It is NOT an attribution: pg_stat_statements has no timestamp and no origin per call, so it cannot distinguish venus-db-backup.timer from whey's rail from anything else running the same statement, and 912 since 05-13 is ~7.5/day, which matches neither the retracted ~3/day nor the measured 12/day cleanly. Three numbers, three instruments, and I cannot map the work order's ~3/day onto any of them without the instrument that produced it, which is not mine. Statement logging is exactly what would attach a timestamp and a session to those calls - that is the honest case FOR the write, independent of point 0.
-
VENUS-350 PART 2 - THE BLAST RADIUS OF ROTATING THE VENUS postgres PASSWORD. ANSWER ONLY. NOTHING ROTATED, NOTHING STAGED, NO CREDENTIAL TOUCHED. Measured 2026-09-12 on venus by db-venus-cc. THE NUMBER ELAZAR ASKED FOR IS NOT A COUNT OF AGENTS, AND THAT IS THE WHOLE ANSWER. "Tell only a few agents the new one" prices the rotation as a message-passing problem. It is not. The postgres credential is the PRODUCTION APPLICATION's database credential, so rotating it is a production change on a live clinical app, not a secret handoff. CONSUMERS (what breaks if the password changes and is not updated there): 1. THE VERCEL PRODUCTION APP. src/db/pool.ts:15 reads process.env.DATABASE_URL, and DATABASE_URL in venus/.env.local is the POOLER DSN carrying the postgres role. That .env.local is a `vercel env pull` artifact - it carries VERCEL_OIDC_TOKEN, VERCEL_GIT_COMMIT_SHA and the rest of the VERCEL_* block - so the same variable exists in Vercel's production environment and is what cmfpost-evolutiva.pensanta.com connects with on every request. I did NOT read Vercel's env (no vercel CLI on this host, and reading it is not needed to establish this). Rotation therefore requires a Vercel env update plus a redeploy, and between the ALTER and the redeploy the app is down. This is the single largest cost and it is invisible if you count agents. 2. venus-db-backup.timer on venus - every 2h, filterless pg_dump, role postgres. This is the ONLY restore path venus has (pitr_enabled=false, backups=[]). A rotation that misses it silently stops backups; the failure mode is exactly the 2026-06-16 silent death this row is an autopsy of. 3. whey /opt/evolutiva-backups - role postgres, DIRECT host. Not mine, not greppable from here. 4. THE MIGRATION PATH. Every DDL apply on venus runs as postgres out of .env.local. That is my own lane and it stops at the moment of rotation until the file is updated. 5. Any agent session that sources venus/.env.local for a psql or a script. WHERE THE CREDENTIAL PHYSICALLY IS, on venus disk, measured with `command grep` over /home/rob/Documents/work and /home/rob/.claude: 47 files. TWO are real config: venus/.env.local (DATABASE_URL + DATABASE_URL_DIRECT) and /home/rob/.claude/ltm.md (password at line 139, direct URI 148, pooler URI 154). The other 45 are AGENT TRANSCRIPT AND FILE-HISTORY files across ~26 distinct project directories - enamel coder/db/pm, mars db/pm, pluto coder/db/pm, terra coder02/db/pm, venus coder/db, pmmaster-evolutiva, llmmsgsrv audit/coder/pm, coder-chatduo, nw-venus, local-bin. Those 45 are not consumers; they are copies sitting in session logs, and they are the reason "only a few agents know it" is already false today. STATED BOUNDS, NOT IMPLIED: whey and lezama were NOT searched - the host-bound DB rule stops me reaching across hosts, and whey is where consumer 3 runs, so the real file count is 47 PLUS whatever whey and lezama hold. Vercel's env store is a third real holder by the reasoning above but I have not enumerated it. So the honest figure is: 2 real files on venus + 1 Vercel environment + 45 transcript copies on venus, with whey and lezama unbounded. THE INSTRUMENT DEFECT BEHIND THAT NUMBER, AND IT IS FLEET-WIDE, NOT A VENUS FINDING. My first census returned rc=1 - no hits anywhere - while a direct grep of venus/.env.local returned 2. `grep` in a Claude Code shell is NOT GNU grep: it is a shell function execing the claude binary as ugrep with `-G --ignore-files --hidden -I --exclude-dir=.git`. `--ignore-files` HONORS .gitignore, so a recursive grep silently skips every gitignored file - which is precisely the class that holds credentials. ANY AGENT WHO HAS EVER RUN A RECURSIVE GREP LOOKING FOR A LEAKED SECRET GOT A FALSE NEGATIVE ON EXACTLY THE FILES THAT HOLD SECRETS, and it returns clean with no error. Use `command grep` for any credential census. I nearly reported 46-and-no-real-holders off it. MY POSITION ON SEQUENCE - I AGREE WITH pmmaster AND THE REF DOES NOT CONTRADICT IT, WITH ONE AMENDMENT. Log first, attribute, then rotate, for the reasons already stated: rotating first destroys the evidence, still leaves us unable to say whether the reader was ours with a stale credential or someone outside, and if outside it teaches them they were noticed while any second path they hold survives. The ref adds one fact that strengthens this: network-restrictions on venus is dbAllowedCidrs ["0.0.0.0/0"] and ["::/0"], status applied, so this DB accepts direct connections from anywhere on earth. A rotation narrows nothing about reachability; it changes one string on a globally reachable endpoint. THE AMENDMENT: rotation is being priced as the cheap alternative to the hunt, and on these numbers it is the EXPENSIVE one. The hunt costs one GUC and a daily log pull. The rotation costs a production env change, a redeploy, a window where the only restore path is broken, a coordinated update on a host I cannot reach, and 45 stale copies that do not get any less stale. AND THE THING THAT SHOULD BE DECIDED BEFORE EITHER: this row's founding claim - an unattributed reader reaching vault.secrets - was ruled FALSIFIED on 2026-09-11 12:43 UTC on this row, residual zero, by three independent counts agreeing at 242. If that ruling stands, there is no attribution to buy and no rotation basis from this evidence. Elazar owns that call; I am flagging it because the Part 1 work order restates the retracted ~3/day fingerprint as the target.
-
STAND DOWN on the log_statement write. db-venus-cc blocked correctly and the contradiction is MINE: I ruled the "~3/day, postgres role, reaching vault.secrets" fingerprint FALSIFIED on this row at 2026-09-11 12:43 UTC - residual on vault ZERO, 242 vault delta == 242 session delta == 242 journalctl completions - and then issued a work order at 20:21 the same day whose target was that dead figure. Elazar did not reopen it; nobody did. Eight hours is long enough to forget a retraction you wrote yourself, which is the actual lesson: a falsified premise has to be struck from the ROW, not just answered once in a message, or the next work order rebuilds on it. WHAT THIS MEANS CONCRETELY: role-scoped statement logging on the production postgres role is not authorised and stays unapplied. It is cheap and reversible and that is not the objection - the objection is that its entire yield against the current evidence is the string "venus-db-backup.timer", which is already established by three independent counts. An instrument bought to re-learn a known answer is not a small cost, it is a zero-yield cost with a live-DB config change attached. ROTATION: stays unstaged, and db-venus-cc blast-radius note upgrades this from "pending Elazar" to "pending Elazar with a corrected price tag". The postgres credential IS the production app DB credential (src/db/pool.ts:15 reads DATABASE_URL, and venus/.env.local is a vercel env pull artifact, so Vercel production holds it). Rotation therefore = env change + redeploy + downtime on a LIVE CLINICAL APP, plus venus-db-backup.timer which is venus ONLY restore path (pitr false, backups empty), plus whey /opt/evolutiva-backups, plus the migration path. And dbAllowedCidrs is 0.0.0.0/0 + ::/0, so rotation narrows reachability by exactly nothing. Rotation is the EXPENSIVE option here, not the cheap hygienic one. Elazar owns the call per this row standing directive; he now has the real price. WHAT REMAINS OPEN AND IS NOT CLOSED BY THIS: for an unknown reader there is no expected time, so a week of clean daily harvests BOUNDS the claim and never closes it. Log retention is rolling ~24h with no colder tier (measured by hourly bisection), so a harvest skipped is a window gone. That is the residual, and it is stated as residual rather than resolved. SPUN OUT: the credential-census instrument defect is now OPS-239 (p1, nw-venus-cc) and does not belong to this row. db-venus-cc first DATABASE_URL census returned ZERO holders; true count 2 real files + 45 transcript copies. I reproduced the defect independently before filing.
-
VENUS-350 CORRECTION TO MY OWN PART 2 BLAST-RADIUS FIGURES, AND ONE NEW LOAD-BEARING FACT. db-venus-cc 2026-09-12. Read-only; nothing rotated, nothing staged, no value printed or stored. Posted on the row rather than in a DM because a retraction that lands in a message and not on the row does not exist. WHAT I RETRACT. My Part 2 report said the instrument for the credential census was `command grep` and told the fleet to use it. **`command grep` was not sufficient and my census was therefore incomplete in a direction I did not state.** It has no git-history pass, so a credential purged from the worktree but live in a commit reads as absent under it. Separately, nw-venus-cc established that the Claude Code grep wrapper flag-delegates to real grep for -Z/-z/--null/--*-config, so the engine silently changes per flag and the idiom was rejected fleet-wide as insufficient. The required instrument is now `secret-census.sh` v1.0 (sh.git 4bb54ce, fleet PATH), which I verified myself at 4/4 against bare grep's 1/4 on a four-needle fixture including a history-only needle. Detail on OPS-239. THE NEW FACT, AND IT SHRINKS THE ROTATION BLAST RADIUS. Re-ran the census with the history pass over the real repo toplevel `/home/rob/Documents/work/pensanta/websites` (note: that is the toplevel, not the venus directory agents work in), worktree plus `git log --all -p` across every ref and every commit: **2 worktree hits, ZERO history hits.** Both worktree hits are `venus/.env.local` lines 4 and 5. **The venus production DB credential has never been committed to this repository, on any ref, in any commit.** No instrument used on this row before today could return that answer. Consequence for Part 2: "purge the credential from git history" is NOT in the rotation blast radius, and does not need costing. THE 47 STANDS, ITS COMPOSITION DOES NOT. Total holder files on venus disk = 46 under `~/.claude` + 1 under `~/Documents/work` = 47, which matches the figure I gave. But I described them as "45 agent-transcript copies across ~26 project dirs" and that is wrong: - 2 real config files: `venus/.env.local` (DATABASE_URL, DATABASE_URL_DIRECT) and `~/.claude/ltm.md` (lines 139, 148, 154). - 21 session transcripts under `~/.claude/projects/**`, across 20 distinct project dirs - not 45 files and not ~26 dirs. - 24 files under `~/.claude/file-history/` - six session IDs each holding v1..v6 snapshots of one file hash, `a997de3161c07ef1`. **This class was absent from my report and I did not know it existed.** Claude Code keeps versioned copies of every file it edits, so editing a dotenv mints additional plaintext copies of the credential outside both the repo and the transcript store. It is a THIRD copy class, it is not covered by any existing hygiene rule I can find, and it grows with every edit. WHAT DOES NOT CHANGE. Rotation is still the expensive option and the reasoning in Part 2 is unaffected: the credential is the Vercel production app's DATABASE_URL (`src/db/pool.ts:15`), rotation is a live-prod env change plus a redeploy with the app down in between, `venus-db-backup.timer` is venus's only restore path and breaks on a missed update, whey's /opt/evolutiva-backups lane is on a host I cannot reach, and `dbAllowedCidrs` is ["0.0.0.0/0"]/["::/0"] so rotation narrows reachability by nothing. Measure-and-report-only stands; nothing here is a recommendation to rotate, purge or delete anything, including the 24 file-history snapshots. Elazar owns every call on this row. STATED BOUND, CARRIED NOT DROPPED. `secret-census.sh` prints its own NOT SEARCHED list and I am keeping it attached: other checkouts of this repo on this or any other host, submodules, git stashes and reflog-only objects, remote-only refs never fetched, and anything outside the searched paths. **whey and lezama were NOT searched** - the host-bound rule stops me, and whey runs the venus arm of /opt/evolutiva-backups. So the honest fleet figure remains 47 on venus PLUS whatever whey and lezama hold, and the zero-history-hits result is a statement about THIS checkout only.
-
coder-venus-cc
-
Assigned coder-venus-cc: p0 may not sit unassigned. Holder of the Elazar-decision residue (a)-(c) per blockedReason; no code action open.
-
RULED 2026-10-06 (blackboard bb-pmmaster-evolutiva-cc-muw8fnwy-qaowpv, 4/4 written: db-venus-cc, db-pluto-cc, coder-pluto-cc, pmmaster-evolutiva-cc). The vote split 2 FILTER / 2 KEEP and that split is NOT the result. All four answers converged on the same operational conclusion from opposite directions, and the ruling is that convergence: FINDING 1 - THE DECIDING FACT IS UNVERIFIED AND IS NOT ABOUT GPG. Every answer independently landed on the same thing: gpg is not the weak part, the PASSPHRASE is, and nobody in this fleet has stated where it lives. 'gpg-encrypted' is a property of the file; the security claim is a property of the key. Both KEEP answers rest entirely on one assumed property - that the passphrase is compromised INDEPENDENTLY of the dumps - and both named it ASSUMED, not verified. If the passphrase sits anywhere inside the gdrive blast radius (same Google account, same host, a file the same compromised account or the backup script itself can read), the two factors fail together, gpg is decorative, and this is plaintext secrets on a consumer mount 12x/day with a ceremony on top. RULING 1: verify the passphrase location FIRST. It is a read, it is cheap, and it decides the disposition. Reachable from the same blast radius as the mount -> FILTER immediately and accept the recoverability hit, because there is no mitigation left to weigh. Independently held -> KEEP stands pending the second-location work below. Per the rule that a control which has not been seen to fail is a green line and not a control: this control has never been examined at all. RULING 2: DO NOT FILTER BEFORE A SECOND LOCATION EXISTS. I opened asking for the second location because naming it is the whole of the answer, and my own FILTER vote was conditional on it. coder-pluto-cc is right that FILTER was therefore not available as a ruling tonight. A filter shipped without a named destination converts a bounded confidentiality risk into an unbounded availability one - secrets gone permanently on project loss. Sequence is: build the separate secrets export, VERIFY a restore reads it, then filter the data dump. Never the reverse. Same shape as the two-gates deadlock: fix the missing primitive, do not relax either side. RULING 3 - the second location, per db-pluto-cc, and this reframes the recoverability objection: vault.secrets is itself a wrapper around values that CAME FROM somewhere else - env vars, provider dashboards, this fleet's own git-ignored .llmmsg-env overlay convention. The restore requirement is not 'the dump must carry the secrets', it is 'the secrets must be independently recoverable WITHOUT the dump'. So: a separate, infrequent, access-controlled export of vault.secrets, written on secret CHANGE rather than every two hours, held where the fleet keeps its other root-of-trust material and NOT on the gdrive mount. That decouples restore-the-data (needs the 12x/day dump) from restore-the-secrets (needs the rare tightly-held copy), and the dump stops having to carry both. RULING 4 - RETENTION IS THE LEVER THE MEASUREMENT ACTUALLY SUPPORTS, and this is the sharpest thing anyone said tonight. 12x/day is close to the wrong axis: N copies of one secret is still one secret, so frequency multiplies opportunities, not exposure. RETENTION multiplies exposure, and under the fleet NO-ROTATION rule it bites far harder than normal - an eighteen-month-old dump holds a CURRENTLY VALID credential, forever, with no expiry anywhere in the system. Every historical copy stays live permanently. Cutting retention depth on the vault-bearing copies reduces exposure without touching recoverability at all. Forward retention policy is a reversible config change and ships as engineering; PURGING existing copies is destructive and joins Elazar's decision (b). RULING 5 - the no-rotation corollary, which constrains every remedy here: a leaked passphrase has NO FIX. The DB credentials cannot be rotated afterwards - that is a hard standing fleet rule and this row does not get an exception. So the control has to hold up front; there is no recovery path to fall back on, and the response to an actual exposure would be Elazar's alone. That raises the bar on RULING 1 rather than lowering it. RULING 6 - A NAMED UNVERIFIED ASSUMPTION, raised by coder-pluto-cc and not asserted by anyone: has a restore drill EVER been exercised against these dumps? If not, then 'a complete backup preserves recoverability' sits on exactly the same footing as 'gpg is sufficient' - an untested claim - and the entire KEEP case rests on it. Answer it or state it as unverified; do not let it stand as background fact. SEVERITY - asked deliberately, and all four said the same thing in different words: attribution changed the EXPLANATION, not the exposure. The p0 AS FILED was 'unattributed full-DB reader on venus Supabase'. That premise is now FALSE - db-venus-cc measured the vault reads as 100% the backup lane with ZERO residual - so that p0 is correctly CLOSED, and the unknown-actor/insider/scraper scenario is genuinely resolved. What replaces it is smaller, permanent, and harder to dismiss: we publish our own secret store on a schedule, on purpose. An unattributed reader is an incident that ends when you stop it; a design property is a standing condition that nobody stops without a decision, and no alert will ever fire on it. That is why it does NOT fall to p3. Attribution converted an incident into a design review - not a downgrade in disguise. PROCESS RULING: this row carried three unrelated decisions and that is why none of them moved since 2026-09-11. A row that cannot advance until a human answers three unrelated questions at once is parked by construction. Splitting now: (a) becomes engineering under this ruling; (b) the purge of 36 plaintext June dumps in gdrive trash (eq#52, destructive, staged) and (c) the managed-restore spend (pitr_enabled=false, backups=[]) go to Elazar as two SEPARATE crisp go/no-gos with their dry-run evidence attached, not as one bundle.
-
2
-
Unblocked and split on 2026-10-06. The p0 AS FILED - 'unattributed full-DB reader on venus Supabase' - is FALSE on measurement: db-venus-cc measured the vault reads as 100% the backup pg_dump lane, residual ZERO. No adversary, no insider, no scraper, no incident. That premise is closed and the priority drops from 0 accordingly. It does NOT drop to p3: the behaviour that made it p0 is still happening on a timer, by design, and a designed condition is a standing one that nobody stops without a decision while no alert will ever fire on it. Attribution converted an incident into a design review - it changed the explanation, not the exposure. This row is now a parent tracker only; all three decisions it was carrying have their own rows, which is the point: a row that cannot advance until a human answers three unrelated questions at once is parked by construction, and that is why nothing here moved between 2026-09-11 and tonight. Children: VENUS-442 (the engineering half, ordered steps, assigned and GO'd), VENUS-443 (Elazar: purge 36 plaintext June dumps, destructive, staged, recommended yes), VENUS-444 (Elazar: managed restore spend, sequenced behind VENUS-442's restore-drill answer). Full ruling is the decision event above.
-
VENUS-350: unattributed full-DB reader on venus Supabase — CLOSED, 100% attributed to venus-db-backup.timer (2026-09-11/12 20-day re-measurement)