Skip to content

Report Web Adaptation Plan (backtestWebsite + new_website)

Goal

Deploy new FinLab package (canonical payload) without breaking website rendering, while allowing phased migration away from legacy strategies docs.

Canonical source of truth:

  • users/{uid}/reports/{sid}

Legacy projection (kept during migration):

  • users/{uid}/strategies/{sid}
  • users/{uid}/strategies/{sid}/positions/position
  • users/{uid}/strategies/{sid}/articles/article (unchanged)

Current Status

  • FinLab client already writes canonical payload (report + execution) to reports/{sid} when using Firebase id_token.
  • Cloud Function projection (report_projection) can project canonical doc into legacy strategy/position documents.
  • Both frontend projects are still legacy-path readers.

Compatibility Contract During Deployment

For zero-break rollout, keep this invariant:

  1. New FinLab client writes canonical doc only.
  2. Trigger projects canonical -> legacy docs.
  3. Frontends continue reading legacy docs unchanged.

This lets us deploy package and server first, then frontend migration independently.

Impacted Frontend Touchpoints

backtestWebsite

Main legacy readers/writers:

  • store/strategy.js
  • realtime read: /users/{uid}/strategies/{sid}
  • components/PositionPanel.vue
  • reads /users/{uid}/strategies/{sid}/positions/{position_id}
  • expects legacy position map schema
  • components/PositionPanelFinlab.vue
  • reads legacy position doc (position2)
  • plugins/strategy.js
  • copy/delete strategy docs under legacy path

new_website

Main legacy readers/writers:

  • src/lib/stores/strategy.js
  • realtime read: strategy root + /positions/position + article
  • src/lib/components/strategy/viewer.svelte
  • expects data.reportPosition?.position2
  • src/lib/components/chatpage/strategy.svelte
  • expects data.reportPosition?.position2
  • src/lib/components/chatpage/panes/StrategyPane.svelte
  • direct live() path to legacy strategy + position + article
  • src/lib/js/strategyDatabase.ts
  • CRUD under legacy strategy/codes/position docs
  • src/routes/embed/+page.svelte
  • direct reads of legacy strategy/position/article docs

Phase Plan

Phase 1 (Now): Deploy Safe Compatibility

  • Deploy report_projection function first.
  • Keep both websites reading legacy docs only.
  • Validate parity on sampled {uid, sid}:
  • strategy.stats, strategy.returns, position.position2 presence
  • visibility flags (public_performance, public_code, public_position)

Exit criteria:

  • Canonical write success rate high.
  • Projection error rate low.
  • Frontends render unchanged for migrated strategies.

Phase 2: Add Frontend Dual-Read (No UI Change)

Implement adapter layer that normalizes canonical payload to existing UI contract.

Read order:

  1. Legacy docs (fast path, current behavior).
  2. If missing, fallback to canonical users/{uid}/reports/{sid}.
  3. Normalize canonical payload to old fields consumed by UI:
  4. strategy equivalent (returns, benchmark, stats, etc.)
  5. reportPosition.position2 equivalent from execution

Why:

  • Makes frontend resilient if projection is delayed or temporarily unhealthy.
  • Allows canary users on canonical-only docs.

Phase 3: Canonical-First Frontend

  • Flip read order to canonical-first, legacy fallback.
  • Keep adapter output stable so components do not change.
  • Optionally remove direct dependency on position2 in new components and use execution directly.

Phase 4: Legacy Cleanup

  • Remove legacy write paths from frontend tools.
  • Stop updating legacy paths except for read-only compatibility window.
  • Decommission projection after all consumers are canonical.

Create one shared adapter module per project:

  • input:
  • canonical doc (report, execution)
  • or legacy docs
  • output:
  • stable “view model” currently used by components

Do not spread path branching (strategies vs reports) across many components.

Validation Checklist (Per Deployment)

  • Upload strategy via new FinLab package and confirm:
  • canonical doc exists at users/{uid}/reports/{sid}
  • projected legacy docs exist and update within expected latency
  • Open strategy page in both sites:
  • performance chart renders
  • position table renders
  • permission-gated view behaves unchanged
  • Test edge cases:
  • no positions
  • multi-strategy execution map
  • private strategy (hide position, show performance)

Canary Script

Run a compatibility canary before each rollout:

uv run python scripts/report_web_canary.py \
  --uid <uid> \
  --sid <sid1> \
  --sid <sid2> \
  --check-legacy

Notes:

  • Uses FINLAB_ID_TOKEN env var by default, or pass --id-token.
  • Validates canonical payload can satisfy both websites' render contracts.
  • With --check-legacy, also checks projected legacy docs exist.

Suggested Execution Order Across Repos

  1. Server: deploy projection + monitoring.
  2. new_website: implement adapter + dual-read first (smaller/faster iteration).
  3. backtestWebsite: keep legacy mode initially; add dual-read adapter only if needed.
  4. After stable period, move both to canonical-first.