Skip to content

fix(signal): stop relaying the expected PNI/ACI cross-check as a WARNING - #125

Merged
juniperbevensee merged 2 commits into
mainfrom
dev/juniperbevensee/signal-pni-crosscheck-noise
Jul 29, 2026
Merged

fix(signal): stop relaying the expected PNI/ACI cross-check as a WARNING#125
juniperbevensee merged 2 commits into
mainfrom
dev/juniperbevensee/signal-pni-crosscheck-noise

Conversation

@juniperbevensee

Copy link
Copy Markdown
Collaborator

The noise

Every agent on the fleet emits this on each gateway start, and home_log_router relays it to the operator's Signal home channel:

WARNING gateway.platforms.signal: Signal: getUserStatus self-lookup returned 288ecc5e-30e
(likely the account PNI) but listIdentities returned ACI a615f34c-8da — using the ACI.
Do not trust getUserStatus for self-identity.

Why it's wrong at WARNING

_resolve_own_uuid's own docstring already documents the cause:

getUserStatus must NOT be used for self-resolution: on a self-lookup, signal-cli (verified on 0.14.5) … returns the account's PNI

So the two values always differ. The mismatch branch is the expected steady state, not an anomaly — the line fires precisely when the code is working correctly. And the ACI from listIdentities is already the only value cached (if candidate: self._own_uuid = candidate), so the warning never signalled a behavioural problem.

It compounds: gateway.platforms.signal is in home_log_router's DEFAULT_LOGGERS, which forwards at WARNING. That module's docstring explicitly warns against routing loggers that emit "lifecycle noise (violates the no-lifecycle-spam rule)" — this is exactly that, and it reaches the operator on every restart of every agent.

Verified benign before changing it

Measured across a 7-agent fleet over 24h rather than assuming:

occurrences/24h signal auth errors own-ACI resolution failures
all 7 agents 2–4 each 0 0

The PNI/ACI pair is stable per account, and the resolved _own_uuid is the ACI everywhere. Nothing downstream is affected.

The change

logger.warninglogger.debug, with a comment recording why DEBUG is the correct level so it doesn't get "fixed" back. The cross-check is still worth having — at DEBUG it's there when you're actually diagnosing identity issues. Message reworded from "likely the account PNI" to "the account PNI, as expected".

Behavior is unchanged.

Tests

4 new in tests/gateway/test_signal_pni_crosscheck_level.py:

380 passed, 1 skipped across the signal gateway suite.

Note for reviewers

home_log_router has HERMES_HOME_LOG_LOGGERS and _LEVEL but no message-pattern denylist, so this could not be filtered without silencing all Signal warnings — including the reconnect/auth ones that genuinely should reach home. Fixing the level is the right layer. If benign-WARNING spam recurs elsewhere, a denylist knob may be worth adding, but correcting levels should be preferred over masking them.

🤖 Generated with Claude Code

juniperbevensee and others added 2 commits July 30, 2026 10:30
`_resolve_own_uuid` resolves the account ACI from `listIdentities`, then
cross-checks it against `getUserStatus`. Its own docstring states that
signal-cli (verified on 0.14.5) ALWAYS returns the account PNI for a self
`getUserStatus` — so the two values always differ and the mismatch branch
is the expected steady state on every gateway start, not a fault.

It logged at WARNING. Because `gateway.platforms.signal` is in
home_log_router's DEFAULT_LOGGERS and that router forwards WARNING to the
operator's home channel, every agent on the fleet relayed this line to the
operator on each restart — the exact lifecycle spam home_log_router's module
docstring forbids. It also reads as a recurring failure when in fact it is
the code working correctly.

Downgraded to DEBUG, so the diagnostic remains available when actually
investigating identity issues. Behavior is unchanged: the ACI from
`listIdentities` was already the only value cached, and still is.

Verified benign across a 7-agent fleet before changing the level: 2-4
occurrences per container per 24h, a stable PNI/ACI pair per account, zero
Signal auth errors and zero own-ACI resolution failures.

Tests: 4 new (no WARNING emitted, DEBUG retained, ACI still wins, silent
when the values agree). 380 signal tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An independent review found DEBUG overshot the goal. home_log_router's
policy floors at WARNING (policy.py:19, WARNING default), so INFO already
stops the home-channel relay completely. DEBUG additionally dropped the line
from gateway.log, whose handler is pinned to INFO+ (hermes_logging.py:345) —
so the claim that the diagnostic "remains available" was false in practice:
the branch only runs inside connect(), meaning you would need a
DEBUG-enabled restart to ever see it. It fires once per connect, so INFO
carries no spam risk.

Also softened "the account PNI, as expected" back to "presumed the account
PNI". Nothing in this code verifies that status_sid IS the PNI — the
docstring notes signal-cli strips the PNI: prefix on self-lookup, so it is
unknowable from these two RPCs. The original hedge was more accurate.

Trimmed the comment block, which had grown longer than the statement it
annotated and duplicated the commit message and test docstring.

Re-verified non-vacuous at the new level: flipping INFO back to WARNING
fails 2 of 4 tests. 380 signal tests + 42 home_log_router tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@juniperbevensee
juniperbevensee merged commit 6dcf0e2 into main Jul 29, 2026
32 checks passed
@juniperbevensee
juniperbevensee deleted the dev/juniperbevensee/signal-pni-crosscheck-noise branch July 29, 2026 23:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant