uttrflow / uttrflow/uttrflow-swift

Recordings are deleted after a day only while the main window is open, so the "kept for a day only" promise lapses for menu-bar-only use

Open
#650 0 comments 0 reactions 0 assignees View on GitHub
area:dictation bug P0 security
Dominant language
Swift
Stars
4
Forks
17
Avg merge
3h 32m
Merged PRs (30d)
277

Description

## What happens

Settings and onboarding promise: "Audio is deleted the moment it becomes text, and kept on this Mac for a day only if it couldn’t be, so you can retry" (`Sources/UttrflowUX/SettingsPresenter.swift:579-581`). `Docs/recordings.md:41` and `:67` say the same.

The 24-hour limit is enforced in only one place, `RecordingStore.waiting(now:)` (`Sources/UttrflowAudio/RecordingStore.swift:88-113`). That method discards files older than `retention` while it lists them (`:104-106`). Its only caller is `refreshMainWindow()` (`Sources/Uttrflow/AppDelegate.swift:1372`), which begins with `guard mainWindow != nil else { return }` (`:1361`). Nothing prunes at launch, on a timer, or after a dictation.

Transcript retention works the same way: expired records are dropped only when the history is read or appended to (`Sources/UttrflowHistory/DictationHistoryStore.swift:38-42`, `:56-62`). Someone who sets a short retention and then stops dictating keeps the old transcripts on disk indefinitely. (#613 covers retention measured against a wrong clock, which is a separate problem.)

## Why it matters

Uttrflow is a menu-bar app. Many people dictate for weeks without opening the main window, and a failed dictation's WAV (their voice, up to the recording cap) then stays on disk for as long as that lasts. That contradicts a promise written on the screen. The same applies to transcripts under the retention setting.

## How to reproduce

1. Close the main window. Make a dictation fail after recording so the audio is kept.
2. Set the file's creation date back two days (`SetFile -d` or `touch -t`), relaunch, and use only the menu bar and shortcut.
3. `ls ~/Library/Application\ Support/Uttrflow/recordings/`: the file is still there. Opening the main window deletes it.

## Acceptance criteria

- Recordings past retention are removed at launch and periodically, or after each dictation, whether or not a window exists. The same goes for transcripts past the retention setting.
- The sweep does not add a steady timer that breaks the energy budget (`Docs/performance.md`). Launch plus "after each dictation" is enough.
- An app-target or `Tests/UttrflowAudioTests` test shows that an old recording is removed without `waiting(now:)` being called from a window.

Contributor guide

Open the contributing guide

Research direction

Start with Sources/UttrflowAudio/RecordingStore.swift, Sources/UttrflowHistory/DictationHistoryStore.swift, and the launch and dictation paths in Sources/Uttrflow/AppDelegate.swift; trace where waiting(now:) and transcript cleanup are currently triggered. Run the existing Tests/UttrflowAudioTests or app-target tests, then verify that old recordings and transcripts are removed without opening the main window and without a steady timer.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.