fix(import): use shared Peanut FX rates safely - #4
Conversation
|
Warning Review limit reached
Next review available in: 32 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. WalkthroughThis PR changes FX data sources and base-specific rate tables, updates money and import parsing, adds immutable import source fingerprints, extends import error payloads, revises import UI checks, and aligns tests and copy with 162 catalog currencies and 156 automatic-conversion currencies. ChangesFX and import flow
Estimated code review effort: 5 (Critical) | ~110 minutes Note 🎁 Summarized by CodeRabbit FreeYour organization has reached its limit of developer seats. For new users, CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please add seats to your subscription by visiting https://app.coderabbit.ai/login. If you believe this is a mistake and have available seats, please assign one to the pull request author through the subscription management page using the link above. Comment |
…mat-audit # Conflicts: # apps/web/src/lib/splash.test.ts
Production egress is default-deny — every runtime fetch rides the pinned squid proxy — and this used the bare global fetch. In prod every refresh would have failed, been swallowed by the existing catch, and left the table on the twelve static rates. The feature would have looked shipped while doing nothing. Uses the same egressFetch path as the model scan. egressFetch now takes a plain RequestInit and returns a full Response so a streamed, byte-bounded read works through it; Response satisfies EgressResponse, so model.ts is unchanged. SPLIT_FX_ENDPOINT makes the API host overridable so staging can be pointed at a staging API instead of prod. STILL BLOCKED ON INFRA: api.peanut.me has to go on the squid CONNECT-443 allowlist and SPLIT_FX_PROXY_URL has to be set, or this stays on static rates.
…mat-audit # Conflicts: # apps/web/src/lib/api.ts # apps/web/src/lib/money.test.ts # apps/web/src/server/expenses.test.ts
The FX refresh rides the same squid pinhole as push and scan, but its failure mode is quieter — no 502 surfaces anywhere; the rate table just stays on the static twelve. Worth naming next to the consumers whose failures are visible.
Summary
GET /fx/rates?base=<room>onapi.peanut.me(endpoint overridable viaSPLIT_FX_ENDPOINT).FX transport and policy
Production egress is default-deny, so the rate fetch rides the pinned
split-egresssquid proxy viaegressFetch, exactly like the model scan — credential-freeAccept-only GET, redirects refused, byte-bounded streamed read, aborted on timeout (5dce9f7). Infra prerequisites before this does anything in prod:api.peanut.meon the squid CONNECT-443 allowlist andSPLIT_FX_PROXY_URLset. Without them every refresh fails quietly and the table stays on the twelve static rates.The merged API contract (API #1277) preserves the atomic selection policy — both provider legs when both are covered, otherwise both reference legs, never a hybrid — with one post-review tightening: live Manteca rails (ARS, BRL) now fail closed instead of substituting a reference leg, while reference-only currencies (COP, BOB, …) keep their fallback so Split's bulk table stays complete. Split requires its 12-currency core set in every accepted table and degrades to cached (≤7 days) then static rows when the feed 503s or comes back incomplete, so the tightened contract needs no client change — there is an API-side regression test pinning the core-set guarantee.
Import compatibility boundary
Migration / branch integration
main(post QA-sesh triage): resolved conflicts inapi.ts(kept main's invalid-member-token notification plus this branch's errordetailspassthrough),money.test.ts(import union), andexpenses.test.ts(kept the room-baseRateTableshape, added main's former-member helper).Rollout
dev) to production and smoke the PLN→EUR pair plus an EUR-base bulk table.api.peanut.meto the squid CONNECT-443 allowlist and setSPLIT_FX_PROXY_URL(ask Hugo — server-side, not shippable from this repo).20260805120000_stable_import_source_fingerprintbefore or with the Split deploy.dev) only after the API is live — it drops the Frankfurter CSP entry, so backend must go first.Related PRs: API #1277 (merged to
dev), UI #2607 (merged todev), content #67.QA
git diff --checkclean, no conflict markers.Screenshots: N/A (behavioral import/backend change; rendered layout is unchanged).