Skip to content

fix(feishu): resolve exec/keychain appSecret SecretRefs on the outbound path#89454

Open
openperf wants to merge 4 commits into
openclaw:mainfrom
openperf:fix/feishu-media-secretref-resolution
Open

fix(feishu): resolve exec/keychain appSecret SecretRefs on the outbound path#89454
openperf wants to merge 4 commits into
openclaw:mainfrom
openperf:fix/feishu-media-secretref-resolution

Conversation

@openperf

@openperf openperf commented Jun 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Problem: Issue [Bug]: Feishu MEDIA/image upload fails when appSecret uses SecretRef (Keychain) #89338 reports that the Feishu MEDIA directive (and image/file uploads in general) silently fails when appSecret is configured as a SecretRef backed by an exec/Keychain provider. Normal chat (WebSocket connection) and text replies keep working; only the media upload is dropped, so the recipient receives no image. The regression appeared after migrating credentials from plaintext to a Keychain-backed SecretRef.
  • Root Cause: Feishu resolves app credentials per outbound API call through resolveFeishuRuntimeAccountresolveFeishuSecretLike, a synchronous resolver that only understands plaintext strings and env-source SecretRefs; for an exec/file/Keychain SecretRef it throws FeishuSecretRefUnavailableError. The runtime config (getRuntimeConfigloadConfig) carries SecretRefs unresolved — they are resolved on demand, not inlined globally — so every path that re-runs this strict resolver against an exec/Keychain appSecret throws. An already-established WebSocket session keeps working because its Lark client and tenant token are built once and reused, with no per-message re-resolution; but each media/outbound send re-runs the per-send strict resolution: it throws, the throw is caught in feishuOutbound.sendMedia (and the local-image path in sendText), and the send degrades to a plain URL/text fallback — the "silent" failure the reporter saw. Plaintext worked because a plaintext value is returned immediately, bypassing SecretRef resolution entirely.
  • Fix: Resolve still-unresolved app-credential SecretRefs at the Feishu outbound seam before the SDK client is built. A new helper resolveFeishuOutboundCredentialsConfig inspects the outbound account's appId/appSecret; if either is still a SecretRef, it resolves it through the async, exec/Keychain-capable SDK resolver (resolveConfiguredSecretInputString) — the sync runtime resolver only handles env/plaintext, which is the gap. The resolved string is inlined into a shallow copy of the config (at the account level when an accounts map exists, top-level otherwise). The three feishuOutbound entry points (sendPayload, sendText, sendMedia), the agent message-tool send/thread-reply action handler (channel.ts), and the source-channel reply dispatcher (createFeishuReplyDispatcher in reply-dispatcher.ts) all call it first, so the existing synchronous downstream resolution now sees a resolved string and the send proceeds.
  • What changed:
    • extensions/feishu/src/accounts.ts — add resolveFeishuOutboundCredentialsConfig (and a small resolveFeishuCredentialRefValue helper) that resolves unresolved appId/appSecret SecretRefs through the async openclaw/plugin-sdk/secret-input-runtime resolver and inlines them into the returned config at the existing matched account-map key.
    • extensions/feishu/src/outbound.ts — resolve credentials at the start of the feishuOutbound sendPayload, sendText, and sendMedia handlers before any SDK client is built.
    • extensions/feishu/src/channel.ts — resolve credentials once at the start of the message-tool send/thread-reply action handler and use the resolved config for the card, media, and text branches.
    • extensions/feishu/src/reply-dispatcher.ts — resolve credentials lazily (memoized per dispatcher instance) via a getResolvedCfg() helper; all six sendMediaFeishu, sendMessageFeishu, and sendStructuredCardFeishu call sites within createFeishuReplyDispatcher now use the resolved config. This covers the source-channel MEDIA/final-reply path that ClawSweeper identified as uncovered (P1 finding).
    • extensions/feishu/src/accounts.test.ts / channel.test.ts / reply-dispatcher.test.ts — regression cases: the strict runtime account throws on an exec/Keychain appSecret SecretRef and succeeds after the helper inlines it; a MEDIA payload via createFeishuReplyDispatcher with an exec SecretRef reaches sendMediaFeishu with the resolved config; plaintext credentials return the same config object unchanged.
  • What did NOT change (scope boundary):
    • No config surface (no schema, defaults, doctor migrations, or docs/reference/config); the on-disk SecretRef shape is read, never rewritten.
    • No plugin SDK surface (no SDK exports, manifest, extensions/* api/runtime-api, registry/loader); the helper only consumes an existing public SDK subpath (openclaw/plugin-sdk/secret-input-runtime), already used by other bundled plugins.
    • No dependency/lockfile changes. Gateway protocol unchanged.
    • The synchronous resolver, its error type, the connection/event-secret resolution, and the existing transient-error fallback are untouched; only the outbound delivery path gains an up-front resolution step.

Reproduction

  1. Configure a Feishu account with appSecret as an exec/Keychain SecretRef, e.g. channels.feishu.accounts.<id>.appSecret = { "source": "exec", "provider": "keychain_feishu_<id>", "id": "value" }.
  2. Restart the gateway; WebSocket chat connects normally.
  3. Send a local image via the MEDIA directive in a Feishu DM.
  4. Before this PR: the upload throws FeishuSecretRefUnavailableError, is caught, and degrades to a URL/text fallback — no image is delivered.
  5. After this PR: the SecretRef is resolved against the secret runtime before the client is built, and the image is uploaded normally.

Deterministic source reproduction (added as regression tests): with the reporter's exact exec SecretRef shape, resolveFeishuRuntimeAccount throws; after resolveFeishuOutboundCredentialsConfig, the same call resolves with the inlined secret. The same pattern is verified for the source-channel reply-dispatcher MEDIA path.

Real behavior proof

Behavior addressed (#89338 — Feishu media upload now works with an exec/Keychain SecretRef appSecret): outbound delivery resolves unresolved app-credential SecretRefs before building the Feishu client, instead of dropping the upload to a URL/text fallback. This now covers both the outbound/message-tool path and the source-channel reply dispatcher path (createFeishuReplyDispatcher).

Real environment tested (Linux, Node — Vitest against the real extensions/feishu/src/accounts.ts resolution path, with the SDK secret resolver mocked to emulate the gateway secret runtime; no live Feishu tenant): verified via accounts.test.ts, channel.test.ts, outbound.test.ts, and reply-dispatcher.test.ts, plus extension production and test type-checks and a format check on the changed files. A live Feishu media send against a real tenant was not run.

Exact steps or command run after this patch (repo-root): node scripts/run-vitest.mjs extensions/feishu/src/{accounts,channel,outbound,reply-dispatcher}.test.ts; node scripts/run-tsgo.mjs -p tsconfig.extensions.json and node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json; pnpm oxfmt --check and node scripts/run-oxlint.mjs on the changed files.

Evidence after fix (Vitest output for the touched test files):

 accounts.test.ts          Tests  27 passed (27)
 channel.test.ts           Tests  62 passed (62)
 outbound.test.ts          Tests  42 passed (42)
 reply-dispatcher.test.ts  Tests  78 passed (78)

The cases prove the regression and its fix on the real resolver: the strict runtime account throws FeishuSecretRefUnavailableError on an exec/Keychain appSecret SecretRef; after resolveFeishuOutboundCredentialsConfig inlines it, the same call resolves successfully. The reply-dispatcher regression test proves a MEDIA payload delivered through createFeishuReplyDispatcher with an exec SecretRef cfg reaches sendMediaFeishu with the resolved config (not the original SecretRef cfg). Plaintext credentials return the identical config object (no clone, no resolver call).

Observed result after fix (all delivery paths): resolveFeishuRuntimeAccount on the resolved config returns configured: true with the resolved appSecret, so the SDK client builds and the upload proceeds. Extension prod + test type-checks pass; oxlint and oxfmt are clean.

What was not tested (live Feishu tenant media send): a real Feishu DM image send over a live WebSocket session with a Keychain-backed secret was not reproduced; the proof is the deterministic module-level reproduction the issue describes.

Risk / Mitigation

  • Risk: an unresolved-credential outbound send now performs an async secret resolution. Mitigation: the resolver is only invoked when appId/appSecret is still a SecretRef; plaintext and already-resolved configs short-circuit with no resolver call and no clone, so the common path is unchanged. When a credential is genuinely unresolvable, the helper leaves the config untouched and the existing transient-error fallback still applies.
  • Risk: an exec/Keychain secret is resolved on each unresolved-credential send (one async resolution per send while the cfg still carries a SecretRef). Mitigation: bounded to the unresolved case — plaintext / already-resolved sends short-circuit — and it is the same resolution the strict resolver would otherwise attempt and throw on. The reply-dispatcher path memoizes the resolution per dispatcher instance (resolved once on first send, reused for all subsequent sends in that reply context).
  • Risk: config rewriting could change account selection or drop per-account settings. Mitigation: the resolved value is inlined at the existing matched account-map key (preserving a noncanonical/mixed-case key and its sibling settings), or top-level when no account entry matches; the original config object is never mutated. Covered by the regression tests.

Out of scope / known siblings

  • Other Feishu client-building paths. Feishu paths that build a client from resolveFeishuRuntimeAccount outside the four entry points covered here (card-action callbacks, comment replies, pins, bitable, chat, directory lookups, monitoring) would still hit FeishuSecretRefUnavailableError with a config carrying an unresolved exec/Keychain SecretRef. They are not part of the reported regression. The structurally complete fix would move resolution to the client-build boundary (createFeishuClient); that is a deliberate separate refactor.
  • Other channels. The underlying shape — a channel re-resolving its outbound app credentials per send through a resolver that does not cover exec/keychain SecretRefs — is not necessarily unique to Feishu. This PR intentionally scopes to the reported Feishu path.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Channels (Feishu)

Linked Issue/PR

Fixes #89338

@openclaw-barnacle openclaw-barnacle Bot added channel: feishu Channel integration: feishu size: M labels Jun 2, 2026
@clawsweeper

clawsweeper Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 29, 2026, 9:06 PM ET / 01:06 UTC.

Summary
The PR resolves Feishu app credential SecretRefs through the async secret-input runtime before outbound sends, message-tool sends, and reply-dispatcher delivery paths build or use Feishu clients.

PR surface: Source +113, Tests +220. Total +333 across 8 files.

Reproducibility: yes. at source level. Current main documents Feishu appSecret as a SecretRef surface, the strict Feishu runtime resolver throws on unresolved non-env SecretRefs, and media/reply paths still pass cfg into that strict path; I did not run a live Feishu tenant send.

Review metrics: 1 noteworthy metric.

  • Credential Resolution Entry Points: 5 Feishu send/dispatch entry points changed. The measured surface changes auth-provider timing on user-visible delivery paths, so green unit tests alone do not settle the merge decision.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #89338
Summary: This PR is an open fix candidate for the canonical Feishu MEDIA upload regression with SecretRef-backed appSecret; sibling PRs target the same user report with narrower or alternative approaches.

Members:

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

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
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:

  • Refresh the branch against current main while preserving the Feishu dispatcher parameters.
  • Have Feishu/SecretRef owners accept send-time SecretRef resolution or request the client-boundary refactor.
  • [P2] Add redacted live Feishu MEDIA proof if maintainers need tenant-level assurance before merge.

Risk before merge

  • [P1] GitHub currently reports mergeable=CONFLICTING and mergeStateStatus=DIRTY, so maintainers need a refreshed branch before judging the actual merge result.
  • [P1] The diff changes when Feishu app credential SecretRefs are resolved on user-visible send paths, so Feishu/SecretRef owners should explicitly accept the send-time credential boundary before merge.
  • [P1] The PR body provides deterministic module-level proof but no redacted live Feishu tenant MEDIA send with a Keychain-backed appSecret; member-authored PRs are not blocked by the external proof gate, but live tenant assurance remains a maintainer choice.

Maintainer options:

  1. Refresh And Confirm Credential Boundary (recommended)
    Resolve the branch conflict against current main and have Feishu/SecretRef owners confirm that scoped send-time SecretRef resolution is acceptable before merge.
  2. Move Resolution Earlier
    Require a refactor that feeds Feishu client creation a resolved runtime credential snapshot so outbound sends do not invoke SecretRef providers independently.
  3. Wait For Tenant Proof
    If maintainers need runtime assurance beyond source-level proof, pause the PR until a redacted live Feishu MEDIA send with a Keychain-backed appSecret is shown.

Next step before merge

  • [P2] Maintainer review is needed because this member-authored PR is currently conflicting and changes Feishu credential-provider timing on send paths.

Security
Cleared: No concrete supply-chain, dependency, workflow, package, permission, or secret-leak issue was found in the diff; credential-provider timing is tracked as merge risk.

Review details

Best possible solution:

Refresh the branch, then either land this scoped Feishu repair after Feishu/SecretRef owners accept send-time credential resolution or move the invariant to a single Feishu client/runtime-snapshot boundary.

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

Yes at source level. Current main documents Feishu appSecret as a SecretRef surface, the strict Feishu runtime resolver throws on unresolved non-env SecretRefs, and media/reply paths still pass cfg into that strict path; I did not run a live Feishu tenant send.

Is this the best way to solve the issue?

Unclear as the final architecture, but acceptable as a bounded repair if owners accept the credential boundary. The cleaner long-term shape is resolving app credentials at one Feishu client/runtime-snapshot boundary rather than from several outbound entry points.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 54b09580f61b.

Label changes

Label justifications:

  • P1: The PR targets a Feishu channel regression where SecretRef-backed credentials can silently prevent MEDIA/image delivery for real users.
  • merge-risk: 🚨 auth-provider: The diff changes when Feishu app credential SecretRefs are resolved on outbound and reply-dispatcher paths, affecting credential-provider timing and failure behavior.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The external-contributor proof gate does not apply to this member-authored PR; the body provides deterministic source-level proof and discloses that no live Feishu tenant MEDIA send was run.
Evidence reviewed

PR surface:

Source +113, Tests +220. Total +333 across 8 files.

View PR surface stats
Area Files Added Removed Net
Source 5 164 51 +113
Tests 3 307 87 +220
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 8 471 138 +333

What I checked:

  • Repository policy applied: Root AGENTS.md was read fully; its review policy treats auth/provider state, channel delivery, fallback behavior, and SecretRef/config behavior as compatibility-sensitive PR surfaces. (AGENTS.md:28, 54b09580f61b)
  • Scoped plugin boundary applied: extensions/AGENTS.md keeps bundled plugin production code on plugin-sdk and local extension surfaces; this PR stays in Feishu and imports the public secret-input-runtime SDK subpath. (extensions/AGENTS.md:17, 54b09580f61b)
  • Current main strict resolver still throws on unresolved SecretRefs: resolveFeishuSecretLike returns plaintext, treats inspect-mode SecretRefs as unavailable, and throws FeishuSecretRefUnavailableError in strict runtime mode for unresolved SecretRefs. (extensions/feishu/src/accounts.ts:56, 54b09580f61b)
  • Feishu appSecret is a documented SecretRef credential surface: The SecretRef credential surface docs list both top-level and per-account Feishu appSecret fields, so SecretRef-backed Feishu credentials are expected current behavior. Public docs: docs/reference/secretref-credential-surface.md. (docs/reference/secretref-credential-surface.md:95, 54b09580f61b)
  • Current main media path reaches the strict resolver: sendMediaFeishu calls resolveFeishuRuntimeAccount before upload, so a cfg carrying an unresolved exec/keychain appSecret SecretRef can fail before media delivery. (extensions/feishu/src/media.ts:879, 54b09580f61b)
  • Current main reply dispatcher still passes raw cfg into strict paths: createFeishuReplyDispatcher resolves the runtime account from cfg at construction and later passes the same cfg to sendMediaFeishu for media replies. (extensions/feishu/src/reply-dispatcher.ts:184, 54b09580f61b)

Likely related people:

  • Peter Steinberger: git log -S ties FeishuSecretRefUnavailableError and the strict/inspect resolver split to ba95d43, and file history shows additional Feishu media/reply refactors on the same paths. (role: introduced credential resolver boundary and adjacent Feishu media/reply refactors; confidence: high; commits: ba95d43e3ce1, fb40b09157d7, 143ae5a5b070; files: extensions/feishu/src/accounts.ts, extensions/feishu/src/accounts.test.ts, extensions/feishu/src/media.ts)
  • Vincent Koc: Recent Feishu history shows runtime-helper and media-adjacent work, including the message-tool/media unblock commit and reply-dispatcher runtime seam changes. (role: recent Feishu runtime and media-adjacent contributor; confidence: medium; commits: 29ad211e7647, 319aa2f1fe67, ddd1c77b49ef; files: extensions/feishu/src/reply-dispatcher.ts, extensions/feishu/src/media.ts, extensions/feishu/src/accounts.ts)
  • Tak Hoffman: Feishu media history includes hardening and capability work around media support, making this person a useful adjacent reviewer for media-delivery risk. (role: adjacent Feishu media hardening contributor; confidence: medium; commits: 3c6a49b27ea0, bc66a8fa81a8; files: extensions/feishu/src/media.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.
Review history (1 earlier review cycle)
  • reviewed 2026-06-22T00:12:27.130Z sha 6f799e5 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added 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. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. 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. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. 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. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 2, 2026
@byungskers

Copy link
Copy Markdown

This looks like a solid seam for fixing #89338 without widening the scope too much. One small question: for the implicit/top-level account case, resolveFeishuOutboundCredentialsConfig still passes channels.feishu.accounts.${account.accountId}.* as the resolver path even though the override gets written back to the top level. Is that path intentionally kept account-shaped just for diagnostics consistency, or would it be safer to align it with the actual source location when the credentials were inherited from the root config?

@openperf
openperf force-pushed the fix/feishu-media-secretref-resolution branch from 5166fc6 to c8c4172 Compare June 3, 2026 07:33
@openperf

openperf commented Jun 3, 2026

Copy link
Copy Markdown
Member Author

@byungskers Not intentional, just an oversight. That path only feeds the unresolved-SecretRef reason string — resolution keys off the value, the config secret defaults, and env, never the path — and this helper drops that reason anyway, so it was a pure mislabel with no behavior behind it. Aligned it with where the override actually lands: channels.feishu.<field> when the creds are inherited from the root, and channels.feishu.accounts.<matchedKey>.<field> (keeping the real, possibly mixed-case key) when they sit under an account. In c8c4172.

@openperf
openperf force-pushed the fix/feishu-media-secretref-resolution branch from c8c4172 to 1981e05 Compare June 3, 2026 08:21
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed 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. rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 3, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. 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 3, 2026
@clawsweeper clawsweeper Bot added the status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. label Jun 3, 2026
openperf added 4 commits June 3, 2026 22:54
…nd path

The strict sync Feishu runtime resolver throws FeishuSecretRefUnavailableError on
an unresolved exec/keychain appId/appSecret SecretRef before the SDK client is
built, dropping outbound and message-tool sends (issue openclaw#89338).

Add resolveFeishuOutboundCredentialsConfig, which inlines a still-unresolved app
credential via the async exec/keychain-capable SDK resolver into an in-memory cfg
copy before the strict resolver runs. Wired into the outbound adapter
(sendPayload/sendText/sendMedia) and the message-tool handleAction (card/media/
text). Resolution writes back at the matched, case-preserving account-map key, or
top-level for an implicit/inherited account, preserving other per-account
settings; the diagnostic path mirrors that write-back location. Plaintext /
already-resolved configs are returned unchanged (no resolver call, no clone).

Fixes openclaw#89338
@openperf
openperf force-pushed the fix/feishu-media-secretref-resolution branch from 9c90c2d to 6f799e5 Compare June 3, 2026 14:54
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jun 15, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. P1 High-priority user-facing bug, regression, or broken workflow. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. P2 Normal backlog priority with limited blast radius. labels Jun 20, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: feishu Channel integration: feishu merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: L stale Marked as stale due to inactivity 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]: Feishu MEDIA/image upload fails when appSecret uses SecretRef (Keychain)

3 participants