Files
zarinpal-analytics-frontend/tasks/plan.md

26 KiB
Raw Blame History

Phase 2 Implementation Plan — Merchant Analytics Dashboard

  • Status: Draft for human review
  • SDD phase: 2 — Plan
  • Capability: Merchant dashboard
  • Implementation authorization: Not granted
  • Task-list target after approval: tasks/todo.md
  • Last updated: 2026-08-20

1. Outcome

Build the approved Persian RTL merchant analytics dashboard as a statically built SvelteKit application behind Nginx. The browser authenticates with the backend-owned server session, consumes the same-origin merchant API, renders the four analytics sections independently through snapshot/SSE delivery, provides safe merchant-owned detail views and CSV export, and meets the approved responsive, theme, privacy, and WCAG 2.2 AA contracts.

This plan does not authorize scaffolding, dependency installation, Svelte components, API code, or deployment changes. After approval, SDD Phase 3 converts each work package into small tasks with explicit acceptance criteria, verification, dependencies, and no more than approximately five files per task.

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 Draft Proposed REST/SSE/CSV behavior; cannot yet authorize implementation
Backend docs/openapi.yaml 0.1.0-draft Draft Proposed generated types and operation contracts
Nginx/static routing contract Unresolved Required before production/static-host verification

3. Planning assumptions

  1. The user's “okay” approves the product and UX specifications for implementation planning, not implementation itself.
  2. The dashboard remains one frontend capability; authentication, analytics calculation, and deployment stay provider capabilities in their existing repositories.
  3. The frontend uses SvelteKit 2, Svelte 5 runes, strict TypeScript, Tailwind CSS v4 through the Vite plugin, and @sveltejs/adapter-static with an Nginx-compatible fallback.
  4. The application is authenticated and client-rendered; it has no SEO requirement, database access, SvelteKit server endpoints, browser-held credentials, or private server secrets.
  5. API DTOs are generated from an approved OpenAPI artifact. The frontend may add view models but does not hand-copy transport schemas.
  6. The same origin serves the static panel and /api/v1; the server session cookie remains unreadable to JavaScript while the approved CSRF value from the session summary remains in memory only.
  7. Exact dependency versions and the package-manager lockfile are selected and committed in the scaffold task after verifying current official documentation.
  8. No work package depending on the API begins until API-SPEC.md and openapi.yaml lose draft status or an explicitly approved version is identified.

If any assumption is rejected, revise this plan before generating Phase 3 tasks.

4. Entry gates

Implementation cannot start until all items in Gate A are approved. Foundation work cannot be called complete until Gate B passes.

Gate A — contract approval

  • Approve or revise the backend draft API/OpenAPI contract and assign a stable version/checksum.
  • Resolve the five API product questions: CSV limits, BOM/headers, audit retention, terminal-id presentation, and production Problem Details base URI.
  • Reconcile the UX export states with synchronous CSV delivery and error handling.
  • Confirm Nginx fallback behavior for deep links and the same-origin /api/v1 proxy.
  • Confirm merchant.displayName from AuthSession is the shell/export display authority.
  • Confirm whether visible chart-data tables are sufficient or chart-data downloads are also required.

Gate B — scaffold verification

  • Exact Node/npm and package versions are pinned in committed manifests/lockfile.
  • Static build, deep-link refresh, global CSS, tracked font loading, and both themes work in the target Nginx topology.
  • Formatting, lint, svelte-check, unit/component test, Playwright, and production-build commands exist and pass on the empty shell.
  • OpenAPI validation/type generation is reproducible and fails CI on drift.

5. Architecture

5.1 Runtime boundary

Browser
  ├─ static SvelteKit application
  ├─ presentation-only local theme choice
  ├─ in-memory session summary / CSRF value
  └─ generated typed API client
       │ same-origin cookie requests
       ▼
Nginx
  ├─ static files + SPA fallback
  └─ /api/v1 proxy
       ▼
Go merchant API
  ├─ server session / tenant authority
  ├─ periods, run snapshots, SSE, retry
  ├─ merchant-owned detail JSON / CSV
  └─ approved aggregate peer results only

The frontend never accepts a merchant id as authorization input. merchantId may be rendered only as an opaque technical value if the approved screen needs it; it never selects scope.

5.2 Proposed source structure

The final scaffold may adjust filenames, but responsibility boundaries remain:

src/
  app.css                         global Tailwind import, semantic tokens, font face
  app.html                        Persian language/direction and pre-paint theme hook
  lib/
    api/
      generated/                  generated OpenAPI transport types only
      client.ts                   same-origin request, Problem Details, CSRF policy
      analytics-stream.ts         approved SSE transport/recovery adapter
    components/
      ui/                         small semantic primitives
      layout/                     app shell, header, sidebar/drawer, status region
      analytics/                  shared metric/chart/table/state presentation
      auth/                       login/session presentation
      details/                    merchant-owned detail and export presentation
    features/
      auth/                       session orchestration
      periods/                    allowlisted period URL state
      analytics-run/              run/section state reducer and event reconciliation
      overview/
      payment-performance/
      fees/
      peer-comparison/
      session-details/
      export/
    format/                       Persian digits, Jalali/Tehran, Rial, percent, bidi
    testing/                      contract-safe fixtures/builders
  routes/
    (auth)/login/
    (app)/dashboard/
    (app)/payments/
    (app)/payments/unverified/
    (app)/payments/failed/
    (app)/payments/retried/
    (app)/fees/
    (app)/peers/
    (app)/methodology/
    (app)/account/
tests/
  e2e/                            critical user and recovery flows
static/fonts/                     tracked approved font and license

Route groups share authentication/layout requirements without changing public URLs. Pages orchestrate; feature modules own business-facing state; reusable components remain presentation-focused.

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

Ready section content remains immutable for a run revision. Event reconciliation is idempotent by event and section identity. A sibling event cannot erase a valid ready section.

5.4 API and error handling

  • One generated client boundary maps successful transport schemas and RFC 9457 Problem responses.
  • UI decisions use stable code, HTTP status, and allowlisted field reasons; they never parse backend title or detail prose.
  • 401 UNAUTHENTICATED clears authorized UI state and returns to login with the approved generic message.
  • 404 RESOURCE_NOT_FOUND does not distinguish absent from cross-tenant resources.
  • 429/retryable 503 honor Retry-After; no tight retry loop exists.
  • Mutations add the in-memory session-bound CSRF token and same-origin evidence through one policy boundary.
  • Decimal strings remain exact until formatting; money/counts remain integers and are never converted to Toman.

5.5 SSE transport decision spike

Resolve before the analytics UI slice:

  1. Test native EventSource with same-origin cookies, named heartbeat events, browser-managed Last-Event-ID, session termination, and server replay/reset behavior.
  2. Verify whether native error opacity prevents typed handling of 429 CONNECTION_LIMIT_REACHED, Retry-After, and non-SSE Problem responses.
  3. Compare a small fetch-stream adapter only if required for approved status/header handling; do not introduce an SSE library without evidence.
  4. Select one transport and document reconnect ownership, heartbeat watchdog, backoff, cleanup, and duplicate-event handling.

The selected approach must preserve ready sections and must not create parallel reconnect loops on top of browser behavior.

5.6 CSV delivery decision spike

The draft API proposes synchronous CSV up to 100,000 rows/50 MiB. Before implementation:

  1. Compare direct browser navigation/download with authenticated fetch plus Blob/object URL.
  2. Verify handling of Problem Details before bytes, 413 EXPORT_TOO_LARGE, 429 Retry-After, 504 EXPORT_TIMEOUT, interrupted streams, and session expiry.
  3. Measure memory and mobile behavior at the proposed cap.
  4. Amend UX copy/state if synchronous delivery cannot truthfully expose separate “generating” and “ready” states.

Do not assemble CSV from paginated browser data. The export always comes from the authorized server endpoint.

5.7 Charts

Start with semantic HTML/SVG and visible table alternatives for the limited approved chart set. A chart dependency is added only if an early spike demonstrates a material accessibility, RTL, interaction, or delivery advantage over focused internal chart components.

Any option must support:

  • Direct labels, keyboard-equivalent values, Persian digits, Rial/percent units, and a semantic table.
  • Stable SSR/static build behavior, though analytics content is client-delivered.
  • Semantic light/dark tokens, non-color cues, and reduced motion.
  • No peer rows, hidden payer data, 3D charts, or inaccessible canvas-only output.

6. Dependency graph and build order

Approved API/OpenAPI + Nginx decisions
  │
  ├─ scaffold + quality commands
  │    ├─ design/theme/font foundation
  │    ├─ generated types + API client
  │    └─ contract-safe fixture/test harness
  │
  ├─ authentication/session vertical slice
  │    └─ authenticated app shell
  │
  ├─ reporting periods + URL state
  │    └─ analytics start/snapshot
  │         └─ SSE spike + run state model
  │              ├─ overview slice
  │              ├─ payment-performance slice
  │              ├─ fees slice
  │              └─ peer-comparison slice
  │                   └─ full partial-delivery recovery checkpoint
  │
  ├─ shared detail query/table foundation
  │    ├─ unverified-paid slice
  │    ├─ failed slice
  │    └─ retried slice
  │         └─ CSV spike + export slice
  │
  └─ methodology/account completion
       └─ responsive/theme/accessibility/security hardening
            └─ static production acceptance

Foundation dependencies are sequential. Once the run state and fixture contracts are stable, independent section presentations can be developed concurrently in isolated feature files, but integration and accessibility checkpoints remain shared gates.

7. Planned work packages

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

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
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
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

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

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

8. Vertical acceptance slices

Each implementation slice must end with user-visible behavior, a mocked/real contract path, focused tests, and the standing Definition of Done.

Slice A — authenticate and identify merchant

User can log in, see the server-returned merchant.displayName, refresh the authenticated shell, log out, and receive safe expired/throttled states. No token or tenant switch enters browser storage/URLs.

Slice B — choose an approved reporting period

User sees the server-selected latest complete Jalali month, changes among allowlisted periods, retains URL-backed state, and never submits arbitrary boundaries.

Slice C — receive the overview independently

User starts one idempotent run, sees stable four-section scaffolding, receives overview without waiting for siblings, and can interpret exact values/comparisons/insight eligibility accessibly.

Slice D — complete partial analytics

Each canonical section becomes independently useful. Failed/suppressed/rate-limited/reconnecting states preserve ready siblings and recover according to the approved transport contract.

Slice E — reconcile merchant-owned evidence

User opens each approved detail view, pages with an opaque cursor, sees only approved merchant-owned fields, and cannot broaden scope through URL/cursor changes.

Slice F — export for handoff

User confirms view/period/filter scope and downloads the synchronous server-owned CSV or receives a truthful typed error. No payer, peer, credential, or hidden browser row is exported.

9. Verification strategy

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

No task is complete with only typecheck/build evidence; runtime behavior and relevant error paths must be exercised.

10. Checkpoints

Checkpoint 1 — contract and scaffold

  • Gate A and Gate B pass.
  • No draft interface is embedded in generated code.
  • The empty shell builds and runs through the target static topology.

Checkpoint 2 — identity and period

  • Two fixture/demo users remain tenant-isolated.
  • Login/session/logout and period URL flows pass keyboard and error-state checks.
  • Persian formatting/theme/font foundations pass both themes.

Checkpoint 3 — first vertical analytics slice

  • Idempotent start plus overview snapshot/SSE works end to end.
  • Stable section scaffolding and restrained status announcements are verified.
  • Review the chosen SSE transport before building remaining sections.

Checkpoint 4 — all analytics sections

  • All four ready states, peer suppression, one-section failure, retry, rate limit, replay/reset, and heartbeat recovery pass.
  • Metric semantics reconcile with the catalogue fixtures.
  • Human review confirms chart/table legibility in RTL/light/dark.

Checkpoint 5 — details and export

  • Three detail views reconcile to aggregates and resist cursor/filter/tenant manipulation.
  • CSV strategy passes cap/error/interruption/privacy checks.
  • Finance/legal handoff copy and behavior receive product approval.

Checkpoint 6 — release candidate

  • Full Definition of Done, acceptance matrix, static Nginx verification, and human review pass.
  • No deployment or release occurs without separate authorization.

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

12. Parallelization after foundation

Safe after P13 stabilizes:

  • Overview, payment-performance, fees, and peer presentation against frozen fixtures.
  • Methodology copy and account presentation.
  • Independent component/accessibility tests for already-defined primitives.

Sequential or coordinated:

  • API approval → type generation → client/state work.
  • Static topology → scaffold/config.
  • Auth/session → protected routes and all merchant data.
  • Period selection → analytics run.
  • SSE spike → run reconciliation → recovery integration.
  • Detail foundation → three detail slices → export.
  • Shared design tokens, formatters, generated files, and route layouts require one owner at a time.

13. Definition of Done

Every Phase 3 task must satisfy its acceptance criteria and the standing project bar:

  • Runtime behavior and error paths are verified; new tests fail without the change and pass with it.
  • Existing checks pass: formatting, lint, strict typing/svelte-check, focused tests, and applicable build/E2E.
  • Code stays scoped, intent-revealing, free of duplication/debug/dead code, and within approved design/API contracts.
  • Accessibility, responsive RTL, light/dark, reduced-motion, security, and privacy implications are checked in proportion to the change.
  • Public behavior/interfaces and durable decisions are documented.
  • The increment is an atomic Commitizen-style commit with no secrets or generated/build debris.
  • Human review occurs at named checkpoints and before merge/deploy.

14. Phase 3 output after approval

After this plan is approved, create tasks/todo.md with one task per focused session. Each task will include:

  • One short outcome-focused title without combined independent concerns.
  • At most three testable acceptance criteria.
  • Focused tests, build/runtime verification, and manual check where needed.
  • Explicit dependency ids and likely files.
  • Estimated XS/S/M scope, normally no more than five files.
  • Checkpoints matching section 10.

No Phase 3 task may say merely “build the dashboard” or combine a foundation layer with multiple unrelated screens.

15. Decisions required to approve this plan

  1. Approve the overall build order and the hard rule that no implementation consumes openapi.yaml while its version remains 0.1.0-draft.
  2. Approve the draft API CSV defaults or send revisions: synchronous delivery; 100,000 rows; 50 MiB; 60 seconds; 3 requests/10 minutes with burst 1; UTF-8 BOM; ASCII snake_case headers.
  3. Choose analytics/export audit retention for the hackathon. Recommendation: 30 days to match demo-auth retention unless finance/legal policy requires longer.
  4. Approve showing/exporting the existing opaque terminal reference, or require a separate display alias.
  5. Supply the production Problem Details base URI and approve the Nginx deep-link/API proxy behavior.
  6. Approve merchant.displayName as the merchant name used throughout the shell and CSV preflight.
  7. Approve the risk-spike approach for SSE, CSV delivery, and chart implementation before committing those dependencies/patterns.

16. Official implementation references