Skip to content

fix: resolve LINE IDs and harden sends, QR login, and media - #271

Open
meramsey wants to merge 9 commits into
beeper:mainfrom
meramsey:integration/linux-build-20261020
Open

meramsey wants to merge 9 commits into
beeper:mainfrom
meramsey:integration/linux-build-20261020

Conversation

@meramsey

Copy link
Copy Markdown

Summary

Fix public LINE ID resolution before DM portal creation, harden outbound RPC and QR-login lifecycle handling, and integrate the focused inbound-media fixes from #196 and part of #189. Add regression coverage and a debugging guide documenting the command paths, synchronization triggers, error handling, and validation boundaries.

This is an integration PR containing nine commits on top of e5cefb281f15f0c91fa9866dcb7440b7523f7cd1. The independent changes are separated by commit; the review map below identifies each area and the adapted contributions.

Public LINE IDs: root cause and repair

The reported workflow was:

start-chat <public LINE ID>
→ Failed to resolve identifier: Failed to create portal room

search <public LINE ID>
start-chat <returned user MID>
→ portal creation succeeds

SearchUsers already used TalkService.findContactByUserid, but ResolveIdentifier cast its input directly to user/portal IDs, created a portal record, and ignored chat-info errors. A public ID beginning with c therefore entered the group getChats path. Its empty result produced chat not found; room creation retried the same invalid lookup because usable portal information was missing.

The repair:

  • Share exact public-ID/MID resolution between search and start-chat, using the existing LINE APIs.
  • Normalize input, validate canonical user MIDs, and reject a mismatched MID returned for an explicit MID lookup.
  • Reuse returned contact data for ghost and complete DM metadata instead of repeating identity lookups.
  • Return the canonical MID and login-scoped portal key; let bridgev2 retain responsibility for portal caching, persistence, room-creation serialization, reuse and reopening.
  • Propagate lookup cancellation and avoid persisting portal rows for failed remote lookups or lookup-only requests.
  • Keep display-name matching search-only. Public-ID bindings are resolved afresh rather than cached across possible reassignment.

A failed Matrix room creation still retains a valid canonical row without an MXID for retry, following framework behavior. Historical invalid alias rows are not migrated or deleted automatically.

Other fixes

Outbound sends

Mocked tests reproduced three defects:

  1. sendMessage did not inherit the Matrix request context.
  2. HTTP-200 error wrappers lost nested TalkException details, preventing existing authentication/recovery classification.
  3. Missing/null/empty acknowledgement data was accepted as success, permitting an empty message ID or nil dereference.

Add SendMessageContext, retain structured error details, and require a non-empty acknowledgement ID. Add body-free event/login/recipient correlation logs. Existing ownership, permission and recovery policies are preserved.

These are reproduced implementation defects, not a claim that the separately reported live Element delivery incident has been diagnosed end to end.

QR login

Reject overlapping Start/Wait operations so callers cannot consume one another's polling stages. Preserve startup deadline errors instead of collapsing them into context.Canceled. Cancellation remains independent of the operation guard.

Tests cover overlapping waiters, deadline classification, callback key parameters, scan/PIN sequencing, token/profile verification, expiry, polling cancellation, missing-keychain persistence rejection, and passwordless reconnect requirements. Required approval and keychain checks remain in place.

Inbound media and attribution

  • Verify inbound E2EE media HMACs #196, by @Adri11334: adapt commit a6d06b0cde098719ac78ed9dd673bfa7244cea17 to the current shared media-decryption flow. Verify HMACs before AES-CTR decryption, distinguishing file-like/thumbnail ciphertext MACs from video chunk-hash MACs. Preserve current fail-closed fallback handling and wire video authentication through the shared normal/direct-media dispatch.
  • Metadata portion of Add Matrix metadata for LINE images #189, by @Adri11334: adapt the final metadata implementation at a4d8c11884a88527e5dbb50c80f7c1dd52b8ad64. Detect MIME type/filename, attach size/dimensions in Matrix FileInfo, and retain bounded ISO-BMFF brand parsing. The older 60-retry OBS policy is not included; current OBS preflight and error distinctions are preserved. The direct-media metadata path is unchanged.

Both adaptation commits retain Co-authored-by attribution and upstream references. These portions overlap the existing PRs and should be reviewed as adaptations of that work, not independent original contributions.

Related: #191, #155, #196, #189.

Synchronization diagnostics and documentation

No direct start-chat-to-full-sync call was found. Add sync_trigger fields for connection/startup, LINE SSE fullSync, and post-backfill reconciliation, without disabling legitimate synchronization. Document the separate outbound and QR paths and the evidence needed to diagnose account-specific failures in readme/DEBUGGING.md, linked from README.

Review map

Commits Area
e55720c Adapt #196: inbound media authentication
ca81ee3 Adapt #189: inbound image metadata
3aa69d8 Race-stable signing/cancellation tests
15ff9e4 Shared identifier resolution and canonical portal initialization
5802c3f QR lifecycle guards and deadline reporting
0597689 Outbound cancellation, error details and acknowledgement validation
b3fb1ac Reopening, mismatched identity, deadline and reconnect regressions
6deb64e, 587164f Synchronization diagnostics and troubleshooting documentation

Validation

Validated locally at 587164f7ced99bc5765ac7df4eafc11314e6d602 on Linux amd64 with Go 1.26.10, CGO enabled, GCC 13.3.0 and libolm 3.2.16.

Check Result
go test -count=1 -json ./... 382 passed, 0 failed, 1 pre-existing skip
go test -race -p 1 -count=1 -timeout=60m -json ./... 382 passed, 0 failed, 1 pre-existing skip
Focused identifier, outbound and QR regressions Passed normally and with five race-enabled repetitions
pre-commit run --all-files 9/9 checks passed, including imports, vet, staticcheck and zerolog checks
gofmt, git diff --check, go mod verify Passed
go build ./... and ./build.sh with scratch output via GOFLAGS Passed
Native binary: architecture, shared libraries, version/help, offline config/registration generation Passed

Counts include tests and subtests, across six tested packages; three packages have no tests. Vet/staticcheck exclude generated pkg/ltsm as prescribed by the repository. The sole skip is the existing TestReplayLTSMVectors stub awaiting its typed-runner rewrite.

The test adjustments address pre-existing race-run problems:

  • The eviction test previously performed 6,000 expensive cache misses. It now checks three complete rotations with explicit per-call cache size, LRU victim and signature assertions, plus the refresh boundary. The separate 6,000-call reuse test and real heap-exhaustion test remain intact.
  • Cancellation tests now give cold signing a separate setup budget and always cancel/join their worker. The original one-second deadline after cancellation is unchanged.
  • The unchanged real heap-exhaustion test takes roughly 22 minutes under race instrumentation. The 60-minute package timeout allows it to complete; no additional tests are skipped or filtered out of the full race run.

Validation boundaries

New integration fixtures use mocked LINE HTTP responses and isolated SQLite databases. There was no live account/device approval or production PostgreSQL validation. Public-ID commands, recipient-side delivery and successful live QR/session restoration still need operator verification. The reported bulk-sync timing association and specific live outbound/QR incident causes remain unconfirmed.

Authentication/permission policies, required device approval, dependencies and database schema are unchanged. Local binaries, logs, caches, generated registrations and release artifacts are not part of this source PR.

meramsey and others added 9 commits October 20, 2026 15:28
Adapt beeper#196 (a6d06b0) to the shared media decryptor, covering both uploads and direct media. Preserve upstream fail-closed key fallback and route video to chunk-hash HMAC verification. Add valid, tampered and wrong-mode coverage for all media kinds.

Co-authored-by: Adrien Vermersch <adrien.vermersch@devolab.net>
Select the image metadata changes from beeper#189 at a4d8c11, retaining current download, size-limit and authentication handling. Keep the separate 60-retry OBS policy out of this scoped fix. Includes bounded ISO-BMFF brand detection and regression tests.

Co-authored-by: Adrien Vermersch <adrien.vermersch@devolab.net>
Replace 6000 expensive eviction cache misses with three complete cache rotations, per-call victim and LRU assertions, and explicit refresh-boundary coverage. Preserve the separate 6000-call reuse and real heap-exhaustion tests. Give cold signing a separate setup budget while retaining the one-second cancellation bound; cancel and join the request worker on every exit path.
Share exact identifier lookup with search, validate canonical user MIDs and reuse returned contact data. Delay portal persistence until remote resolution succeeds, honor lookup-only requests, and pass complete DM information to bridgev2. Add cancellable lookup RPCs and isolated database regressions for identity consistency, errors, cancellation, concurrent portal reuse and Matrix creation retries.
Reject overlapping Start/Wait calls before they consume polling stages or mutate authentication state. Preserve caller and attempt expiry instead of reporting every canceled start as context.Canceled. Reproduce both defects and cover mocked QR presentation, scan/PIN approval, token verification, missing-keychain persistence rejection, expiry and cancellation.
Pass the Matrix request context to sendMessage, preserve structured TalkException details for existing recovery logic, and reject missing acknowledgements instead of returning success or dereferencing nil. Add correlated send-stage logs without message bodies and regressions for ownership, canonical recipients, API failures and cancellation. These defects are reproduced locally; the reported live Element delivery failure still needs event-level evidence.
Verify public-ID reopening after leaving a Matrix room, rejection of mismatched MIDs and expired lookup requests, and mandatory fresh approval for passwordless QR sessions after token recovery is unavailable.
Label existing connect, LINE fullSync and post-backfill synchronization triggers without changing policy. Document canonical DM resolution, retained retryable portal rows, outbound stage/account diagnostics, independent QR lifecycle findings and live-verification boundaries.
Label connection, LINE fullSync and historical-state reconciliation without changing sync behavior. Document canonical identity resolution, portal retry/reopening, outbound correlation and ownership checks, QR lifecycle fixes, mocked coverage and remaining live-verification requirements.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant