In-ride audio recording — design note and deliberate deferral
Status: not implemented. This document explains why, and what implementing it properly requires, so that the next person to pick it up starts from a decision rather than from a blank file.
Decided: 2026-08-12, during the safety centre build.
The decision
Consent-based in-ride audio recording appears on every 2026 ride-hailing safety feature list, and Uber has shipped it in a number of markets. It was in scope for this pass. It is not in this pass, and no stub, disabled toggle, or "coming soon" affordance was left behind — a safety feature that looks present and is not is worse than one that is visibly absent, because a rider who believes they are being recorded may behave as though they have protection they do not have.
Three things drove the call.
1. It cannot be built correctly from the rider app alone
Recording audio inside a vehicle records two people. In two-party-consent jurisdictions — which include a large share of the markets in the preset pack — a recording made without the driver's knowledge is not merely inadmissible, it is unlawful, and the operator (not the rider) carries that liability. Making it lawful means the driver must be told, per ride, that recording is active, and in strict jurisdictions must be able to decline.
That is a driver-app feature. The driver app was out of scope for this work and being actively modified by another workstream at the time. Building the rider half now would produce exactly the dangerous artefact described above: a rider recording, a driver with no indication it is happening, and an operator exposed in every two-party market they sell into. There is no version of "just the rider side" that is safe to ship.
2. The store-policy surface is larger than the feature
Both stores treat audio as a sensitive data class with declaration duties that attach to the binary, not to whether the feature is switched on:
- Google Play Data safety must declare audio collection, purpose, sharing, retention and deletion — and the declaration must match observed runtime behaviour. A microphone permission present in a build that most installs never use is still a declaration obligation, and a mismatch is a rejection or a removal.
- Apple requires a purpose string for
NSMicrophoneUsageDescriptionand a matching privacy-nutrition-label entry; background audio capture additionally needs a justified background mode, which review scrutinises.
This platform ships as a source zip that buyers rebuild and submit under their own developer accounts. So the cost is not paid once by us — it is paid by every buyer, in every submission, including the ones who never enable the feature. Shipping the permission by default would tax all of them for a feature few would turn on.
3. Retention is a duty, not a setting
An encrypted upload is the easy half. The hard half is that the recording must
be deleted — reliably, on a schedule, including when the operator's storage
driver is S3 and the delete fails, including for rides that were disputed and
whose retention was legitimately extended, and including when the retention
window itself is market-configurable (India's MoRTH data-residency rules already
sit in MarketConfig.dataResidency and would govern this too). A retention
policy that is not enforced by a job with its own tests is a liability
masquerading as a feature: the operator has told regulators the data is deleted
after N days, and it is not.
None of this is unbuildable. It is simply a piece of work of comparable size to the entire rest of this safety pass, and doing it half-way is the one option that is worse than not doing it.
What a correct implementation requires
Recorded here so the estimate is not re-derived from scratch.
Backend
ride_recordingstable —rideId,riderId,driverId,storageKey,sizeBytes,durationSeconds,encryptionKeyId,consentRiderAt,consentDriverAt,retainUntil,deletedAt,deletionAttempts.retainUntilis written at upload time from market config, never computed at read time — the deletion job must not depend on config that may have changed.- Per-ride consent records for BOTH parties, captured before the first byte is recorded, stored with the timestamp and the app version that asked. In one-party-consent markets the driver's record is an acknowledgement rather than a veto; in two-party markets it is a precondition and a refusal disables recording for that ride.
- Encryption at rest with a key the app never holds. The existing storage
driver (
backend/src/storage/) handles placement; envelope encryption viacrypto/secret.service.tshandles the content. The upload endpoint must accept a stream and never buffer a whole recording in memory. - A retention cron in the safety module, alongside the check-in sweeper,
deleting anything past
retainUntil, retrying failures with backoff, and raising an ops incident when a recording cannot be deleted after N attempts — silent deletion failure is the specific way this becomes a legal problem. - A dedicated RBAC permission (
recording.access), separate fromincident.manage, so that the ability to work the safety queue is not automatically the ability to listen to riders' conversations. Playback issues a short-lived signed URL; the URL is never stored. - An audit row on every access, written by the existing
@Auditedinterceptor with the recording id as the resource — who listened, to which ride, when. This is the control that makes the feature defensible; without it, "only support can access recordings" is an assertion nobody can check.
Rider app
- Per-ride opt-in (not an account-level default), an unmistakable persistent in-app indicator while recording is active, and a one-tap stop. Recording must end automatically when the ride reaches a terminal state — a recorder still running after drop-off is a bug that records someone's front door.
Driver app (out of scope for this pass; blocking)
- A per-ride notification that recording is active, and in two-party markets a decline control, with the decision propagated back before recording starts.
Market configuration
MarketConfig.safety.recording:{ enabled, consentModel: 'one_party' | 'two_party', retentionDays, maxDurationMinutes }.enableddefaults to false everywhere.consentModelis a legal fact about the jurisdiction, not a preference, and should be seeded per country the way emergency numbers now are.
Operator documentation
- A page in the buyer-facing docs covering: which jurisdictions require two-party consent, what must go in their privacy policy, what to declare in Play Data safety and Apple's privacy labels, how to answer a data-subject access request for a recording, and the fact that enabling this feature makes them a controller of biometric-adjacent data in several markets.
What was shipped instead
The safety centre delivered in this pass covers the same threat model by other means, and every part of it is auditable without recording anyone:
- Trusted contacts + live trip link on SOS — the people who would act get told, with a link that shows the moving car and nothing identifying.
- Auto-share — the same link at the start of every ride, per contact, by standing request.
- Ride check-in — the platform notices a trip running far over, or a car that has stopped, asks the rider, and escalates their silence to a human.
- Market emergency numbers — the right number for the right service in all 37 markets, correctable by the operator without an app release.
Recording would add evidence after the fact. The above is aimed at intervention during it, which is the more valuable half — and, unlike recording, it carries no obligation the buyer has to discharge in every store submission for the rest of the product's life.