Skip to content

fix(weixin): startAccount preserves session routing#93686

Merged
sliverp merged 7 commits into
openclaw:mainfrom
zhangguiping-xydt:fix/issue-93556
Jun 26, 2026
Merged

fix(weixin): startAccount preserves session routing#93686
sliverp merged 7 commits into
openclaw:mainfrom
zhangguiping-xydt:fix/issue-93556

Conversation

@zhangguiping-xydt

@zhangguiping-xydt zhangguiping-xydt commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Summary

What problem does this PR solve?

  • Root cause: manifest channel account listing normalized raw config keys into route-safe IDs, but manifest account resolution used a different mapping contract and looked up that normalized route ID directly in the raw accounts object. A raw key like 59000514e8ad@im.bot could be listed as 59000514e8ad-im-bot but then fail to resolve before startAccount.
  • This PR makes manifest account resolution use the same normalized account lookup invariant as listing, and tightens the shared lookup helper so invalid config-map candidate keys such as "constructor " cannot collapse through normalizeAccountId to default.

Why does this matter now?

  • User impact: a configured external Weixin account can be dropped before startup, which prevents the channel from handling inbound or outbound messages.
  • The maintainer follow-up identified one remaining shared-helper edge case after the main Weixin/session-routing fix: invalid raw account keys could still be selected as the default account through fallback normalization.

What is the intended outcome?

  • Fix classification: root-cause bug fix, scoped to external channel/plugin account config resolution.
  • Maintainer-ready confidence: high. The fix is covered by focused routing and read-only plugin tests, plus the existing live openclaw-weixin proof that the external account starts and reaches running state.
  • Why this is root-cause fix: the resolver and lister now share one account-id mapping contract, and fallback matching only considers candidate config keys that have a valid optional canonical account ID instead of letting invalid keys silently select default.

What is intentionally out of scope?

What does success look like?

  • A raw provider account key that normalizes to a route-safe ID resolves back to its original config entry.
  • Invalid/prototype-like config-map keys do not resolve as default through the shared normalized lookup helper.
  • Focused tests pass for the helper and the manifest/read-only plugin path.

What should reviewers focus on?

  • Architecture / source-of-truth check: resolveNormalizedAccountEntry is the source-of-truth helper for normalized config-map account lookup, and manifest account resolution calls it with the optional validating normalizer for config keys.
  • Patch quality notes: this is not a fallback workaround; it rejects invalid candidate keys before fallback comparison while preserving valid exact-key and route-safe ID behavior.
Summary guidance

This PR description is the contributor's durable explanation of the change. Write it for human maintainers first; ClawSweeper and Barnacle use the same text to understand intent, proof, risk, and current review state.

Describe the intent and outcome in 2-5 bullets. Avoid restating the diff; reviewers and bots can read the changed files.

If this PR fixes a plugin beta-release blocker, title it fix(<plugin-id>): beta blocker - <summary> and link the matching Beta blocker: <plugin-name> - <summary> issue labeled beta-blocker. Contributors cannot label PRs, so the title is the PR-side signal for maintainers and automation.

Linked context

Which issue does this close?

Closes #93556.

Which issues, PRs, or discussions are related?

Related #93686.

Was this requested by a maintainer or owner?

Yes. A maintainer requested tightening the shared lookup helper so invalid raw config-map keys do not collapse to default.

Linked context guidance

Link the issue, PR, discussion, maintainer request, or owner request that explains why this PR should exist. Maintainer context helps reviewers and automation distinguish intended work from drive-by churn.

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: a live external openclaw-weixin channel account whose raw provider ID normalizes to a route-safe account ID can be loaded by the Gateway, started through the channel plugin, and reported as running instead of being dropped before startAccount.

  • Real environment tested: macOS Darwin 25.5.0, Node v24.15.0, OpenClaw 2026.6.2, external @tencent-weixin/openclaw-weixin@2.4.3, isolated OpenClaw home, live QR login with Weixin.

  • Exact steps or command run after this patch:

    pnpm openclaw plugins install "@tencent-weixin/openclaw-weixin@2.4.3" --force
    pnpm openclaw config set plugins.entries.openclaw-weixin.enabled true
    pnpm openclaw channels login --channel openclaw-weixin
    pnpm openclaw config set gateway.mode local
    pnpm openclaw config set gateway.port 18790
    pnpm dev gateway --port 18790
    pnpm openclaw channels status --probe
    pnpm test src/channels/plugins/read-only.test.ts src/routing/account-lookup.test.ts
  • Evidence after fix (sanitized live output from the existing PR proof):

    Installed plugin: openclaw-weixin
    Restart the gateway to load plugins.
    
    已将此 OpenClaw 连接到微信。
    
    $ node scripts/run-node.mjs gateway --port 18790
    [gateway] auto-enabled plugins for this runtime without writing config:
    - openclaw-weixin configured, enabled automatically.
    [plugins] loading openclaw-weixin from <proof-home>/.openclaw/npm/projects/tencent-weixin-openclaw-weixin-.../node_modules/@tencent-weixin/openclaw-weixin/dist/index.js
    [gateway] http server listening (... plugins ...)
    [gateway] starting channels and sidecars...
    [openclaw-weixin] [<route-safe-weixin-account-id>] starting weixin provider (https://ilinkai.weixin.qq.com/...)
    [gateway] ready
    [openclaw-weixin] weixin monitor started (https://ilinkai.weixin.qq.com/..., account=<route-safe-weixin-account-id>)
    [openclaw-weixin] [weixin] no previous sync buf, starting fresh
    
    $ node scripts/run-node.mjs channels status --probe
    Checking channel status (probe)…
    Gateway reachable.
    - openclaw-weixin <route-safe-weixin-account-id>: enabled, configured, running
    
  • Observed result after fix: the external Weixin manifest account is listed with the route-safe ID, resolves back to the raw configured account entry, enters provider startup, starts the Weixin monitor, and is reported by channels status --probe as enabled, configured, running; the issue-specific unable to resolve account failure before startAccount is no longer present.

  • What was not tested: a fresh live Weixin login was not re-run for the small maintainer follow-up commit; the follow-up is a shared helper guard for invalid config-map candidate keys and is covered by focused regression tests below.

  • Proof limitations or environment constraints: local dependency installation reports a node-llama-cpp postinstall build failure because this machine has CMake 3.18.2 while that package asks for CMake 3.19+, but the focused Vitest suites needed for this PR ran successfully from the installed workspace.

  • Before evidence (optional but encouraged): the new regression test failed before the helper guard with expected { id: 'blocked' } to deeply equal undefined for resolveNormalizedAccountEntry({ "constructor ": cfg }, "default", normalizeAccountId).

Real behavior proof guidance

External contributors must show after-fix evidence from a real OpenClaw setup. Unit tests, mocks, lint, typechecks, snapshots, and CI are supplemental only.

Screenshots are encouraged even for CLI, console, text, or log changes. Terminal screenshots, copied live output, redacted runtime logs, recordings, and linked artifacts count.

If your environment cannot produce the ideal proof, explain that under Proof limitations or environment constraints so reviewers and ClawSweeper can direct the next step properly.

Be mindful of private information like IP addresses, API keys, phone numbers, non-public endpoints, or other private details when providing evidence.

Tests and validation

Which commands did you run?

  • Target test file: src/routing/account-lookup.test.ts via pnpm exec vitest run src/routing/account-lookup.test.ts — pass, 8 tests.
  • Target test file: src/channels/plugins/read-only.test.ts via pnpm exec vitest run src/channels/plugins/read-only.test.ts — pass, 31 tests.
  • ClawSweeper local commit review — pass.

What regression coverage was added or updated?

  • Scenario locked in: resolveNormalizedAccountEntry({ "constructor ": cfg }, "default", normalizeAccountId) returns undefined instead of selecting the invalid raw key as the default account.
  • Existing manifest/read-only plugin tests continue to cover opaque raw provider IDs like 59000514e8ad@im.bot resolving through their route-safe account IDs.

What failed before this fix, if known?

  • The new regression test failed before the fix because the shared helper returned { id: "blocked" } for the invalid "constructor " key when resolving default.
  • Why this is the smallest reliable guardrail: it exercises the shared helper contract directly and keeps the manifest plugin path covered without adding provider-specific code or broader fixture churn.

If no test was added, why not?

  • Not applicable; a focused regression test was added.
Testing guidance

List focused commands, not every incidental check. CI is useful support, but external PRs still need real behavior proof above when behavior changes.

Risk checklist

Did user-visible behavior change? (Yes/No)

Yes, only for invalid account config keys that previously collapsed to default during normalized fallback lookup.

Did config, environment, or migration behavior change? (Yes/No)

No migration or schema change. Existing valid account keys keep the same matching behavior.

Did security, auth, secrets, network, or tool execution behavior change? (Yes/No)

Yes, the account lookup helper is stricter about invalid/prototype-like config-map keys so they cannot be selected through fallback matching.

What is the highest-risk area?

  • Risk labels considered: merge-risk: compatibility, merge-risk: security-boundary, and session/account routing state.
  • Risk explanation: resolveNormalizedAccountEntry is exported through plugin SDK account surfaces, so the compatibility-sensitive behavior is that invalid raw account keys which only matched through fallback normalization now stop matching.

How is that risk mitigated?

  • Why acceptable: the guard uses the existing optional account-id normalizer as the validating source-of-truth for config-map candidate keys, preserves valid exact-key lookup, and preserves the route-safe opaque provider ID behavior covered by tests.
  • The change does not alter the public manifest schema, account ID route normalization, gateway lifecycle, or provider-specific code.
Risk guidance

Use this for author judgment that is not obvious from the diff. ClawSweeper can see touched files, but it cannot know which behavior you think is risky, why the risk is acceptable, or what mitigation reviewers should verify.

Current review state

What is the next action?

Maintainer review after this PR update; local submit checks, focused validations, and remote exact-head CI are complete.

What is still waiting on author, maintainer, CI, or external proof?

  • Waiting on author: no known author-side code, proof, or CI gap after this update.
  • Waiting on maintainer: final acceptance of the exported-helper compatibility/security-boundary tradeoff.
  • Waiting on CI: none at the latest checked exact head; visible remote checks are complete with no failures.

Which bot or reviewer comments were addressed?

  • RF-001: ClawSweeper's exact-head CI wait is satisfied by the latest remote status: visible checks are complete with no failures.
  • RF-002: The exported-helper compatibility risk is mitigated by using the existing optional account-id validity check for fallback candidates, while preserving valid exact-key and route-safe ID behavior.
  • RF-003: ClawSweeper's earlier pending checks-node-compact-small-whole-2 validation state is stale because the exact-head check has completed successfully.
  • RF-004: The remaining shared-helper compatibility/security-boundary choice is documented for maintainer acceptance; there is no separate narrow author repair unless maintainers prefer a localized-guard direction.
  • RF-005: The checking maintainer signal is superseded by the later concrete follow-up and no longer has a separate author action.
  • RF-006: sliverp's follow-up about "constructor " collapsing to default is fixed by the helper guard and regression test.
  • RF-007: The author sync/comment thread is addressed by the pushed PR update; no separate code action is required beyond RF-006.
  • RF-008: The latest author comment summarizes the completed fix and does not introduce a new code or proof action.
Review state guidance

Keep this as the durable state for review progress. If useful information appears in comments, fold the current next action or blocker back here so maintainers and ClawSweeper do not need to reconstruct state from comment history.

@openclaw-barnacle openclaw-barnacle Bot added size: S proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 16, 2026
@clawsweeper

clawsweeper Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 26, 2026, 2:29 AM ET / 06:29 UTC.

Summary
The PR makes manifest channel account resolution use normalized account-key lookup, hardens the shared normalized account lookup helper against invalid/prototype-like fallback matches, and adds focused regression tests.

PR surface: Source +22, Tests +103. Total +125 across 4 files.

Reproducibility: yes. Current main has a source-level reproduction path: manifest listing normalizes raw account keys while manifest resolution looks up the normalized id directly in the raw accounts map before Gateway startAccount handoff; the PR body also provides redacted live Weixin startup/status output after the fix.

Review metrics: 1 noteworthy metric.

  • Exported helper semantics: 1 changed. resolveNormalizedAccountEntry is exported through plugin SDK account surfaces, so the stricter invalid-key fallback behavior needs maintainer visibility before merge.

Stored data model
Persistent data-model change detected: serialized state: src/routing/account-lookup.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #93556
Summary: This PR is the open candidate fix for the canonical raw Weixin account-key normalization startup bug; nearby Weixin startup and catalog items are related but do not replace this account-resolution fix.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Have a maintainer explicitly accept the shared helper hardening or request the localized-guard variant before merge.

Risk before merge

  • [P2] Merging changes an exported SDK account lookup helper so invalid/prototype-like raw account keys that previously matched through fallback normalization no longer resolve; maintainers should explicitly accept that compatibility behavior.

Maintainer options:

  1. Accept Shared Helper Hardening (recommended)
    Proceed if maintainers agree invalid/prototype-like account keys should stop resolving through the exported normalized account helper.
  2. Localize The Guard
    Move the invalid-key rejection into manifest account listing/resolution if maintainers want to avoid changing exported helper semantics.
  3. Pause For SDK Contract Direction
    Hold the PR if maintainers want a broader plugin SDK compatibility decision before changing shared account lookup behavior.

Next step before merge

  • [P2] Maintainer review should accept or redirect the exported helper compatibility tradeoff; there is no narrow automated repair unless maintainers choose the localized-guard option.

Security
Cleared: The diff adds no dependency, workflow, secret, package, or code-execution surface and hardens account-key lookup against prototype-like fallback matching.

Review details

Best possible solution:

Land this or an equivalent normalized manifest account resolver after maintainer acceptance of the shared helper hardening; localize the guard if maintainers want the SDK helper contract preserved for now.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main has a source-level reproduction path: manifest listing normalizes raw account keys while manifest resolution looks up the normalized id directly in the raw accounts map before Gateway startAccount handoff; the PR body also provides redacted live Weixin startup/status output after the fix.

Is this the best way to solve the issue?

Yes, with a maintainer compatibility choice left. Aligning manifest listing and resolution through the normalized lookup invariant is the narrow generic fix; the shared helper hardening is best if maintainers accept the SDK behavior change, otherwise the guard should be localized.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 4fc504d321b6.

Label changes

Label justifications:

  • P1: The bug can prevent a configured external Weixin channel account from reaching startAccount, breaking a real channel workflow.
  • merge-risk: 🚨 compatibility: The PR changes exported normalized account lookup behavior for invalid/prototype-like raw keys that previously matched through fallback normalization.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes redacted live OpenClaw Weixin install/login/gateway/status output showing the external account reaches running state after the fix; the later invalid-key guard is covered by focused tests.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes redacted live OpenClaw Weixin install/login/gateway/status output showing the external account reaches running state after the fix; the later invalid-key guard is covered by focused tests.
Evidence reviewed

PR surface:

Source +22, Tests +103. Total +125 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 28 6 +22
Tests 2 103 0 +103
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 131 6 +125

What I checked:

  • Current main still has the mismatch: Manifest account listing normalizes raw account keys, but resolution reads the normalized account id directly from the raw accounts map, so a raw key such as 59000514e8ad@im.bot can list as route-safe but fail to resolve. (src/channels/plugins/read-only.ts:352, 4fc504d321b6)
  • Gateway startup depends on that resolver: Gateway startup lists account ids, resolves each account, checks configuration, and only then hands off to startAccount. (src/gateway/server-channels.ts:435, 4fc504d321b6)
  • Latest release is also affected: The v2026.6.10 tag shows the same manifest list-normalized/direct-resolve code, so the central fix is not shipped in the latest release. (src/channels/plugins/read-only.ts:352, fac1b04e4b19)
  • PR head implements the central fix: The PR head imports resolveNormalizedAccountEntry, validates manifest candidate keys with normalizeOptionalAccountId, and resolves manifest config through the normalized helper instead of direct raw-key lookup. (src/channels/plugins/read-only.ts:357, 9448fae03776)
  • PR head hardens the shared helper: resolveNormalizedAccountEntry now skips blocked exact keys and fallback candidates whose raw key is not a valid optional account id, preventing constructor-like keys from collapsing to default. (src/routing/account-lookup.ts:35, 9448fae03776)
  • Focused regression coverage exists: The PR adds tests for opaque raw provider ids resolving through route-safe ids and for invalid constructor-like keys not resolving as default. (src/channels/plugins/read-only.test.ts:1078, 9448fae03776)

Likely related people:

  • zhang-guiping: Blame shows the current read-only manifest account listing/resolution path and current account-lookup file copy came through bead84f on main. (role: recent area contributor; confidence: high; commits: bead84f0ee6e; files: src/channels/plugins/read-only.ts, src/routing/account-lookup.ts)
  • Peter Steinberger: Git history shows the normalized account lookup helper was introduced in d06413e and later exposed through plugin SDK account surfaces in 4ca0755. (role: shared helper and SDK surface introducer; confidence: high; commits: d06413e335ac, 4ca07559abe4; files: src/routing/account-lookup.ts, src/plugin-sdk/account-core.ts)
  • sliverp: The live PR discussion includes a focused maintainer review that accepted the main fix direction and requested the invalid-key helper guard now present in the PR head. (role: reviewer; confidence: medium; files: src/routing/account-lookup.ts, src/channels/plugins/read-only.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@zhangguiping-xydt

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 17, 2026
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. and removed proof: supplied External PR includes structured after-fix real behavior proof. proof: sufficient ClawSweeper judged the real behavior proof convincing. labels Jun 17, 2026
@zhangguiping-xydt

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. agents Agent runtime and tooling labels Jun 17, 2026
@zhangguiping-xydt

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 17, 2026
@zhangguiping-xydt zhangguiping-xydt changed the title Bug: openclaw-weixin startAccount ???,?????????? session fix(weixin): startAccount preserves session routing Jun 22, 2026
@sliverp

sliverp commented Jun 23, 2026

Copy link
Copy Markdown
Member

checking

@zhangguiping-xydt

Copy link
Copy Markdown
Contributor Author

checking

Hi @sliverp, quick sync: this PR is cleanly mergeable against main (0b69870), all checks pass, and proof: sufficient holds. Happy to adjust if you spot anything.

@sliverp

sliverp commented Jun 26, 2026

Copy link
Copy Markdown
Member

I think the main Weixin/session-routing fix is pointed at the right problem: manifest account listing emits the route-safe normalized id, while resolution previously looked up that normalized id directly in the raw accounts map, so config keys like 59000514e8ad@im.bot could be listed as 59000514e8ad-im-bot but fail to resolve at startup.

One remaining issue is in the shared lookup helper, not the Weixin-specific path. resolveNormalizedAccountEntry now filters exact blocked object keys and normalized blocked keys, but callers that pass normalizeAccountId can still let invalid raw config keys collapse to default. For example, a key like "constructor " is not an exact blocked key, and normalizeAccountId("constructor ") falls back to default, so resolveNormalizedAccountEntry({ "constructor ": cfg }, "default", normalizeAccountId) can still return that invalid entry as the default account.

Could we tighten the helper/call contract so config-map candidate keys are normalized with the optional/validating normalizer, or otherwise skipped when their canonical form is invalid, instead of falling back to default? A regression test for "constructor " not matching default would cover the gap.

@zhangguiping-xydt

Copy link
Copy Markdown
Contributor Author

I think the main Weixin/session-routing fix is pointed at the right problem: manifest account listing emits the route-safe normalized id, while resolution previously looked up that normalized id directly in the raw accounts map, so config keys like 59000514e8ad@im.bot could be listed as 59000514e8ad-im-bot but fail to resolve at startup.

One remaining issue is in the shared lookup helper, not the Weixin-specific path. resolveNormalizedAccountEntry now filters exact blocked object keys and normalized blocked keys, but callers that pass normalizeAccountId can still let invalid raw config keys collapse to default. For example, a key like "constructor " is not an exact blocked key, and normalizeAccountId("constructor ") falls back to default, so resolveNormalizedAccountEntry({ "constructor ": cfg }, "default", normalizeAccountId) can still return that invalid entry as the default account.

Could we tighten the helper/call contract so config-map candidate keys are normalized with the optional/validating normalizer, or otherwise skipped when their canonical form is invalid, instead of falling back to default? A regression test for "constructor " not matching default would cover the gap.

Thanks for the detailed review, I'll take a look~

@zhangguiping-xydt

zhangguiping-xydt commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@sliverp Thanks for the follow-up. I updated the PR to address the shared helper gap you pointed out:

  • resolveNormalizedAccountEntry now validates raw config-map candidate keys with the optional/validating normalizer before fallback comparison, so invalid keys like "constructor " no longer collapse to default.
  • Added a focused regression test covering resolveNormalizedAccountEntry({ "constructor ": cfg }, "default", normalizeAccountId) returning undefined.
  • Re-ran the focused suites: src/routing/account-lookup.test.ts and src/channels/plugins/read-only.test.ts both pass.
  • Updated the PR body with the root cause, proof, review-state mapping, and compatibility/security-boundary risk notes.

The branch has been pushed; the last watch window had no failing checks, only a few still pending.

@sliverp sliverp merged commit e9f9a68 into openclaw:main Jun 26, 2026
24 checks passed
@sliverp

sliverp commented Jun 26, 2026

Copy link
Copy Markdown
Member

Landed via temp rebase onto main.

  • Gate: skipped per maintainer request (PR already includes tests)
  • Land commit: ff00f01
  • Merge commit: e9f9a68

Thanks @zhangguiping-xydt!

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 27, 2026
* fix(channels): resolve manifest account config by normalized id

* fix(routing): ignore blocked keys during normalized account lookup

* fix(routing): block normalized unsafe account keys

* test(routing): type normalized account lookup case

* trigger CI

* fix account lookup invalid key fallback

* fix(weixin): startAccount preserves session routing (openclaw#93686) (thanks @zhangguiping-xydt)

---------

Co-authored-by: sliverp <870080352@qq.com>
QiuYuang pushed a commit to QiuYuang/openclaw that referenced this pull request Jul 1, 2026
* fix(channels): resolve manifest account config by normalized id

* fix(routing): ignore blocked keys during normalized account lookup

* fix(routing): block normalized unsafe account keys

* test(routing): type normalized account lookup case

* trigger CI

* fix account lookup invalid key fallback

* fix(weixin): startAccount preserves session routing (openclaw#93686) (thanks @zhangguiping-xydt)

---------

Co-authored-by: sliverp <870080352@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: openclaw-weixin startAccount ???,?????????? session

2 participants