Report Server Migration (Canonical reports Path)
Goal
Migrate report storage to canonical path:
users/{uid}/reports/{sid}with pure payload:schemareportexecution
Keep old readers working by projecting canonical docs into legacy paths using a Cloud Function trigger.
Scope
- Client write path: direct Firestore REST write to canonical
reports. - Client read path: canonical first, then legacy fallback.
- Server projection:
onWrite(users/{uid}/reports/{sid}) -> legacy documents.
Canonical Schema
{
"schema": "report.payload.v1",
"sid": "my_strategy",
"name": "my_strategy",
"report": { "...report.v1..." },
"execution": { "...report.execution.v1..." },
"updated_at": "2026-03-05T00:00:00Z"
}
Migration TODO
- [ ] Deploy
report_projectionCloud Function (Gen1) fromcloud_functions/report_projection. - [ ] Release finlab client version with canonical upload:
Report.upload()writes tousers/{uid}/reports/{sid}when usingid_token.api_tokenkeeps legacywrite_databasefallback.- [ ] Release canonical-first cloud read:
CloudReport.from_cloud()tries canonical doc first.- fallback to
auth_get_strategy. - [ ] Backfill old strategies into canonical path:
- Source:
users/{uid}/strategies/{sid}+positions/position. - Target:
users/{uid}/reports/{sid}. - [ ] Validate legacy projection parity on sampled users:
- summary fields
- strategy doc
- positions doc
- [ ] Monitor Cloud Function errors/latency and Firestore write cost.
- [ ] Announce legacy endpoint deprecation window.
- [ ] Remove legacy endpoint write path after migration window.
Backfill Strategy
- Enumerate users and legacy strategies.
- For each
{uid, sid}: - if canonical exists: skip.
- else rebuild canonical payload from legacy (
payload_v1if present, otherwise mapreport+execution/position2). - Write canonical doc.
- Trigger automatically refreshes legacy projection.
Rollout Order
- Deploy trigger.
- Deploy client with canonical write/read.
- Run backfill.
- Observe metrics and logs for at least one release cycle.
- Disable legacy write endpoint.
Risk Notes
- Legacy projection derives some fields from
report.metrics; values may differ slightly from historicalwrite_databaseformatting. - Use canonical doc as single source of truth; do not write directly to legacy paths in new clients.