thinkpool-pair 0.7.116 → 0.7.117
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bridge.mjs +17 -1
- package/package.json +1 -1
package/bridge.mjs
CHANGED
|
@@ -2409,7 +2409,19 @@ flowChannel
|
|
|
2409
2409
|
cleanupFlowLanes(payload.flowId, 600)
|
|
2410
2410
|
process.stderr.write(`\n ${A.yel}◆ flow cancelled — closing its lanes (${String(payload.flowId).replace(/-/g, '').slice(0, 8)}).${A.rst}\n`)
|
|
2411
2411
|
})
|
|
2412
|
-
.subscribe(
|
|
2412
|
+
.subscribe(status => {
|
|
2413
|
+
// BRG-2 (audit 2026-07-02): tpflow had a bare subscribe with no status handler, so a
|
|
2414
|
+
// channel-specific CHANNEL_ERROR (socket still healthy → the main tpcode watchdog
|
|
2415
|
+
// never trips) dropped flow dispatch/plan/done silently until the next bridge
|
|
2416
|
+
// restart. Surface it. supabase-js auto-rejoins every channel on a socket reconnect,
|
|
2417
|
+
// so a transient drop self-heals; an active per-channel re-subscribe is deliberately
|
|
2418
|
+
// NOT added here — re-subscribing a live supabase channel is a known lifecycle
|
|
2419
|
+
// footgun (the 2026-06-30 channel-collision family) and can't be two-device verified
|
|
2420
|
+
// from a single host.
|
|
2421
|
+
if (status === 'CHANNEL_ERROR' || status === 'TIMED_OUT' || status === 'CLOSED') {
|
|
2422
|
+
process.stderr.write(`\n ⚠ flow realtime ${status} (tpflow:${room}).\n`)
|
|
2423
|
+
}
|
|
2424
|
+
})
|
|
2413
2425
|
|
|
2414
2426
|
// Watchdog — if the realtime channel is stuck (never connected, or dropped and
|
|
2415
2427
|
// not recovered) for >60s, exit non-zero so a supervisor/launchd restarts a
|
|
@@ -2565,6 +2577,10 @@ async function shutdown(code = 0, farewell = true) {
|
|
|
2565
2577
|
// socket is alive; on a wedge it won't flush and the hard backstop above wins).
|
|
2566
2578
|
try { await channel.untrack() } catch { /* noop */ }
|
|
2567
2579
|
try { await supabase.removeChannel(channel) } catch { /* noop */ }
|
|
2580
|
+
// BRG-2 (audit 2026-07-02): shutdown removed only the room channel, leaking the flow
|
|
2581
|
+
// topic (no presence to untrack, but the subscription + socket join outlived the
|
|
2582
|
+
// process teardown). Close it too so shutdown is symmetric.
|
|
2583
|
+
try { await supabase.removeChannel(flowChannel) } catch { /* noop */ }
|
|
2568
2584
|
setTimeout(() => process.exit(code), 250) // grace for the leave/close frames to flush
|
|
2569
2585
|
}
|
|
2570
2586
|
process.on('SIGINT', () => shutdown(0))
|