Fixes#97021.
The WhatsApp bridge's human-facing lifecycle lines -- startup
("bridge listening", "session stored"), connection state (connected,
logged out, restart/reconnect), and "[bridge] ..." warning lines --
were bare console.log/console.warn output with no timestamp. The
platform adapter pipes the bridge's stdout/stderr verbatim into
bridge.log, so no timestamp is added downstream either. Only
structured JSON events (pair events, allowlist rejections from #92683)
carried a timestamp. During incident forensics this made bridge.log
impossible to sequence on its own -- the exact durations of a
relaunch/re-pair loop, or the ordering of "Logged out" relative to a
fatal stream error, couldn't be reconstructed without cross-correlating
gateway logs and the sparser pino output.
Added timestampedLine() to bridge_helpers.js (the existing pure,
testable helper module bridge.js already draws from for reconnect
scheduling and version resolution) -- a small function that prefixes a
message with an ISO-8601 UTC timestamp in brackets, matching the
issue's own suggested fix direction and kept deliberately distinct
from the `ts: Date.now()` epoch-ms convention #92683 already
established for the JSON event stream (these are plain human-readable
lines, not JSON payloads).
Applied it at the exact lifecycle line sites the issue's own line
inventory cites: the core startup lines ("bridge listening on port",
"session stored in"), the connection lifecycle lines (connected,
logged out, restart-code-515, reconnect-in-3s, pairing complete), and
the five "[bridge] ..." warning lines (poll update/upsert aggregation
failures, gif/ffmpeg conversion fallback, failed read receipt).
Scoped narrowly to what the issue asked for -- did not touch the
already-structured JSON event lines, or the separate config-summary
startup block (allowed users / DM policy lines) the issue didn't cite.
Added a new test file (bridge_helpers.timestamp.test.mjs), following
the established plain-assert, no-framework pattern from the existing
bridge.reconnect.test.mjs: verifies the prefix is a valid, parseable
ISO-8601 timestamp; the original message text (including
template-literal-interpolated content, matching the actual call sites)
survives byte-for-byte after the prefix; and two calls a moment apart
produce non-decreasing timestamps, confirming the prefix reflects
actual call time rather than a cached value -- so a relaunch loop's
individual lines stay independently sequenceable, the issue's core ask.
All assertions pass in the new test file. Ran the existing
bridge.reconnect.test.mjs, bridge.sendqueue.test.mjs, and
allowlist.test.mjs directly -- all pass unchanged (no regression to
bridge_helpers.js's other exports or to bridge.js's own logic, since
this only wraps pre-existing message strings passed to console.log/
console.warn without changing any control flow).