fn_notify_applog_err COALESCEs userAgent to empty string in NOTIFY payload
Pluto live function is public.fn_notify_applog_err(), NOT Venus applog_notify_error. Live source is db/migrations/applied/061-pluto-545-fn-notify-applog-err-route-signature.sql (later than June supabase/migrations copy). Current live prosrc, measured read-only on 2026-10-06, applies COALESCE to NEW.userAgent before left(..., 300); owner postgres, EXECUTE ACL postgres/service_role, search_path public. This turns NULL into empty string in the NOTIFY payload. Pluto PLUTO-160 deliberately stores NULL userAgent for stripped categories; this collapses policy-stripped, never-captured and absent. Last 30d notify-level appEvents (error/fatal/warn): 105 NULL userAgent of 266 rows, 0 empty strings (read-only aggregate). Fix is trigger-only: left(NEW.userAgent, 300), preserving quoted SQL identifier and the 300 cap. Pluto source writers already preserve NULL; do not port Venus 2-caller change or Mars 500 cap. VENUS-344 is DONE; no longer a dependency. BEFORE WRITING: original row required a second check for any catch-up sweep SQL that COALESCEs userAgent and a consumer null-safety check. Narrow Pluto src/scripts/db and accessible terminal scans found no local listener/sweep implementation; support-evolutiva-cc asked for external path/owner. Do not assert absent until that is answered. Migration uses numbered pending db/migrations file, never edits applied 061 or older supabase lineage. Preflight must assert exact live old fragment including space after comma, and postflight must assert new fragment and forbid old COALESCE. Audit pre-apply review required. Pluto has no write-capable DB seat in db-pluto-ca; production apply is Elazar-gated, with new exact-byte GO only after source and tests.
Activity
-
db-pluto-ca
-
fn_notify_applog_err COALESCEs userAgent to empty string in NOTIFY payload
-
Premise corrected per support-evolutiva-cc spec /data-venus/evolutiva/2026-10-06-pluto-770-useragent-coalesce-spec.md (md5 f467e24e0ca3c08990f40c134df1ffb7): Pluto function is fn_notify_applog_err, not Venus applog_notify_error. Pluto live lineage is db/migrations/applied/061, not older supabase/migrations copy. Trigger-only fix removes COALESCE around NEW.userAgent while retaining 300-char cap; no app caller change. db-pluto-ca owns source migration via forwarded db-pluto-cc seat; apply remains Elazar-gated because no writer credential. Prior row description remains historical evidence, not current target name.
-
Assigned to db-pluto-ca. Corrected function name; verified spec md5 and live postgres-owned fn_notify_applog_err body, ACL {postgres,service_role}, search_path public, exact COALESCE fragment. Last 30d notify-level appEvents: 105 NULL userAgent of 266 rows. Holding source draft until original row pre-write gate (external catch-up sweep and consumer null-safety) is resolved; support asked for exact path/owner. No production write.
-
was: pluto/db/migrations/applied/061-pluto-545-fn-notify-applog-err-route-signature.sql:35 emits left(COALESCE(NEW."userAgent", ''), 300), byte-identical to venus's applog-notify-add-useragent.sql. mars (012-mars173, 046-mars439) emits left(NEW."userAgent", 500) with no COALESCE and is the correct reference, so the fleet split is mars=null, venus+pluto=''. Consequence: never-captured and captured-empty are indistinguishable at the alert rail for every error row with a NULL userAgent. Measured on venus 2026-10-06: 104 of 191 level=error rows carry NULL userAgent, i.e. the majority, and all of them notify as ''; pluto's population is unmeasured from this seat and must be censused before sizing. BLOCKED-BY VENUS-344 BY DESIGN, not by preference: fix venus first and copy the applied shape. Do NOT write this one independently. Check BEFORE writing anything, because venus's investigation turned up a site the original venus spec missed: pluto may have the same SECOND collapse in its own catch-up sweep SELECT (venus's is applog-listen.ts:1501, left(COALESCE("userAgent",''),300)). The trigger and the sweep are two independent paths to the same field, and fixing one alone makes the two rails disagree on the same row, which splits burst-dedup into two keys (the key is userAgent ?? '__no_ua__', so '' and null are different keys). That is a regression, not a partial fix. Census pluto's sweep path first. Also verify pluto's consumers null-guard before dropping the COALESCE - on venus classify.ts:172, the payload parse and the burst key were all already null-safe, with a test asserting it, but that is a venus measurement and says nothing about pluto. Trigger DDL: db lane, audit pre-apply review.
-
was: Pluto live function is public.fn_notify_applog_err(), NOT Venus applog_notify_error. Live source is db/migrations/applied/061-pluto-545-fn-notify-applog-err-route-signature.sql (later than the June supabase/migrations copy). Current live prosrc, measured read-only on 2026-10-06, emits userAgent as left(COALESCE(NEW."userAgent", '\), 300); owner postgres, EXECUTE ACL postgres/service_role, search_path public. This turns NULL into empty string in the NOTIFY payload. Pluto PLUTO-160 deliberately stores NULL userAgent for stripped categories; this collapses policy-stripped, never-captured and absent. Last 30d notify-level appEvents (error/fatal/warn): 105 NULL userAgent of 266 rows, 0 empty strings (read-only aggregate). Fix is trigger-only: left(NEW."userAgent", 300), preserve 300 cap. Pluto source writers already preserve NULL; do not port Venus 2-caller change or Mars 500 cap. VENUS-344 is DONE; no longer a dependency. BEFORE WRITING: original row required a second check for any catch-up sweep SQL that COALESCEs userAgent and a consumer null-safety check. Narrow Pluto src/scripts/db plus accessible terminal scans found no local listener/sweep implementation; support-evolutiva-cc asked for its external path/owner. Do not assert absent until that is answered. Migration uses numbered pending db/migrations file, never edits applied 061 or older supabase lineage. Preflight must assert exact live old fragment (including space after comma), and postflight must assert new fragment and forbid old COALESCE. Audit pre-apply review required. Pluto has no write-capable DB seat in db-pluto-ca; production apply is Elazar-gated, with new exact-byte GO only after source and tests.
-
Source draft db/migrations/135-pluto-770-notify-useragent-null.sql SHA256 dc73dbd6e68101c1d8552e4ec943ddbfa5e74290ac8a7161ba4ac03a5b6448f2 sent to audit-general-ca for source-only review; old live body hash f5d4fb36, expected one-substitution new body 0dffcf2e. Shared Venus sweep source is null-safe (6964dbe) but long-lived applog-listen@pluto process started 2026-09-22 before that code, so running null-safety unverified; registered maintainer coder-venus-cc asked to verify/restart. No Pluto write-capable DB seat and no exact-byte apply GO. Do not apply until runtime consumer, audit, and apply route clear.
-
Support finding independently verified 2026-10-06: old Venus listener commit 44743e7 enqueue :1138 maps null userAgent to __no_ua__, and running applog-listen@pluto MainPID 3624921 started 2026-09-22. Direct NOTIFY null payload is compatible; the earlier "running null safety unverified" hold is withdrawn. Caveat measured in same old source: catchUp SELECT :1468 still COALESCEs stored NULL to empty string, then enqueues newRows through the same burstMap. Once Pluto trigger stops COALESCEing, NOTIFY and catch-up can classify two NULL-UA events into different burst keys, potentially suppressing a second-occurrence page. Current Venus HEAD fixed catch-up normalization but running process predates it. Trigger migration 135 unchanged SHA dc73dbd6e68101c1d8552e4ec943ddbfa5e74290ac8a7161ba4ac03a5b6448f2; source audit still pending; no apply GO/seat.
-
Direct NOTIFY runtime-null compatibility verified in old running listener; remaining cross-rail mismatch: old catchUp COALESCEs stored NULL to empty string while new Pluto NOTIFY would send NULL, splitting burst keys. Need maintainer restart/verification of null-normalizing listener or explicit PM residual acceptance, plus source audit, exact-byte apply GO and writer seat. No DDL run.
-
audit-general-ca source-only PASS on exact SHA-256 dc73dbd6e68101c1d8552e4ec943ddbfa5e74290ac8a7161ba4ac03a5b6448f2, tag audit-general-ca-muwsra0dfc9r. Audit independently rehashed draft and prosrc: live 061 preimage MD5 f5d4fb36, new 0dffcf2e, sole body difference left(COALESCE(NEW."userAgent", '\), 300) to left(NEW."userAgent", 300). Preflight pins old body/owner/ACL/search_path/trigger; postflight pins new body and unchanged metadata in file transaction. No SQL run, no listener/process exercise, no apply GO. Separate live listener finding: old running 44743e7 direct NOTIFY path maps NULL to __no_ua__, but its catch-up SQL maps stored NULL to empty, splitting burst keys until 6964dbe process restart or explicit residual acceptance. PM order: 133 review/handoff first, 770 second; no overlapping DB objects.
-
Exact-byte SOURCE PASS audit-general-ca-muwsra0dfc9r on dc73dbd6. PM sequence: 133 first, 770 handoff second. Remaining: long-lived listener catch-up cross-rail NULL/empty burst-key mismatch pending maintainer restart/readback or PM acceptance; no authorized writer/apply GO (Elazar-gated). No SQL applied.
-
Cross-rail burst-key divergence hold is CLEARED by a restart, not a deploy: the applog-listen units run tsx against the LIVE venus working tree (node .../venus/node_modules/.bin/../tsx/dist/cli.mjs scripts/applog-listen.ts), and scripts/applog-listen.ts + scripts/lib/burst-classify.ts are both clean at 6964dbe, so the VENUS-344 code half was already on disk and only the process was stale (all five instances had run since 2026-09-22 19:16:23). Restarted applog-listen@pluto and applog-listen@venus 2026-10-06 15:02:54 UTC by support-evolutiva-cc; new MainPIDs 2965047 and 2964927, both active, 'catch-up clean', heartbeat written, no missed events. Pluto now runs catchUp SELECT left("userAgent",300) at :1505 plus normalizeUserAgent at :1516 and :1634, so NULL and '' produce a bit-identical burst key on both rails and the DDL is a grouping no-op as specified. NOT restarted: mars, terra, enamel - their triggers still COALESCE to '', so both rails already agree and normalizeUserAgent maps both to null; they remain on the Sep-22 process. Apply authority for the DDL itself is unchanged (Elazar-gated, pluto has no write-capable DB seat).
-
coder-venus-cc verified actual running applog-listen@pluto image is Venus 8404168, MainPID 3624921 started 2026-09-22 19:16:23 UTC (tag coder-venus-cc-muwt043rx4df), not 6964dbe. Independently read exact 8404168: enqueue :1151 maps NULL UA to __no_ua__, catch-up SELECT :1481 maps stored NULL to empty string, and :1520 passes missed rows through SAME enqueue/burstMap. After migration 135, a two-event NULL-UA burst split NOTIFY then catch-up can key as signature::__no_ua__ versus signature::, each first-in-key/log-only, missing second-occurrence page. This is apply compatibility residual only, not source/handoff blocker; maintainer asked for any contrary rail invariant. No restart, SQL or apply. Source PASS dc73dbd6 remains valid; PM sequence 133 first, 770 second.
-
2026-10-06 listener compatibility READBACK after support-evolutiva-cc restart: systemctl --user show applog-listen@pluto.service reports MainPID=2965047, ExecMainStartTimestamp=2026-10-06 15:02:54 UTC, ActiveState=active. Venus working-tree scripts/applog-listen.ts + scripts/lib/burst-classify.ts clean and byte-identical to commit 6964dbe (git diff 6964dbe HEAD -- paths exit 0; path status empty): catch-up SQL :1505 left("userAgent",300), catch-up normalize :1516, NOTIFY normalize :1634, shared burstKey in lib :87-88 maps null/empty to same no-UA sentinel. Cross-rail apply compatibility hold CLEARED. Support reports catch-up clean/heartbeat; I did not independently read logs/heartbeat. Draft 135 unchanged SHA-256 dc73dbd6e68101c1d8552e4ec943ddbfa5e74290ac8a7161ba4ac03a5b6448f2, audit SOURCE PASS. No production DDL/apply; PM 133-first handoff sequence and Elazar-gated writer/apply remain.
-
Listener cross-rail gate cleared by restarted Pluto unit PID 2965047 and clean 6964dbe dual-rail code. Source PASS on 135 dc73dbd6. Await 133 handoff first, then coder-pusher handoff of 770 frozen file; production DDL apply remains Elazar-gated with no local writer seat/GO. No SQL applied.
-
Maintainer coder-venus-cc tag coder-venus-cc-muwta02nkee8 confirms post-restart Pluto listener PID 2965047, child tsx 2965124, active since 2026-10-06 15:02:54 UTC, loaded 6964dbe dual-rail code. Journal readback reported state loaded cursor=2026-10-06 15:02:17.097475+00, catch-up clean, heartbeat written; cursor continuity across explicit restart. Listener path no commits after 6964dbe; catch-up left(userAgent,300) and normalize at :1516, NOTIFY normalize :1634. Cross-rail NULL/empty burst-key residual CLEARED. Mars/terra/enamel units remain on old 8404168 image but their triggers still COALESCE; no action on other apps in PLUTO-770. No production DDL/apply.
-
133 frozen-file handoff landed e710767; PLUTO-770 exact-byte source PASS dc73dbd6, listener gate cleared, coder-pluto-cc asked to handoff-push migration 135 only. No apply GO/writer seat.
-
Read-only 2026-10-06 live preimage recheck immediately before handoff: public.fn_notify_applog_err() prosrc MD5 f5d4fb36580432490f074262c32ccb1d, owner postgres, ACL {postgres=X/postgres,service_role=X/postgres}, proconfig {search_path=public}; source file 135 SHA-256 dc73dbd6e68101c1d8552e4ec943ddbfa5e74290ac8a7161ba4ac03a5b6448f2 unchanged, audit SOURCE PASS tag audit-general-ca-muwsra0dfc9r. Support spec md5 f467e24e0ca3c08990f40c134df1ffb7 read; listener restart gate cleared. Coder-pluto-cc handoff requested tag db-pluto-ca-muwu2p24dzsx, 135 exact path only, no db/schema.md sweep. No production SQL/apply.
-
REVIEWED FROZEN FILE, NOT APPLIED. Coder-pluto-cc handoff-pushed commit 23f021aa3212d052a1288ff53d0f5cded7e0d040 on main, one migration-only file db/migrations/135-pluto-770-notify-useragent-null.sql (125 insertions); working and committed SHA-256 dc73dbd6e68101c1d8552e4ec943ddbfa5e74290ac8a7161ba4ac03a5b6448f2 both match audit-general-ca exact-byte SOURCE PASS (audit-general-ca-muwsra0dfc9r). db/schema.md excluded; no app version bump, deploymentId, or PTD because SQL-only handoff deploys no app change. Production fn_notify_applog_err remains unchanged until Elazar-authorized apply: Pluto has no write-capable DB seat and this source PASS is not apply GO. No production SQL/DDL executed. Listener compatibility was independently read back after applog-listen@pluto restart, but post-apply NOTIFY behavior is not exercised. The draft preserves the 300-character cap and changes only NULL-to-empty COALESCE in the NOTIFY payload. Apply and postflight remain Elazar-gated.