Skip to content

consolidated: Phase 7 speech rollout gates and safe fallback #2665

Description

@superdav42

Supersedes #2649 — this issue is the consolidated spec.

What

Complete Phase 7, the rollout and availability layer around the merged managed-speech foundations. Add one shared, typed speech-availability decision for authenticated and public surfaces; gate managed speech by the local feature flag, connection, service entitlement/cohort/capability state, browser support, and the existing authoritative route checks. Keep typed chat available whenever speech is unavailable or fails.

Managed speech remains the primary path. Browser Web Speech is an explicitly labelled degraded-mode preference available only while managed speech is unavailable; no managed validation, entitlement, rate-limit, timeout, provider, or playback failure may automatically send content to browser/vendor speech. Public embed speech remains separately site-opt-in and must never default to browser-speech fallback.

Why

The authenticated foundation merged in #2650 at 78f2fdbe, and the anonymous static-embed foundation merged in #2660 at ee4fdc59; the managed service transport, billing/limits, and privacy-safe service telemetry are also merged. The remaining work is the shared rollout layer: safe availability decisions, service-authoritative entitlement metadata, content-free diagnostics, and a reversible user experience. It must preserve all existing authenticated capability, anonymous token/origin/rate/concurrency/budget/one-use-grant/CORS controls rather than creating replacement transports or public controllers.

Tier

Selected tier: tier:standard

Tier rationale: The architecture and files are decided, but this spans authenticated/public trust boundaries, privacy redaction, service-authoritative metadata, and client fallback recovery. Workers must apply the existing guards without weakening them.

How (Approach)

Progressive Context Plan

  • Read first: includes/Core/Features.php, includes/REST/SpeechController.php, includes/REST/PublicSpeechController.php, src/components/use-text-to-speech.js, and src/embed-widget/index.js — identify the existing capability, transport, fallback, and opt-in patterns.
  • Load only if: includes/Core/PublicChatSecurity.php and public methods in includes/REST/SessionController.php — when routing public availability/configuration, to preserve token, origin, rate, concurrency, budget, grant, and CORS checks.
  • Load only if: includes/Core/ProviderTraceLogger.php and includes/Core/SuperdavSiteConnectionService.php — when adding content-free trace projection and the allowlisted service metadata projection.
  • Stop when: the current public/authenticated response shapes, existing route guards, service metadata sanitizer, and the listed test patterns are clear.

Worker Quick-Start

  1. Do not recreate the managed speech transports from GH#2647: add managed two-way voice conversation #2650/GH#2648: add abuse-resistant public embed speech #2660 or add a public controller.
  2. Make SD_AI_AGENT_FEATURE_SPEECH the local rollback gate, but retain every pre-existing authentication, capability, origin, token, grant, rate, concurrency, and spend check as authoritative.
  3. Project only service-advertised speech entitlement/capability/cohort/usage fields. Do not infer currency, credits, or entitlement from local estimates.
  4. Before saving or returning diagnostics, reduce speech data to low-cardinality surface/backend/operation/outcome/reason buckets, numeric limit/usage buckets, and sanitized request IDs.

Files to Modify

  • EDIT: includes/Core/Features.php and tests/SdAiAgent/Core/FeaturesTest.php — add and cover Features::SPEECH, backed by SD_AI_AGENT_FEATURE_SPEECH, including enabled, disabled, and default behavior.
  • NEW: includes/Core/SpeechAvailability.php and NEW: tests/SdAiAgent/Core/SpeechAvailabilityTest.php — define the typed shared availability result and stable reason codes.
  • EDIT: includes/Core/SuperdavSiteConnectionService.php, includes/REST/SettingsController.php, and tests/SdAiAgent/REST/SettingsControllerTest.php — project an allowlisted backwards-compatible set of service-authoritative speech usage, entitlement, capability, and cohort metadata.
  • EDIT: includes/Core/ProviderTraceLogger.php and includes/REST/SpeechController.php — prevent speech transcripts, synthesis text, audio, filenames, raw locales, credentials, and raw upstream errors from reaching provider traces or diagnostics.
  • EDIT: includes/Core/PublicChatSecurity.php, includes/REST/PublicSpeechController.php, includes/REST/SessionController.php, tests/SdAiAgent/REST/SpeechControllerTest.php, tests/SdAiAgent/REST/PublicSpeechControllerTest.php, and tests/SdAiAgent/REST/PublicChatControllerTest.php — route safe public/authenticated availability through the shared decision without exposing account-only metadata or weakening anonymous safeguards.
  • EDIT: src/store/slices/uiSlice.js, src/components/use-speech-recognition.js, src/components/use-text-to-speech.js, and src/components/use-voice-conversation.js — consume shared availability and make browser speech an explicit degraded-mode preference only; failed managed speech returns to typed chat.
  • EDIT: src/embed-widget/index.js and src/embed-widget/__tests__/index.test.js — retain separately site-opt-in public speech with no browser-speech fallback and safe minimal public configuration.
  • EDIT: src/settings-page/superdav-account-manager.js and src/settings-page/usage-dashboard.js — expose service-advertised supported turn-based surfaces, languages/voices, remote-processing/retention disclosure, staged rollout, rollback categories, and safe fallback behavior without unverified production guarantees.
  • EDIT: tests/e2e/text-to-speech.spec.js, tests/e2e/floating-widget.spec.js, and tests/e2e/shared-conversations.spec.js — cover authenticated/public availability, typed-chat continuity, and no automatic browser fallback.
  • EDIT: README.md, CHANGELOG.md, docs/frontend-widget-capabilities.md, docs/embed-widget.md, and DESIGN.md — document supported surfaces, service-advertised capability limits, disclosure, staged rollout/rollback, and safe fallback.

Complete Write Surface

  • Callers/readers: authenticated capability/UI hooks (use-speech-recognition.js, use-text-to-speech.js, use-voice-conversation.js), settings UI, and public embed configuration/UI must consume the shared availability result appropriate to their trust boundary.
  • Writers/mutation paths: SpeechController.php, PublicSpeechController.php, SessionController.php, and PublicChatSecurity.php retain their existing authorization and abuse-control mutation paths; no new public route or grant/token format is permitted.
  • Existing verification/tests: the scoped PHP, JS, and Playwright speech/public-chat tests encode current transport and fallback behavior; add focused coverage only for the new availability/redaction/fallback contract.
  • Schemas/config: add only SD_AI_AGENT_FEATURE_SPEECH; public responses expose the minimum safe booleans, bounded limits, approved language/voice metadata, disclosure, and stable reason category required by the embed.
  • Generated/deployed mirrors: production bundles are produced by pnpm run build; do not hand-edit generated output.
  • Migrations/backfills: older service responses lacking speech fields remain valid; no migration or local entitlement/billing inference is allowed.
  • Cleanup/rollback paths: turning SD_AI_AGENT_FEATURE_SPEECH off immediately prevents new managed public/authenticated speech operations while typed chat remains available.

Implementation Steps

  1. Add the feature flag and typed SpeechAvailability result. Include stable reason categories for local feature disablement, connection, entitlement/cohort, service capability, browser capture/playback support, authenticated availability, public-site opt-in, and temporary rate/limit/provider failure.
  2. Integrate the decision into authenticated capabilities/UI and safe public configuration/UI. Existing authorization and abuse controls are mandatory and override availability presentation.
  3. Add the narrowly allowlisted service-metadata projection. Preserve older service responses; never derive currency, credits, or entitlement from token estimates.
  4. Add a content-free speech trace/diagnostic projection or explicit exclusion. Preserve the existing content-free sd_ai_agent_public_speech_metric hook.
  5. Replace automatic managed-failure browser synthesis with an explicit user choice visible only when managed speech is unavailable. Ensure every managed failure leaves typed chat usable.
  6. Update embed/settings/docs and the scoped test coverage. Inspect the exact PR-head diff before submission to prove speech text/audio cannot serialize into diagnostics or persisted client payloads.

Hazards and Compatibility

  • Concurrency/atomicity: preserve current route rate, concurrency, budget, and one-use-grant controls; availability must not bypass an authoritative route decision.
  • Migration/rollback: the feature constant is an immediate local rollback; old service responses without speech fields continue to work.
  • Mixed-version/backward compatibility: public callers receive only safe minimal metadata; authenticated account/cohort details never cross into anonymous responses.
  • Idempotency/retry: do not change token/grant semantics or transport retry behavior; temporary failures produce a stable reason and typed-chat recovery.
  • Partial failure/recovery: validation, entitlement, rate-limit, timeout, provider, and playback errors must not trigger browser speech automatically or make typed chat unavailable.

Verification Before Dispatch

pnpm run test:php -- --filter='FeaturesTest|SpeechAvailabilityTest|SpeechControllerTest|PublicSpeechControllerTest|PublicChatControllerTest|SettingsControllerTest|ProviderTrace'
pnpm run test:js
pnpm run test:e2e:playwright -- tests/e2e/text-to-speech.spec.js tests/e2e/floating-widget.spec.js tests/e2e/shared-conversations.spec.js
pnpm run verify
  • Surface mapping: PHP tests prove feature/availability/route/security/trace behavior; JS and E2E tests prove UI/embed fallback behavior; verify proves required lint, analysis, full PHPUnit, build, and bundle checks.
  • Runtime evidence: toggle SD_AI_AGENT_FEATURE_SPEECH off/on; exercise authenticated and public availability; prove typed chat remains usable; prove browser speech is not invoked after managed failure; run bounded Chromium coverage and one browser using a different supported MediaRecorder format.
  • Diff audit: inspect the exact PR-head diff for diagnostic, event-log, feedback/export, Redux-persistence, and browser-debug payloads that could serialize speech text or audio.

Files Scope

  • includes/Core/Features.php
  • tests/SdAiAgent/Core/FeaturesTest.php
  • includes/Core/SpeechAvailability.php
  • tests/SdAiAgent/Core/SpeechAvailabilityTest.php
  • includes/Core/SuperdavSiteConnectionService.php
  • includes/REST/SettingsController.php
  • tests/SdAiAgent/REST/SettingsControllerTest.php
  • includes/Core/ProviderTraceLogger.php
  • includes/REST/SpeechController.php
  • includes/Core/PublicChatSecurity.php
  • includes/REST/PublicSpeechController.php
  • includes/REST/SessionController.php
  • tests/SdAiAgent/REST/SpeechControllerTest.php
  • tests/SdAiAgent/REST/PublicSpeechControllerTest.php
  • tests/SdAiAgent/REST/PublicChatControllerTest.php
  • src/store/slices/uiSlice.js
  • src/components/use-speech-recognition.js
  • src/components/use-text-to-speech.js
  • src/components/use-voice-conversation.js
  • src/embed-widget/index.js
  • src/embed-widget/__tests__/index.test.js
  • src/settings-page/superdav-account-manager.js
  • src/settings-page/usage-dashboard.js
  • tests/e2e/text-to-speech.spec.js
  • tests/e2e/floating-widget.spec.js
  • tests/e2e/shared-conversations.spec.js
  • README.md
  • CHANGELOG.md
  • docs/frontend-widget-capabilities.md
  • docs/embed-widget.md
  • DESIGN.md

Acceptance Criteria

  • Features::SPEECH and the shared typed availability result gate managed speech with stable reason codes while preserving existing authoritative route checks.
  • Authenticated and public UI/configuration consume safe shared availability; anonymous callers never receive account-only entitlement/cohort data.
  • Service metadata projection is allowlisted and backward-compatible; it neither infers billing currency/credits nor locally invents entitlement.
  • Speech provider traces and client/server diagnostics cannot contain transcripts, synthesis text, audio, filenames, raw locales, credentials, or raw upstream errors; sd_ai_agent_public_speech_metric remains content-free.
  • Browser speech is an explicit degraded-mode choice only while managed speech is unavailable, never an automatic managed-failure fallback; typed chat works in every unavailable/failed state.
  • Public embed speech is separately site-opt-in, has no browser-speech fallback, and a feature/cohort/account rollback stops new speech operations without weakening PublicChatSecurity.
  • Settings and docs accurately describe only service-advertised languages/voices and supported turn-based surfaces, remote processing/retention disclosure, staged rollout/rollback, and safe fallback.
  • All listed focused tests, E2E coverage, and pnpm run verify pass; runtime checks cover feature-toggle, both trust boundaries, typed-chat continuity, no automatic browser fallback, and two supported recorder formats.

Context & Decisions

  • Original parent specification: Phase 7 adds a common rollout/availability layer around already merged authenticated and public speech foundations, not another transport.
  • Per @superdav42 (comment 1): the original clean-room brief was blocked because the public/authenticated contracts were not yet merged and their paths did not exist; do not invent those boundaries.
  • Per @superdav42 (comment 2): that dependency is now resolved: GH#2647: add managed two-way voice conversation #2650 and GH#2648: add abuse-resistant public embed speech #2660 are merged, the brief is re-grounded in the present architecture, and no worker claim, lease, blocked-by:* label, or dispatch hold remains.
  • Final approach: implement the scoped shared availability, metadata, privacy, UI, documentation, and verification work against the merged boundaries. Preserve all existing security/abuse controls, never auto-send content to browser speech, and keep typed chat usable.

Contributors

cc: @superdav42


aidevops.sh v3.32.306 plugin for OpenCode v1.18.28 with gpt-5.6-terra spent 2m and 68,809 tokens on this as a headless worker.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

consolidatedIssue superseded by a consolidated childorigin:workerAuto-created by pulse labelless backfill (t2112)priority:highHigh severity — significant quality issuesecuritySecurity-sensitive issue or changesolved:workerTask was solved by a headless workerstatus:doneTask is completetier:standardAuto-created by pulse labelless backfill (t2112)type:featureuiAuto-created from TODO.md tag

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions