docs: record what still needs a device check and a decision after the fix pass

The audit gains a "Fix pass, 2026-09-24" section after the summary. It
says how the pass was done and tested, and lists what the fix agents
could not settle from the code alone:
- the device and server checks that matter before a release
- the product calls, starting with the release signing key and secrets
  that have to exist before the next version bump
- the follow-ups the agents left, one line each
This commit is contained in:
Linus Rath
2026-09-24 21:02:08 +02:00
parent 06ce86e31a
commit d4ac1e1df4
+108
View File
@@ -89,6 +89,114 @@ Effort: S (hours), M (a day or two), L (a week or more).
Everything else below is narrower (file trees past 500 nodes; tasks, which are off by default),
suspected, or cosmetic.
## Fix pass, 2026-09-24
One orchestrating session and one fix agent per area, each in its own git worktree; their
commits were cherry-picked onto `main` (`ee04e95..main`, about 160 commits). `npx tsc --noEmit`
and `npx vitest run` passed after every merge (1,886 tests at `b7a5953`). Nothing has run on a
device yet: a ticked box means the fix landed with unit tests, not that it was checked on the
emulator, and the startup numbers in PF2 come from `npx expo export`, not from device timings. A
device build and smoke test are in progress.
Result: of the 93 bug, UI, performance and webmail-gap items, 80 are ticked, 7 are fixed in part
and 6 are open (B2, U8, PF9, the viewer's undo-send bar, Tabler icons, the password hand-off).
13 of the 14 stale parity entries are resolved; `dateLocale` is still missing.
### Check on a device or server
- **Android intents (B9–B11):** the Kotlin was reviewed but never compiled. Check `SEND` with a
`content://` image, `SENDTO mailto:` with extras on a cold and a warm start, and
`VIEW mailto:alice+news@partner.example`.
- **First build:** `063432b` adds `babel.config.js` and `metro.config.js`, so start Metro once with
`npx expo start --clear`. The AsyncStorage limit from `24849ba` only applies after a native
rebuild.
- **Timings:** record PF1, PF2, PF3, U1 and U2 again with `screenrecord`; none were re-measured.
- **Push:** the `forbidden` fallback with a mailbox shared by ACL (`d8046a8`), revoke detection
(`a3d3af7`), a group-mailbox notification tap (`8618abf`), and that a replacement subscription
fits under `maxPushSubscriptions`, since the old one is kept until the new one is verified.
- **Echo skip (`018accd`):** it assumes `Mailbox.totalEmails` matches the `Email/query` total on
Stalwart; confirm on the wire.
- **Scheduled send on Stalwart:** the 7-day hold clamp (`4e7ae2f`), the create-then-cancel
reschedule (`7e598c5`) and scheduled mail held in shared accounts (`72f48db`).
- **Server-side recurrence (`8454889`, `f397ee3`, `96c5a3f`):** needs Stalwart 0.16.20 or later;
check the synthetic-id probe, a single-occurrence edit and an RSVP to one occurrence.
- **Calendar time zone (`a8e6f6e`, `8af163a`):** open and save an event and a task with the
calendar zone set away from the device zone.
- **Sieve round trip:** save filters on the phone while the auto-reply is on; it should stay on,
and the webmail should read the script back unchanged (`d53bfec`, `3f88868`, `6c31c8d`).
- **Sign-in:** add a second OAuth account (`ab84578`), and restore a session behind a redirecting
proxy (`859770b`).
- **Composer WebView:** the editor CSP (`235f4ea`) and the 400 ms change throttle (`fc00781`).
- **iOS:** the app-icon badge (`25c0883`) and the in-app PDF preview (`409cdb1`).
- **Translations (`67935d2`):** 26 languages written without a native speaker; wording with no
precedent in the webmail catalog needs a review.
### Decisions for the maintainer
- **Release signing, before the next version bump:** create the release key, the rotation lineage
(`apksigner rotate`) and the five repository secrets (`docs/android-release.md`). The release
workflow now fails without them, and a local release build needs
`-PallowDebugSignedRelease=true`. `versionCode` is derived from `VERSION` (0.1.62 → 10062).
- **Trusted-sender sync:** the webmail turns "Sync trusted senders to address book" on at login;
the app now leaves it off until the user turns it on (`d89e331`). Follow the webmail, or keep
it opt-in?
- **Sender favicons:** still on by default, and the phone fetches them from icons.duckduckgo.com
itself, having no proxy like the webmail's `/api/favicon`. Default off, a proxy, or keep?
- **Design language:** "Flat fields" and the Tabler icons are not ported (open question below).
- **Short messages:** the quick reply now sits at the bottom of the page so it never jumps
(`54b169c`), which leaves empty space under a short message.
- **Android app badge:** the icon badge is iOS-only (`25c0883`). On Android, expo-notifications
clears a badge with `cancelAll()`, which would also dismiss mail notifications and reminders,
and launchers already badge from the notifications on display.
- **Password hand-off:** taking the password out of the `bulwarkmobile://…#password=` fragment
needs a one-time code exchange on the webmail (`/api/auth/mobile/handoff` plus a redeem call,
PKCE-style).
- **Composer font size:** the webmail's font-size picker was left out; it needs a
selection-rewriting command in the editor page that can only be tested on a device.
- The other open questions at the end (tasks default, office documents, barcode scanner, package
name, settings sync, feature requests) are unchanged.
### Follow-ups worth doing
- Offline cache: a cached message over about 2 MB can't be read back on Android; keep bodies in
files.
- Offline cache: eviction only counts the active account.
- Session restore: a store that hydrates after the 5 s timeout merges over the restored state.
- Calendar subscriptions and search history don't use `createPersistStorage` yet.
- Bodies cached truncated before `4767805` are never fetched again.
- Push: `expires` is patched on every launch, because Stalwart's 7-day cap equals the refresh
threshold; check revoke detection and expiry for users who open the app less than weekly.
- Push: the onboarding prompt comes back after push was turned off.
- Webmail: `lib/web-push.ts` has the same shared-account `emailPush` bug as B18.
- Mail list: the swipe drag still runs on the JS thread (needs gesture-handler or reanimated).
- Unified Inbox: the inline `renderItem` pattern `ebd8dac` removed from the folder list, no
attachment chips, and `patchRows` duplicates the keyword-patch helper.
- Mail: the webmail's opt-in "All unread" and "All starred" views are missing.
- Composer: the undo-send bar only exists on the list screen, so a quick reply can't be undone.
- Composer: drafts can't be saved offline (B16 now says so instead of dropping the text).
- Composer: `findReceivingIdentity` scans identities in list order; no "remove text colour".
- Startup: the date-fns main barrel still adds about 300 modules; the 4.3 MB of catalogs stay in
the bundle, only no longer evaluated at startup.
- Startup: screens other than the mail list take their top inset from the native `SafeAreaView`
and jump; the window colour follows the system theme, not the app's.
- Intents: a `mailto:` without a recipient opens nothing; Bcc can't be passed through
`bulwarkmobile://compose`.
- Files: no refresh after a partly failed delete; the webmail's share-rights conversion for
Stalwart before 0.16.6 (`c3225b3f`) is not ported.
- File preview: no PDF renderer on Android, no audio, video, HTML or Markdown preview, and text
is read as UTF-8 only.
- Filters: calendar and contacts settings aren't scoped when managing a shared account; no UI for
the forward limit (`maxNumberRedirects`) or the auto-reply length warning (webmail
`f3aec163`); `fileinto` lingers in `require`.
- Settings search: sidebar apps aren't indexed, and theme names aren't translated.
- i18n pass 2: hard-coded English is left in the viewer, calendar, email store, drawer, Unified
Inbox and `App.tsx`; then top up the translations (`node scripts/rn-missing-translations.mjs`).
- Release workflow: the `workflow_dispatch` hint "leave empty to skip upload" doesn't match what
the workflow does (older than this pass).
- Upstream: GitHub `main` has `c2584c2` and `5b8c435` (PR #53, links in event descriptions),
which local `main` lacks.
- `src/lib/mdn.ts`: the top comment still names `sendMdn`.
## Bugs
### Crashes