Commit graph

579 commits

Author SHA1 Message Date
Sabiha Khan
7cc0467cfb
chore(main): release dograh 1.37.0 (#452) 2026-06-19 17:20:44 +05:30
yogi6969
ae2023e315
fix(ui): proxy WebSocket signaling upgrade so local web calls work (#425) (#454)
* fix(ui): proxy WebSocket signaling upgrade so local web calls work (#425)

1.34.0 replaced the next.config `/api/* -> BACKEND_URL` rewrite with the
Route Handler `api/v1/[...path]/route.ts`. Route Handlers proxy HTTP fine
(so `/api/v1/*` still 200s) but cannot upgrade WebSocket connections. The
removed *rewrite* used to carry the upgrade, so without it the signaling
socket (`/api/v1/ws/signaling/...`) has no proxy path and every local web
call dies before WebRTC negotiation — the symptom reported in #425. nginx
would proxy the upgrade but only runs in the `remote` compose profile, so
local OSS deployments have nothing to carry it.

Re-add a `beforeFiles` rewrite scoped to `/api/v1/ws/:path*` so the upgrade
is proxied to the backend *before* the `[...path]` Route Handler can swallow
it. HTTP `/api/v1/*` is untouched and still flows through the Route Handler
(auth/cookie handling intact).

Verified on a 1.34.0-derived source build: signaling WS now reports
`[accepted]` / `connection open` server-side and `WebSocket connected` +
`ICE connection state: connected` client-side; WebRTC negotiates end-to-end.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ui): use direct localhost WebSocket signaling

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-19 17:20:07 +05:30
nuthalapativarun
7d053320df
fix: disable duplicate trigger nodes in workflow builder (#402)
* fix: disable duplicate trigger nodes in workflow builder

AddNodePanel: disable trigger buttons and show tooltip when a trigger
already exists on the canvas, using bySpecName to identify trigger-
category specs from the live node list.
useWorkflowState: preflight in saveWorkflow rejects saves with multiple
trigger nodes via a sonner toast before the network request is made.
text_chat_session_service: include the original exception message in
TextChatSessionExecutionError so the HTTP 500 detail surfaces the root
cause without DB inspection.

Closes #378

* style: format test_text_chat_session_service.py with ruff

* chore: retrigger CI checks

* fix(workflow): enforce node instance constraints

---------

Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-19 15:59:30 +05:30
Faisal Ansari
7c31dd3eec
fix(devcontainer): expose UI/API ports for host access (#405)
* added 3000 & 8000 in docker compose for devcontainer

* fix(devcontainer): bind app ports to localhost

---------

Co-authored-by: faisal <faisal@afreespace.com>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-19 14:26:07 +05:30
Mubashir R
6e194f4b59
fix(qa): tolerate non-dict JSON from QA LLM instead of crashing (#408)
* fix(qa): tolerate non-dict JSON from QA LLM instead of crashing

parse_llm_json is explicitly designed to return a list when the model emits a
top-level JSON array (it has a dedicated test for that). The QA analyzers then
call parsed.get("tags", ...) directly on the result. When parsed is a list,
that raises AttributeError, which is NOT caught by the surrounding
except (json.JSONDecodeError, ValueError) — so a single stray array response
from the QA model crashed the entire QA analysis run instead of degrading to
empty results.

The live variable-extraction path already guards this exact case with an
isinstance(..., dict) check; mirror it in both QA analysis call sites
(_run_qa_analysis per-node and _run_whole_call_qa_analysis fallback) so a
non-dict parse result coerces to {} and the run produces empty defaults.

Adds a regression test that drives the whole-call analyzer with an array
response and asserts empty results rather than a crash.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(qa): log non-object QA JSON responses

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-19 14:10:53 +05:30
Mubashir R
ed06de73a3
fix(workflow): detect duplicate trigger paths when first node has no id (#409)
validate_trigger_paths used seen_paths.get(trigger_path) and treated a None
result as "path not seen yet". But None is also what node.get("id") returns
for a node without an id, so when the first trigger node sharing a path had no
id, it was stored as None and every later node with the same path was silently
accepted as unique — duplicate trigger paths slipped through validation.

Use a membership test (trigger_path not in seen_paths) so "first occurrence"
and "node_id happens to be None" are no longer conflated. Behavior is
unchanged for nodes that have ids.

Adds a regression test that fails before and passes after.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 13:53:34 +05:30
Manasseh
fc37d5058f
feat: add Inworld TTS provider support (#420)
* Add Inworld TTS provider integration

* chore: move from HTTP Service to Websocket Service

---------

Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-19 13:23:27 +05:30
Abhishek Kumar
00a0de8a62 chore: update SDKs 2026-06-18 19:08:58 +05:30
Sabiha Khan
d77312095b
chore(main): release dograh 1.36.0 (#437) 2026-06-18 18:57:21 +05:30
Abhishek Kumar
5dfd261930 fix: signature mismatch for telephony 2026-06-18 18:56:58 +05:30
Abhishek Kumar
d60065bf0a fix: fix auth provider caching 2026-06-18 17:34:48 +05:30
Abhishek Kumar
2939726b2c Merge branch 'main' of https://github.com/dograh-hq/dograh 2026-06-18 17:18:59 +05:30
nuthalapativarun
2a92406f02
feat(examples): add multi-node Workflow SDK example in Python and TypeScript (#440)
* feat(examples): add multi-node Workflow SDK example in Python and TypeScript

Closes #369

* docs: preserve workflow name in SDK build examples

---------

Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-18 15:13:10 +05:30
Abhishek Kumar
867856d108 chore: make default worker count as 2 2026-06-18 14:48:23 +05:30
Harshita Jain
bec8a23dfb
fix: sync Smallest AI voice dropdown with selected model (#451)
Add model_options to SmallestAITTSConfiguration's voice field so the UI
renders the correct voice list per model — 15 standard voices for
lightning_v3.1 and 6 premium voices (meher, rhea, aviraj, cressida,
willow, maverick) for lightning_v3.1_pro. All 21 voice IDs verified
against the Smallest AI API. The frontend's existing model_options
machinery already handles dropdown filtering and auto-reset on model
change, so no UI changes are needed.
2026-06-18 14:36:08 +05:30
nuthalapativarun
e7b67e0efb
feat(examples): add load-and-edit workflow SDK example in Python and TypeScript (#441)
Closes #370
2026-06-18 14:30:04 +05:30
Abhishek Kumar
f586aebe5b feat: enable stack auth config from backend 2026-06-18 14:17:28 +05:30
nuthalapativarun
788ff94cec
fix: add language field to CartesiaTTSConfiguration and pass to Cartesia TTS service (#442)
* fix: add language field to CartesiaTTSConfiguration and pass to TTS service

Closes #432

* chore: regenerate OpenAPI spec to fix drift-check

The openapi.json snapshot had drifted from the FastAPI app definition
because main gained new organization endpoints (billing, credits,
context) after this branch was created. Regenerate it with
'python -m scripts.dump_docs_openapi' to bring it back in sync.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: clarify Cartesia language schema

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-18 13:23:27 +05:30
NEGM
abfd5e4cdd
feat: allow self-hosters to enable Stack Auth via Dockerfile build args (v33.0) (#445)
* allow self-hosters to enable Stack Auth via Dockerfile build args

* fix: drop unrelated whitespace churn from ui/Dockerfile

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: NEGM <abdelrhmannegm@Abdelrhmans-MacBook-Air.local>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:17:33 +05:30
Aymenbenpakiss
37c4bda0c7
fix(ui): release microphone stream on call teardown so a second test call works (#446)
* fix(ui): release microphone stream on call teardown

The browser "Call Voice Agent" test call worked only once per page load.
A second attempt failed (mic stuck / "Could not acquire media") until the
user reloaded the page or cleared site data and re-granted mic permission.

Root cause: the MediaStream from getUserMedia() was added to the peer
connection but never retained or explicitly stopped on teardown. On hangup
only sender.track.stop() (via pc.getSenders()) ran; browsers can keep the
microphone device held through the original MediaStream reference, so the
next getUserMedia() is blocked.

Fix: keep the stream in localStreamRef and stop all of its tracks in
cleanupConnection() (the shared teardown path) and in the unmount cleanup,
so the device is fully released between calls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ui): harden microphone release in webrtc hook and embed widget

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: AYMENPAKISS2 <tech.nomatrade@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-18 12:47:14 +05:30
Sabiha Khan
951e73a645
feat: add custom sarvam tts voice (#449)
* feat: add custom sarvam tts voice

* chore: refactor registry and add deepgram multi

---------

Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-18 12:33:21 +05:30
Abhishek Kumar
344c8220de chore: bump pipecat submodule to 1.4.0 2026-06-18 12:17:36 +05:30
Abhishek Kumar
7efc19c812 fix: merge initial context during update workflow run 2026-06-18 09:25:02 +05:30
Abhishek
d2cda85b78
fix: validate workflow status filter to prevent 500 on invalid enum value (#450)
* Validate workflow status filter to prevent 500 on invalid enum value

The /workflow/fetch and /workflow/summary endpoints accepted a free-form
status query param and passed it straight into a query that casts to the
workflow_status PG enum (active/archived). Any other value — e.g. an
external caller passing 'published' (a workflow_definitions version state,
not a workflow status) — failed deep in Postgres as
InvalidTextRepresentationError, surfacing as an unhandled HTTP 500.

Add _validate_status_filter() to reject values outside WorkflowStatus with
a clean 422 before any DB query, for both the single and comma-separated
paths. Add route tests covering invalid, valid-single, comma-separated, and
mixed valid/invalid cases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: add tests

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 08:39:59 +05:30
Abhishek Kumar
9a1b980f91 Merge branch 'main' of https://github.com/dograh-hq/dograh 2026-06-17 19:53:31 +05:30
Abhishek
00b35d6963
feat: UI refresh and user onboarding (#430)
* docs: design spec for lead-gen surfaces (Credits & Billing, Hire-an-Expert, Top-up, Enterprise)

Add brainstorming spec for: sidebar OBSERVE→MANAGE rename + Credits & Billing
link + Hire-an-Expert footer button; new /billing page with extracted Dograh
Model Credits card + CTAs; Top-up / Hire-an-Expert / Enterprise intake modals
with inline math captcha; and a workflow-builder Hire-an-Expert nudge. Frontend
only; submissions fire PostHog events via a submitLead() seam for a future
MongoDB endpoint. Also gitignore .superpowers/ brainstorm mockups.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: implementation plan for user-onboarding lead-gen surfaces

14 bite-sized tasks: PostHog events, shared helpers (field options,
work-email blocklist, submitLead seam, math captcha), three intake modals
(enterprise/hire/top-up), LeadFormsProvider context, AppLayout mount, sidebar
MANAGE rename + Credits & Billing link + footer Hire button, extracted
DograhCreditsCard, /billing page, credits removal from Agent Runs, builder
nudge, and a full verification/dogfood pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): register PostHog events for lead-gen surfaces

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): shared field options, work-email validation, and submit seam

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): inline math captcha field

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): enterprise intake modal

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): hire-an-expert modal with enterprise link

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): top-up modal with >20k volume-pricing gate

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): shared lead-forms context provider

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): mount LeadFormsProvider in app layout

Wrap the sidebar branch of AppLayout with LeadFormsProvider so the shared
lead modals are available to the sidebar, billing card, and builder nudge.
Includes eslint import-order auto-fixes in TopUpModal and LeadFormsContext.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): rename OBSERVE to MANAGE, add Credits & Billing link and Hire-an-Expert footer button

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): extract DograhCreditsCard with top-up + hire CTAs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): add Credits & Billing page

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(lead-gen): move Dograh Model Credits card out of Agent Runs to /billing

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(lead-gen): delayed Hire-an-Expert nudge on the workflow builder

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(ui): add lint:lead-flow guard script

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(ui): restructure lead forms, self-serve Buy Credits, dialog blur

Revised lead-capture surfaces and credits bar:

- Dialog overlay gains backdrop blur (bg-black/60 backdrop-blur-sm).
- Shared primitives: LeadModalShell (icon/eyebrow header, scrollable body,
  sticky footer, trust-line slot), PhoneField (react-international-phone,
  dark, E.164 out), FormTrustLine ("Average response: under 10 minutes...").
- HireExpertModal: Name, Company, Job title, agent goal, Phone (required),
  monthly volume. EnterpriseModal: + work email (required logged-out),
  conditional deployment (yes/no/maybe, source-gated), agent goal.
  OnboardingModal: drop useCase. Phone mandatory except onboarding.
- Volume buckets match the backend qualifier (0-5k/5k-100k/100k+/not-sure).
- Delete TopUpModal; DograhCreditsCard now self-serve Buy Credits (amount
  chips $5/$10/$25/$50/$100 + custom min $5 → startTopUp seam) + Hire an
  Expert + dashed custom-pricing link opening Enterprise (billing_custom_pricing).
- PostHog events: drop topup_*, add buy_credits_clicked,
  buy_credits_amount_selected, custom_pricing_clicked. LeadFormsContext
  drops topup; LeadKind/LeadSource updated.
- Introduce a single --cta warm accent token (CTAs + focus rings only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(ui): split-screen auth + enterprise CTA + dark theme default

- AuthShell: dark two-column auth layout (brand/value panel with CSS-only
  waveform motif + proof points + Bland-style enterprise CTA block on the
  left, zinc-900 form card on the right; single-column on mobile).
- AuthEnterpriseCTA: "Talk to our team" → dograh.com/contact?intent=enterprise.
- stack-theme: dark StackTheme token overrides synced to globals.css.
- page.tsx: wrap StackHandler (non-fullPage) in AuthShell + StackTheme;
  local-auth fallback preserved inside the shell. BackButton slimmed for the card.
- Dark locked as default: <html className="dark">, next-themes ThemeProvider
  (defaultTheme="dark", enableSystem=false); inline no-FOUC script defaults dark.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ui rezig, onboarding, billing, hire us & on prem cues

* ui changes

* chore: update comment

* chore: untrack docs/superpowers and gitignore it

* feat: refactor user configuration table

* feat(ui): 'check your email' confirmation on lead forms

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* added email and country in form submissions

* chore: update leads api

* fix: wrap dograh model config in card

---------

Co-authored-by: Pritesh <pritesh@dograh.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 19:49:33 +05:30
Abhishek Kumar
072d20ce9c chore: upgrade posthog versions 2026-06-17 19:05:26 +05:30
Sabiha Khan
a2d9ed24ed
fix: add pace option in sarvam tts config (#447)
* fix: add pace option in sarvam tts config

* fix: generate client
2026-06-17 14:45:09 +05:30
Harshita Jain
e79cb42f31
feat: add Smallest AI TTS and STT provider integration (#444)
* feat: add Smallest AI TTS and STT provider integration

Integrates Smallest AI's Waves (TTS) and Pulse (STT) APIs as selectable
providers in the Dograh platform. Dograh's pipecat fork already contains
the pipecat-level service implementations; this wires them into the API
configuration registry and service factory.

- Added `SMALLEST = "smallest"` to `ServiceProviders` enum
- Registered `SmallestAITTSConfiguration` (lightning-v3.1/v2, voices,
  language, speed) and `SmallestAISTTConfiguration` (pulse model, 30+
  languages) Pydantic config classes with the TTS/STT registries
- Added factory branches in `create_tts_service` and `create_stt_service`
  routing to `SmallestTTSService` and `SmallestSTTService` from pipecat

* fix: update Smallest AI models to v4 naming convention

- TTS: rename lightning-v3.1 → lightning_v3.1, add lightning_v3.1_pro, drop deprecated lightning-v2
- STT: keep pulse only (pulse-pro is not a streaming model)

* fix: change default TTS voice from emily to sophia for lightning_v3.1

emily is not a verified lightning_v3.1 voice; sophia is the pipecat
SmallestTTSService default and confirmed to work with the standard pool.

* fix: replace 9 invalid lightning_v3.1 voice IDs with verified ones

jasmine, james, michael, aria, lara, asel, sarah, rishi, deepika do not
exist in the lightning_v3.1 voice catalog. Replaced with avery, liam,
lucas, olivia, freya, devansh, maya, dhruv, maithili — all verified
against the API.

* fix: smallest ai config validation and tts model compatibility

* chore: ruff fix

* chore: updated smallest ai schema in openapi.json

---------

Co-authored-by: Sabiha Khan <sabihak89@gmail.com>
Co-authored-by: Sabiha Khan <87858386+chewwbaka@users.noreply.github.com>
2026-06-17 12:55:53 +05:30
Abhishek Kumar
a849c9b244 chore: add dograh plugin in documentations 2026-06-16 19:17:09 +05:30
Abhishek Kumar
3d1886c450 feat: persist split user and bot audio 2026-06-16 15:19:49 +05:30
Abhishek Kumar
dd3f2e7323 feat: add huggingface inferece provider endpoint 2026-06-15 22:56:01 +05:30
Sabiha Khan
ef266daa6e
chore(main): release dograh 1.35.0 (#417) 2026-06-12 22:07:31 +05:30
Abhishek Kumar
281656b960 feat: centralise workflow run authorization 2026-06-12 18:16:30 +05:30
Abhishek Kumar
5bf7518829 fix: close MCP sessions in text chat runner 2026-06-12 14:56:38 +05:30
Abhishek
1f1149f4d5
feat: billing and credit management v2 (#429)
* feat: use mps generated correlation ID

* chore: update pipecat submodule

* feat: add credit purchase URL

* feat: carve out billing page and show credit ledger

* feat: deprecate dograh based quota tracking

* fix: remove cost calculation from dograh codebase

* fix: create mps account on migrate to v2

* chore: update pipecat
2026-06-12 14:55:30 +05:30
Abhishek
97d7103480
feat: add a start docker script (#426)
Adds a start docker script so that we have required values like OSS_JWT_SECRET at runtime
2026-06-11 11:51:30 +05:30
Mubashir R
a81cccc68b
fix(telephony): handle Cloudonix CDR webhooks missing session/disposition (#407)
* fix(telephony): handle Cloudonix CDR payloads missing session/disposition

The /cloudonix/cdr webhook is a public, unauthenticated endpoint that parses
arbitrary external JSON. It dereferenced cdr_data.get("session").get("token")
unconditionally, so a partial or malformed CDR payload that omits "session"
(or sends "session": null) raised AttributeError -> HTTP 500. The existing
"Missing call_id field" guard right below it was unreachable because the crash
happened first.

StatusCallbackRequest.from_cloudonix_cdr had the same fragility plus a second
one: data.get("disposition", "") returns None when the key is present-but-null,
and None.upper() then crashed.

Navigate both fields defensively so missing/null values fall through to the
intended graceful error path instead of crashing. Adds regression tests
covering missing session, null session, null disposition, and the well-formed
mapping path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: harden cloudonix cdr session validation

* chore: renamed test path

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Sabiha Khan <sabihak89@gmail.com>
2026-06-10 17:49:36 +05:30
Manasseh
e79c3e26f0
feat: add Cartesia Sonic 3.5 TTS model (#423) 2026-06-10 15:18:13 +05:30
Abhishek Kumar
91ac460799 chore: finish renaming UserConfiguration 2026-06-09 16:30:03 +05:30
Abhishek
cdbd06c8d9
feat: add config v2 to simplify billing (#428)
* feat: add model config v2

* chore: centralize user org selection

* chore: move preferences to platform settings

* fix: decouple org preference and ai model preferences
2026-06-09 16:10:26 +05:30
Abhishek Kumar
49e68b49d5 fix: harden the postgres default password 2026-06-05 14:30:02 +05:30
Abhishek Kumar
418592178c chore: update docs for pre-call data fetch 2026-06-05 14:16:56 +05:30
Abhishek Kumar
79ff04d8a9 fix: harden vobiz signature verification
Fixes #327
2026-06-05 12:14:37 +05:30
Sabiha Khan
2326a2f65a
chore(main): release dograh 1.34.0 (#389) 2026-06-03 21:41:13 +05:30
nuthalapativarun
dace4a7efc
fix: add CORS preflight handler and ACAO header for embed config endpoint (#403)
* fix: add CORS preflight handler and ACAO header for embed config endpoint

The GET /public/embed/config/{token} endpoint is fetched by external
websites (third-party embed sites). The global CORSMiddleware only covers
first-party origins, so external origins received no Access-Control-Allow-
Origin header, causing browser preflight failures.

Add an OPTIONS /config/{token} handler that validates the origin against the
token's allowed_domains list and returns the appropriate CORS headers.
Also inject Access-Control-Allow-Origin into the GET response via FastAPI's
response parameter so the actual request succeeds cross-origin.

Closes #383

* fix: complete public embed CORS handling

---------

Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-03 21:27:44 +05:30
Abhishek
cdb27c1d4f
fix: use runtime BACKEND_URL for proxying (#411)
* fix: use runtime BACKEND_URL for proxying

Fixes #400

* chore: run formatter
2026-06-03 18:47:04 +05:30
developer603
acc2ef9e96
fix: make email lookup case-insensitive in get_user_by_email (#397)
* fix: make email lookup case-insensitive in get_user_by_email

Email addresses are case-insensitive in practice, but get_user_by_email
compared with an exact `UserModel.email == email` predicate. A user who
signed up as "User@example.com" could not be found when logging in as
"user@example.com" (and vice-versa), so the same person could fail to log
in — or be treated as a brand-new account — depending only on how their
client capitalized the address.

Compare on `func.lower(UserModel.email) == func.lower(email)` so lookups
are robust to capitalization. Minimal and backwards-compatible: it works
with existing mixed-case rows immediately, with no migration required.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: enforce case-insensitive user emails

---------

Co-authored-by: developer603 <vrramsolutions@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-06-02 13:43:20 +05:30
Abhishek Kumar
8b9059fbe2 chore: format release please changelogs 2026-06-02 13:42:55 +05:30
shiminshen
51ab9303ec
fix(webrtc): enforce embed allowed-domain policy on public signaling websocket (#388)
The public WebRTC signaling WebSocket (`/public/signaling/{session_token}`)
validated only the session token and its expiry, not the embed token's
allowed-domain policy that the HTTP embed endpoints already enforce. A leaked
or replayed session token could therefore attach to the signaling path from
an arbitrary origin.

Validate the request origin against `embed_token.allowed_domains` (reusing the
existing `validate_origin` helper) before the signaling handoff, rejecting
disallowed origins with a 1008 close — mirroring the HTTP embed endpoints.

Closes #330

Co-authored-by: shiminshen <16914659+shiminshen@users.noreply.github.com>
2026-06-02 13:10:30 +05:30