Microphone Permission Management Feature
Version: 0.234.108
Implementation Date: January 2, 2026
Overview
The Microphone Permission Management feature provides users with granular control over how microphone permissions are handled for speech-to-text input. Users can choose between different permission request strategies and receive clear visual feedback about their microphone access state.
Features
1. User Preference Options
Users can select from three permission management strategies:
- Remember my choice - Permission choice is saved permanently and the system will not re-request
- Ask every browser session (Recommended) - Permission is requested once per browser session
- Ask every page load - Permission is requested each time a page loads
2. Visual State Indicators
The microphone icon in the chat interface displays different colors based on permission state:
- Green (
text-success) - Microphone access granted - Red (
text-danger) - Microphone access denied - Gray (
text-secondary) - Permission state not yet determined
3. Interactive Tooltips
Hovering over the microphone button shows contextual information:
- "Voice Input (Microphone access granted)" - When permission is granted
- "Microphone access denied - Click to manage permissions" - When permission is denied
- "Voice Input (Click to enable microphone)" - When permission not yet determined
4. Automatic Navigation
When the microphone icon is red (denied), clicking it automatically navigates to the profile page's microphone settings section (/profile#speech-settings) where users can:
- View their current permission status
- Change their permission preference
- See browser-level permission information
Implementation Details
Backend Changes
File: route_backend_users.py
Added two new allowed settings keys:
microphonePermissionPreference- Stores user's permission strategy choicemicrophonePermissionState- Stores the last known permission state
allowed_keys = {
# ... existing keys ...
'microphonePermissionPreference', 'microphonePermissionState',
# ... other keys ...
}
Frontend - Profile Page
File: templates/profile.html
Added new "Speech & Microphone Settings" section (visible only when enable_speech_to_text_input is enabled):
- Permission Status Badge - Shows current browser permission state
- Preference Radio Buttons - Three options for permission management
- Save Button - Persists user preferences to backend
- Info Alert - Provides context about permission management
JavaScript Functions:
saveMicrophoneSettings()- Saves user preference to backend via/api/user/settingsloadMicrophoneSettings()- Loads user preference from backend on page loadupdateMicrophoneStatusBadge(status)- Updates visual status badge
Frontend - Chat Interface
File: static/js/chat/chat-speech-input.js
New State Variables:
let microphonePermissionState = 'prompt'; // 'granted', 'denied', or 'prompt'
let userMicrophonePreference = 'ask-every-session'; // User's preference
let sessionPermissionRequested = false; // Session tracking
New Functions:
handleSpeechButtonClick()- Intercepts button clicks to check permissions firstloadMicrophonePreference()- Fetches user preference from/api/user/settingsshouldRequestPermission()- Determines if permission should be requested based on preferencecheckMicrophonePermissionState()- Attempts to access microphone to determine permission stateupdateMicrophoneIconState(state)- Updates icon color and tooltip based on permission statesavePermissionState(state)- Persists permission state when "remember" is selected
Permission Request Logic:
Remember:
- Requests permission once
- Saves state permanently
- Never requests again unless permission state changes
Ask every session:
- Requests permission once per browser session
- Uses
sessionPermissionRequestedflag to track - Resets when browser is closed/reopened
Ask every page load:
- Requests permission each time a page loads
- Provides maximum privacy but may be intrusive
User Workflow
Normal Usage (Permission Granted)
- User navigates to chat page
- System loads user's permission preference
- If preference requires it, system checks permission state
- Icon appears green
- User clicks microphone → Recording starts immediately
First-Time Usage
- User clicks microphone icon (gray)
- Browser prompts for microphone permission
- User grants permission
- Icon turns green
- Preference is saved based on user's settings
- Recording begins
Denied Permission Workflow
- User denies microphone permission
- Icon turns red
- User clicks red microphone icon
- User is redirected to
/profile#speech-settings - User can:
- See their permission preference
- Change their preference
- Understand they need to change browser-level permissions
Changing Preferences
- User navigates to Profile page
- Scrolls to "Speech & Microphone Settings" section
- Sees current permission status badge
- Selects desired permission preference
- Clicks "Save Microphone Settings"
- Settings are persisted to backend
- New preference takes effect on next page load or button click
Technical Architecture
Data Flow
User Action → Frontend JavaScript → Backend API → Cosmos DB
↓
Icon State Update
↓
Tooltip Update
Storage
Location: Cosmos DB users-<environment> container
Document Structure:
{
"id": "user-id",
"settings": {
"microphonePermissionPreference": "ask-every-session",
"microphonePermissionState": "granted",
...other settings...
}
}
Browser Compatibility
The feature uses try/catch for permission detection, making it compatible with:
- Chrome/Edge (full support)
- Firefox (full support)
- Safari/iOS (graceful degradation - relies on getUserMedia try/catch)
Configuration
The feature is automatically enabled when:
app_settings.enable_speech_to_text_input = True
No additional configuration is required.
Testing
Test File: functional_tests/test_microphone_permission_management.py
Tests validate:
- Backend accepts microphone permission settings keys
- Profile.html contains all required UI elements and functions
- chat-speech-input.js contains permission management code
- Version was updated correctly
Run Test:
python functional_tests/test_microphone_permission_management.py
Security Considerations
- Browser-level permissions are always respected
- No permissions can be granted programmatically
- User must explicitly grant via browser prompt
- Settings are stored per-user and isolated
- No cross-user permission state leakage
Accessibility
- Tooltips provide screen reader context
- Color states supplemented with icon changes
- Clear button labels and help text
- Keyboard navigation supported
Future Enhancements
Potential future improvements:
- Add Permissions API support for browsers that support it (for more accurate state detection)
- Add permission reset button on profile page
- Show permission request history/log
- Add analytics for permission grant/deny rates
- Localization support for all text content
Related Files
route_backend_users.py- Backend API endpointtemplates/profile.html- Settings UIstatic/js/chat/chat-speech-input.js- Permission management logicstatic/js/chat/chat-user-settings.js- Settings persistence helperfunctional_tests/test_microphone_permission_management.py- Automated tests
Version History
- 0.234.108 - Initial implementation (January 2, 2026)
- User preference selection
- Visual state indicators
- Automatic navigation on denied permissions
- Persistent storage in user settings