From 2db1f25f2ca95611091185b723037e128ebcd270 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Wed, 19 Aug 2026 03:19:36 -0700 Subject: [PATCH] fix(pairing): accept spaced approval codes Port from qwibitai/nanoclaw#3282: normalize visual whitespace in DM pairing codes while preserving exact-match rejection for chatter-wrapped input. --- gateway/pairing.py | 4 +++- tests/gateway/test_pairing.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/gateway/pairing.py b/gateway/pairing.py index 989153b351..bac6f74e78 100644 --- a/gateway/pairing.py +++ b/gateway/pairing.py @@ -464,7 +464,9 @@ class PairingStore: """ with self._lock: self._cleanup_expired(platform) - code = code.upper().strip() + # Chat UIs insert visual spacing between code characters; strip all + # whitespace, then match exactly (surrounding words still fail). #89937 + code = "".join(str(code or "").upper().split()) # Before the lookup, or an already-issued valid code would bypass lockout. if self._is_locked_out(platform): return None diff --git a/tests/gateway/test_pairing.py b/tests/gateway/test_pairing.py index a8ef808b5d..f97bfcb3cf 100644 --- a/tests/gateway/test_pairing.py +++ b/tests/gateway/test_pairing.py @@ -275,6 +275,25 @@ class TestApprovalFlow: assert result["user_id"] == "user1" assert result["user_name"] == "Alice" + def test_approve_code_with_internal_spacing(self, tmp_path): + with patch("gateway.pairing.PAIRING_DIR", tmp_path): + store = PairingStore() + code = store.generate_code("telegram", "user1", "Alice") + spaced_code = " ".join(code) + result = store.approve_code("telegram", f" {spaced_code} ") + + assert isinstance(result, dict) + assert result["user_id"] == "user1" + assert result["user_name"] == "Alice" + + def test_approve_code_with_words_still_fails(self, tmp_path): + with patch("gateway.pairing.PAIRING_DIR", tmp_path): + store = PairingStore() + code = store.generate_code("telegram", "user1", "Alice") + result = store.approve_code("telegram", f"code {code}") + + assert result is None + def test_approved_user_is_approved(self, tmp_path): with patch("gateway.pairing.PAIRING_DIR", tmp_path): store = PairingStore()