* fix(voice-call): close in-flight limiter fail-open on empty remote address
The webhook in-flight limiter (createWebhookInFlightLimiter in
src/plugin-sdk/webhook-request-guards.ts) returns true unconditionally
when tryAcquire is called with an empty key — that is its by-contract
fail-open path used to mean 'caller is opting out of the limiter'.
The voice-call webhook handler reached that path silently: it computed
'req.socket.remoteAddress ?? ""' and passed the empty string straight
into tryAcquire. Whenever req.socket.remoteAddress was absent (closed
socket, edge proxy quirk), the limiter became a no-op and the request
proceeded directly to readBody without any concurrency cap.
Fix: when remoteAddress is missing, log a warning and fall back to a
constant non-empty key ('__voice_call_no_remote__') so all such
requests share one in-flight bucket instead of bypassing the limiter
entirely. The bucket size stays maxInFlightPerKey (default 8), which
is the right defense-in-depth posture against slow-body attacks
arriving with stripped IP info.
Scoped to voice-call only. Other consumers of the SDK helper
(bluebubbles via openclaw/plugin-sdk/webhook-ingress) are not changed
to avoid drive-by edits to plugins this PR does not own. The shared
SDK contract (empty key = bypass) is left as-is and documented
implicitly by the fix's comment block.
The existing 8-concurrent test in webhook.test.ts continues to assert
the limiter engages on the happy path; no new test added since the
private handleRequest path is not unit-test exposed and the change is
two-line auditable from the diff alone.
* test(voice-call): cover missing webhook remote address limiter
* test: align changed package sdk routing
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Tighten Google Vertex ADC manifest evidence to canonical project env vars and canonical ADC fallback paths only.
Local proof:
- OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test src/agents/model-auth.profiles.test.ts src/plugins/manifest-registry.test.ts src/secrets/provider-env-vars.dynamic.test.ts
- pnpm exec oxfmt --check --threads=1 docs/plugins/manifest.md extensions/google/openclaw.plugin.json src/agents/model-auth-env.ts src/agents/model-auth.profiles.test.ts src/plugins/manifest.ts
- git diff --check origin/main...HEAD
CI note: checks-node-core-support-boundary was red on an unrelated tooling assertion in test/scripts/test-projects.test.ts for packages/sdk/src/index.test.ts routing; that file and scripts/test-projects.mjs are unchanged from origin/main.
* fix(pi-embedded): strip [tool calls omitted] from user-facing text
The internal replay placeholder '[tool calls omitted]' was leaking
into channel output (e.g. Telegram) after aborted tool calls.
Fix: strip the placeholder early in sanitizeUserFacingText so all
channels are protected by default. The replay transcript path in
turns.ts is unaffected — it uses the placeholder internally.
Fixes#74573.
Signed-off-by: Blasius Patrick <blasius.patrick@gmail.com>
* fix(pi-embedded): preserve whitespace when stripping placeholder
* test(pi-embedded): document replay placeholder sanitization
* fix(pi-embedded): strip consecutive replay placeholders
---------
Signed-off-by: Blasius Patrick <blasius.patrick@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>