The audit log
What HealthyRides records about access to PHI and ride actions, and how long it keeps the record.
What is recorded
The app writes an audit row for each kind of ride action its ride timeline shows: a booking, a bid, a provider pick, a crew punch and a notification sent (docs/decisions/0034-audit-rows-are-archived-daily-to-a-retention-locked-bucket.md).
Reads of PHI through the app, such as opening a patient record, write their own kind of row, phi_access, apart from changes, permission decisions and SMS consent events (platform/packages/database/src/schema/enums.ts; platform/packages/domain/src/patients/service.ts).
Each row names the organization, the person who acted and the role that let them, the action, and the record it touched (platform/packages/domain/src/audit/entities.ts). Its details are cleaned when written and hold ids rather than patient demographics (docs/decisions/0034-audit-rows-are-archived-daily-to-a-retention-locked-bucket.md).
Nobody can change it
The database refuses to update or delete an audit row: a trigger rejects both, for every caller (platform/apps/migrations/migrations/001_initial_schema.sql).
Erasing a patient's PHI on request leaves the audit log as it was written (docs/decisions/0034-audit-rows-are-archived-daily-to-a-retention-locked-bucket.md; docs/prd/healthyrides-mvp-prd.md).
How long it is kept
Once a day, every new audit row is copied to a storage bucket whose retention policy is locked for 2,555 days, about seven years, in production. Once locked, the policy cannot be shortened or removed by anyone, and an object in it cannot be deleted or overwritten before it is 2,555 days old (docs/decisions/0034-audit-rows-are-archived-daily-to-a-retention-locked-bucket.md; infrastructure/modules/audit-archive/main.tf).
The service that writes the archive may only add objects: it cannot read, list, delete or overwrite them (docs/decisions/0034-audit-rows-are-archived-daily-to-a-retention-locked-bucket.md).
A row reaches the archive up to a day and an hour after it is written. Until then it exists in the database and its backups (docs/decisions/0034-audit-rows-are-archived-daily-to-a-retention-locked-bucket.md).
Google Cloud's own audit logs, the record of calls made against the production project, go to a separate bucket locked for the same period (infrastructure/modules/audit-logging/main.tf; docs/decisions/0034-audit-rows-are-archived-daily-to-a-retention-locked-bucket.md).
Who can read it
A facility admin or a provider admin reads their own organization's audit log on the Admin screen (platform/packages/auth/src/roles.ts), filters it and exports it as a CSV file of the rows they filtered. The file carries the screen's columns, never a row's details, and each export writes its own audit row (docs/prd/healthyrides-mvp-prd.md).
A read of the audit log takes its scope from the reader's organization and offers no field that names another, so one organization cannot ask for another's rows (platform/packages/domain/src/audit/entities.ts).