feat: redesign routed ZarinPal merchant dashboard

This commit is contained in:
2026-08-20 21:41:18 +03:30
parent d8eeff57cd
commit 9ce2e6ec83
183 changed files with 7991 additions and 1569 deletions

View File

@@ -15,17 +15,17 @@ Implementation is authorized through the approved Phase 3 task list. Each work p
## 2. Approved inputs
| Input | Status | Planning use |
|---|---|---|
| `docs/DASHBOARD-SPEC.md` | Approved for planning | Product scope and acceptance criteria |
| `docs/DASHBOARD-UX-SPEC.md` | Approved for planning | Screen, state, content, responsive, export, and accessibility behavior |
| `DESIGN.md` `0.3.2` | Approved baseline | Tokens, themes, FaNum font, RTL, component contracts, and motion |
| Backend `IDENTITY-SPEC.md` | Approved | Session, login, logout, CSRF, throttle, and tenant boundary |
| Backend `ANALYTICS-SPEC.md` | Approved | Metric lifecycle, partial delivery, retries, thresholds, and privacy |
| Backend `METRIC-CATALOGUE.md` `0.4.0` | Approved definitions | Metric semantics and formatting evidence |
| Backend `API-SPEC.md` | Approved | REST/SSE/CSV behavior and provider boundary |
| Backend `docs/openapi.yaml` `1.0.0` | Approved | Generated types and operation contracts |
| Nginx/static routing contract | Approved | Production/static-host verification contract |
| Input | Status | Planning use |
| ------------------------------------- | --------------------- | ---------------------------------------------------------------------- |
| `docs/DASHBOARD-SPEC.md` | Approved for planning | Product scope and acceptance criteria |
| `docs/DASHBOARD-UX-SPEC.md` | Approved for planning | Screen, state, content, responsive, export, and accessibility behavior |
| `DESIGN.md` `0.3.2` | Approved baseline | Tokens, themes, FaNum font, RTL, component contracts, and motion |
| Backend `IDENTITY-SPEC.md` | Approved | Session, login, logout, CSRF, throttle, and tenant boundary |
| Backend `ANALYTICS-SPEC.md` | Approved | Metric lifecycle, partial delivery, retries, thresholds, and privacy |
| Backend `METRIC-CATALOGUE.md` `0.4.0` | Approved definitions | Metric semantics and formatting evidence |
| Backend `API-SPEC.md` | Approved | REST/SSE/CSV behavior and provider boundary |
| Backend `docs/openapi.yaml` `1.0.0` | Approved | Generated types and operation contracts |
| Nginx/static routing contract | Approved | Production/static-host verification contract |
## 3. Planning assumptions
@@ -137,16 +137,16 @@ Route groups share authentication/layout requirements without changing public UR
### 5.3 State ownership
| State | Owner | Persistence |
|---|---|---|
| Server session and merchant scope | Backend | Secure server session; cookie unreadable to frontend |
| Session summary and CSRF value | Auth feature/context | Memory only; cleared on logout/401 |
| Theme choice | Theme service | Local presentation-only preference |
| Period type/id and detail filters/cursor | URL | Query parameters using server-allowlisted values |
| Analytics run and section states | Analytics-run feature | Memory; recover from run snapshot/SSE replay |
| Last SSE event id/liveness | Stream adapter | Memory for the current authorized run only |
| Form/dialog/drawer state | Owning component | Local Svelte rune state |
| Generated transport types | Build output/source | Regenerated from approved OpenAPI; never hand-edited |
| State | Owner | Persistence |
| ---------------------------------------- | --------------------- | ---------------------------------------------------- |
| Server session and merchant scope | Backend | Secure server session; cookie unreadable to frontend |
| Session summary and CSRF value | Auth feature/context | Memory only; cleared on logout/401 |
| Theme choice | Theme service | Local presentation-only preference |
| Period type/id and detail filters/cursor | URL | Query parameters using server-allowlisted values |
| Analytics run and section states | Analytics-run feature | Memory; recover from run snapshot/SSE replay |
| Last SSE event id/liveness | Stream adapter | Memory for the current authorized run only |
| Form/dialog/drawer state | Owning component | Local Svelte rune state |
| Generated transport types | Build output/source | Regenerated from approved OpenAPI; never hand-edited |
Ready section content remains immutable for a run dataset snapshot. Event reconciliation is idempotent by event and section identity. A sibling event cannot erase a valid ready section.
@@ -234,58 +234,58 @@ These are Phase 2 packages, not yet implementable Phase 3 tasks.
### Phase I — contracts and foundation
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P01 | Freeze API/OpenAPI and product limits | Gate A decisions | Approved versioned transport contract |
| P02 | Verify static-SPA/Nginx topology | P01, deployment decision | Deep links, `/api/v1`, assets, cache rules proven |
| P03 | Scaffold pinned SvelteKit/Svelte/Tailwind project | P02 | Minimal strict project and lockfile |
| P04 | Establish quality/test commands | P03 | Format, lint, check, unit, E2E, build scripts |
| P05 | Generate and drift-check API types | P01, P03 | Reproducible generated contract types |
| P06 | Implement design/theme/font foundation | P03 | RTL root, semantic themes, no-flash choice, tracked font |
| P07 | Establish contract-safe fixtures | P05 | Sensitive-free builders for all states/errors/events |
| ID | Work package | Depends on | Result |
| --- | ------------------------------------------------- | ------------------------ | -------------------------------------------------------- |
| P01 | Freeze API/OpenAPI and product limits | Gate A decisions | Approved versioned transport contract |
| P02 | Verify static-SPA/Nginx topology | P01, deployment decision | Deep links, `/api/v1`, assets, cache rules proven |
| P03 | Scaffold pinned SvelteKit/Svelte/Tailwind project | P02 | Minimal strict project and lockfile |
| P04 | Establish quality/test commands | P03 | Format, lint, check, unit, E2E, build scripts |
| P05 | Generate and drift-check API types | P01, P03 | Reproducible generated contract types |
| P06 | Implement design/theme/font foundation | P03 | RTL root, semantic themes, no-flash choice, tracked font |
| P07 | Establish contract-safe fixtures | P05 | Sensitive-free builders for all states/errors/events |
### Phase II — identity and reporting context
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P08 | Deliver login/session/logout slice | P04–P07 | Generic/throttled login and revocable session flow |
| P09 | Deliver authenticated shell | P08 | RTL sidebar/drawer, merchant identity, theme, route protection |
| P10 | Deliver Persian formatters | P04, P06 | Digits, Rial, Jalali/Tehran, percent, bidi isolation |
| ID | Work package | Depends on | Result |
| --- | ------------------------------------ | ------------- | --------------------------------------------------------------- |
| P08 | Deliver login/session/logout slice | P04–P07 | Generic/throttled login and revocable session flow |
| P09 | Deliver authenticated shell | P08 | RTL sidebar/drawer, merchant identity, theme, route protection |
| P10 | Deliver Persian formatters | P04, P06 | Digits, Rial, Jalali/Tehran, percent, bidi isolation |
| P11 | Deliver periods and URL filter slice | P05, P08, P10 | Server-allowlisted default/selection and navigation restoration |
### Phase III — partial analytics
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P12 | Resolve SSE transport spike | P01, P05, P08 | Documented tested transport choice |
| ID | Work package | Depends on | Result |
| --- | ---------------------------------------- | ------------- | ------------------------------------------------------------ |
| P12 | Resolve SSE transport spike | P01, P05, P08 | Documented tested transport choice |
| P13 | Deliver run/snapshot/section state model | P07, P11, P12 | Idempotent start, independent sections, typed errors/retries |
| P14 | Deliver overview slice | P10, P13 | KPI priority, comparisons, eligible insights, definitions |
| P15 | Deliver payment-performance slice | P10, P13 | Outcomes, retry, timing, stage semantics |
| P16 | Deliver fees slice | P10, P13 | Session-grain real Rial fees and rate |
| P17 | Deliver peer-comparison slice | P10, P13 | Median/percentile or privacy-safe suppression |
| P18 | Integrate recovery and rate-limit flows | P13–P17 | Heartbeat, replay/reset, sibling isolation, manual retry |
| P14 | Deliver overview slice | P10, P13 | KPI priority, comparisons, eligible insights, definitions |
| P15 | Deliver payment-performance slice | P10, P13 | Outcomes, retry, timing, stage semantics |
| P16 | Deliver fees slice | P10, P13 | Session-grain real Rial fees and rate |
| P17 | Deliver peer-comparison slice | P10, P13 | Median/percentile or privacy-safe suppression |
| P18 | Integrate recovery and rate-limit flows | P13–P17 | Heartbeat, replay/reset, sibling isolation, manual retry |
### Phase IV — merchant-owned evidence and export
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P19 | Deliver shared cursor-detail foundation | P05, P09–P11 | Semantic responsive table, URL filters, cursor rules |
| P20 | Deliver unverified-paid detail slice | P15, P19 | Authorized read-only `Paid` evidence |
| P21 | Deliver failed detail slice | P15, P19 | Safe observed-stage filters without invented causes |
| P22 | Deliver retried detail slice | P15, P19 | Ordered attempt summaries and recovery evidence |
| P23 | Resolve CSV delivery spike | P01, P08, P19 | Approved browser download/error strategy |
| P24 | Deliver CSV export slice | P20–P23 | Current-filter authorized export and handoff UX |
| ID | Work package | Depends on | Result |
| --- | --------------------------------------- | ------------- | ---------------------------------------------------- |
| P19 | Deliver shared cursor-detail foundation | P05, P09–P11 | Semantic responsive table, URL filters, cursor rules |
| P20 | Deliver unverified-paid detail slice | P15, P19 | Authorized read-only `Paid` evidence |
| P21 | Deliver failed detail slice | P15, P19 | Safe observed-stage filters without invented causes |
| P22 | Deliver retried detail slice | P15, P19 | Ordered attempt summaries and recovery evidence |
| P23 | Resolve CSV delivery spike | P01, P08, P19 | Approved browser download/error strategy |
| P24 | Deliver CSV export slice | P20–P23 | Current-filter authorized export and handoff UX |
### Phase V — completion and hardening
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P25 | Deliver methodology and account screens | P09–P18 | Metric/privacy explanations and demo switching/logout guidance |
| P26 | Complete responsive RTL and theme matrix | P14–P25 | 360/768/1024/1440 and both themes |
| P27 | Complete accessibility/reduced-motion verification | P14–P26 | WCAG 2.2 AA critical flows and chart/table equivalence |
| P28 | Complete security/privacy negative tests | P08–P24 | No cross-tenant/payer/peer/token exposure |
| P29 | Complete static production acceptance | P02–P28 | Build artifact passes target Nginx critical flows |
| P30 | Final documentation and human review | P29 | Current docs, evidence, approval for release handoff |
| ID | Work package | Depends on | Result |
| --- | -------------------------------------------------- | ---------- | -------------------------------------------------------------- |
| P25 | Deliver methodology and account screens | P09–P18 | Metric/privacy explanations and demo switching/logout guidance |
| P26 | Complete responsive RTL and theme matrix | P14–P25 | 360/768/1024/1440 and both themes |
| P27 | Complete accessibility/reduced-motion verification | P14–P26 | WCAG 2.2 AA critical flows and chart/table equivalence |
| P28 | Complete security/privacy negative tests | P08–P24 | No cross-tenant/payer/peer/token exposure |
| P29 | Complete static production acceptance | P02–P28 | Build artifact passes target Nginx critical flows |
| P30 | Final documentation and human review | P29 | Current docs, evidence, approval for release handoff |
## 8. Vertical acceptance slices
@@ -319,18 +319,18 @@ User confirms view/period/filter scope and downloads the synchronous server-owne
Exact command names are established in P04 and recorded in `package.json`; the required categories are:
| Level | Purpose | Required evidence |
|---|---|---|
| OpenAPI validation/generation | Prevent interface drift | Approved contract validates; generated output is reproducible |
| Unit | Formatters, reducers, error mapping, insight eligibility | Boundary tables for zero/null/decimal/RTL/event duplication |
| Component | Semantic states and interactions | Roles/names/focus/live-region behavior in both themes |
| Integration with contract fixtures | API client, auth, run/SSE, details/export | Every success/problem/event state maps correctly |
| Playwright | Critical user journeys | Login, default period, partial order, reconnect, detail, export, logout |
| Accessibility automation | Detect common WCAG failures | Axe-equivalent checks plus no serious/critical violations |
| Manual accessibility | Cover automation gaps | Keyboard, screen reader status, zoom/reflow, focus restoration |
| Visual/responsive | RTL/theme/layout stability | 360/768/1024/1440, light/dark, known long Persian content |
| Static production | Prove target topology | Built files behind Nginx, deep-link refresh, API/SSE/CSV proxy |
| Security/privacy | Negative authorization/data tests | Manipulated ids/cursors/filters and sensitive-field absence |
| Level | Purpose | Required evidence |
| ---------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------- |
| OpenAPI validation/generation | Prevent interface drift | Approved contract validates; generated output is reproducible |
| Unit | Formatters, reducers, error mapping, insight eligibility | Boundary tables for zero/null/decimal/RTL/event duplication |
| Component | Semantic states and interactions | Roles/names/focus/live-region behavior in both themes |
| Integration with contract fixtures | API client, auth, run/SSE, details/export | Every success/problem/event state maps correctly |
| Playwright | Critical user journeys | Login, default period, partial order, reconnect, detail, export, logout |
| Accessibility automation | Detect common WCAG failures | Axe-equivalent checks plus no serious/critical violations |
| Manual accessibility | Cover automation gaps | Keyboard, screen reader status, zoom/reflow, focus restoration |
| Visual/responsive | RTL/theme/layout stability | 360/768/1024/1440, light/dark, known long Persian content |
| Static production | Prove target topology | Built files behind Nginx, deep-link refresh, API/SSE/CSV proxy |
| Security/privacy | Negative authorization/data tests | Manipulated ids/cursors/filters and sensitive-field absence |
No task is complete with only typecheck/build evidence; runtime behavior and relevant error paths must be exercised.
@@ -373,21 +373,21 @@ No task is complete with only typecheck/build evidence; runtime behavior and rel
## 11. Risks and mitigations
| Risk | Impact | Mitigation |
|---|---|---|
| Implementing against draft OpenAPI | High rework/contract drift | Hard Gate A; generated types only from approved version |
| Native `EventSource` hides HTTP error detail | High recovery/accessibility gap | P12 spike; select fetch stream only if evidence requires it |
| Two reconnect owners create duplicate streams | High rate-limit/data duplication | One transport owner, explicit cleanup, concurrency tests |
| Synchronous CSV cannot support promised ready/error UX | High misleading behavior | P23 spike and UX amendment before export implementation |
| 50 MiB Blob download harms mobile memory | Medium/High | Measure at cap; prefer server streaming/direct download or revise policy |
| Static fallback mishandles deep links/API paths | High production failure | P02 Nginx proof before feature work |
| Chart library adds inaccessible/RTL-heavy dependency | Medium | Start semantic SVG/HTML; add dependency only after focused evaluation |
| Decimal strings are coerced to floating point | High financial display error | Exact parsing/format tests; format transport decimals deliberately |
| Persian/Jalali/bidi formatting corrupts technical ids | High trust/usability issue | Central formatters, long/mixed fixtures, screen-reader and visual review |
| Theme initialization flashes or leaks state across tests | Medium | Pre-paint presentation-only bootstrap and deterministic theme tests |
| Completion-order rendering shifts layout/focus | High accessibility issue | Stable frames, reducer tests, focus-preservation E2E |
| Handwritten DTOs drift from OpenAPI | High integration failure | Generated types plus CI drift check; view models remain separate |
| Fixtures accidentally contain source-sensitive data | High privacy issue | Synthetic builders, forbidden-field scans, review gate |
| Risk | Impact | Mitigation |
| -------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------ |
| Implementing against draft OpenAPI | High rework/contract drift | Hard Gate A; generated types only from approved version |
| Native `EventSource` hides HTTP error detail | High recovery/accessibility gap | P12 spike; select fetch stream only if evidence requires it |
| Two reconnect owners create duplicate streams | High rate-limit/data duplication | One transport owner, explicit cleanup, concurrency tests |
| Synchronous CSV cannot support promised ready/error UX | High misleading behavior | P23 spike and UX amendment before export implementation |
| 50 MiB Blob download harms mobile memory | Medium/High | Measure at cap; prefer server streaming/direct download or revise policy |
| Static fallback mishandles deep links/API paths | High production failure | P02 Nginx proof before feature work |
| Chart library adds inaccessible/RTL-heavy dependency | Medium | Start semantic SVG/HTML; add dependency only after focused evaluation |
| Decimal strings are coerced to floating point | High financial display error | Exact parsing/format tests; format transport decimals deliberately |
| Persian/Jalali/bidi formatting corrupts technical ids | High trust/usability issue | Central formatters, long/mixed fixtures, screen-reader and visual review |
| Theme initialization flashes or leaks state across tests | Medium | Pre-paint presentation-only bootstrap and deterministic theme tests |
| Completion-order rendering shifts layout/focus | High accessibility issue | Stable frames, reducer tests, focus-preservation E2E |
| Handwritten DTOs drift from OpenAPI | High integration failure | Generated types plus CI drift check; view models remain separate |
| Fixtures accidentally contain source-sensitive data | High privacy issue | Synthetic builders, forbidden-field scans, review gate |
## 12. Parallelization after foundation

View File

@@ -20,11 +20,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Confirm the provider-owned API specification and OpenAPI artifact are approved, versioned, and no longer marked draft before frontend transport code is generated.
**Acceptance criteria:**
- [ ] Backend `API-SPEC.md` and `openapi.yaml` identify an approved matching version.
- [ ] Approved CSV defaults, 90-day analytics/export audit retention, 30-day demo-authentication audit retention, opaque terminal reference, and stable Problem Details base URI are recorded by the provider.
- [ ] A checksum or immutable commit hash is recorded for frontend generation.
**Verification:**
- [ ] Validate OpenAPI 3.1 with the provider's contract command.
- [ ] Manually compare approved operations/schemas with `tasks/plan.md` Gate A.
@@ -39,11 +41,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Obtain the deployment-owned rules for SPA deep-link fallback, immutable assets, `static/fonts`, and same-origin `/api/v1` HTTP/SSE/CSV proxy behavior.
**Acceptance criteria:**
- [ ] Deep-link fallback never intercepts `/api/v1` or static assets.
- [ ] SSE buffering/compression and CSV streaming headers follow the approved API contract.
- [ ] The target development and production origins are documented without frontend secrets.
**Verification:**
- [ ] Review the deployment contract against SvelteKit `adapter-static` fallback requirements.
- [ ] Record the approved deployment commit/reference in `tasks/plan.md`.
@@ -58,11 +62,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Create the minimal SvelteKit 2/Svelte 5 strict-TypeScript project with npm, Tailwind CSS v4's Vite plugin, and the static adapter using current verified versions.
**Acceptance criteria:**
- [ ] Exact production/dev dependencies and Node/npm requirements are pinned in the lockfile/manifests.
- [ ] Tailwind's Vite plugin precedes SvelteKit and strict TypeScript extends generated SvelteKit config.
- [ ] No server endpoint, database dependency, secret, or placeholder auth token is introduced.
**Verification:**
- [ ] Run dependency install from the lockfile.
- [ ] Run the generated typecheck and production build.
@@ -83,11 +89,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Configure deterministic formatting, linting, `svelte-check`, Vitest, and Playwright commands used by every later task.
**Acceptance criteria:**
- [ ] `format:check`, `lint`, `check`, `test:unit`, `test:e2e`, and `build` scripts are documented and executable.
- [ ] Unit/component tests use a browser-like environment appropriate for Svelte components.
- [ ] Playwright has desktop/mobile projects without embedding credentials.
**Verification:**
- [ ] Run every new command against the empty scaffold.
- [ ] Confirm a deliberately failing sample test/check fails, then remove it.
@@ -102,11 +110,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Establish the Persian RTL document root, route fallback settings, error boundary, and minimal auth/app route groups without feature UI.
**Acceptance criteria:**
- [ ] Root markup declares `lang="fa" dir="rtl"` and permits browser zoom.
- [ ] Static fallback and trailing-slash behavior match Task 2.
- [ ] `/login` and one protected-shell placeholder deep-link correctly after refresh.
**Verification:**
- [ ] Run `npm run check` and `npm run build`.
- [ ] Serve the build through the target Nginx topology and refresh both routes.
@@ -121,11 +131,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Add reproducible generation from the approved OpenAPI commit and a drift check that prevents handwritten or stale DTOs.
**Acceptance criteria:**
- [ ] Generated schemas preserve decimal strings, integer Rial values, discriminated section states, Problem Details, and SSE payloads.
- [ ] Generated files carry provenance and are never manually edited.
- [ ] CI/local check fails when approved OpenAPI and generated output differ.
**Verification:**
- [ ] Run generation twice and confirm no diff.
- [ ] Run the contract-drift command against a deliberate schema change, then restore it.
@@ -148,11 +160,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Build one same-origin fetch boundary for generated JSON operations, RFC 9457 errors, request ids, CSRF mutations, `Retry-After`, and session termination.
**Acceptance criteria:**
- [ ] UI code can branch on stable status/code without parsing server prose.
- [ ] Cookies use browser credentials policy while auth tokens never enter storage or headers.
- [ ] `401`, safe `404`, `429`, retryable `503`, and validation field errors map to typed results.
**Verification:**
- [ ] Run focused unit tests for success/error/header mappings.
- [ ] Run `npm run check` and inspect logs/storage for sensitive values.
@@ -167,11 +181,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Translate `DESIGN.md` `0.3.2` into global semantic CSS, load the tracked FaNum variable font, and apply system/explicit theme before paint.
**Acceptance criteria:**
- [ ] Components can consume semantic light/dark roles without raw palette values.
- [ ] `IRANYekanXVFaNumVF.woff2` loads from `static/fonts` with the approved fallback and weights.
- [ ] Theme choice persists as presentation-only state with no first-paint flash.
**Verification:**
- [ ] Run build plus focused theme bootstrap tests.
- [ ] Manually inspect first paint in light/dark/system modes and verify the license remains adjacent.
@@ -186,11 +202,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Create synthetic builders for sessions, periods, all run/section states, problems, detail pages, and SSE events without copying source data.
**Acceptance criteria:**
- [ ] Fixtures cover zero, null, empty, unavailable comparison, suppression, failure, rate limit, and replay reset.
- [ ] Builders typecheck against generated schemas and use distinct synthetic merchants.
- [ ] Forbidden payer/credential/peer-row fields are absent and scanned.
**Verification:**
- [ ] Run fixture type tests and forbidden-field scan.
- [ ] Regenerate API types and confirm fixture compilation detects drift.
@@ -211,11 +229,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Centralize Persian digits, Rial-only money, exact decimal percentages, Jalali/Tehran dates, units, and LTR isolation metadata.
**Acceptance criteria:**
- [ ] Integer Rial/count values and decimal strings format without unintended floating-point changes.
- [ ] Dates use Jalali/`Asia/Tehran`; technical ids remain canonical and bidi-safe.
- [ ] Zero, null, undefined, and unavailable states have distinct typed output.
**Verification:**
- [ ] Run table-driven unit tests for boundary, long, mixed-direction, and negative comparison values.
- [ ] Manually review representative Persian output with the FaNum font.
@@ -230,11 +250,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Build the accessible Persian login screen and connect it to `createAuthSession` with generic, throttled, pending, and service-error states.
**Acceptance criteria:**
- [ ] Visible labels, password-manager autocomplete, paste, and generic credential failure match the UX spec.
- [ ] Pending submission prevents duplicates; `429` honors `Retry-After` without a retry loop.
- [ ] Successful login stores only the session summary/CSRF value in memory and navigates to the dashboard.
**Verification:**
- [ ] Run component/integration tests for success, invalid credentials, throttle, and dependency failure.
- [ ] Run keyboard and accessible-name checks at 360 px and desktop.
@@ -249,11 +271,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Restore authorized session context on refresh, revoke it on logout, and clear merchant/run state on expiry or revocation.
**Acceptance criteria:**
- [ ] Refresh calls `getAuthSession` and renders only the server-returned merchant scope.
- [ ] Logout sends CSRF/origin evidence, clears memory after server revocation, and returns to login.
- [ ] `401` from HTTP or later stream recovery produces the approved generic session-ended flow.
**Verification:**
- [ ] Run focused auth-state tests and Playwright refresh/logout/expiry flows.
- [ ] Inspect storage, URL, and logs for session/CSRF/auth-token leakage.
@@ -276,11 +300,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Implement the RTL desktop sidebar, tablet/mobile drawer, utility header, skip link, merchant display name, theme control, and active navigation.
**Acceptance criteria:**
- [ ] `merchant.displayName` is identity context, never a selector.
- [ ] Drawer traps/restores focus, closes with Escape/backdrop, and locks background scroll.
- [ ] Navigation order, landmarks, `aria-current`, touch targets, and safe areas match the UX spec.
**Verification:**
- [ ] Run component tests plus Playwright keyboard navigation at 360/768/1024/1440.
- [ ] Run axe-equivalent checks in both themes.
@@ -295,11 +321,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Render server-allowlisted periods, select the backend default, and synchronize applied period state with navigation/history without client-computed boundaries.
**Acceptance criteria:**
- [ ] Default uses `isDefault`; options show `jalaliLabelFa` and approved types only.
- [ ] Apply/reset and Back/Forward restore valid URL state without fetching on pending edits.
- [ ] Unknown/stale period ids fail safely and never broaden scope.
**Verification:**
- [ ] Run unit/component tests for default, apply, reset, invalid URL, and history restoration.
- [ ] Run Playwright period flow with Persian labels.
@@ -314,11 +342,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Test native `EventSource` against the approved contract and compare fetch streaming only where typed status/header behavior requires it.
**Acceptance criteria:**
- [ ] The chosen transport proves cookie auth, named heartbeats, replay/reset, cleanup, and one reconnect owner.
- [ ] Handling for connection limits, session end, liveness timeout, and duplicate event ids is documented.
- [ ] No third-party SSE dependency is added without measured need and approval.
**Verification:**
- [ ] Run a focused browser harness against scripted SSE fixtures for disconnect/replay/reset.
- [ ] Record the decision and rejected alternative in `docs/SSE-TRANSPORT.md`.
@@ -339,11 +369,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Create a pure, typed state reducer for run snapshots and all named SSE events, preserving independent ready sections and ignoring duplicates/regressions.
**Acceptance criteria:**
- [ ] All four sections support queued/calculating/ready/failed and peer suppression.
- [ ] Duplicate/replayed/out-of-order events cannot duplicate or erase valid ready results.
- [ ] Overall progress derives from section state without animation dependence.
**Verification:**
- [ ] Run exhaustive reducer tests for every state transition and duplicate event.
- [ ] Run generated-schema typecheck.
@@ -358,11 +390,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Connect applied period state to idempotent run creation, current snapshot recovery, the chosen stream, heartbeat watchdog, and authorized teardown.
**Acceptance criteria:**
- [ ] One applied period intent produces a stable idempotency key and no duplicate equivalent starts.
- [ ] Ready snapshot sections render immediately while unfinished siblings stream independently.
- [ ] Replay reset, stream close, period change, logout, and component teardown preserve correct ownership.
**Verification:**
- [ ] Run integration tests for `200`/`202`, replay, reset, period change, and teardown.
- [ ] Run Playwright with different section completion orders.
@@ -377,11 +411,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Render headline KPIs in approved order, exact comparisons, empty/undefined states, provenance, and stable loading/ready layout.
**Acceptance criteria:**
- [ ] Amount, count, success, and verification KPIs use correct semantics, Persian formatting, unit, period, and definitions.
- [ ] Unavailable baseline and undefined denominator never display as zero or trend.
- [ ] Overview becomes useful without waiting for other sections and does not steal focus.
**Verification:**
- [ ] Run component tests across queued/calculating/ready/empty/unavailable/failed fixtures.
- [ ] Run visual checks at four viewports in both themes.
@@ -402,11 +438,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Render action cards only when the server comparison and approved evidence thresholds make the insight eligible.
**Acceptance criteria:**
- [ ] Insight copy includes observation, exact evidence, relevant sessions, possible action, and limitation.
- [ ] Below-threshold, zero-baseline, missing, or undefined comparisons never create action claims.
- [ ] Language remains observational and uses correct Persian percentage-point terminology.
**Verification:**
- [ ] Run table-driven component tests at 99/100 sessions and threshold boundaries.
- [ ] Manually review all Persian insight variants for causality and نیم‌فاصله.
@@ -421,11 +459,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Render final outcomes, verification gap, observed stages, retry sessions, and recovery rate without misclassifying `Paid`, `NoAttempt`, or `InBank`.
**Acceptance criteria:**
- [ ] `Paid` and `Verified` are bank-paid while only `Verified` is finalized.
- [ ] Stage and retry values use session grain, exact denominators, and approved safe language.
- [ ] Chart/table alternatives expose the same labeled values without color-only meaning.
**Verification:**
- [ ] Run component tests for every status/stage and undefined retry rate.
- [ ] Run keyboard/table-equivalence and both-theme checks.
@@ -440,11 +480,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Render init/verify p50 and p95 with sample and non-null coverage using an accessible paired visualization and table.
**Acceptance criteria:**
- [ ] Missing timing remains unavailable, never zero.
- [ ] Milliseconds are primary and readable seconds may only supplement them.
- [ ] Exact p50/p95/sample/coverage is available without hover or pointer precision.
**Verification:**
- [ ] Run component tests for null, zero, sparse, and full-coverage fixtures.
- [ ] Verify chart/table equivalence, Persian digits, and mobile height.
@@ -465,11 +507,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Render real session-grain paid fees, paid amount denominator, fee rate, comparison, and accessible trend/table in Rial only.
**Acceptance criteria:**
- [ ] Fee totals are labeled real merchant fees and never multiplied by attempts.
- [ ] Rial and percentage never share an ambiguous axis; undefined fee rate is explicit.
- [ ] Period, denominator, comparison, definition version, and calculation time are visible.
**Verification:**
- [ ] Run tests with duplicate attempts, zero denominator, unavailable baseline, and large Rial amounts.
- [ ] Run responsive/light/dark chart-table review.
@@ -484,11 +528,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Render approved merchant-weighted medians and direction-aware percentiles or the privacy-safe suppressed state.
**Acceptance criteria:**
- [ ] Higher displayed percentile always means better, with lower-is-better metrics explained.
- [ ] Suppression exposes no peer values/rows/identities and does not hide merchant analytics.
- [ ] Chart/table/labels cannot imply an individual peer distribution or rank.
**Verification:**
- [ ] Run ready/suppressed boundary fixtures and sensitive-field absence tests.
- [ ] Run accessible-name, keyboard, both-theme, and mobile checks.
@@ -503,11 +549,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Integrate section-local failure/manual retry, rate limits, heartbeat loss, replay/reset, and overall status across all analytics pages.
**Acceptance criteria:**
- [ ] Manual retry targets one exhausted failed section and preserves ready siblings.
- [ ] `Retry-After` and connection recovery never create a tight loop or competing announcements.
- [ ] Heartbeats are silent while meaningful progress/recovery uses one restrained live region.
**Verification:**
- [ ] Run integration/Playwright tests for mixed terminal states, retry conflicts, `429`, disconnect, and reset.
- [ ] Screen-reader check confirms no heartbeat/countdown announcement spam.
@@ -530,11 +578,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Build typed detail queries, opaque-cursor URL state, server pagination, semantic desktop table, and mobile priority-row disclosure.
**Acceptance criteria:**
- [ ] View/period/allowlisted filters come from URL while cursor changes cannot broaden scope.
- [ ] Page size follows the contract and no browser-side total/fake pagination is invented.
- [ ] Table captions, headers, row disclosures, sort/order statement, and LTR ids are accessible.
**Verification:**
- [ ] Run integration tests for next cursor, invalid cursor, filter change, empty, and `404`.
- [ ] Run 320/360 px reflow plus keyboard/screen-reader table checks.
@@ -549,11 +599,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Provide read-only merchant-owned `Paid` evidence with accurate bank-paid/unverified language and empty/error states.
**Acceptance criteria:**
- [ ] Only the approved `UNVERIFIED_PAID` view/fields are requested and rendered.
- [ ] `Paid` is never styled or announced as failure.
- [ ] Period, result context, amounts in Rial, ids, attempts, and export eligibility are explicit.
**Verification:**
- [ ] Run focused route/component tests for rows, empty, cursor, and session expiry.
- [ ] Reconcile fixture rows with the unverified aggregate.
@@ -568,11 +620,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Provide read-only failed-session evidence with allowlisted observed-stage filters and no invented bank/PSP causes.
**Acceptance criteria:**
- [ ] Only `NO_ATTEMPT`, `REACHED_BANK`, and `OTHER_OBSERVED` filters are available.
- [ ] `NoAttempt` and `InBank` copy preserves approved observed-stage meaning.
- [ ] Filter/cursor manipulation returns safe typed errors without cross-tenant hints.
**Verification:**
- [ ] Run focused tests for each stage, empty, invalid cursor/filter, and safe `404`.
- [ ] Manually review Persian stage copy against the metric catalogue.
@@ -593,11 +647,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Provide read-only retried-session evidence with bounded ordered attempt summaries and eventual payment outcome.
**Acceptance criteria:**
- [ ] Attempt sequences are ordered, bounded, and never depend on source row order.
- [ ] Payer tokens, response codes, and undocumented causes remain absent.
- [ ] `Paid` or `Verified` eventual recovery is represented accurately.
**Verification:**
- [ ] Run tests for multiple attempts, long bounded history, null timing, and recovered/unrecovered outcomes.
- [ ] Reconcile fixture rows with retry aggregates.
@@ -612,11 +668,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Measure and document direct navigation versus authenticated fetch/Blob at the approved cap, including typed errors and interrupted streams.
**Acceptance criteria:**
- [ ] Selected approach handles `413`, `429`, `504`, session expiry, and pre-byte failures truthfully.
- [ ] Memory/mobile behavior is measured at representative and maximum approved sizes.
- [ ] UX “requesting/downloading/failed” copy is amended if separate generating/ready states are not observable.
**Verification:**
- [ ] Run browser tests against success, Problem Details, and interrupted CSV fixtures.
- [ ] Record the decision and measurements in `docs/CSV-DELIVERY.md` before export UI work.
@@ -631,11 +689,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Add scope preflight and server-owned synchronous CSV download to the three eligible detail views using the Task 29 decision.
**Acceptance criteria:**
- [ ] Preflight states merchant display name, view, period, filters, Rial unit, and sensitive-field exclusion.
- [ ] Export always reauthorizes the server endpoint and never assembles hidden browser rows.
- [ ] Empty, requesting/downloading, rate-limited, too-large, timeout, interrupted, and session-ended states are distinct.
**Verification:**
- [ ] Run component/Playwright tests for all three views and every typed export outcome.
- [ ] Scan downloaded fixtures for BOM/header/timestamp/Rial policy and forbidden fields/formulas.
@@ -658,11 +718,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Implement metric/period/lifecycle/coverage/peer/insight explanations plus account identity, theme, logout, and demo merchant-switch guidance.
**Acceptance criteria:**
- [ ] Definitions are linkable, versioned, keyboard reachable, and consistent with approved contracts.
- [ ] Account uses `merchant.displayName` and explains switching only by logout/new login.
- [ ] No profile editing, roles, registration, recovery, peer detail, or AI claims appear.
**Verification:**
- [ ] Run route/component tests and broken-anchor checks.
- [ ] Manually proofread Persian copy and mixed-direction identifiers.
@@ -677,11 +739,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Complete shell/header/navigation/filter responsiveness, long Persian content handling, safe areas, focus visibility, and semantic dark-mode states.
**Acceptance criteria:**
- [ ] Shell/filter/navigation work at 360/768/1024/1440 and 320 CSS px reflow.
- [ ] Light/dark cover focus, hover, pressed, disabled, skeleton, scrim, status, and native controls.
- [ ] No sticky/fixed UI obscures focus or content.
**Verification:**
- [ ] Run responsive Playwright screenshots/interactions in both themes.
- [ ] Manually test 200% zoom, long merchant names, keyboard drawer, and reduced motion.
@@ -696,11 +760,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Complete KPI/chart/table/detail/export layout behavior, stable async footprints, content overflow, and mobile disclosure patterns.
**Acceptance criteria:**
- [ ] Section completion order causes no material layout shift or focus movement.
- [ ] Charts remain at least 240 px with exact value/table first-class alternatives.
- [ ] Detail/export tasks remain usable at 320 CSS px without hidden critical fields/actions.
**Verification:**
- [ ] Run visual regression and interaction checks across all routes/viewports/themes.
- [ ] Manually test long ids, maximum formatted values, empty/error/suppressed states.
@@ -721,11 +787,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Close WCAG 2.2 AA gaps across authentication, shell, filters, async statuses, charts, tables, dialogs, and errors.
**Acceptance criteria:**
- [ ] Critical flows are keyboard complete with visible/restored/unobscured focus.
- [ ] Screen readers receive headings, labels, chart tables, associated errors, and restrained status messages.
- [ ] Automated checks have no serious/critical violations in both themes.
**Verification:**
- [ ] Run the full accessibility Playwright suite at acceptance viewports.
- [ ] Perform manual keyboard, screen-reader, 200% zoom/reflow, and reduced-motion checks.
@@ -740,11 +808,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Verify frontend behavior under manipulated ids/cursors/filters/events, session changes, hostile CSV/text content, and sensitive-field attempts.
**Acceptance criteria:**
- [ ] Cross-tenant/absent resources remain indistinguishable and clear no valid sibling data unexpectedly.
- [ ] Payer tokens, peer rows, cookies, CSRF/auth values, credentials, and internal keys never reach DOM/storage/URL/log/download.
- [ ] CSV formula prefixes and hostile bidi/long content remain safely presented.
**Verification:**
- [ ] Run security-focused unit/integration/Playwright tests and forbidden-field scans.
- [ ] Inspect browser storage/network/log artifacts for both demo merchants.
@@ -759,11 +829,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Build the release candidate and exercise it behind the approved Nginx config with real proxy semantics for HTTP, SSE, CSV, fonts, and deep links.
**Acceptance criteria:**
- [ ] Lockfile install and all quality commands pass from a clean checkout.
- [ ] Deep-link refresh, immutable assets/font, `/api/v1`, SSE replay, and CSV download work through Nginx.
- [ ] No source map, env value, credential, generated secret, or unintended artifact is shipped.
**Verification:**
- [ ] Run the complete CI-equivalent command sequence and target-topology Playwright suite.
- [ ] Inspect build contents, response headers, caching, compression, and fallback routing.
@@ -784,11 +856,13 @@ Commands named below are established by Task 4. Before then, verification uses t
**Description:** Reconcile README, specs, plan, completed checklist, commands, source structure, transport decisions, and verification reports with the implemented state.
**Acceptance criteria:**
- [ ] Documentation describes current behavior and exact commands without stale draft assumptions.
- [ ] Durable SSE/CSV/chart/static decisions are linked and surprising decisions receive ADRs where required.
- [ ] Completed tasks and remaining limitations are accurate; no secret or private operational value is documented.
**Verification:**
- [ ] Run markdown/link/diff checks and compare every acceptance criterion with evidence.
- [ ] Obtain final human review before merge/release handoff.