Skip to content

test(gateway): stabilize suite session-store config#52193

Merged
frankekn merged 3 commits intoopenclaw:mainfrom
ImLukeF:imlukef/gateway-test-harness-stability
Mar 22, 2026
Merged

test(gateway): stabilize suite session-store config#52193
frankekn merged 3 commits intoopenclaw:mainfrom
ImLukeF:imlukef/gateway-test-harness-stability

Conversation

@ImLukeF
Copy link
Copy Markdown
Contributor

@ImLukeF ImLukeF commented Mar 22, 2026

Summary

  • stabilize gateway suite test state so seeded session stores stay visible across suite-scoped runs
  • mirror the test session store override into the config locations the runtime consults and clear runtime/session caches during resets
  • update gateway classification/allowlist drift for sessions.steer and GatewayClient callsites

Testing

  • pnpm check
  • pnpm protocol:check
  • pnpm canvas:a2ui:bundle && pnpm exec vitest run --config vitest.unit.config.ts
  • OPENCLAW_TEST_WORKERS=1 OPENCLAW_TEST_SHARDS=6 OPENCLAW_TEST_SHARD_INDEX=6 pnpm test
  • pnpm build
  • pnpm test:gateway still fails on fresh main, but this patch reduced the failure set from 48 failing tests / 13 files to 23 failing tests / 11 files

Remaining Gateway Baseline Failures

  • src/gateway/gateway.test.ts
  • src/gateway/server.agent.gateway-server-agent-b.test.ts
  • src/gateway/server.auth.control-ui.test.ts
  • src/gateway/server.auth.default-token.test.ts
  • src/gateway/server.auth.modes.test.ts
  • src/gateway/server.canvas-auth.test.ts
  • src/gateway/server.models-voicewake-misc.test.ts
  • src/gateway/server.node-invoke-approval-bypass.test.ts
  • src/gateway/server.reload.test.ts
  • src/gateway/server.sessions.gateway-server-sessions-a.test.ts
  • src/gateway/server.plugins-http.test.ts

@openclaw-barnacle openclaw-barnacle bot added gateway Gateway runtime size: S labels Mar 22, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 22, 2026

Greptile Summary

This PR stabilizes the gateway test suite by ensuring seeded session stores remain visible across suite-scoped test runs. It moves testState into vi.hoisted() (so mock factories can access it), persists the session store path into on-disk config files via a new persistTestSessionStorePath helper, adds runtime/session cache clearing around state resets, and switches suite-scope hooks to a stable (non-sequenced) config root. It also adds sessions.steer to the operator method-scope allowlist and updates the GatewayClient callsite guard to reflect a moved instantiation site.

Key changes:

  • test-helpers.mocks.ts: testState moved into vi.hoisted() so it is accessible inside vi.mock() factory closures that run before module-level code initialises.
  • test-helpers.server.ts: New persistTestSessionStorePath writes session.store into the real on-disk config files the runtime reads; clearSessionStoreCacheForTest and clearConfigCache/clearRuntimeConfigSnapshot are called at reset and around store writes to prevent stale-cache reads. Suite-scope hooks switch uniqueConfigRoot to false for a stable shared directory.
  • method-scopes.ts: sessions.steer added to the operator scope group.
  • client-callsites.guard.test.ts: Allowlist updated from the Discord extension to src/gateway/operator-approvals-client.ts.

Confidence Score: 5/5

  • Test infrastructure and scope-classification changes only — no production runtime logic modified. Safe to merge.
  • All four modified files are either test helpers or a small scope-list addition. The testState hoisting fix correctly resolves the Vitest execution-order issue. The persistTestSessionStorePath implementation is straightforward and handles missing-file/missing-env gracefully. Cache clearing is applied consistently. No logic errors or data-loss risks are present, and the PR is transparent about the remaining failures it does not yet address.
  • No files require special attention.

Reviews (1): Last reviewed commit: "test(gateway): stabilize suite session-s..." | Re-trigger Greptile

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: 4c5c9dba1a

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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: 68c748765c

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@frankekn frankekn merged commit ad24fcc into openclaw:main Mar 22, 2026
35 of 37 checks passed
@frankekn frankekn self-assigned this Mar 22, 2026
@frankekn
Copy link
Copy Markdown
Contributor

Landed in ad24fcc from 1ae9ba6.

Thanks @ImLukeF.

frankekn pushed a commit to CharZhou/openclaw that referenced this pull request Mar 22, 2026
* test(gateway): stabilize suite session-store config

* test(gateway): preserve seeded config semantics

* test(gateway): update seeded session store overrides
MaheshBhushan pushed a commit to MaheshBhushan/openclaw that referenced this pull request Mar 22, 2026
* test(gateway): stabilize suite session-store config

* test(gateway): preserve seeded config semantics

* test(gateway): update seeded session store overrides
frankekn pushed a commit to artwalker/openclaw that referenced this pull request Mar 23, 2026
* test(gateway): stabilize suite session-store config

* test(gateway): preserve seeded config semantics

* test(gateway): update seeded session store overrides
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 24, 2026
* test(gateway): stabilize suite session-store config

* test(gateway): preserve seeded config semantics

* test(gateway): update seeded session store overrides

(cherry picked from commit ad24fcc)
alexey-pelykh added a commit to remoteclaw/remoteclaw that referenced this pull request Mar 24, 2026
…1959)

* refactor: share gateway client auth retry helpers

(cherry picked from commit 5f34391)

* Gateway: preserve discovered session store paths

(cherry picked from commit 60c1577)

* refactor: share node pending test client

(cherry picked from commit 644fb76)

* fix: add null guards to usage sort comparators

Prevents crash when totals is undefined in byModel/byProvider/byAgent
sort comparators. Fixes 'Cannot read properties of undefined (reading
totalTokens)' crash that causes context overflow in active sessions.

(cherry picked from commit 6921716)

* refactor: share gateway credential secretref assertions

(cherry picked from commit 6cc86ad)

* fix: force-stop lingering gateway client sockets

(cherry picked from commit 727fc79)

* Gateway: lazily resolve channel runtime

(cherry picked from commit 776e5d8)

* test: stabilize gateway alias coverage

(cherry picked from commit 7b00a06)

* Gateway: preserve trusted-proxy browser scopes

(cherry picked from commit 8661c27)

* test: simplify control ui http coverage

(cherry picked from commit 91d4f5c)

* test: tighten server method helper coverage

(cherry picked from commit 91f1894)

* fix(gateway): remove re-introduced auth.mode=none pairing bypass

The revert of openclaw#43478 (commit 39b4185) was silently undone by
3704293 which was based on a branch that included the original
change. This removes the auth.mode=none skipPairing condition again.

The blanket skip was too broad - it disabled pairing for ALL websocket
clients, not just Control UI behind reverse proxies.

(cherry picked from commit 92fc806)

* fix(gateway): avoid probe false negatives after connect

(cherry picked from commit 93df5f6)

* fix(gateway): skip device pairing when auth.mode=none

Fixes openclaw#42931

When gateway.auth.mode is set to "none", authentication succeeds with
method "none" but sharedAuthOk remains false because the auth-context
only recognises token/password/trusted-proxy methods. This causes all
pairing-skip conditions to fail, so Control UI browser connections get
closed with code 1008 "pairing required" despite auth being disabled.

Short-circuit the skipPairing check: if the operator explicitly
disabled authentication, device pairing (which is itself an auth
mechanism) must also be bypassed.

Fixes openclaw#42931

(cherry picked from commit 9bffa34)

* Gateway: cover lazy channel runtime resolution

(cherry picked from commit 9ee0fb5)

* fix(gateway): propagate real gateway client into plugin subagent runtime

Plugin subagent dispatch used a hardcoded synthetic client carrying
operator.admin, operator.approvals, and operator.pairing for all
runtime.subagent.* calls. Plugin HTTP routes with auth:"plugin" require
no gateway auth by design, so an unauthenticated external request could
drive admin-only gateway methods (sessions.delete, agent.run) through
the subagent runtime.

Propagate the real gateway client into the plugin runtime request scope
when one is available. Plugin HTTP routes now run inside a scoped
runtime client: auth:"plugin" routes receive a non-admin synthetic
operator.write client; gateway-authenticated routes retain admin-capable
scopes. The security boundary is enforced at the HTTP handler level.

Fixes GHSA-xw77-45gv-p728

(cherry picked from commit a1520d7)

* refactor: share control ui hardlink asset setup

(cherry picked from commit a3ece09)

* test(gateway): avoid hoisted reply mock tdz

(cherry picked from commit a60a4b4)

* fix(gateway): pin plugin webhook route registry (openclaw#47902)

(cherry picked from commit a69f619)

* test(gateway): stabilize suite session-store config (openclaw#52193)

* test(gateway): stabilize suite session-store config

* test(gateway): preserve seeded config semantics

* test(gateway): update seeded session store overrides

(cherry picked from commit ad24fcc)

* test: share plugin http auth helpers

(cherry picked from commit b644669)

* refactor: deduplicate push test fixtures

(cherry picked from commit b6b5e5c)

* test: share gateway reload helpers

(cherry picked from commit b72ac79)

* test: dedupe cron config setup

(cherry picked from commit ba34266)

* test: simplify talk config and path env coverage

(cherry picked from commit bec76be)

* refactor: share agent wait dedupe cleanup

(cherry picked from commit c889803)

* test(gateway): restore agent request route mock

(cherry picked from commit ccba943)

* fix: add gateway session reset routing coverage (openclaw#44773) (thanks @Lanfei)

(cherry picked from commit d40a4e3)

* fix(gateway): enforce caller-scope subsetting in device.token.rotate

device.token.rotate accepted attacker-controlled scopes and forwarded
them to rotateDeviceToken without verifying the caller held those
scopes. A pairing-scoped token could rotate up to operator.admin on
any already-paired device whose approvedScopes included admin.

Add a caller-scope subsetting check before rotateDeviceToken: the
requested scopes must be a subset of client.connect.scopes via the
existing roleScopesAllow helper. Reject with missing scope: <scope>
if not.

Also add server.device-token-rotate-authz.test.ts covering both the
priv-esc path and the admin-to-node-invoke chain.

Fixes GHSA-4jpw-hj22-2xmc

(cherry picked from commit dafd61b)

* refactor: share readiness test harness

(cherry picked from commit db9c755)

* test: simplify method scope coverage

(cherry picked from commit e1b9250)

* refactor: share node wake test apns fixtures

(cherry picked from commit e351a86)

* refactor: reuse gateway talk provider schema fields

(cherry picked from commit e94ac57)

* fix(gateway): enforce browser origin check regardless of proxy headers

In trusted-proxy mode, enforceOriginCheckForAnyClient was set to false
whenever proxy headers were present. This allowed browser-originated
WebSocket connections from untrusted origins to bypass origin validation
entirely, as the check only ran for control-ui and webchat client types.

An attacker serving a page from an untrusted origin could connect through
a trusted reverse proxy, inherit proxy-injected identity, and obtain
operator.admin access via the sharedAuthOk / roleCanSkipDeviceIdentity
path without any origin restriction.

Remove the hasProxyHeaders exemption so origin validation runs for all
browser-originated connections regardless of how the request arrived.

Fixes GHSA-5wcw-8jjv-m286

(cherry picked from commit ebed3bb)

* refactor(security): reuse hook agent routing normalization

(cherry picked from commit eece586)

* Hardening: tighten preauth WebSocket handshake limits (openclaw#44089)

* Gateway: tighten preauth handshake limits

* Changelog: note WebSocket preauth hardening

* Gateway: count preauth frame bytes accurately

* Gateway: cap WebSocket payloads before auth

(cherry picked from commit eff0d5a)

* test: share gateway chat run helpers

(cherry picked from commit f8efa30)

* refactor: share shared auth scope assertion

(cherry picked from commit feba7ea)

* fix: adapt cherry-picks for fork TS strictness and naming

* fix: resolve remaining TS errors from cherry-picks

* fix: revert push test to fork version — no relay transport in fork

* fix: remove duplicate function declarations in cron test

* fix: remove TalkSpeak schema refs removed by upstream refactoring

* fix: remove remaining TalkSpeak refs after upstream schema refactoring

* fix: add missing clampProbeTimeoutMs and fix testCase ref in control-ui test

* fix: resolve final TS type errors in cherry-picked tests

* fix: use InstanceType for GatewayClient type refs in test

* fix: resolve CI lint and test failures (no-explicit-any, hook audit finding ID)

---------

Co-authored-by: Peter Steinberger <[email protected]>
Co-authored-by: Gustavo Madeira Santana <[email protected]>
Co-authored-by: Stephen Schoettler <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
Co-authored-by: Andrew Demczuk <[email protected]>
Co-authored-by: Robin Waslander <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
Co-authored-by: Luke <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
furaul pushed a commit to furaul/openclaw that referenced this pull request Mar 24, 2026
* test(gateway): stabilize suite session-store config

* test(gateway): preserve seeded config semantics

* test(gateway): update seeded session store overrides
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants