uttrflow / uttrflow/uttrflow-swift
AI suggestions saves one-time codes, card security codes and PINs typed into web forms, because only fields named "password", "passwd" or "passcode" count as secure
- Dominant language
- Swift
- Stars
- 4
- Forks
- 17
- Avg merge
- 3h 32m
- Merged PRs (30d)
- 277
Description
## What happens
When the master switch is on, capture runs in every application except the four editors that ship off and any the user has switched off (`Sources/UttrflowPredict/SuggestionPreferences.swift:22-27`, `:125-130`). Consent for an app is recorded as allowed automatically on first use (`Sources/Uttrflow/Suggestion/SuggestionCoordinator.swift:616`).
The app uses `.whereReturnSends` (`SuggestionCoordinator.swift:119`). Outside terminals and chat apps, that policy counts a field as finished when focus leaves it, the app is deactivated, or the line goes idle, not only on Return (`Sources/UttrflowPredictCapture/CommitPolicy.swift:24-33`; reasons at `CommitDetector.swift:29-37`). A finished value of 2 or more characters is written as plain text to `predict.v1.sqlite`. It is skipped only in these cases (`Sources/UttrflowPredictCapture/CaptureGate.swift:33-42`):
- the field is secure;
- the value matches the clipboard's secret shapes (`SecretShapes`);
- the value is a destructive command.
A field counts as secure only if one of these holds (`Sources/UttrflowPredict/SecureField.swift:11-26`):
- it publishes `AXSecureTextField`;
- its identifier, placeholder or description contains `password`, `passwd` or `passcode`;
- its value reads back as mask characters only.
A browser field for a one-time code, a card security code, a PIN, an account or card number without separators, a date of birth or a security answer usually meets none of these. Nothing in the app excludes password managers or banking apps by default either. #544 covers the separate problem that an app cannot be switched off before something has been learned there.
## Why it matters
Codes and PINs are among the most sensitive things typed, and a web form is where most of them are typed. Once stored, they sit in an unencrypted file and can be offered back as a suggestion in the same field. The person never pressed anything that looked like "save".
## Decision needed
1. Which field signals mark a field "never learn". Candidates include web `autocomplete` hints exposed through Accessibility (`one-time-code`, `cc-csc`, `cc-number`, `current-password`, `new-password`), `inputmode=numeric` with a short max length, and names or placeholders such as `otp`, `code`, `pin`, `cvv`, `cvc`, `security`, `ssn`.
2. Whether to refuse to learn short all-digit values anywhere outside terminals.
3. Whether to ship a default "never learn" list of app categories (password managers, banking), switched off like the four editors.
## Acceptance criteria
- The decision is written down in `Docs/predict.md` under what is never learned.
- `SecureField` or `CaptureGate` implements it, with table-driven tests in `Tests/UttrflowPredictTests` / `Tests/UttrflowPredictCaptureTests` covering each field shape above.
- The Settings copy for AI suggestions says what is never learned.
Contributor guide
Research direction
Start with Sources/UttrflowPredict/SecureField.swift, Sources/UttrflowPredictCapture/CaptureGate.swift, and the related commit-policy files to trace how fields are classified and saved. Read Docs/predict.md and the Settings implementation, then inspect the test targets under Tests/UttrflowPredictTests and Tests/UttrflowPredictCaptureTests. Done means the decision is documented, the protection is implemented, table-driven tests cover the listed field shapes, and the AI suggestions Settings copy explains what is never learned.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- desktop, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100