* fix(sessions): preserve Matrix room-id case in session keys (#75670)
Matrix room IDs (and thread event IDs) are opaque, case-sensitive per the
Matrix spec, but session-key canonicalization lowercased them. That forked
one room into duplicate sessions and produced 403 M_FORBIDDEN on recovery /
delivery paths that reconstruct the target from the (lowercased) session key,
even though deliveryContext.to stayed correct.
Introduce a generic, opt-in case-preservation registry (CASE_PRESERVING_PEERS)
consulted at all three lowercasing sites:
- construction: normalizeSessionPeerId
- store canonicalization: normalizeSessionKeyPreservingOpaquePeerIds
- gateway send: explicit request.sessionKey
Signal group preservation is encoded to match prior behavior exactly (segment
span, unscoped, thread suffix still lowercased). Matrix channel/group enrolls
the opaque tail (room id with embedded :server + any 🧵<event> suffix).
Exact mixed-case keys now win over folded legacy aliases in
resolveSessionStoreEntry and delivery-info lookup; existing lowercased rows
collapse on the next write. Matrix DM/MXID and non-enrolled channels keep the
default lowercase behavior.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): guard Matrix folded alias delivery proof
* test(agents): cover cold OpenAI gpt-5.5 fallback
* fix(sessions): preserve non-opaque alias freshness
* fix(sessions): prevent Matrix cross-room thread recovery
* build(protocol): refresh tools effective Swift models
* test(codex): include effective cwd in startup fixture
* test(codex): align startup failure cleanup expectation
* fix(sessions): keep Signal folded aliases fresh
* fix(sessions): preserve unscoped Matrix room keys
* fix(sessions): recover legacy Matrix thread aliases
* fix(sessions): preserve Matrix keys in state migrations
* fix(sessions): keep Matrix structural alias freshness
* fix(sessions): preserve unscoped Matrix migration keys
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Summary:
- The branch replaces the Crabbox wrapper's hardcoded provider allow-list with help-output parsing, preserves current aliases and a known help omission, adds wrapper tests, and updates the changelog.
- Reproducibility: yes. source-reproducible: current main only rejects selected providers that are already in ... rovider names can bypass wrapper validation. I did not run the PR branch because this review was read-only.
Automerge notes:
- PR branch already contained follow-up commit before automerge: refactor(crabbox): parse provider list from binary help instead of ha…
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8530…
Validation:
- ClawSweeper review passed for head c99388d92a.
- Required merge gates passed before the squash merge.
Prepared head SHA: c99388d92a
Review: https://github.com/openclaw/openclaw/pull/85302#issuecomment-4517730136
Co-authored-by: masonxhuang <masonxhuang@tencent.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: hxy91819
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>