- http: a request whose 401 arrived after another request's refresh had finished refreshed again;
it now resends with the new token. A refresh finishing after logout no longer restores tokens.
- logout sends the refresh token current at send time (after a 401 -> refresh it had sent the
rotated-out one and left the new session alive on the server for 30 days).
- Sign-out/sign-in in another browser tab is followed (storage event).
- Navigator removes its history entries when the main app unmounts (Back did nothing after logout).
- Login: +98 / 0098 / 9xxxxxxxxx phone input (autofill, typing, paste) normalised; incomplete OTP
is not sent (each wrong guess burns one of five).
- Quiz resumes at the same question after hearts refill instead of restarting; the no-hearts
screen re-checks while due (phone clock ahead of the server left it stuck at zero).
- Payment return: a pending order is re-checked for about a minute instead of shown as failed;
the pay button is reset when the page comes back from bfcache.
- Tutor: retry keeps the quiz question id; a network error no longer forgets the conversation;
daily quota detected by code ai_daily_quota.
- Root error boundary and vite:preloadError reload instead of a white screen; deploy.sh keeps
hashed assets of earlier builds for 30 days so open apps can still load their chunks.
- Sheet: labelled dialog, focus moves in and back, Escape closes only the top sheet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A linked child (demo user Ali) was told "you are linked to Ali" and the
screen asked for the parent-only weekly report, which 404s. GET /family/link
does not say which side the caller is on, so the role now comes from the
weekly report: it answers only for the parent. The child sees a line saying
their parent follows their progress and no invite/accept forms. Found on the
live site with the demo accounts. deploy.sh now prints the full API URL.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The API moved to mathapi.tadrisino2.ir on 2026-09-26; api.math.tadrisino2.ir
no longer resolves. .env.production is the only place that names it.
deploy.sh fetches, runs npm ci and the type-check, builds into dist.next and
swaps it in only when everything succeeded, so the site is never served half
a build. The previous build stays in dist.prev for rollback, and a
hand-edited dist/config.js on the server survives the release.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>