One file per feature, in the v2 shape that worked: goal, context, design, implementation, acceptance criteria, tests, risks, out of scope -- written before implementing so the risks are on paper rather than walked into. Three carry more weight than their size suggests. V3-01 ships the port's first real migration, and since the destructive fallback is gone, getting addColumn and a v1-database test right matters more than the feature. V3-08 forces a routing-engine decision with ongoing cost, so it sits behind a RoutingService interface mirroring what LocationSource did for GPS. V3-13 is not code at all -- it answers the three questions open since v2, and V3-15 may close unbuilt as a result, which is a legitimate outcome. Several tickets record constraints that are easy to lose: no activity picker in front of Start, because the founding premise is press-and-go with gloves; the Route-to-Trip foreign key must not cascade, or deleting an old plan deletes the ride; V3-14 will deliberately break the parity harness by adding GPX <type>, and that expectation should be updated rather than the check dropped; and V3-16 must not regress the explicit text colours that exist because of the black-on-black bug. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
53 lines
2.0 KiB
Markdown
53 lines
2.0 KiB
Markdown
# V3-12 — Crash reporting
|
|
|
|
**Phase** Quality · **Depends on** nothing · **Size** S · **Status** Not started
|
|
|
|
## Goal
|
|
Know when the app dies mid-ride.
|
|
|
|
## Context
|
|
There is none. A recorder that crashes during a ride currently leaves no trace beyond
|
|
logcat, which nobody reads — and the failure mode that matters most (recording stopping
|
|
silently) is exactly the one the user cannot report usefully.
|
|
|
|
Becomes important the moment anyone who is not Dylan uses it.
|
|
|
|
## Design
|
|
Sentry or Firebase Crashlytics. **Sentry is the better fit**: it is not tied to Google
|
|
services, works identically on both platforms, and its free tier is ample here.
|
|
|
|
**A crash reporter in a location app is a privacy surface.** Configure it deliberately:
|
|
|
|
- No location data in breadcrumbs or context, ever
|
|
- No device id, no ride contents
|
|
- Explicit opt-out in settings, and disclosed in the privacy policy
|
|
- Debug builds report nowhere
|
|
|
|
Beyond crashes, one custom event is worth having: **recording ended unexpectedly** — the
|
|
engine stopping without a user stop. That is the failure the app exists to avoid.
|
|
|
|
## Implementation
|
|
1. Add `sentry_flutter`, initialised in `main()` behind a config flag
|
|
2. Scrub: no coordinates, no ids, no trip contents in any payload
|
|
3. Breadcrumbs for lifecycle transitions only
|
|
4. A custom event when a recording ends without a user action
|
|
5. Settings toggle, defaulting **off** until a privacy policy exists
|
|
|
|
## Acceptance criteria
|
|
- [ ] A forced crash appears in Sentry from a release build
|
|
- [ ] No coordinate ever appears in a payload — inspect a real one
|
|
- [ ] The toggle genuinely disables reporting
|
|
- [ ] Debug builds send nothing
|
|
|
|
## Tests
|
|
- The scrubber strips coordinates from a representative payload
|
|
- Reporting disabled means the client is never initialised
|
|
- Manual: force a crash in a release build and check it lands
|
|
|
|
## Risks
|
|
Leaking location through breadcrumbs or a stack frame's captured state. Inspect a real
|
|
payload rather than assuming the scrubber works.
|
|
|
|
## Out of scope
|
|
Analytics or usage tracking. Different purpose, different consent.
|