38 KiB
Phase 3 Task List — Merchant Analytics Dashboard
- Status: Draft for human review
- SDD phase: 3 — Tasks
- Source plan:
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.mdandopenapi.yamlidentify 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.mdGate 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/v1or 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-staticfallback 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, andbuildscripts 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.
/loginand one protected-shell placeholder deep-link correctly after refresh.
Verification:
- Run
npm run checkandnpm 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, safe404,429, retryable503, and validation field errors map to typed results.
Verification:
- Run focused unit tests for success/error/header mappings.
- Run
npm run checkand 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.woff2loads fromstatic/fontswith 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.mdwithout 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;
429honorsRetry-Afterwithout 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
getAuthSessionand renders only the server-returned merchant scope. - Logout sends CSRF/origin evidence, clears memory after server revocation, and returns to login.
401from 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.displayNameis 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 showjalaliLabelFaand 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:
PaidandVerifiedare bank-paid while onlyVerifiedis 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-Afterand 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_PAIDview/fields are requested and rendered. Paidis 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, andOTHER_OBSERVEDfilters are available. NoAttemptandInBankcopy 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.
PaidorVerifiedeventual 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.mdbefore 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.displayNameand 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.mdchangelog. - 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.