405 Commits

Author SHA1 Message Date
Fred blum
9b1bde2561 fix(voice-call): close webhook in-flight limiter fail-open on empty remote address (#74453)
* 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>
2026-04-30 01:02:14 +00:00
Peter Steinberger
83267e99b0 chore: update dependencies 2026-04-29 22:42:45 +01:00
Vincent Koc
1b25dcf57a docs(types): mark legacy hook surfaces deprecated 2026-04-28 23:31:32 -07:00
Shakker
f1aaa2cd91 feat: declare startup plugin imports explicitly 2026-04-28 04:33:47 +01:00
Peter Steinberger
e1acb61317 refactor: expose SDK test helper subpaths 2026-04-28 03:28:17 +01:00
Peter Steinberger
90b6665ded refactor: move plugin api test helper to sdk 2026-04-28 00:24:54 +01:00
Peter Steinberger
e9b1fbb8c4 refactor: pin remaining extension api surfaces 2026-04-27 21:02:53 +01:00
Peter Steinberger
4336a7f3a9 refactor(plugin-sdk): narrow config runtime imports 2026-04-27 14:58:32 +01:00
Peter Steinberger
8e37ee4bf2 fix(voice-call): avoid blocking gateway startup 2026-04-27 13:40:30 +01:00
Peter Steinberger
0141471dd5 refactor: move shared helpers off reserved sdk seams 2026-04-27 13:07:54 +01:00
Peter Steinberger
7688b696de refactor: remove bundled plugin sdk self imports 2026-04-27 11:36:08 +01:00
VACInc
614a2846a2 fix: continue Google Live consult responses (#72189) (thanks @VACInc)
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
2026-04-27 10:52:00 +01:00
Josh Avant
db09f68ce5 Support SecretRef for voice-call credentials and bundled plugin SecretInputs (#72607)
* fix: support voice-call secretrefs

* test: classify plugin secretref targets

* docs: credit voice-call secretref change

* fix: keep plugin secret target discovery lightweight
2026-04-27 01:16:50 -05:00
Peter Steinberger
ecf71da888 fix(voice-call): avoid duplicate webhook logs 2026-04-26 12:05:34 +01:00
Peter Steinberger
9a529ca78b chore: update dependencies 2026-04-26 10:54:58 +01:00
Peter Steinberger
f1b1c3dc99 chore: update workspace dependencies 2026-04-25 22:48:44 +01:00
Peter Steinberger
b732f21a86 fix: clarify voice-call setup diagnostics 2026-04-25 20:24:36 +01:00
Peter Steinberger
7fcefd56b7 chore: bump version to 2026.4.25 2026-04-25 10:31:52 +01:00
Peter Steinberger
938b53698e test(voice-call): cover tunnel startup 2026-04-25 05:43:42 +01:00
Peter Steinberger
2b87d9f3ec fix(voice-call): reject local webhook fallback 2026-04-25 05:41:29 +01:00
Peter Steinberger
b8239be46b fix(voice-call): settle cleared tts queue 2026-04-25 05:38:36 +01:00
Peter Steinberger
05fbdd4b28 fix: handle missing tailscale binary 2026-04-25 04:28:32 +01:00
Peter Steinberger
455e84f776 fix(voice-call): start listening after telnyx greetings 2026-04-25 03:57:47 +01:00
Peter Steinberger
5381625f45 fix(voice-call): terminate expired restored calls 2026-04-25 03:55:01 +01:00
Peter Steinberger
250acdd2a2 test(voice-call): cover cloudflare twilio signatures 2026-04-25 03:52:31 +01:00
Peter Steinberger
a669ba7df1 fix(voice-call): reap stale pre-answer calls 2026-04-25 03:50:27 +01:00
Peter Steinberger
7dc005fab6 fix(voice-call): honor telephony tts timeout 2026-04-25 03:47:56 +01:00
Peter Steinberger
8f11e5ad18 fix(voice-call): scope sandbox session to agent 2026-04-25 03:43:01 +01:00
Peter Steinberger
c150110e02 test(voice-call): cover inbound transcript response handoff 2026-04-25 03:39:07 +01:00
Peter Steinberger
9a3dece879 fix(voice-call): allow dedicated response agent 2026-04-25 03:32:09 +01:00
Peter Steinberger
f7caf83da4 fix(voice-call): coalesce webhook server starts 2026-04-25 03:27:33 +01:00
Peter Steinberger
31d8fdb525 fix(voice-call): answer telnyx inbound calls 2026-04-25 03:23:45 +01:00
Peter Steinberger
a3862ffdf1 feat(voice-call): add setup smoke checks 2026-04-25 03:12:21 +01:00
Peter Steinberger
ba4cd90dbc fix(voice-call): share webhook runtime across contexts 2026-04-25 03:11:21 +01:00
Peter Steinberger
a5ab488691 fix(voice-call): pin response model sessions 2026-04-25 03:02:30 +01:00
Peter Steinberger
304126ad79 refactor(realtime-voice): centralize consult policy helpers 2026-04-24 23:45:49 +01:00
Peter Steinberger
e2f13959d4 feat(voice-call): share realtime agent consult tool
Centralize the shared realtime agent consult tool for browser Talk, Google Meet, and Voice Call.
2026-04-24 23:11:18 +01:00
Peter Steinberger
8a9d02dd82 fix(voice-call): keep outbound realtime streams attached (#71266)
Fixes outbound Twilio realtime conversations so the TwiML fetch returns the realtime <Connect><Stream> path for outbound directions and the answered-call path does not overwrite it with legacy <Say> TwiML.

Local proof:
- pnpm test extensions/voice-call/src/manager.notify.test.ts extensions/voice-call/src/webhook.test.ts
- pnpm check:changed
- pnpm check
- pnpm build
- local VoiceCallWebhookServer + CallManager smoke for Direction=outbound-api

Closes #68713.
2026-04-24 22:35:26 +01:00
Peter Steinberger
27c61ed0d4 chore(deps): update workspace dependencies 2026-04-24 16:55:08 +01:00
Peter Steinberger
b5e5f2cede feat(google): add realtime voice provider 2026-04-24 09:36:20 +01:00
Peter Steinberger
fa139b4fca fix(voice-call): handle Telnyx callback payloads 2026-04-24 07:25:44 +01:00
Peter Steinberger
b164bb3717 refactor: centralize realtime voice resolution 2026-04-24 01:50:43 +01:00
Peter Steinberger
57e139100b refactor: share realtime voice bridge sessions 2026-04-24 01:50:43 +01:00
Peter Steinberger
958afeb397 refactor: share provider selection runtime helper 2026-04-24 01:50:43 +01:00
Peter Steinberger
7c19c31144 feat: support DTMF for voice-call 2026-04-24 01:50:42 +01:00
Peter Steinberger
61c25704e6 fix: harden realtime voice setup (#70764) 2026-04-23 21:54:50 +01:00
Peter Steinberger
e88d8512a7 perf(discord): narrow monitor runtime imports 2026-04-23 08:21:01 +01:00
Peter Steinberger
e3caacd530 lint: enforce exhaustive switches 2026-04-23 06:02:12 +01:00
Peter Steinberger
4aa35d85fa test: clean up voice-call event timers 2026-04-23 06:02:12 +01:00
Peter Steinberger
0b0662b1c9 chore: apply extension lint cleanups 2026-04-23 05:30:49 +01:00