Allow same-origin microphone access for voice issue capture #933

Closed
opened 2026-08-16 03:19:38 +00:00 by timmy · 0 comments
Owner

Problem

Voice-to-draft capture is exposed in the dashboard, but every response currently sends Permissions-Policy: microphone=(). Supporting browsers therefore cannot use the microphone even after the operator explicitly taps Start. The start path also enters a misleading Listening state if SpeechRecognition.start() throws synchronously.

Vertical slice

Make the shipped voice issue capture usable without weakening unrelated browser permissions:

  • allow microphone requests only from the same-origin dashboard (microphone=(self)), while retaining camera and unrelated capability denial;
  • keep capture explicitly user-initiated;
  • handle synchronous recognition-start rejection truthfully, restoring the Start control and preserving typed/transcribed content;
  • retain keyboard fallback and private transcript recovery.

Acceptance tests

  1. Dashboard pages, static assets, health responses, and API errors all emit microphone=(self), camera=(), and the existing strict CSP/security headers.
  2. A successful explicit tap starts recognition and enters Listening state.
  3. If recognition startup throws, the UI does not remain Listening, Start is restored, Stop is hidden, and existing draft/transcript text is unchanged.
  4. Existing voice recovery/privacy tests and the full suite remain green.

Non-duplication evidence

Issues #929 and #931 implemented voice capture and private recovery but did not change the deny-all microphone policy or test synchronous start rejection. Historical issue #295 established the general browser boundary; it did not cover same-origin microphone access. No open issue or recent commit addresses this compatibility gap.

## Problem Voice-to-draft capture is exposed in the dashboard, but every response currently sends `Permissions-Policy: microphone=()`. Supporting browsers therefore cannot use the microphone even after the operator explicitly taps Start. The start path also enters a misleading Listening state if `SpeechRecognition.start()` throws synchronously. ## Vertical slice Make the shipped voice issue capture usable without weakening unrelated browser permissions: - allow microphone requests only from the same-origin dashboard (`microphone=(self)`), while retaining camera and unrelated capability denial; - keep capture explicitly user-initiated; - handle synchronous recognition-start rejection truthfully, restoring the Start control and preserving typed/transcribed content; - retain keyboard fallback and private transcript recovery. ## Acceptance tests 1. Dashboard pages, static assets, health responses, and API errors all emit `microphone=(self)`, `camera=()`, and the existing strict CSP/security headers. 2. A successful explicit tap starts recognition and enters Listening state. 3. If recognition startup throws, the UI does not remain Listening, Start is restored, Stop is hidden, and existing draft/transcript text is unchanged. 4. Existing voice recovery/privacy tests and the full suite remain green. ## Non-duplication evidence Issues #929 and #931 implemented voice capture and private recovery but did not change the deny-all microphone policy or test synchronous start rejection. Historical issue #295 established the general browser boundary; it did not cover same-origin microphone access. No open issue or recent commit addresses this compatibility gap.
timmy self-assigned this 2026-08-16 03:19:38 +00:00
timmy closed this issue 2026-08-16 03:28:44 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stackchain/stackchain-dashboard#933
No description provided.