github murtaza-nasir/speakr v0.10.0-alpha

latest release: v0.10.1-alpha
4 hours ago

Release Notes - v0.10.0-alpha

This release fixes two reported issues (#332, #333), eliminates duplicate recordings from a double-clicked upload button, stops failed file uploads from being copied into the Downloads folder, and substantially hardens incognito mode's zero-retention guarantees. The minor version bump reflects one intentional API behavior change: unauthenticated API requests now return a JSON 401 instead of a redirect to the login page.

API Behavior Change

  • Unauthenticated API requests return 401 with a JSON body (#333). Previously, a request with a missing, invalid, expired, or revoked API token received Flask-Login's default 302 redirect to /login. Most HTTP clients follow redirects, so integrations saw a 200 HTML login page and concluded the call succeeded; in the worst case an upload with a bad token was reported as successful while the recording never existed. Requests to /api/ paths, and any request presenting an API token on any path, now receive 401 {"error": ...} with a WWW-Authenticate: Bearer header. Browser page loads keep the login redirect. This matches what the API documentation always stated.

Bug Fixes

  • The 200 MB size warning no longer fires in server-streaming mode (#332). With ENABLE_SERVER_RECORDING_CHUNKS=true, chunks flush to the server as they are produced and no size limit exists, but the 80% warning toast and the "approaching limit" banner still appeared. Both now appear only on the legacy in-memory path, where the 200 MB cap genuinely protects browser RAM. In their place, recordings in either mode get a warning toast at 80% of RECORDING_MAX_HOURS so a long session announces the hard stop instead of cutting off by surprise. The gate keys off whether the streaming session actually opened, so a failed session open that falls back to in-memory recording still shows the RAM warning.

  • Double-clicking Upload can no longer create duplicate recordings. Finalizing an in-app recording first drains the remaining chunk backlog, which can take several seconds with no visible feedback; users double-clicked, and every extra click minted another recording racing over the same session, with all but one orphaned in "Processing" forever. The upload button now disables immediately with a spinner, duplicate clicks are ignored client-side, and the finalize endpoint is idempotent server-side: the session is claimed atomically and replayed finalize calls return the same recording.

  • Failed file uploads are no longer duplicated into Downloads. The failed-upload safety net (IndexedDB persistence plus a browser-download fallback) exists to protect in-app recordings, whose only copy lives in browser memory. It also fired for drag-and-drop and file-picker uploads, so a large file rejected by a reverse proxy was pointlessly copied into the Downloads folder. Recovery now applies only to in-app recordings; failed file uploads simply remain in the queue as failed, since the original still exists on disk. Additionally, when an in-app recording exhausts its automatic retries, the audio is handed back as a download instead of sitting invisibly in browser storage forever.

Incognito Mode Hardening

  • Incognito recordings never touch server storage while recording. With server-side chunk streaming enabled, in-app recordings made in incognito mode also streamed their chunks to the server. Incognito recordings now stay entirely in the browser until the explicit process-without-saving upload; the in-browser 200 MB cap applies to them. Switching a normally-streamed recording to incognito in the review pane deletes its server-side chunks before processing, and resuming a streamed session clears the incognito toggle, since that audio already reached the server.
  • No user filenames in incognito logs. Incognito temp files are named by extension only and every log line sees an anonymized name; filenames can themselves be sensitive.
  • PRESERVE_TEMP_AUDIO no longer retains incognito audio. The debugging flag's untracked audio copy is skipped for incognito processing.
  • Crash recovery preserves incognito. A recording interrupted mid-incognito is now offered back in incognito mode instead of silently becoming a normal, permanently stored recording.

Maintenance

  • The recording-session cleanup sweep now also removes orphaned session directories that have no matching database row.

Compatibility

This release is backwards compatible with the v0.9.x line and involves no database migrations. Integrations that depended on the previous 302 redirect for unauthenticated API calls (none should, but note it) must handle the documented 401 instead.

Don't miss a new speakr release

NewReleases is sending notifications on new releases.