Export
- Both stores already held the audio (server /audio-backups/:id/audio and
the local IndexedDB record) but nothing exposed it, so a recording could
not be taken out of the app. Each backup row now has a download, naming
the file by its timestamp and using the extension actually recorded
(webm, or m4a on iOS). A local record is only handed over to the account
that owns it.
Robustness
- MediaRecorder had no onerror and nothing watched the audio track, so a
recorder that failed, or a microphone claimed by another app, unplugged,
or revoked, left the tab saying "recording" while capturing nothing.
Both are now reported once, with the chunks captured so far kept, so
stopping still returns the audio up to the failure.
Deliberately not added: a wake lock. Stopping when the screen sleeps or the
session ends is the intended behaviour — recording is meant to be
deliberate, and nothing is left behind.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
- Add Cloudflare Turnstile to login, register, and password reset forms
- Switch AI provider to LiteLLM, transcription to OpenAI Whisper
- Change domain to scribe.pedshub.com
- Fix PPTX export: add tables, bold/italic, numbered lists, code blocks, blockquotes
- Fix announcement banner close button (CSP was blocking inline onclick)
- Fix auth middleware: empty Bearer token now falls through to cookie auth
- Fix audio backups: only save on transcription failure, stop auto-deleting on success
- Soften AI correction injection to prevent model hallucination from correction history
- Fix LiteLLM TTS model name handling (no incorrect openai/ prefix)
- Expand AI instructions textarea in Learning Hub CMS
- Update README for v6 with all features and providers
- Add comprehensive docs/: architecture, API reference, database schema,
authentication, AI providers, speech, learning hub, configuration, deployment
Audio Backups:
- New audio_backups table in PostgreSQL (bytea, gzip compressed)
- POST /api/audio-backups — upload with gzip compression (level 6)
- GET /api/audio-backups — list user's backups
- GET /api/audio-backups/:id/audio — download decompressed audio
- DELETE /api/audio-backups/:id — delete backup
- Auto-cleanup every hour (24h expiry)
- Frontend saves to server first, falls back to IndexedDB
- Settings shows source badge (server/local) per backup
AI Corrections:
- Corrections list is now expandable — click to view original vs corrected
- Shows red "Original" and green "Corrected to" sections
- Click arrow to expand/collapse each correction
- Date shown on each correction