Work / Chitragupt / Wiki / Decisions
2026-07-09-recovery-and-compute-correctness
Decisioncanonicalverified 2026-07-09
DECISION.2026-07-09.RECOVERY-AND-COMPUTE-CORRECTNESSDecision
Close two more findings from the 2026-07-09 fresh-perspective audit
of production-readiness-audit-v2:
Recovery paths — add the missing "undo the accidental deny" and "navigate to the newer version" affordances so no confirmed doc sits in a dead-end state:
restoreOwnershipcallable + client button — bounces arejected_owner_denieddoc back topending_owner_confirmationbefore the 7-day sweep deletes it.supersededdocs get a "View the newer version →" link in the fallback view.needs_ocrcopy tells the user the truth ("V1 doesn't OCR scans — please re-upload as a text-based PDF") and offers Delete.
Compute correctness — three real tax bugs surface:
- CG surcharge cap wired.
applySurchargenow takes the tax split into a CG portion (§111A + §112A, capped atcapital_gains_cap_pct— 15 %) and a non-CG portion (slab + VDA, full band rate). Previously the full band rate applied to everything, over-taxing wealthy filers with big CG. - VDA + cess rates read from the AY table. §115BBH crypto rate
and the 4 % health-and-education cess are no longer hardcoded in
tax-computer.ts; both come fromcapital_gains.rules[virtual_digital_asset].ltcg_rateandcess.health_education_pcton the verified tax table. - Portfolio LTCG / STCG numbers become server-computed and
AY-scoped.
PortfolioReviewgainsstcg_tax_paise,ltcg_tax_paise,ltcg_exemption_paise,stcg_rate_pct,ltcg_rate_pct; the engine reads all five off the AY table. The client-sideRealisedCgSectiononPortfolioPagedeletes its hardcodedLTCG_EXEMPTION_PAISE = 12_500_000 / LTCG_RATE = 0.125 / STCG_RATE = 0.2and renders the server values verbatim.
Predicate consolidation — useTaxViewModel was still using a
URL-string compare (ayParam !== ACTIVE_AY) for isPastAy, which
labelled the future AY as "past" and let it slip past the paywall.
Now imports the shared date-based predicate.
Why
The 2026-07-09 audit flagged three dead-end statuses that let paid
users lose an upload with no user-visible recovery:
rejected_owner_denied (mis-click), superseded (no link to newer),
needs_ocr (lied about running OCR).
Same audit flagged four hardcoded compute paths that would drift
from statute the moment a Finance Act changed a rate: 0.3 VDA,
0.04 cess, 12_500_000 LTCG exemption, 0.2 STCG / 0.125 LTCG
rates in the client, and the missing CG surcharge cap in the
computer.
Prior 2026-07-06-v1-launch-blockers fixes closed 28 blockers + 24 HIGH. These items were the follow-on cleanup that survived that round.
Impact
Backend
apps/functions/src/inbox/ownership.ts— newrestoreOwnershipcallable, registered inapps/functions/src/index.ts.packages/shared/src/contracts/inbox.ts— newRestoreOwnershipInputSchema/RestoreOwnershipOutputSchema; registry codegen picked it up (143 → 144 callables).packages/shared/src/rules/v1/tax-computer.ts—applySurchargesignature changes to(cgTax, otherTax, totalIncome, regime); newpickVdaRate(table)helper; cess pct read fromtable.cess.health_education_pct.apps/functions/src/portfolio/portfolio-review-engine.ts— reads the verified AY table for STCG / LTCG rates + exemption; persists the derivedstcg_tax_paise,ltcg_tax_paise,stcg_rate_pct,ltcg_rate_pct,ltcg_exemption_paisefields.packages/shared/src/schemas/portfolio-review.ts— five new fields added underPortfolioReviewSchema.
Frontend
apps/website/src/components/inbox/InboxDocFallbackView.tsx— restore button onrejected_owner_denied, "View the newer version →" link onsuperseded, Delete button on the remaining dead-end statuses.apps/website/src/components/inbox/StatusBanner.tsx— honestneeds_ocrcopy;rejected_owner_deniedmentions Restore.apps/website/src/app/(app)/portfolio/components/PortfolioPage.tsx— theRealisedCgSectionreads all CG numbers off the server review; no more client-side tax math with hardcoded rates.apps/website/src/app/(app)/tax/use-tax-view-model.ts—isPastAyuses the shared date-based predicate.apps/website/src/store/documents.ts— newsuperseded_byfield onDocumentDetail.apps/website/src/api/documents.ts— newrestoreOwnershipwrapper.
Tests
yarn typecheck— 7 workspaces green.yarn test— 424 functions + 122 shared + 185 mobile = 731 tests pass. All existing tax-computer snapshot tests survive the surcharge refactor (rebate → surcharge decomposition is algebraically equivalent for CG-free filers, and the CG cap only kicks in above ₹50L income where the previous test fixtures don't reach).yarn lint— 0 errors.yarn format:check— clean.
Status
Active.
Sources
- Fresh-perspective audit of the recovery paths and compute
correctness, 2026-07-09 (branch
production-readiness-audit-v2). - Related decisions: 2026-07-06-v1-launch-blockers (Phase 7c B3
wired setEncryptedPdfPassword on web — this closes the same class
of dead-end for ownership-denied),
2026-07-09-dedup-content-hash-and-purge (Phase A of the same
audit — introduced
onDocumentPurgedwhich cleans up ledger entries when a doc leavesconfirmed, complementing restoreOwnership), 2026-07-09-mapper-rollup-contract (Phase C). - Related concepts / entities: pillar-tax, pillar-portfolio, upload-only, money-in-paise.
Every project of mine is written down like this.
Read the résumé