Skip to content

fix: group key errors#215

Merged
highesttt merged 2 commits into
mainfrom
highest/plat-37877
Jul 13, 2026
Merged

fix: group key errors#215
highesttt merged 2 commits into
mainfrom
highest/plat-37877

Conversation

@highesttt

Copy link
Copy Markdown
Collaborator

No description provided.

@linear-code

linear-code Bot commented Jul 13, 2026

Copy link
Copy Markdown

PLAT-37877

@indent-zero

indent-zero Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
PR Summary

Refactors LINE E2EE group-key registration to be more resilient and prevent stale-cache clobbering. Introduces helper functions for member filtering (groupKeyMemberMIDs), batch/fallback key resolution (resolveGroupMemberPublicKeys), and defensive member-cache writes (cacheGroupMemberMIDs), and wraps transient/parse/incomplete per-member failures with line.ErrNoUsableE2EEGroupKey so send_message.go degrades to plain text instead of hard-failing the whole send. Follow-up commit (a5b02d8) applies review fixes: makes isUserMID case-insensitive to match LINE's lowercase MID wire format, tightens auth-error handling in resolveGroupMemberPublicKeys so recovery failures still hard-fail, and preserves the original auth error via double-%w in callLineWithRecovery.

  • pkg/connector/creategroup.go — Splits registerGroupKey into groupKeyMemberMIDs and resolveGroupMemberPublicKeys. Per-member failures now wrap line.ErrNoUsableE2EEGroupKey (except auth/ctx/session-invalidated errors, which stay hard-fail) so lineGroupE2EEFetchFailureError allows plain-text fallback.
  • pkg/connector/e2ee_keys.go — Adds cacheGroupMemberMIDs helper (no-ops on len <= 1, defensive copy). Filters MemberMids/InviteeMids via isUserMID. Copies the cached slice under the mutex in autoRegisterGroupKey. Dedupes and filters Matrix-derived member lists. Wraps auto-register failures as auto-register group key: %w. Comment updated to reflect the conditional self-add.
  • pkg/connector/sync.go — Replaces ad-hoc HasPrefix(m,"c")||HasPrefix(m,"r") filters with !isUserMID(m)||lc.isOwnMID(m), routes cache writes through cacheGroupMemberMIDs, adds lc.UserLogin.UserLogin != nil guard in isOwnMID, and makes isUserMID accept both U and u prefixes.
  • pkg/connector/auth_recovery.go + test — callLineWithRecovery now returns fmt.Errorf("failed to recover token after LINE auth error (%w): %w", err, errRecover) so the original auth error remains detectable via errors.Is and line.IsAuthError.
  • pkg/connector/e2ee_keys_test.go — Adds coverage for isUserMID case-insensitivity, mixed-case member filtering, plain-text fallback on generic member errors, and preservation of auth-recovery failures (no ErrNoUsableE2EEGroupKey wrap).
  • pkg/connector/send_message_test.go — Updates one test to expect the auto-register group key: %w wrapper.

Issues

1 potential issue found:

  • cacheGroupMemberMIDs returns without touching the cache whenever len(mids) <= 1; that protects against LINE's ambiguous self-only responses but also means a group that legitimately shrinks to only the bridge user never has its cache evicted. Later autoRegisterGroupKey fallback (e2ee_keys.go:275-285) will keep serving the stale richer list and try to wrap keys for members who already left. → Autofix
2 issues already resolved
  • resolveGroupMemberPublicKeys now hard-fails whole-group key registration on any per-member negotiate error (transient 5xx, parse error, incomplete key, wrap failure). Previously the loop continued and produced a partial registration. The wrapped errors (negotiate E2EE key for member %s, wrap group key for member %s, incomplete E2EE public key for member %s) are NOT matched by line.IsNoUsableE2EEGroupKey, so they bypass the plain-text fallback in lineGroupE2EEFetchFailureError and surface as Matrix send failures — meaning one flaky peer can now block every send to the group. (fixed by commit a5b02d8)
  • isUserMID requires uppercase "U" but every in-repo reference (pkg/ltsm/crypto.go:297, ltsm/e2ee test vectors, login_keys_test.go) documents LINE MIDs as lowercase "u"; this PR extends isUserMID into every group-member enumeration path, so if MIDs are actually lowercase on the wire, getChatMemberMIDs returns "no members or invitees", groupKeyMemberMIDs returns empty, and every group loses E2EE registration and member sync. Verify against a real chat.Extra.GroupExtra.MemberMids payload — the new unit tests use "U-*" fixtures so they can't catch this. (fixed by commit a5b02d8)

CI Checks

Waiting for CI checks...


⚡ Autofix All Issues

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 00662c6a-4e07-4122-b980-31fd77405efa

📥 Commits

Reviewing files that changed from the base of the PR and between ee77030 and a5b02d8.

📒 Files selected for processing (6)
  • pkg/connector/auth_recovery.go
  • pkg/connector/auth_recovery_test.go
  • pkg/connector/creategroup.go
  • pkg/connector/e2ee_keys.go
  • pkg/connector/e2ee_keys_test.go
  • pkg/connector/sync.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/connector/creategroup.go
  • pkg/connector/sync.go
  • pkg/connector/e2ee_keys.go
📜 Recent review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: Lint with 1.25
  • GitHub Check: build-docker
  • GitHub Check: build-docker
  • GitHub Check: Lint with 1.25
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use go fmt for code formatting across all Go files
Use goimports with -local "github.com/highesttt/matrix-line-messenger" flag to group project-local imports correctly
Use zerolog for logging throughout the codebase
Do not use Msgf in logging; use Msg with structured fields instead
Use Stringer interface where applicable in Go code

Files:

  • pkg/connector/auth_recovery.go
  • pkg/connector/auth_recovery_test.go
  • pkg/connector/e2ee_keys_test.go
**/!(ltsm)/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/!(ltsm)/**/*.go: Run staticcheck on all Go files excluding pkg/ltsm package (transpiled WASM code)
Run go vet on all Go files excluding pkg/ltsm package (transpiled WASM code)

Files:

  • pkg/connector/auth_recovery.go
  • pkg/connector/auth_recovery_test.go
  • pkg/connector/e2ee_keys_test.go
🔇 Additional comments (4)
pkg/connector/e2ee_keys_test.go (2)

164-198: LGTM!


313-378: LGTM!

pkg/connector/auth_recovery_test.go (1)

32-32: LGTM!

Also applies to: 66-66, 119-121

pkg/connector/auth_recovery.go (1)

21-37: 🎯 Functional Correctness

Multiple %w wraps are supported here. Go 1.25.0 allows wrapping both errors, so this change is fine.


📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved E2EE group-key registration and key recovery behavior, with stricter failure handling on missing/invalid member keys.
    • Enhanced member MID filtering/deduplication (user-only MIDs; correct casing; bridge MID included only when appropriate) to prevent bad identifiers from impacting key operations.
    • Improved error chaining and messaging when auth recovery fails, preserving the original auth error for detection.
  • Tests
    • Added/expanded unit tests for member filtering, cache behavior, batch-versus-negotiation key resolution, and error/fallback edge cases.

Walkthrough

Group E2EE member discovery now validates and deduplicates user MIDs, preserves richer cached lists, resolves missing public keys through batch and individual calls, and propagates wrapped registration errors.

Changes

E2EE group key handling

Layer / File(s) Summary
Member MID filtering and caching
pkg/connector/e2ee_keys.go, pkg/connector/sync.go, pkg/connector/e2ee_keys_test.go
Member extraction now keeps valid unique user MIDs, excludes the bridge MID where applicable, uses defensive cache updates, and tests filtering and cache preservation.
Group key resolution and registration
pkg/connector/creategroup.go, pkg/connector/e2ee_keys_test.go
Registration resolves batch and missing individual public keys, and returns errors for unresolved or invalid key material.
Auto-registration error propagation
pkg/connector/e2ee_keys.go, pkg/connector/auth_recovery.go, pkg/connector/auth_recovery_test.go, pkg/connector/send_message_test.go
Auto-registration and recovery failures are logged or wrapped while preserving underlying authentication errors, with fallback behavior tested against wrapped no-usable-key errors.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant registerGroupKey
  participant resolveGroupMemberPublicKeys
  participant GetLastE2EEPublicKeys
  participant negotiateE2EEPublicKey
  registerGroupKey->>resolveGroupMemberPublicKeys: resolve candidate member keys
  resolveGroupMemberPublicKeys->>GetLastE2EEPublicKeys: request batch last keys
  resolveGroupMemberPublicKeys->>negotiateE2EEPublicKey: negotiate missing or invalid keys
  resolveGroupMemberPublicKeys-->>registerGroupKey: return resolved keys or error
  registerGroupKey->>registerGroupKey: wrap group key for each member
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No meaningful pull request description was provided, so the change intent is not described. Add a short description summarizing the main behavior changes and why the group key error handling was updated.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and matches the main theme of the change: fixing group key error handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch highest/plat-37877

Warning

Tools execution failed with the following error:

Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)


Comment @coderabbitai help to get the list of available commands.

Comment thread pkg/connector/creategroup.go Outdated
// A self-only result is ambiguous: LINE sometimes returns an empty member
// map for active groups. Keep a previously complete list for fallback.
if len(mids) <= 1 {
return

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipping writes when len(mids) <= 1 protects against LINE's ambiguous self-only responses (good), but it also means a group that legitimately shrinks to only self will never update the cache: autoRegisterGroupKey at lines 275-285 will keep falling back to the stale richer list and attempt to wrap keys for departed members, which RegisterE2EEGroupKey will reject (or worse, silently accept with stale members).

Consider adding an authoritative-source flag or a TTL so genuine shrinkage can evict the cache while still shielding against ambiguous server responses.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/connector/e2ee_keys.go`:
- Around line 245-248: Update the comments preceding the `isUserMID(lc.Mid)`
checks in both locations to remove the inaccurate “always include” wording and
describe the conditional behavior accurately, including that the MID is added
only when `isUserMID` returns true.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9207cd09-70e7-4e94-944c-9837855c0464

📥 Commits

Reviewing files that changed from the base of the PR and between 717f42f and ee77030.

📒 Files selected for processing (5)
  • pkg/connector/creategroup.go
  • pkg/connector/e2ee_keys.go
  • pkg/connector/e2ee_keys_test.go
  • pkg/connector/send_message_test.go
  • pkg/connector/sync.go
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: Lint with 1.25
  • GitHub Check: build-docker
  • GitHub Check: build-docker
  • GitHub Check: Lint with 1.25
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use go fmt for code formatting across all Go files
Use goimports with -local "github.com/highesttt/matrix-line-messenger" flag to group project-local imports correctly
Use zerolog for logging throughout the codebase
Do not use Msgf in logging; use Msg with structured fields instead
Use Stringer interface where applicable in Go code

Files:

  • pkg/connector/send_message_test.go
  • pkg/connector/e2ee_keys_test.go
  • pkg/connector/creategroup.go
  • pkg/connector/sync.go
  • pkg/connector/e2ee_keys.go
**/!(ltsm)/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/!(ltsm)/**/*.go: Run staticcheck on all Go files excluding pkg/ltsm package (transpiled WASM code)
Run go vet on all Go files excluding pkg/ltsm package (transpiled WASM code)

Files:

  • pkg/connector/send_message_test.go
  • pkg/connector/e2ee_keys_test.go
  • pkg/connector/creategroup.go
  • pkg/connector/sync.go
  • pkg/connector/e2ee_keys.go
🔇 Additional comments (14)
pkg/connector/e2ee_keys.go (3)

44-51: LGTM!


196-209: LGTM!

Also applies to: 257-259, 275-284, 326-326, 335-343


234-244: 🎯 Functional Correctness

No issue: isUserMID matches LINE MID format. LINE user IDs are uppercase U-prefixed, so the case-sensitive check does not drop valid members.

			> Likely an incorrect or invalid review comment.
pkg/connector/sync.go (3)

684-731: LGTM!


733-741: LGTM!


928-939: LGTM!

pkg/connector/e2ee_keys_test.go (3)

164-181: LGTM!


183-195: LGTM!


197-294: LGTM!

pkg/connector/creategroup.go (4)

16-22: LGTM!


142-156: LGTM!


158-206: LGTM!


211-247: LGTM!

pkg/connector/send_message_test.go (1)

53-58: LGTM!

Comment thread pkg/connector/e2ee_keys.go Outdated
@highesttt highesttt merged commit 740b83d into main Jul 13, 2026
9 of 10 checks passed
@highesttt highesttt deleted the highest/plat-37877 branch July 13, 2026 16:21
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