diff --git a/README.md b/README.md index 1af4332..99f8227 100644 --- a/README.md +++ b/README.md @@ -7,5 +7,6 @@ Current state: design/specification only. No frontend scaffold or runtime code h - [`DESIGN.md`](DESIGN.md): visual language, interaction rules, responsive behavior, and current design-system state. - [`docs/DASHBOARD-SPEC.md`](docs/DASHBOARD-SPEC.md): approved product requirements and acceptance criteria for implementation planning. - [`docs/DASHBOARD-UX-SPEC.md`](docs/DASHBOARD-UX-SPEC.md): detailed screen map, RTL layouts, async states, data presentation, accessibility, and authorized export workflows. -- [`tasks/plan.md`](tasks/plan.md): SDD Phase 2 dependency order, risk spikes, vertical slices, and approval gates; implementation remains unauthorized. +- [`tasks/plan.md`](tasks/plan.md): approved SDD Phase 2 dependency order, risk spikes, vertical slices, and approval gates. +- [`tasks/todo.md`](tasks/todo.md): draft SDD Phase 3 task list awaiting review before implementation. - [`AGENTS.md`](AGENTS.md): durable rules for future coding agents and contributors. diff --git a/tasks/todo.md b/tasks/todo.md new file mode 100644 index 0000000..9181f94 --- /dev/null +++ b/tasks/todo.md @@ -0,0 +1,803 @@ +# Phase 3 Task List — Merchant Analytics Dashboard + +- Status: Draft for human review +- SDD phase: 3 — Tasks +- Source plan: [`plan.md`](plan.md) +- Implementation authorization: Not granted +- Last updated: 2026-08-20 + +Tasks are ordered by dependency. Each implementation task must satisfy its acceptance criteria plus the Definition of Done in `tasks/plan.md`. Likely files are planning targets and may be adjusted before work begins, but a task must be split if it would exceed approximately five files or one focused session. + +Commands named below are established by Task 4. Before then, verification uses the scaffold's generated commands and read-only contract checks. + +## Phase A — Contract and executable foundation + +## Task 1: Freeze the merchant API contract + +**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, 30-day analytics/export 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. + +**Dependencies:** None + +**Files likely touched:** External backend contract artifacts; no frontend source files. + +**Estimated scope:** XS — external gate + +## Task 2: Freeze the static Nginx routing contract + +**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`. + +**Dependencies:** Task 1 + +**Files likely touched:** `tasks/plan.md`; external deployment artifacts. + +**Estimated scope:** XS — external gate + +## Task 3: Scaffold the pinned SvelteKit project + +**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. + +**Dependencies:** Tasks 1–2 + +**Files likely touched:** `package.json`, `package-lock.json`, `svelte.config.js`, `vite.config.ts`, `tsconfig.json` + +**Estimated scope:** M — 5 files + +### Checkpoint A1 — Contract and scaffold + +- [ ] Tasks 1–3 are complete and reviewed. +- [ ] No draft OpenAPI artifact is consumed by frontend code. +- [ ] The minimal project installs and builds reproducibly. + +## Task 4: Establish frontend quality commands + +**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. + +**Dependencies:** Task 3 + +**Files likely touched:** `package.json`, `eslint.config.js`, `.prettierrc`, `vitest.config.ts`, `playwright.config.ts` + +**Estimated scope:** M — 5 files + +## Task 5: Configure the static application root + +**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. + +**Dependencies:** Tasks 2–4 + +**Files likely touched:** `src/app.html`, `src/routes/+layout.svelte`, `src/routes/+layout.ts`, `src/routes/+error.svelte`, `svelte.config.js` + +**Estimated scope:** M — 5 files + +## Task 6: Generate OpenAPI transport types + +**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. + +**Dependencies:** Tasks 1, 3–4 + +**Files likely touched:** `package.json`, `scripts/generate-api.mjs`, `src/lib/api/generated/schema.ts`, `docs/API-CONTRACT.md` + +**Estimated scope:** M — 4 files + +### Checkpoint A2 — Executable contract foundation + +- [ ] Tasks 4–6 pass all configured checks. +- [ ] Static deep links and generated contract drift are proven. +- [ ] Human review confirms no server authority moved into the browser. + +## Phase B — Design, transport, and identity + +## Task 7: Implement the typed HTTP client boundary + +**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. + +**Dependencies:** Task 6 + +**Files likely touched:** `src/lib/api/client.ts`, `src/lib/api/problem.ts`, `src/lib/api/client.test.ts`, `src/lib/api/problem.test.ts` + +**Estimated scope:** M — 4 files + +## Task 8: Implement tokens, font, and pre-paint theme + +**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. + +**Dependencies:** Tasks 3–5 + +**Files likely touched:** `src/app.css`, `src/app.html`, `src/routes/+layout.svelte`, `src/lib/components/ui/ThemeControl.svelte`, `src/lib/components/ui/ThemeControl.test.ts` + +**Estimated scope:** M — 5 files + +## Task 9: Create contract-safe fixture builders + +**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. + +**Dependencies:** Tasks 6–7 + +**Files likely touched:** `src/lib/testing/fixtures.ts`, `src/lib/testing/events.ts`, `src/lib/testing/problems.ts`, `src/lib/testing/fixtures.test.ts` + +**Estimated scope:** M — 4 files + +### Checkpoint B1 — Design and transport primitives + +- [ ] Tasks 7–9 pass focused tests and production build. +- [ ] Theme/font work matches `DESIGN.md` without new system decisions. +- [ ] Fixtures contain no sensitive or peer-level source data. + +## Task 10: Implement Persian financial formatters + +**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. + +**Dependencies:** Tasks 8–9 + +**Files likely touched:** `src/lib/format/number.ts`, `src/lib/format/date.ts`, `src/lib/format/bidi.ts`, `src/lib/format/format.test.ts` + +**Estimated scope:** M — 4 files + +## Task 11: Deliver the login vertical slice + +**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. + +**Dependencies:** Tasks 7–10 + +**Files likely touched:** `src/routes/(auth)/login/+page.svelte`, `src/lib/components/auth/LoginForm.svelte`, `src/lib/features/auth/session.svelte.ts`, `src/lib/components/auth/LoginForm.test.ts`, `tests/e2e/login.spec.ts` + +**Estimated scope:** M — 5 files + +## Task 12: Deliver session restoration and logout + +**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. + +**Dependencies:** Task 11 + +**Files likely touched:** `src/lib/features/auth/session.svelte.ts`, `src/routes/(app)/+layout.svelte`, `src/lib/components/auth/LogoutButton.svelte`, `src/lib/features/auth/session.test.ts`, `tests/e2e/session.spec.ts` + +**Estimated scope:** M — 5 files + +### Checkpoint B2 — Identity slice + +- [ ] Tasks 10–12 pass all checks and runtime verification. +- [ ] Two synthetic/demo users remain tenant-isolated. +- [ ] Human review approves Persian login copy and session transitions. + +## Phase C — Shell, periods, and partial analytics + +## Task 13: Deliver the authenticated app shell + +**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. + +**Dependencies:** Tasks 8, 12 + +**Files likely touched:** `src/lib/components/layout/AppShell.svelte`, `src/lib/components/layout/Sidebar.svelte`, `src/lib/components/layout/Drawer.svelte`, `src/routes/(app)/+layout.svelte`, `src/lib/components/layout/AppShell.test.ts` + +**Estimated scope:** M — 5 files + +## Task 14: Deliver reporting-period URL state + +**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. + +**Dependencies:** Tasks 7, 10, 13 + +**Files likely touched:** `src/lib/features/periods/periods.svelte.ts`, `src/lib/components/analytics/PeriodFilter.svelte`, `src/routes/(app)/dashboard/+page.svelte`, `src/lib/features/periods/periods.test.ts`, `tests/e2e/periods.spec.ts` + +**Estimated scope:** M — 5 files + +## Task 15: Resolve the SSE transport spike + +**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`. + +**Dependencies:** Tasks 1, 7, 9, 12 + +**Files likely touched:** `src/lib/api/analytics-stream.ts`, `src/lib/api/analytics-stream.test.ts`, `tests/e2e/fixtures/sse.ts`, `tests/e2e/sse-spike.spec.ts`, `docs/SSE-TRANSPORT.md` + +**Estimated scope:** M — 5 files + +### Checkpoint C1 — Shell, periods, and SSE decision + +- [ ] Tasks 13–15 pass responsive, keyboard, and transport tests. +- [ ] Human review approves the SSE decision before run orchestration begins. +- [ ] No reconnect duplication or merchant-scope state survives logout. + +## Task 16: Implement the analytics run reducer + +**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. + +**Dependencies:** Tasks 9, 15 + +**Files likely touched:** `src/lib/features/analytics-run/model.ts`, `src/lib/features/analytics-run/reducer.ts`, `src/lib/features/analytics-run/reducer.test.ts` + +**Estimated scope:** M — 3 files + +## Task 17: Deliver run start, snapshot, and stream orchestration + +**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. + +**Dependencies:** Tasks 14–16 + +**Files likely touched:** `src/lib/features/analytics-run/controller.svelte.ts`, `src/lib/components/analytics/RunStatus.svelte`, `src/routes/(app)/dashboard/+page.svelte`, `src/lib/features/analytics-run/controller.test.ts`, `tests/e2e/partial-run.spec.ts` + +**Estimated scope:** M — 5 files + +## Task 18: Deliver the overview vertical slice + +**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. + +**Dependencies:** Tasks 10, 17 + +**Files likely touched:** `src/lib/features/overview/OverviewSection.svelte`, `src/lib/components/analytics/MetricCard.svelte`, `src/lib/components/analytics/SectionFrame.svelte`, `src/lib/features/overview/OverviewSection.test.ts`, `src/routes/(app)/dashboard/+page.svelte` + +**Estimated scope:** M — 5 files + +### Checkpoint C2 — First complete analytics slice + +- [ ] Tasks 16–18 pass focused tests, Playwright, check, and build. +- [ ] Idempotent start plus independently ready overview works end to end. +- [ ] Human review approves stable layout and restrained live announcements. + +## Task 19: Deliver deterministic overview insights + +**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 نیم‌فاصله. + +**Dependencies:** Task 18 + +**Files likely touched:** `src/lib/features/overview/InsightCard.svelte`, `src/lib/features/overview/insights.ts`, `src/lib/features/overview/InsightCard.test.ts` + +**Estimated scope:** M — 3 files + +## Task 20: Deliver payment-performance outcomes and retry + +**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. + +**Dependencies:** Tasks 17–18 + +**Files likely touched:** `src/lib/features/payment-performance/OutcomeSummary.svelte`, `src/lib/features/payment-performance/RetrySummary.svelte`, `src/lib/components/analytics/AccessibleChart.svelte`, `src/lib/features/payment-performance/payment-performance.test.ts`, `src/routes/(app)/payments/+page.svelte` + +**Estimated scope:** M — 5 files + +## Task 21: Deliver processing-time analysis + +**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. + +**Dependencies:** Tasks 10, 20 + +**Files likely touched:** `src/lib/features/payment-performance/TimingSummary.svelte`, `src/lib/features/payment-performance/TimingChart.svelte`, `src/lib/features/payment-performance/TimingSummary.test.ts` + +**Estimated scope:** M — 3 files + +### Checkpoint C3 — Payment performance + +- [ ] Tasks 19–21 pass metric-semantic and accessibility checks. +- [ ] No actionable claim appears below approved thresholds. +- [ ] Human review confirms status/stage copy does not invent causes. + +## Task 22: Deliver the fees vertical slice + +**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. + +**Dependencies:** Tasks 17–18 + +**Files likely touched:** `src/lib/features/fees/FeesSection.svelte`, `src/lib/features/fees/FeesChart.svelte`, `src/lib/features/fees/FeesSection.test.ts`, `src/routes/(app)/fees/+page.svelte` + +**Estimated scope:** M — 4 files + +## Task 23: Deliver the peer-comparison vertical slice + +**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. + +**Dependencies:** Tasks 17–18 + +**Files likely touched:** `src/lib/features/peer-comparison/PeerSection.svelte`, `src/lib/features/peer-comparison/PeerMetric.svelte`, `src/lib/features/peer-comparison/PeerSection.test.ts`, `src/routes/(app)/peers/+page.svelte` + +**Estimated scope:** M — 4 files + +## Task 24: Deliver failure, retry, and recovery integration + +**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. + +**Dependencies:** Tasks 19–23 + +**Files likely touched:** `src/lib/features/analytics-run/controller.svelte.ts`, `src/lib/components/analytics/SectionError.svelte`, `src/lib/components/analytics/RunStatus.svelte`, `src/lib/features/analytics-run/recovery.test.ts`, `tests/e2e/recovery.spec.ts` + +**Estimated scope:** M — 5 files + +### Checkpoint C4 — Complete partial analytics + +- [ ] Tasks 22–24 pass all section-state and recovery scenarios. +- [ ] All four sections are independently useful in any completion order. +- [ ] Human review approves charts/tables, suppression, rate-limit, and recovery UX. + +## Phase D — Merchant-owned evidence and CSV + +## Task 25: Implement the cursor-detail client and table foundation + +**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. + +**Dependencies:** Tasks 10, 13–14, 24 + +**Files likely touched:** `src/lib/features/session-details/client.ts`, `src/lib/features/session-details/state.svelte.ts`, `src/lib/components/details/DetailTable.svelte`, `src/lib/components/details/DetailRow.svelte`, `src/lib/features/session-details/details.test.ts` + +**Estimated scope:** M — 5 files + +## Task 26: Deliver the unverified-paid detail view + +**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. + +**Dependencies:** Task 25 + +**Files likely touched:** `src/routes/(app)/payments/unverified/+page.svelte`, `src/lib/features/session-details/UnverifiedPaidView.svelte`, `src/lib/features/session-details/UnverifiedPaidView.test.ts` + +**Estimated scope:** M — 3 files + +## Task 27: Deliver the failed-session detail view + +**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. + +**Dependencies:** Task 25 + +**Files likely touched:** `src/routes/(app)/payments/failed/+page.svelte`, `src/lib/features/session-details/FailedView.svelte`, `src/lib/components/details/FailureStageFilter.svelte`, `src/lib/features/session-details/FailedView.test.ts` + +**Estimated scope:** M — 4 files + +### Checkpoint D1 — First detail views + +- [ ] Tasks 25–27 pass cursor, responsive-table, and privacy checks. +- [ ] Aggregates remain reconciliation source; no unbounded client count query exists. +- [ ] Human review confirms row priority and observed-stage language. + +## Task 28: Deliver the retried-session detail view + +**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. + +**Dependencies:** Task 25 + +**Files likely touched:** `src/routes/(app)/payments/retried/+page.svelte`, `src/lib/features/session-details/RetriedView.svelte`, `src/lib/components/details/AttemptHistory.svelte`, `src/lib/features/session-details/RetriedView.test.ts` + +**Estimated scope:** M — 4 files + +## Task 29: Resolve synchronous CSV delivery behavior + +**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. + +**Dependencies:** Tasks 1, 7, 25 + +**Files likely touched:** `src/lib/features/export/csv-spike.ts`, `src/lib/features/export/csv-spike.test.ts`, `tests/e2e/csv-spike.spec.ts`, `docs/CSV-DELIVERY.md`, `docs/DASHBOARD-UX-SPEC.md` + +**Estimated scope:** M — 5 files + +## Task 30: Deliver the authorized CSV export slice + +**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. + +**Dependencies:** Tasks 26–29 + +**Files likely touched:** `src/lib/features/export/ExportDialog.svelte`, `src/lib/features/export/download.ts`, `src/lib/features/export/ExportDialog.test.ts`, `tests/e2e/export.spec.ts`, `src/lib/components/details/DetailTable.svelte` + +**Estimated scope:** M — 5 files + +### Checkpoint D2 — Evidence and export + +- [ ] Tasks 28–30 pass reconciliation, cap/error, interruption, and privacy checks. +- [ ] Finance/legal handoff copy and synchronous behavior receive human approval. +- [ ] No payer token, peer row, credential, or other-merchant value reaches DOM/download/logs. + +## Phase E — Completion and hardening + +## Task 31: Deliver methodology and account screens + +**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. + +**Dependencies:** Tasks 12–14, 19–24 + +**Files likely touched:** `src/routes/(app)/methodology/+page.svelte`, `src/lib/features/methodology/MetricDefinitions.svelte`, `src/routes/(app)/account/+page.svelte`, `src/lib/features/methodology/MetricDefinitions.test.ts` + +**Estimated scope:** M — 4 files + +## Task 32: Harden shell responsiveness and themes + +**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. + +**Dependencies:** Tasks 13–14, 31 + +**Files likely touched:** `src/lib/components/layout/AppShell.svelte`, `src/lib/components/layout/Drawer.svelte`, `src/lib/components/analytics/PeriodFilter.svelte`, `src/app.css`, `tests/e2e/responsive-shell.spec.ts` + +**Estimated scope:** M — 5 files + +## Task 33: Harden analytics and detail responsiveness + +**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. + +**Dependencies:** Tasks 18–30 + +**Files likely touched:** `src/lib/components/analytics/SectionFrame.svelte`, `src/lib/components/analytics/AccessibleChart.svelte`, `src/lib/components/details/DetailTable.svelte`, `src/lib/features/export/ExportDialog.svelte`, `tests/e2e/responsive-data.spec.ts` + +**Estimated scope:** M — 5 files + +### Checkpoint E1 — Complete responsive product + +- [ ] Tasks 31–33 pass all route, viewport, theme, and copy checks. +- [ ] No new design-system decision was introduced without `DESIGN.md` changelog. +- [ ] Human review approves the complete visual/interaction hierarchy. + +## Task 34: Complete accessibility verification + +**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. + +**Dependencies:** Tasks 30–33 + +**Files likely touched:** `tests/e2e/accessibility.spec.ts`, `tests/e2e/keyboard.spec.ts`, `docs/ACCESSIBILITY-REPORT.md`, plus at most two focused defect files per implementation increment. + +**Estimated scope:** M — split fixes into separate tasks if more than 5 files + +## Task 35: Complete security and privacy negative tests + +**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. + +**Dependencies:** Tasks 24–34 + +**Files likely touched:** `tests/e2e/security.spec.ts`, `src/lib/testing/forbidden-fields.ts`, `src/lib/testing/forbidden-fields.test.ts`, `docs/SECURITY-VERIFICATION.md` + +**Estimated scope:** M — 4 files + +## Task 36: Verify the production static artifact + +**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. + +**Dependencies:** Tasks 2, 34–35 + +**Files likely touched:** `tests/e2e/production.spec.ts`, `docs/PRODUCTION-VERIFICATION.md`, and up to three focused config/test files if defects are found. + +**Estimated scope:** M — split defects if needed + +### Checkpoint E2 — Release candidate + +- [ ] Tasks 34–36 and the full Definition of Done pass. +- [ ] Product, accessibility, security, finance/legal export, and deployment evidence are reviewed. +- [ ] No deployment or release occurs without separate authorization. + +## Task 37: Finalize implementation documentation + +**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. + +**Dependencies:** Task 36 + +**Files likely touched:** `README.md`, `docs/DASHBOARD-SPEC.md`, `docs/DASHBOARD-UX-SPEC.md`, `tasks/plan.md`, `tasks/todo.md` + +**Estimated scope:** M — 5 files + +## Final implementation gate + +- [ ] Human approves this Phase 3 task list. +- [ ] Tasks 1–2 are complete before Task 3 begins. +- [ ] Implementation proceeds one task at a time with tests first where behavior/logic changes. +- [ ] Every completed increment is verified and committed atomically without pushing unless separately requested.