Commit Graph

19208 Commits

Author SHA1 Message Date
Rai Butera 9f3d7a3e7d fix(gateway): reject inter_session delivery before run tracking 2026-03-15 22:25:52 +00:00
Rai Butera 9efa86be99 fix(gateway): keep reserved channel ids immutable 2026-03-15 22:25:52 +00:00
Rai Butera f616055958 fix(test): add authOk to backend pairing cases 2026-03-15 22:25:52 +00:00
Rai Butera b46869b9fc test(gateway): lock backend internal auth boundaries 2026-03-15 22:25:52 +00:00
Rai Butera 1000873a25 Protect reserved channel ids from alias remapping 2026-03-15 22:25:52 +00:00
Rai Butera fd2e3a8fc0 fix(gateway): trust bootstrap-token backend pairing 2026-03-15 22:25:52 +00:00
Rai Butera ad656987e4 fix: decouple tailscale attestation from sharedAuthOk gate 2026-03-15 22:25:52 +00:00
Rai Butera b6c4c82a63 fix: pre-emptive review pass — cover all auth methods and routing edge cases 2026-03-15 22:25:52 +00:00
Rai Butera e01a6d7c49 fix: decouple device-token attestation from sharedAuthOk gate 2026-03-15 22:25:52 +00:00
Rai Butera a390cd1a0a fix: trust device-token auth for internal backend attestation 2026-03-15 22:25:52 +00:00
Rai Butera 9f63b4c460 fix: allow remote backend clients with shared-secret auth as internal 2026-03-15 22:25:52 +00:00
Rai Butera 42284cc2da fix: remove session-key channel hint fallback for inter-session turns 2026-03-15 22:25:52 +00:00
Rai Butera 75ed865796 fix: attest internal backend client when auth mode is none 2026-03-15 22:25:52 +00:00
Rai Butera 5d8057708a fix(test): satisfy connect params types in attestation coverage 2026-03-15 22:25:51 +00:00
Rai Butera aa3eb2d444 test(gateway): cover trusted backend attestation policy 2026-03-15 22:25:51 +00:00
Rai Butera 91de302a70 fix(gateway): derive inter-session attestation from handshake trust 2026-03-15 22:25:51 +00:00
Rai Butera ba5fe7130d Fix internal gateway attestation for inter-session sends 2026-03-15 22:25:51 +00:00
Rai Butera dc61211802 fix: require server attestation for inter-session sentinel 2026-03-15 22:25:51 +00:00
Rai Butera d32cd5340e Gateway: reject delivered inter_session sentinel 2026-03-15 22:25:51 +00:00
Rai Butera 7e38aee263 Gateway: block public inter_session sentinel 2026-03-15 22:25:51 +00:00
Rai Butera 62080b6283 fix: allow INTER_SESSION_CHANNEL through agent.ts validation and turnSource
sessions_send calls callGateway({ method: 'agent', params: sendParams })
with channel: INTER_SESSION_CHANNEL. Two things blocked the sentinel from
working in the real gateway path:

1. Channel hint validation rejected 'inter_session' as an unknown channel
   (isGatewayMessageChannel returns false since we excluded it from
   listGatewayMessageChannels). Fix: isKnownGatewayChannel now also passes
   RESERVED_CHANNEL_IDS, letting internal sentinels through.

2. turnSourceMessageChannel discarded 'inter_session' because
   isGatewayMessageChannel returns false for it, so ctx.OriginatingChannel
   was never set to the sentinel and resolveLastChannelRaw never fired the
   sentinel path. Fix: isInterSessionChannel check added alongside
   isGatewayMessageChannel in the turnSourceMessageChannel assignment.

TypeScript TS2339 workaround: GatewayMessageChannel includes (string & {})
so after the type guard, value narrows to never. Captured as String(raw)
before the guard to preserve the plain string type.
2026-03-15 22:25:51 +00:00
Rai Butera e252fa3995 fix: exclude INTER_SESSION_CHANNEL from listGatewayMessageChannels + guard in agent-delivery
INTER_SESSION_CHANNEL was added to listGatewayMessageChannels(), making
isGatewayMessageChannel('inter_session') return true. This allowed external
RPC callers to pass channel='inter_session', bypassing delivery validation
and triggering unintended inter-session routing behaviour.

Fix:
- Remove INTER_SESSION_CHANNEL from listGatewayMessageChannels() runtime
  list. It remains in the GatewayMessageChannel type union so internal
  tools (sessions-send-tool.ts) can still use it with type safety.
  isGatewayMessageChannel('inter_session') now returns false.
- Add explicit RESERVED_CHANNEL_IDS guard in agent-delivery.ts before the
  isGatewayMessageChannel branch. Belt-and-suspenders: even if the sentinel
  somehow reaches the delivery resolver via an internal path, it falls back
  to INTERNAL_MESSAGE_CHANNEL rather than being treated as a real channel.

The sentinel still functions correctly in resolveLastChannelRaw /
resolveLastToRaw, which call isInterSessionChannel() directly.
2026-03-15 22:25:51 +00:00
Rai Butera 73057ebc65 fix: widen RESERVED_CHANNEL_IDS to Set<string> to fix TS2345
TypeScript infers Set<'inter_session' | 'webchat'> from the literal
values, making .has(string) a type error. Explicit Set<string>
annotation fixes CI typecheck without changing runtime behaviour.
2026-03-15 22:25:51 +00:00
Rai Butera 6698c1af84 fix: strip reserved names from channel aliases at registration (Codex P2)
registerChannel blocked reserved ids but not reserved aliases.
normalizeMessageChannel resolves aliases before routing, so a plugin
with alias 'inter_session' would remap the sentinel into a real
deliverable channel, bypassing resolveLastChannelRaw/resolveLastToRaw.

Fix: after the id guard, scan plugin.meta.aliases for reserved names.
Emit an error diagnostic and strip the reserved alias rather than
blocking the whole channel registration (so the rest of the plugin
still works). The reserved id set already covers both 'inter_session'
and 'webchat'.

Adds loader.test.ts case: plugin with reserved alias still registers
but alias is stripped and error diagnostic is emitted.
2026-03-15 22:25:51 +00:00
Rai Butera 1192e3ccf9 test: harden sentinel edge cases (empty channel, leaked state, non-discord external)
Pre-empt edge case regressions flagged in review:
- empty string persistedLastChannel treated as absent (no mismatch risk)
- sentinel value leaked into persistedLastChannel returns undefined (corrupted state guard)
- non-discord external channels (telegram etc.) correctly preserve persistedLastTo
2026-03-15 22:25:51 +00:00
Rai Butera 5ba0b7d0e7 fix: avoid stale lastTo when channel resolves via session-key hint
Codex P1: resolveLastToRaw's inter-session sentinel was unconditionally
returning persistedLastTo. When resolveLastChannelRaw falls back to a
session-key hint (e.g. agent:navi:discord:direct:* → 'discord') because
persistedLastChannel is not yet external (e.g. still 'webchat'), blindly
returning persistedLastTo creates a mismatched lastChannel/lastTo pair
(discord channel + stale webchat target), causing subsequent 'last'
replies to be routed to an invalid destination.

Fix: mirror resolveLastChannelRaw's sentinel logic — only preserve
persistedLastTo when persistedLastChannel is already an external routing
channel (consistent pair). Return undefined otherwise so the caller
derives an appropriate target from the resolved channel.

Adds two new tests:
- 'returns undefined when channel resolves via session-key hint'
- 'preserves persistedLastTo when persisted channel is already external'

21/21 session-delivery tests, 19/19 sessions tests, 23/23 install tests.
2026-03-15 22:25:51 +00:00
Rai Butera a570b7d40c fix: extend sentinel reservation to registerChannel in registry
Codex P2: validatePluginId in install.ts only blocks the npm package
install path. A channel loaded via discovery/config can still call
registerChannel with id='inter_session', bypassing the guard.

- Move RESERVED_CHANNEL_IDS to message-channel.ts (canonical location
  for channel constants) and export it
- Import RESERVED_CHANNEL_IDS in both install.ts and registry.ts
- Add guard in registerChannel: push error diagnostic and return early
  if a plugin attempts to register a reserved channel ID

All three reservation paths are now covered:
  1. Package install (validatePluginId in install.ts)
  2. Runtime channel registration (registerChannel in registry.ts)
  3. isInterSessionChannel deliverability guard (existing)

60/60 tests green.
2026-03-15 22:25:51 +00:00
Rai Butera 8fc4eff1af fix: reserve inter_session and webchat as plugin ids
Codex P2: a plugin named 'inter_session' would make
isInterSessionChannel return false (deliverable guard), silently
disabling the sentinel routing path in sessions_send.

Add RESERVED_CHANNEL_IDS set to validatePluginId() covering both
INTER_SESSION_CHANNEL and INTERNAL_MESSAGE_CHANNEL. Any attempt to
install a channel plugin with those ids now returns a clear error.

Adds regression test covering both sentinel ids.
2026-03-15 22:25:51 +00:00
Rai Butera e35a2041fb refactor(sessions): address Greptile dead-variable and Codex P2 plugin-collision concerns
Greptile: originatingChannel was computed before the isInterSessionChannel guard
but never used inside it, wasting a normalizeMessageChannel call on the fast path.
Moved the declaration to after the guard where it is actually needed.

Codex P2: isInterSessionChannel had no protection against a real deliverable plugin
channel named 'inter_session'. Added isDeliverableMessageChannel check so that if a
plugin registers that id, the sentinel path is skipped and normal routing applies.

Test: added invariant test documenting the Codex P2 guard (19 tests green).
2026-03-15 22:25:51 +00:00
Rai Butera 45981e0e82 fix(sessions): use INTER_SESSION_CHANNEL sentinel in sessions_send to preserve receiver's external route
Codex P2 on #43353: threading agentChannel alone without paired to/accountId/threadId
causes resolveLastToRaw to fall back to a stale persistedLastTo, producing mismatched
channel+to state (e.g. channel=discord but routing to an old Telegram destination).

Instead, use a new INTER_SESSION_CHANNEL ("inter_session") sentinel. Both
resolveLastChannelRaw and resolveLastToRaw handle it explicitly:

- resolveLastChannelRaw: returns the persisted external channel (or session-key hint)
  without injecting the sender's channel or flipping to webchat
- resolveLastToRaw: returns persistedLastTo, preserving the receiver's destination

The sender's agentChannel is still captured in inputProvenance.sourceChannel for
observability but is no longer used to mutate the receiver's routing state.

Tests:
- sessions.test.ts: updated two agentChannel-threading tests to assert inter_session
  sentinel is used (not webchat, not sender channel)
- session-delivery.test.ts: 6 new tests covering INTER_SESSION_CHANNEL routing cases
  including the original webchat-flip regression and the stale-to preservation

Fixes https://github.com/openclaw/openclaw/issues/43318
2026-03-15 22:25:51 +00:00
Rai Butera cb878abad1 test(sessions): verify agentChannel threads through sessions_send to agent gateway call
Add two regression tests for #43318:
- asserts that when agentChannel is provided, the 'agent' gateway call
  receives that channel (not 'webchat') in sendParams
- asserts that when agentChannel is absent, channel falls back to webchat
  (preserving existing behaviour for internal spawns)

Closes #43318
2026-03-15 22:25:51 +00:00
Rai Butera 61d9fb3190 fix(sessions): thread agentChannel through sessions_send instead of hardcoding INTERNAL_MESSAGE_CHANNEL
When sessions_send injects a message into a target session, it was
hardcoding channel: INTERNAL_MESSAGE_CHANNEL ('webchat'). For main
sessions with an active external channel route (Discord, Telegram etc),
this caused resolveLastChannelRaw to flip lastChannel to 'webchat' for
that turn, silently routing the agent's reply to the control UI instead
of the user's channel.

Fix: pass opts?.agentChannel ?? INTERNAL_MESSAGE_CHANNEL so external-
originated A2A sends carry the correct source channel through. Falls
back to INTERNAL_MESSAGE_CHANNEL for internal spawns with no agentChannel.

Fixes: openclaw/openclaw#43318
2026-03-15 22:25:51 +00:00
Peter Steinberger 392ddb56e2
build(plugins): add bundled provider plugin manifests 2026-03-15 15:18:32 -07:00
Peter Steinberger 4a0f72866b
feat(plugins): move provider runtimes into bundled plugins 2026-03-15 15:18:32 -07:00
Gustavo Madeira Santana 14137bef22
Plugins: clean stale bundled skill outputs 2026-03-15 21:48:09 +00:00
Gustavo Madeira Santana 50a6902a9a
Plugins: skip nested node_modules in bundled skills 2026-03-15 21:43:13 +00:00
Gustavo Madeira Santana 1839bc0b1a
Plugins: relocate bundled skill assets 2026-03-15 21:42:02 +00:00
Vincent Koc b810e94a17
Commands: lazy-load non-interactive plugin provider runtime (#47593)
* Commands: lazy-load non-interactive plugin provider runtime

* Tests: cover non-interactive plugin provider ordering

* Update src/commands/onboard-non-interactive/local/auth-choice.plugin-providers.runtime.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-15 14:37:41 -07:00
Nimrod Gutman 50c8934231
fix(dev): align gateway watch with tsdown wrapper (#47636) 2026-03-15 23:28:57 +02:00
Vincent Koc 5a7aba94a2
CLI: support package-manager installs from GitHub main (#47630)
* CLI: resolve package-manager main install specs

* CLI: skip registry resolution for raw package specs

* CLI: support main package target updates

* CLI: document package update specs in help

* Tests: cover package install spec resolution

* Tests: cover npm main-package updates

* Tests: cover update --tag main

* Installer: support main package targets

* Installer: support main package targets on Windows

* Docs: document package-manager main updates

* Docs: document installer main targets

* Docs: document npm and pnpm main installs

* Docs: document update --tag main

* Changelog: note package-manager main installs

* Update src/infra/update-global.test.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-15 14:18:12 -07:00
Vincent Koc 3735156766
fix(ci): restore config baseline release-check output (#47629)
* Docs: regenerate config baseline

* Chore: ignore generated config baseline

* Update .prettierignore

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-15 14:14:30 -07:00
Nimrod Gutman 47fd8558cd
fix(plugins): fix bundled plugin roots and skill assets (#47601)
* fix(acpx): resolve bundled plugin root correctly

* fix(plugins): copy bundled plugin skill assets

* fix(plugins): tolerate missing bundled skill paths
2026-03-15 23:00:30 +02:00
Vincent Koc 7931f06c00 Plugins: harden context engine ownership 2026-03-15 13:51:15 -07:00
Gustavo Madeira Santana 4fb0160309
Gateway: sync runtime post-build artifacts 2026-03-15 20:44:15 +00:00
Vincent Koc b795ba1d02 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  Plugins: reserve context engine ownership (#47595)
  fix(release): block oversized npm packs that regress low-memory startup (#46850)
  Scripts: rebuild on extension and tsdown config changes (#47571)
  Docs: move release runbook to maintainer repo (#47532)
  docs(zalo): document current Marketplace bot behavior (openclaw#47552)
2026-03-15 13:42:21 -07:00
Vincent Koc 85dd0ab2f8
Plugins: reserve context engine ownership (#47595)
* Plugins: reserve context engine ownership

* Update src/context-engine/registry.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-15 13:33:37 -07:00
Ted Li 07f890fa45
fix(release): block oversized npm packs that regress low-memory startup (#46850)
* fix(release): guard npm pack size regressions

* fix(release): fail closed when npm omits pack size
2026-03-15 21:31:30 +01:00
Gustavo Madeira Santana 594920f8cc
Scripts: rebuild on extension and tsdown config changes (#47571)
Merged via squash.

Prepared head SHA: edd8ed8254
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-15 16:19:27 -04:00
Onur Solmaz a2080421a1
Docs: move release runbook to maintainer repo (#47532)
* Docs: redact private release setup

* Docs: tighten release order

* Docs: move release runbook to maintainer repo

* Docs: delete public mac release page

* Docs: remove zh-CN mac release page

* Docs: turn release checklist into release policy

* Docs: point release policy to private docs

* Docs: regenerate zh-CN release policy pages

* Docs: preserve Doctor in zh-CN hubs

* Docs: fix zh-CN polls label

* Docs: tighten docs i18n term guardrails

* Docs: enforce zh-CN glossary coverage
2026-03-15 20:42:39 +01:00
Tomáš Dinh 4a7fbe090a
docs(zalo): document current Marketplace bot behavior (openclaw#47552)
Verified:
- pnpm check:docs

Co-authored-by: Tomáš Dinh <82420070+No898@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-15 14:40:35 -05:00