Skip to content

Report Server Migration (Canonical reports Path)

Goal

Migrate report storage to canonical path:

  • users/{uid}/reports/{sid} with pure payload:
  • schema
  • report
  • execution

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_projection Cloud Function (Gen1) from cloud_functions/report_projection.
  • [ ] Release finlab client version with canonical upload:
  • Report.upload() writes to users/{uid}/reports/{sid} when using id_token.
  • api_token keeps legacy write_database fallback.
  • [ ] 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

  1. Enumerate users and legacy strategies.
  2. For each {uid, sid}:
  3. if canonical exists: skip.
  4. else rebuild canonical payload from legacy (payload_v1 if present, otherwise map report + execution / position2).
  5. Write canonical doc.
  6. Trigger automatically refreshes legacy projection.

Rollout Order

  1. Deploy trigger.
  2. Deploy client with canonical write/read.
  3. Run backfill.
  4. Observe metrics and logs for at least one release cycle.
  5. Disable legacy write endpoint.

Risk Notes

  • Legacy projection derives some fields from report.metrics; values may differ slightly from historical write_database formatting.
  • Use canonical doc as single source of truth; do not write directly to legacy paths in new clients.