Add multi-method tax engine with FX-ready pricing hierarchy (#317) - #382
Merged
robertocarlous merged 3 commits intoAug 27, 2026
Merged
Conversation
…lth#317) Cost-basis consumption is now method-parameterized (FIFO/LIFO/HIFO/ SPECIFIC_ID) via a whitelisted registry in src/tax/methods/, resolved per user from the new User.accountingMethod (default FIFO, byte- identical to prior behavior). SPECIFIC_ID withdrawals carry their lot selection on Transaction.selectedLotIds so the event listener has it when disposals are recorded on confirmation. Method changes are forward-only (User.methodEffectiveAt) — disposals already recorded are never rewritten. The tax report's `method` query param is a confirmation gate against the account's real setting, not a what-if recompute switch, since disposals are an immutable ledger of what actually happened. A mid-year method change is flagged in the report's caveats rather than silently mixed. Pricing gains a real source hierarchy (user-declared -> market feed -> stablecoin assumption -> unpriced) with a documented, always-null feed stub as the integration point for a future price source. See docs/TAX_REPORT.md.
Syncs with 40+ commits of upstream history (websocket streaming, user API keys, session hardening, the user-event bridge replacing the old webhook dispatcher, etc.) — no real conflicts, git merged cleanly. Adds the rollback.sql the migration-rollback-check CI job requires for 20260824215727_add_multi_method_tax_engine.
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/tax/methods/, resolved per user from the newUser.accountingMethod(defaultFIFO, byte-identical to the pre-existing behavior — verified against the original FIFO fixture tests).Transaction.selectedLotIdscolumn so the Stellar event listener has it once the on-chain withdrawal confirms (disposal recording happens on that confirmation path, the same timing every other method already uses).User.methodEffectiveAt) — disposals already recorded are never rewritten.buildTaxReport's?method=query param is a confirmation gate against the account's real setting, not a what-if recompute switch, since the ledger is an immutable record of what actually happened; a mid-year method change is flagged in the report's caveats instead of silently mixed.src/tax/pricing.ts) gains a real source hierarchy — user-declared → market feed → stablecoin assumption → unpriced — with a documented, always-null feed stub as the integration point for a future price source (no live feed/credentials exist yet, so volatile assets stay honestly unpriced).docs/TAX_REPORT.md.Test plan
npx tsc --noEmitcleannpx eslintclean on all new/touched filesprisma migrate reset+migrate dev, no drift)accountingMethodto LIFO/HIFO, deposit + withdraw, confirm the report reflects the expected consumption order and rejects a mismatched?method=query param with 400.closes #317