Skip to content

feat(slack): support alternate Web API roots#97154

Merged
RomneyDa merged 13 commits into
mainfrom
codex/slack-mock-api-root
Jun 29, 2026
Merged

feat(slack): support alternate Web API roots#97154
RomneyDa merged 13 commits into
mainfrom
codex/slack-mock-api-root

Conversation

@RomneyDa

@RomneyDa RomneyDa commented Jun 27, 2026

Copy link
Copy Markdown
Member

What Problem This Solves

PR #95920 was too broad to review because Slack channel extensibility, WhatsApp channel extensibility, and QA Lab Crabline wiring were bundled together.

This PR isolates the Slack foundation: the Slack plugin can route Slack Web API traffic to an alternate Slack-compatible API root without adding Crabline-specific code to Slack.

Why This Change Was Made

A fake Slack API only works if all Slack WebClient construction paths can use the same alternate root. This change centralizes Slack WebClient option resolution so send, action, probe, scope, directory, allowlist, monitor, and cached write-client paths all inherit the same routing behavior.

The production contract preserves normal Slack SDK precedence: explicit WebClientOptions.slackApiUrl wins, otherwise trusted runtime env can set SLACK_API_URL as the default API root. OPENCLAW_SLACK_API_URL is intentionally not supported as a channel config-style alias.

Security / Operator Contract

SLACK_API_URL is a trusted operator/global runtime override. It must not be loaded from an untrusted workspace .env; this PR blocks workspace SLACK_API_URL injection while preserving trusted global/state .env and process env behavior.

Any process that sets SLACK_API_URL is choosing the fallback destination for Slack Web API bearer-token requests when a caller has not supplied an explicit SDK API root.

User Impact

Normal Slack users keep the default Slack API behavior. QA and integration harnesses can run Slack against a Slack-compatible mock API by setting SLACK_API_URL in trusted runtime env, while direct SDK callers can still override the route explicitly with WebClientOptions.slackApiUrl.

The cached write-client helper remains intentionally narrow: it only accepts the API-root option it keys on, while the uncached write-client constructor still accepts full WebClientOptions.

Stack:

Evidence

  • node scripts/run-vitest.mjs extensions/slack/src/client.test.ts extensions/slack/src/client.web-api.test.ts src/infra/dotenv.test.ts extensions/slack/src/config-schema.test.ts
  • pnpm tsgo:extensions
  • pnpm tsgo:extensions:test
  • PATH="$HOME/.opengrep/cli/latest:$HOME/.local/bin:$PATH" scripts/run-opengrep.sh --changed --sarif --error
  • git diff --check
  • Manual CrabLine smoke against a local Slack fake-provider server on commit 742981f59a: set SLACK_API_URL to CrabLine's manifest endpoints.apiRoot; OpenClaw's Slack client successfully ran auth.test, chat.postMessage, and conversations.history; CrabLine recorder observed POST /api/auth.test, POST /api/chat.postMessage, and POST /api/conversations.history. Commit e2a707746a only narrows the cached helper type contract and does not change runtime routing behavior.

@clawsweeper

clawsweeper Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

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

Summary
The PR routes Slack Web API clients through explicit slackApiUrl or trusted SLACK_API_URL, blocks workspace dotenv injection for that key, partitions cached write clients by API root, and adds Slack/dotenv coverage.

PR surface: Source +22, Tests +275. Total +297 across 8 files.

Reproducibility: not applicable. as a bug reproduction; this PR adds a Slack routing feature. The changed behavior is source-verifiable and covered by PR-head tests that route real WebClient requests to a local fake Slack API root.

Review metrics: 3 noteworthy metrics.

  • Env routing surface: 1 added: SLACK_API_URL. This env key can redirect Slack Web API bearer-token requests, so maintainers should notice the operator/security boundary before merge.
  • Workspace dotenv guard: 1 blocked key added. Blocking workspace SLACK_API_URL is the concrete mitigation that keeps untrusted repository .env files from choosing the Slack API destination.
  • Exported cached helper parameter: 1 optional parameter added. getSlackWriteClient is exported through the Slack API barrel, so its new API-root option and cache key are compatibility-relevant.

Stored data model
Persistent data-model change detected: serialized state: extensions/slack/src/client.web-api.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🐚 platinum hermit
Patch quality: 🦐 gold shrimp
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] Record maintainer acceptance or requested changes for the trusted SLACK_API_URL routing boundary before merge.

Risk before merge

  • [P1] SLACK_API_URL becomes a trusted process/global default for Slack Web API bearer-token requests, so any existing trusted runtime environment that sets it will redirect Slack traffic after upgrade.
  • [P1] Blocking workspace .env injection mitigates untrusted repository control, but maintainers still need to accept the global/state env operator boundary before merge.
  • [P1] The linked WhatsApp and QA Lab Crabline PRs depend on this Slack foundation, so changing this contract later can ripple into that split stack.

Maintainer options:

  1. Accept the trusted env boundary explicitly (recommended)
    Maintainers can proceed if they intentionally want trusted process/global SLACK_API_URL to control the default Slack Web API destination and treat workspace dotenv blocking as the required mitigation.
  2. Rename or narrow the routing surface before merge
    If the global SLACK_API_URL name is too broad, replace it with a narrower approved operator surface or harness-only seam before landing the dependent stack.
  3. Pause dependent fake-provider wiring
    If the Slack routing boundary is not settled, hold the linked WhatsApp and QA Lab Crabline PRs until this foundation has an accepted contract.

Next step before merge

  • [P2] A maintainer-labeled PR needs human acceptance of the trusted env/security boundary; no narrow automated repair remains after the cached helper contract was narrowed.

Security
Needs attention: The diff introduces no dependency or supply-chain change, but it intentionally adds a trusted env route for Slack bearer-token Web API requests and needs maintainer acceptance of that boundary.

Review details

Best possible solution:

Land the env-only Slack API-root seam only after maintainer acceptance of the trusted SLACK_API_URL boundary, keeping workspace dotenv blocked and the cached write-client API narrow.

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

Not applicable as a bug reproduction; this PR adds a Slack routing feature. The changed behavior is source-verifiable and covered by PR-head tests that route real WebClient requests to a local fake Slack API root.

Is this the best way to solve the issue?

Yes, conditionally: using Slack SDK slackApiUrl in the existing Slack client option resolver is the narrowest owner-boundary seam and avoids Slack config-schema churn. The remaining question is not code shape but whether maintainers accept trusted env as the product/security boundary.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add 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 maintainer-labeled MEMBER PR; the body nevertheless includes focused commands and a manual CrabLine smoke summary for the routing behavior.
  • remove status: ⏳ waiting on author: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P2: This is a bounded Slack/QA foundation feature with compatibility and security-boundary review needs but no active production outage shown.
  • merge-risk: 🚨 compatibility: The PR adds a trusted env/default route and changes the exported Slack cached write-client helper signature, which can affect existing runtime environments and plugin callers.
  • merge-risk: 🚨 security-boundary: The PR lets trusted process/global env choose the destination for Slack Web API bearer-token requests.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • 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 maintainer-labeled MEMBER PR; the body nevertheless includes focused commands and a manual CrabLine smoke summary for the routing behavior.
Evidence reviewed

PR surface:

Source +22, Tests +275. Total +297 across 8 files.

View PR surface stats
Area Files Added Removed Net
Source 4 49 27 +22
Tests 4 284 9 +275
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 8 333 36 +297

Security concerns:

  • [medium] Trusted env can redirect Slack bearer-token calls — extensions/slack/src/client-options.ts:50
    SLACK_API_URL becomes the fallback Slack Web API root; the Slack SDK uses that value as the request base URL while sending the bearer token, so trusted process/global env chooses the destination when no explicit SDK root is supplied.
    Confidence: 0.88

What I checked:

  • Root policy read and applied: Root review policy treats plugin APIs, env/config defaults, fallback behavior, and security boundaries as compatibility-sensitive, which applies to this Slack env-routing PR. (AGENTS.md:31, 4a4657a1828f)
  • Scoped extension policy read: Bundled plugin exports are plugin-boundary contracts, so changes to exported Slack helpers must be reviewed as compatibility-sensitive API surface. (extensions/AGENTS.md:1, 4a4657a1828f)
  • Current main lacks env API-root fallback: Current main only spreads caller options and adds proxy/retry defaults; it does not read SLACK_API_URL, so the PR is not obsolete on main. (extensions/slack/src/client-options.ts:46, 4a4657a1828f)
  • PR head adds trusted env fallback: PR head resolves slackApiUrl from explicit options first, then process.env.SLACK_API_URL, and uses that root for Slack WebClient options. (extensions/slack/src/client-options.ts:49, e2a707746ae0)
  • Cached write helper narrowed: The latest head narrows getSlackWriteClient options to Pick<WebClientOptions, "slackApiUrl"> and keys the cache by token plus API root, addressing the previous broad-options cache defect. (extensions/slack/src/client.ts:9, e2a707746ae0)
  • Workspace dotenv mitigation added: PR head adds SLACK_API_URL to the workspace dotenv blocklist while tests keep trusted global/state .env loading for that key. (src/infra/dotenv.ts:167, e2a707746ae0)

Likely related people:

  • steipete: Recent current-main history includes Slack write-client cache and token-key work, plus merging the adjacent Slack proxy PR that this change extends. (role: recent Slack client/cache contributor and merger; confidence: high; commits: b69e3b633b28, d399ac74f752, b4034b32c365; files: extensions/slack/src/client.ts, extensions/slack/src/client.test.ts, extensions/slack/src/client-options.ts)
  • mjamiv: Authored the merged Slack Socket Mode env-proxy work whose WebClient/proxy option path is now being extended for alternate API roots. (role: introduced adjacent Slack proxy behavior; confidence: medium; commits: c9dec92691f2, 6060275b4d89, b08d6307bb2c; files: extensions/slack/src/client.ts, extensions/slack/src/client.test.ts)
  • mmaps: Authored the merged workspace dotenv credential-blocking work whose blocklist pattern this PR extends with SLACK_API_URL. (role: workspace dotenv trust-boundary contributor; confidence: medium; commits: 85277c2db1fa; files: src/infra/dotenv.ts, src/infra/dotenv.test.ts)
  • vincentkoc: Most recent current-main dotenv refactor touched the shared dotenv loader that this PR updates. (role: recent infra dotenv contributor; confidence: medium; commits: 645679028714; files: src/infra/dotenv.ts, src/infra/dotenv-global.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.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. 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. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 27, 2026
@RomneyDa

Copy link
Copy Markdown
Member Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 27, 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.

@RomneyDa
RomneyDa force-pushed the codex/slack-mock-api-root branch from 8a44502 to 26988b8 Compare June 28, 2026 05:41
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jun 29, 2026
@RomneyDa

Copy link
Copy Markdown
Member Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 29, 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.

@RomneyDa
RomneyDa force-pushed the codex/slack-mock-api-root branch from 7430b67 to 258b831 Compare June 29, 2026 00:52
@RomneyDa RomneyDa changed the title feat(slack): support alternate Web API roots feat(slack): route Web API via SLACK_API_URL Jun 29, 2026
@RomneyDa

Copy link
Copy Markdown
Member Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 29, 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.

@RomneyDa RomneyDa changed the title feat(slack): route Web API via SLACK_API_URL feat(slack): support alternate Web API roots Jun 29, 2026
@RomneyDa

Copy link
Copy Markdown
Member Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 29, 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.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 29, 2026
@RomneyDa

Copy link
Copy Markdown
Member Author

@clawsweeper re-review

1 similar comment
@RomneyDa

Copy link
Copy Markdown
Member Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 29, 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.

@clawsweeper clawsweeper Bot added status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 29, 2026
@RomneyDa
RomneyDa merged commit 39e1be0 into main Jun 29, 2026
109 of 114 checks passed
@RomneyDa
RomneyDa deleted the codex/slack-mock-api-root branch June 29, 2026 01:52
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 29, 2026
* Allow Slack to target alternate Web API roots

* Protect Slack API URL routing

* Simplify Slack API URL routing

* Use env-only Slack API root routing

* Remove Slack client option alias

* Keep Slack API URL dotenv test inline

* Remove leftover Slack PR churn

* Block workspace Slack API URL dotenv

* Preserve Slack proxy HTTPS protocol

* Keep Slack option resolution explicit

* Remove Slack probe formatting diff

* fix(slack): preserve explicit API root precedence

* fix(slack): narrow cached write client options
QiuYuang pushed a commit to QiuYuang/openclaw that referenced this pull request Jul 1, 2026
* Allow Slack to target alternate Web API roots

* Protect Slack API URL routing

* Simplify Slack API URL routing

* Use env-only Slack API root routing

* Remove Slack client option alias

* Keep Slack API URL dotenv test inline

* Remove leftover Slack PR churn

* Block workspace Slack API URL dotenv

* Preserve Slack proxy HTTPS protocol

* Keep Slack option resolution explicit

* Remove Slack probe formatting diff

* fix(slack): preserve explicit API root precedence

* fix(slack): narrow cached write client options
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 1, 2026
* Allow Slack to target alternate Web API roots

* Protect Slack API URL routing

* Simplify Slack API URL routing

* Use env-only Slack API root routing

* Remove Slack client option alias

* Keep Slack API URL dotenv test inline

* Remove leftover Slack PR churn

* Block workspace Slack API URL dotenv

* Preserve Slack proxy HTTPS protocol

* Keep Slack option resolution explicit

* Remove Slack probe formatting diff

* fix(slack): preserve explicit API root precedence

* fix(slack): narrow cached write client options
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 3, 2026
* Allow Slack to target alternate Web API roots

* Protect Slack API URL routing

* Simplify Slack API URL routing

* Use env-only Slack API root routing

* Remove Slack client option alias

* Keep Slack API URL dotenv test inline

* Remove leftover Slack PR churn

* Block workspace Slack API URL dotenv

* Preserve Slack proxy HTTPS protocol

* Keep Slack option resolution explicit

* Remove Slack probe formatting diff

* fix(slack): preserve explicit API root precedence

* fix(slack): narrow cached write client options
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: M 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.

1 participant