Skip to content

fix(line): synthesize media/auth/routing webhook regressions#32546

Merged
Takhoffman merged 14 commits intomainfrom
task-line-ws2-minimal
Mar 3, 2026
Merged

fix(line): synthesize media/auth/routing webhook regressions#32546
Takhoffman merged 14 commits intomainfrom
task-line-ws2-minimal

Conversation

@Takhoffman
Copy link
Copy Markdown
Contributor

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: LINE had overlapping regressions/fixes across media download typing (including M4A), command authorization propagation, peer routing ids, and webhook method compatibility.
  • Why it matters: these overlaps caused inconsistent behavior and high merge risk, especially for M4A transcription paths and slash command gating.
  • What changed: synthesized the minimal runtime-safe subset: file media download gate, M4A content-type classification, CommandAuthorized propagation from gating, raw group/room peer id routing, and HEAD webhook probe support.
  • What did NOT change (scope boundary): no status/config cleanup bundle, no optional rich-directives UX features, no saveMediaBuffer migration path, no cleanup-timer behavior changes.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • LINE inbound file messages are now included in the media download path.
  • LINE M4A voice payloads are classified as audio/mp4 (preserving .m4a handling and transcription routing expectations).
  • LINE inbound context now carries CommandAuthorized from authorization decisions for message and postback flows.
  • LINE group/room routing uses raw source ids for peer matching (fixes binding mismatches).
  • LINE webhook handler accepts HEAD probes and returns 204.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local Node 22 + pnpm workspace
  • Model/provider: n/a
  • Integration/channel (if any): LINE
  • Relevant config (redacted): default test fixtures

Steps

  1. Build LINE webhook and handler modules with this branch.
  2. Run focused LINE tests for handlers, media download classification, context routing, and webhook endpoint methods.
  3. Validate that file media and M4A classification paths pass expected assertions.

Expected

  • LINE file messages download and pass media refs.
  • M4A payloads classify to audio/mp4 and .m4a extension path.
  • Context payload includes CommandAuthorized and raw peer id routing matches bindings.
  • Webhook returns 204 for HEAD and preserves existing GET/POST behavior.

Actual

  • Matches expected; focused suite passed.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: ran focused vitest suites for bot-handlers, download, bot-message-context, and webhook-node under the synthesized branch.
  • Edge cases checked: M4A vs MP4 header classification, file media type gate, authorized/unauthorized command payload, group/room peer binding ids, HEAD method response.
  • What you did not verify: full pnpm check end-to-end (blocked by pre-existing formatting in unrelated Feishu files in this branch base).

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert this PR or revert specific commits for media classification (download.ts) and auth/routing context (bot-message-context.ts, bot-handlers.ts).
  • Files/config to restore: src/line/bot-handlers.ts, src/line/download.ts, src/line/bot-message-context.ts, src/line/webhook-node.ts and corresponding tests.
  • Known bad symptoms reviewers should watch for: M4A routed as video/mp4, missing slash command execution on LINE, group/room bindings not matching expected peer ids, webhook health probes receiving 405.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: overlap with alternate media-store migration path can reintroduce M4A misclassification if combined incorrectly.
    • Mitigation: this synthesis intentionally keeps the explicit download.ts classifier path and excludes the saveMediaBuffer migration variant.
  • Risk: context authorization propagation changes command behavior in previously misconfigured setups.
    • Mitigation: retains existing access policy checks and adds explicit tests for authorized vs unauthorized payload states.

@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot bot commented Mar 3, 2026

🤖 We're reviewing this PR with Aisle

We're running a security check on the changes in this PR now. This usually takes a few minutes. ⌛
We'll post the results here as soon as they're ready.

Progress:

  • Analysis
  • Triage
  • Finalization

Latest run failed. Keeping previous successful results. Trace ID: 019cb1ffc284e783a6653c243142973a.

Last updated on: 2026-03-03T04:41:05Z

Latest run failed. Keeping previous successful results. Trace ID: 019cb20c37ae8aa5de21210124cfc234.

Last updated on: 2026-03-03T04:54:41Z

Latest run failed. Keeping previous successful results. Trace ID: 019cb2192df5c5d990db6736cf35bad3.

Last updated on: 2026-03-03T05:12:51Z

Latest run failed. Keeping previous successful results. Trace ID: 019cb22466c2c576380d13fd6e55ea16.

Last updated on: 2026-03-03T05:23:36Z

Latest run failed. Keeping previous successful results. Trace ID: 019cb230e280d3cfc4a0b8a2c17f1466.

Last updated on: 2026-03-03T05:38:15Z

Latest run failed. Keeping previous successful results. Trace ID: 019cb236a84b75f05dfeaf2dd917572b.

Last updated on: 2026-03-03T05:42:33Z

@openclaw-barnacle openclaw-barnacle bot added size: M maintainer Maintainer-authored PR channel: feishu Channel integration: feishu labels Mar 3, 2026
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot bot commented Mar 3, 2026

🤖 We're reviewing this PR with Aisle

We're running a security check on the changes in this PR now. This usually takes a few minutes. ⌛
We'll post the results here as soon as they're ready.

Progress:

  • Analysis
  • Triage
  • Finalization

Latest run failed. Keeping previous successful results. Trace ID: 019cb2043b1caa78ca647f40c15a4ef9.

Last updated on: 2026-03-03T04:48:59Z

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 3, 2026

Greptile Summary

This PR synthesizes five targeted regressions/fixes for the LINE integration: adding file messages to the media download path, expanding M4A ftyp brand detection, propagating CommandAuthorized from authorization decisions into message/postback contexts, switching group/room peer routing to use raw source IDs (fixing binding mismatches), and accepting HEAD webhook probes with 204. All changes are backed by focused tests.

  • File media download"file" added to LINE_DOWNLOADABLE_MESSAGE_TYPES; downloadLineMedia is now called for file messages and the result forwarded to buildLineMessageContext. Correct.
  • M4A classificationdetectContentType now covers a broader set of audio ftyp brands (m4p, m4r, f4a, f4b) in addition to m4a/m4b, with toLowerCase() normalisation. The audioBrands Set is re-created on every call; hoisting it to a module-level constant would be a small improvement.
  • CommandAuthorized propagationshouldProcessLineEvent now returns { allowed, commandAuthorized } and the value is threaded through to finalizeLineInboundContext. For non-text media messages resolveEventRawText returns "", so commandAuthorized reflects allowlist membership only (no command text); if downstream skill gating checks CommandAuthorized before processing file/audio/video attachments, allowlisted group senders could be incorrectly gated.
  • Raw peer ID routingbuildPeerId strips the group:/room: prefix, aligning with binding config expectations. This is the correct fix, but silently breaks session-key continuity for existing group/room sessions whose keys were derived from the old prefixed format. Worth noting in migration docs.
  • HEAD webhook supportwebhook-node.ts returns 204 for HEAD and updates the Allow header; minimal and correct.

Confidence Score: 4/5

  • Safe to merge with low risk; no security surface changes and all fixes are backed by tests.
  • All five regressions are addressed with accompanying tests and the scope is tightly bounded to the LINE integration. Two minor concerns prevent a 5: (1) audioBrands is heap-allocated on every detectContentType call instead of being a module-level constant; (2) commandAuthorized for non-text media messages in allowlisted groups is driven by allowlist membership rather than command presence, which could incorrectly gate file/audio/video processing downstream. Neither is a blocking bug but both merit follow-up.
  • src/line/bot-handlers.ts (commandAuthorized logic for media messages) and src/line/bot-message-context.ts (session-key continuity after peer-ID format change).

Last reviewed commit: e5b2524

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 3, 2026

Additional Comments (1)

src/line/bot-message-context.ts
buildPeerId format change may silently orphan in-progress group/room sessions

buildPeerId now returns the raw groupId / roomId instead of the previously prefixed "group:<id>" / "room:<id>" form. This value feeds resolveAgentRoute which derives route.sessionKey. Any existing group/room session whose key was computed against the old prefixed format will no longer resolve to the same session key, silently starting a fresh session.

The From/OriginatingTo addresses in resolveLineAddresses still use the line:group:<id> format, so routing and display are diverging in a way that could surprise operators. It may be worth logging a one-time migration warning if a session keyed on the old format exists, or documenting the session-key break explicitly in the migration notes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/line/bot-message-context.ts
Line: 51-62

Comment:
**`buildPeerId` format change may silently orphan in-progress group/room sessions**

`buildPeerId` now returns the raw `groupId` / `roomId` instead of the previously prefixed `"group:<id>"` / `"room:<id>"` form. This value feeds `resolveAgentRoute` which derives `route.sessionKey`. Any existing group/room session whose key was computed against the old prefixed format will no longer resolve to the same session key, silently starting a fresh session.

The `From`/`OriginatingTo` addresses in `resolveLineAddresses` still use the `line:group:<id>` format, so routing and display are diverging in a way that could surprise operators. It may be worth logging a one-time migration warning if a session keyed on the old format exists, or documenting the session-key break explicitly in the migration notes.

How can I resolve this? If you propose a fix, please make it concise.

@Takhoffman
Copy link
Copy Markdown
Contributor Author

Addressed review comments in commit e65bc32:

  1. src/line/download.ts
  • Hoisted M4A audioBrands set to a module-level constant (AUDIO_BRANDS) to avoid per-call allocation.
  1. src/line/bot-handlers.ts
  • Updated command authorization behavior for non-text LINE message events (image/video/audio/file) so CommandAuthorized is set to true for those events.
  • This avoids accidental downstream gating for media-only messages that cannot carry slash commands.
  1. src/line/bot-handlers.test.ts
  • Added assertion coverage to lock non-text file-message behavior with commandAuthorized: true.

For the session-key continuity concern from the peer-id prefix change:

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e65bc320c4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@Takhoffman
Copy link
Copy Markdown
Contributor Author

Addressed the P1 retry/ack concern in cdf1184.

What changed:

  • src/line/bot-handlers.ts
    • handleLineWebhookEvents now records per-event failures and throws after processing when any event fails (line: <n> webhook event(s) failed).
  • src/line/webhook-node.ts
    • moved success response to after await bot.handleWebhook(body)
    • failures now return 500 (instead of sending 200 and swallowing)
  • src/line/webhook.ts
    • same process-before-ack behavior for Express middleware

Tests added/updated:

  • src/line/webhook-node.test.ts: asserts 500 on processing failure
  • src/line/webhook.test.ts: asserts 500 when onEvents rejects
  • src/line/bot-handlers.test.ts: asserts handleLineWebhookEvents rejects when a handler fails

This makes handler failures observable to LINE so retries can occur instead of silently dropping failed events.

@openclaw-barnacle openclaw-barnacle bot added channel: feishu Channel integration: feishu size: L and removed channel: feishu Channel integration: feishu size: M labels Mar 3, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fbefe8cb0a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

shenghui kevin and others added 10 commits March 2, 2026 23:14
The LINE plugin was not downloading file attachments (PDF, Word, Excel,
JSON, etc.) because the media download condition only checked for
image, video, and audio types.

Added `message.type === "file"` to the condition so files are downloaded
and made available to the agent, consistent with other media types.

Fixes #26330
LINE voice messages use ISO BMFF ftyp containers and were misclassified as video/mp4, which skipped audio transcription. Detect major audio brands (e.g. M4A) so voice attachments are treated as audio/mp4 and saved as .m4a.
@Takhoffman Takhoffman force-pushed the task-line-ws2-minimal branch from fbefe8c to 0bbd398 Compare March 3, 2026 05:15
@openclaw-barnacle openclaw-barnacle bot added size: M and removed channel: feishu Channel integration: feishu size: L labels Mar 3, 2026
kevinWangSheng pushed a commit to kevinWangSheng/openclaw that referenced this pull request Mar 3, 2026
…w#32546) thanks @Takhoffman

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
yumesha pushed a commit to yumesha/openclaw that referenced this pull request Mar 3, 2026
…w#32546) thanks @Takhoffman

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
mrosmarin added a commit to mrosmarin/openclaw that referenced this pull request Mar 3, 2026
* main: (134 commits)
  fix(telegram): warn when accounts.default is missing in multi-account setup (openclaw#32544)
  agents: propagate config for embedded skill loading
  Gateway: fix stale self version in status output (openclaw#32655)
  feat(mattermost): add native slash command support (refresh) (openclaw#32467)
  Diffs: Migrate tool usage guidance from before_prompt_build to a plugin skill (openclaw#32630)
  bug: Workaround for QMD upstream bug (openclaw#27028)
  fix: improve compaction summary instructions to preserve active work (openclaw#8903)
  chore: Updated Brave documentation (openclaw#26860)
  security(line): synthesize strict LINE auth boundary hardening
  test(e2e): isolate module mocks across harnesses
  fix(telegram): debounce forwarded media-only bursts
  test(live): harden gateway model profile probes
  fix(ci): handle disabled systemd units in docker doctor flow
  fix(test): stabilize appcast version assertion
  fix(line): synthesize media/auth/routing webhook regressions (openclaw#32546) thanks @Takhoffman
  fix(gateway+acp): thread stopReason through final event to ACP bridge (openclaw#24867)
  docs(changelog): reattribute duplicated PR credits
  fix: scope extension runtime deps to plugin manifests
  ci: enable stale workflow
  chore(release): bump to 2026.3.3 and seed changelog
  ...
dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026