5.1 KiB
5.1 KiB
Merchant Dashboard Capability Spec
- Status: Draft — not approved for implementation
- Capability: Merchant dashboard
- Last updated: 2026-08-20
Objective
Give a non-technical merchant a fast, trustworthy Persian RTL view of payment performance, problems, opportunities, and anonymized peer context, with every claim traceable to deterministic metrics.
Actors
- Demo merchant user: signs in with assigned username/password and sees one merchant.
- Merchant user: same MVP permissions; broader roles are out of scope until specified.
- Judge/operator: can use different seeded merchant accounts but receives no hidden cross-tenant browser privilege.
Functional requirements
- Login establishes a secure backend session and returns a generic failure for invalid credentials.
- The app shell identifies the active merchant and offers logout.
- Overview shows data freshness, selected period, primary outcomes, trend, and prioritized deterministic insights.
- Payment performance supports success/failure/retry/timing analysis and traceable drill-downs.
- Peer comparison excludes the active merchant and exposes only eligible anonymized cohort aggregates. It displays a value only when at least 10 other merchants and 1,000 combined peer sessions contribute; otherwise it explains that there is not enough data. This never hides the merchant's own analytics.
- Filters and pagination are reflected in the URL where sharing/reload is useful.
- Every screen implements loading, empty, partial-data, stale, unauthorized, forbidden, and recoverable-error behavior as applicable.
- Responsive behavior and component contracts follow
DESIGN.md. - Merchant-facing dates use the Jalali calendar in
Asia/Tehran; API instants remain explicit ISO-8601 UTC and filtering sends unambiguous boundaries. - Approved reporting periods are daily, weekly, Jalali-month, and Persian-season views. Weekly periods run Saturday through Friday in
Asia/Tehran. Every comparison states its exact period and baseline. - Only source session status
Verifiedcounts as a confirmed successful payment.Paidappears as a separate operational state until an approved metric-catalogue revision defines it otherwise. - The first relevant dashboard access starts all approved analytics-section jobs in bounded parallel. The app opens an authenticated, merchant-scoped SSE stream and renders each section as soon as its
readyevent arrives. A failed section has its own retry/error state and does not hide successful siblings. - Later equivalent requests reuse current high-TTL Redis entries. PostgreSQL merchant/cohort revision changes select new cache keys and cause only missing sections to be recalculated; cache age alone does not make static data stale.
- SSE reconnect uses stable event ids/resume semantics, shows a connection-recovery state, and never exposes job status or analytics for another merchant.
Frontend architecture baseline
- SvelteKit 2 + Svelte 5 runes + strict TypeScript + Tailwind CSS v4.
- Static/client-rendered application behind Nginx, consuming the Go API under the same origin where practical.
- Route groups separate authentication and authenticated application layouts.
- Server state belongs to a typed API layer; local UI state uses the smallest appropriate Svelte primitive/context.
- No SvelteKit server endpoints, database access, or private secrets in the frontend baseline.
- API types should be generated from the approved interface description.
Acceptance criteria
- A user can authenticate as at least two distinct seeded merchants and each dashboard shows different, correctly isolated data.
- Direct URL/API manipulation cannot expose another merchant's details.
- Critical flows work at 360 px, 768 px, 1024 px, and a wide desktop viewport in RTL.
- Login, navigation drawer, filters, chart alternatives, and logout are keyboard complete and screen-reader understandable.
- Values visibly specify period and unit; missing/suppressed/zero states are distinct.
- Confirmed-success views include only
Verified;Paidis separately labeled and testable. - All core sections begin on first access and become visible independently in completion order without blocking the whole dashboard.
- A second equivalent access reuses current Redis entries, and concurrent first accesses do not enqueue duplicate equivalent section jobs.
- One section failure is isolated, retryable, and accessible; already-ready sections remain usable.
- Disconnecting and reconnecting the SSE stream resumes safely without cross-merchant data or duplicated final sections.
- Daily, weekly, Jalali-month, and Persian-season filters use the same explicit boundaries as the API and database.
- Production build passes type checking, linting, unit/component tests, and Playwright critical-flow tests.
- No raw dataset record, payer-card key, credential, or AvalAI key enters client bundles/logging/storage.
Unresolved dependencies
- Approved analytics metric catalogue and cohort suppression policy
- Approved authentication/session API
- OpenAPI/interface contract and error format
- Decisions listed in
DESIGN.md - Static adapter fallback/routing behavior under the final Nginx configuration