28 open questions in this doc
- L7 — How to read this document: SellVia's docs record decisions chronologically, with later "Update" sections superseding earlier text in the same file. This list reflects the latest resolved state as of the most recent updates (through 2026-08-23), not the origina…
- L60 — Edge cases: Application-rejected notification content unspecified (open question — Needs clarification); real-time vs. digest cadence for "sale made" unspecified (Needs clarification); exact merchant "milestone reached" thresholds undefined (Needs clarificatio…
- L91 — Creator↔Offer matching | Ranks offer discovery results by embedding similarity on top of existing category/commission filters | Creator discovery/browse screen | Post-MVP per some docs, but described as an "initial AI level" item elsewhere — Needs clarificatio…
- L94 — Disclosure nudge | Fixed, legally-reviewed FTC-style disclosure template shown at link-generation time | Creator "Get Link" moment | Deliberately templated, NOT LLM-generated (legal text) — Pakistan-specific disclosure norms not yet reviewed, Needs clarificati…
- L107 — Expected frontend behavior: Nav: logo left, links center/right ("How It Works," "For Businesses," "For Creators"), single "Join Waitlist" CTA — no dropdowns, no mega menus. Zeroed-metric device persists into early product messaging. Copy should reflect Pakista…
SellVia — Frontend Feature List
Purpose
Every product feature the frontend needs to support, derived exclusively from the documentation in /Docs. Grouped by product area. Each feature lists: description, user goal, main actions, expected frontend behavior, important states, relevant screens (see SCREEN_INVENTORY.md), backend/API dependencies, permissions, edge cases, and source docs.
How to read this document: SellVia's docs record decisions chronologically, with later "Update" sections superseding earlier text in the same file. This list reflects the latest resolved state as of the most recent updates (through 2026-08-23), not the original/superseded framing. Where a doc contains stale, unresolved, or contradictory statements, this is marked "Needs clarification" rather than guessed at. See SITE_MAP.md and SCREEN_INVENTORY.md for the navigation and screen-level counterparts to this list.
Critical context for every feature below (updated 2026-08-23):
- Market: Pakistan-only, PKR only. Every Merchant is a Pakistani business. No USD/EUR/GBP for MVP.
- Payment processor: Swich (swichnow.io), confirmed 2026-08-23. Merchant billing runs through Swich's recurring billing/invoice-link product; creator payout runs through Swich's disbursement API (bank, JazzCash, EasyPaisa, Raast). There is no embedded Paddle Checkout anywhere in the frontend, and no manual admin-run bank-transfer workflow either — both legs are Swich-integrated, webhook-confirmed. Swich is a payment processor, not a Merchant of Record — SellVia keeps its own tax responsibility (see Payments/Tax Considerations). Swich's exact API shapes/pricing/onboarding requirements are unconfirmed pending real integration — every Swich-specific field/flow below is a working draft.
- Merchant integration: Shopify only, via native webhook. Every MVP merchant connects a Shopify store (OAuth/app-install); Shopify's
orders/paidwebhook reports sales, not a copy-paste JS snippet. The customer still buys on the merchant's own (Shopify) checkout — SellVia has never hosted checkout for this model, unrelated to this change. - No separate Campaign entity. "Offer is offer, it is not turning into any campaign at all." An Offer carries its commission rate and lifecycle status (draft/live/paused/ended) directly — one creation flow, not a two-step Offer-then-Campaign wrap. Applications, AffiliateLinks, and Sales attach to an Offer.
Full reasoning for all four: Technical Architecture/Architecture Decision Log, Product Foundation/MVP Scope. Auth provider is Ory Kratos (switched from Clerk 2026-08-04) — unaffected by this revision.
0. Cross-Cutting Platform Features
These apply across every module rather than belonging to one screen.
0.1 Unified Authentication (Sign Up / Log In / Session)
- Description: Single sign-up form; user selects Merchant or Creator role (a user may hold both roles on one account). Auth handled by Ory Kratos.
- User goal: Get into the product with minimal friction, on the correct role-specific path.
- Main user actions: Register (email/password, optionally social login — provider TBD), verify email, log in, log out, log out of all other devices, reset password.
- Expected frontend behavior: Ory Kratos SDK/components drive the sign-in/sign-up/session UI. Role selection branches the post-signup flow (Merchant onboarding vs. Creator onboarding). Session is server-validated (not a cached JWT) — sensitive actions re-verify live.
- Important states: loading (session check), unauthenticated, authenticated (role-resolved), email-unverified (gated), error (invalid credentials, account locked), MFA-challenge (if enabled).
- Relevant screens: Login, Register, Forgot/Reset Password, Verify Email, MFA setup/challenge.
- API/backend dependencies: Ory Kratos REST API (session issuance, verification, password reset, email verification); backend resolves role(s) from Kratos identity
traits, never trusts a client-supplied role. - Permissions/roles: N/A (pre-role-gating layer); role is attached to session after auth.
- Edge cases: Session expires at 14-day ceiling forcing re-login; 5 concurrent sessions per account (Admin may need a higher cap — unresolved); instant revocation on password change, Admin suspension, or IP-anomaly ban escalation.
- Source: Security/Authentication, Security/Session Management, API/API Authentication, Business Logic/User Roles.
0.2 Dual-Role Context Switching
- Description: A single account can be both Merchant and Creator. Each role has its own separate profile, data, and nav.
- User goal: Operate as either "hat" without the two experiences bleeding together.
- Main user actions: Switch active context (Merchant ↔ Creator).
- Expected frontend behavior: Explicit role switcher (mechanism not yet designed in docs) rather than a merged nav — Merchant nav (Offers/Applications/Sales/Payouts) and Creator nav (Discover/My Links/Earnings) never combine into one menu.
- Important states: active-context indicator; empty state if the user hasn't set up the other role yet.
- Relevant screens: Present in the global app shell/header of both dashboards.
- API/backend dependencies: Role(s) resolved server-side per request; a Merchant-context request never leaks Creator-context data and vice versa (tested explicitly per Cross-Tenant Isolation Testing).
- Permissions/roles: Merchant, Creator (same user, two contexts).
- Edge cases: Self-dealing block — a dual-role user's CreatorProfile can never apply to an Offer owned by their own MerchantProfile (hard-blocked server-side, not just hidden in UI).
- Source: Business Logic/User Roles, UX/Navigation, Edge Cases/User Edge Cases, Business Logic/Business Rules.
0.3 Notifications
- Description: In-app + email notifications for key lifecycle events, kept quiet/informational (no gamification, per design philosophy).
- User goal: Know when something requiring attention or worth celebrating has happened, without checking manually.
- Main user actions: View notification feed, mark as read, click through to the relevant screen.
- Expected frontend behavior: Real-time or near-real-time delivery for high-trust moments (e.g., application approved → link issued) — this is one of the product's "trust moments" and should not feel delayed/black-box. Quiet visual treatment (no confetti/badges).
- Important states: unread/read, empty ("no notifications yet"), loading.
- Relevant screens: Notification center/feed (shared component across Merchant/Creator/Admin shells).
- API/backend dependencies:
notificationstable; triggers per Notification Logic; async job completion also notifies (job_completed). - Permissions/roles: Scoped to the recipient
user_idonly. - Edge cases: Application-rejected notification content unspecified (open question — Needs clarification); real-time vs. digest cadence for "sale made" unspecified (Needs clarification); exact merchant "milestone reached" thresholds undefined (Needs clarification).
- Source: Business Logic/Notification Logic, Technical Architecture/Async Job Pattern & Idempotency, UX/Interaction Patterns.
0.4 Empty / Loading / Error States (Design System Requirement)
- Description: A calm, intentional empty-state pattern reused throughout the product, echoing the public site's own "0 creators, 0 sales, ₨0" zeroed-dashboard honesty device.
- User goal: Never mistake "nothing here yet" for "something is broken."
- Expected frontend behavior: Empty states read as expected/calm, not broken (e.g., "link generated, zero clicks yet"). Loading states are simple fades/skeletons, never playful spinner copy (restrained-animation design rule). Errors are specific and actionable ("You've already applied to this offer," never "Something went wrong").
- Relevant screens: Every list/table view across the app (offers, applications, sales, payouts, links).
- API/backend dependencies: Structured error shape
{ "error": { "code", "message", "status" } }from every endpoint; two-layer error handling (safe message to user, full detail to private log) — no raw stack traces ever reach the UI. - Source: UX/Components, UX/Copy Guidelines, API/Error Responses, Infrastructure/Error Handling & Logging Pipeline.
0.5 Accessibility (Binding, Not Aspirational)
- Description: Full keyboard navigation, screen-reader compatibility, and verified WCAG AA color contrast across the entire product — explicitly called out as enforced pre-launch gates, not nice-to-haves.
- Expected frontend behavior: Logical tab order; visible focus rings (lime accent, consistent with the design system's "active state" use of lime); all custom interactive components (offer discovery filters, the "Get Link" component, status badges with actions) independently verified for keyboard operability — shadcn/ui defaults aren't assumed sufficient; all form fields have real associated labels (no placeholder-only labels);
aria-describedby/aria-invalidon validation errors; all meaningful images have alt text (including product images — schema currently lacks an alt-text field, flagged as a gap); icon-only controls getaria-label; async status changes usearia-live. - Contrast status — RESOLVED 2026-08-23: Lime (#BFFF13) and Gray 01 (#A1A1AA) both verified compliant against black (17.5:1 and 8.2:1). Gray 02 was the actual failure at 4.35:1 — corrected to #787882 (4.82:1). See UX/Accessibility for the full computed table. No longer an open risk.
- Source: UX/Accessibility, Security/Security Checklist.
0.6 Machine-Readability of Public Content (SEO / AI-Agent Legibility)
- Description: Public Offer pages carry
schema.orgProduct/OfferJSON-LD; semantic HTML landmarks; OpenAPI spec auto-generated from the backend;llms.txtat the marketing site root; deliberaterobots.txtallowing known AI crawlers on public pages only. - User goal (indirect): Let AI shopping agents, search AI answers, and link-preview tools understand SellVia's public offers correctly.
- Expected frontend behavior: Every public Offer detail page renders JSON-LD with accurate price/currency (PKR)/availability. Standard OG/Twitter-card/canonical-URL meta tags on all public pages, generated from the base page template.
- What does NOT get this treatment: Authenticated dashboards, any tenant-private data — same boundary as accessibility, but for machines instead of humans.
- Source: UX/AI Agent & Machine Readability.
0.7 AI-Assisted Features
| Feature | What it does | User-facing surface | Notes |
|---|---|---|---|
| Creator↔Offer matching | Ranks offer discovery results by embedding similarity on top of existing category/commission filters | Creator discovery/browse screen | Post-MVP per some docs, but described as an "initial AI level" item elsewhere — Needs clarification on MVP vs. post-MVP timing |
| Application screening assist | One LLM-generated plain-language fit summary per application, cached, shown to the reviewing Merchant | Merchant application review screen | Never shown to any other Merchant (tenant-private) |
| Offer copy assist | Merchant provides product name + price (PKR); LLM drafts an editable offer description | Merchant offer creation form | Draft is editable, not final |
| Disclosure nudge | Fixed, legally-reviewed FTC-style disclosure template shown at link-generation time | Creator "Get Link" moment | Deliberately templated, NOT LLM-generated (legal text) — Pakistan-specific disclosure norms not yet reviewed, Needs clarification |
- Source: Technical Architecture/AI Services, Product Foundation/MVP Scope, Security/Tenant Isolation Audit.
1. Public Marketing & Discovery
1.1 Marketing Site (wesellvia.com)
- Description: The existing live public site — hero, concept walkthrough, roadmap-stage visibility, FAQ, waitlist form. Deliberately shows zeroed real metrics ("0 creators approved, 0 sales, ₨0 tracked revenue") as a radical-transparency positioning device, not a placeholder.
- User goal: Understand what SellVia is, see it's early/honest, and join the waitlist.
- Main user actions: Read hero/roadmap/FAQ, submit waitlist form (business or creator, "why do you want to join").
- Expected frontend behavior: Nav: logo left, links center/right ("How It Works," "For Businesses," "For Creators"), single "Join Waitlist" CTA — no dropdowns, no mega menus. Zeroed-metric device persists into early product messaging. Copy should reflect Pakistan-only scope once product messaging catches up to the 2026-08-23 revision — Needs clarification on whether the current live site copy needs an update pass.
- Important states: waitlist form submitted (confirmation), roadmap stage indicator ("you are literally here" — currently Stage 02: Validation).
- Relevant screens: Public Home / Landing.
- API/backend dependencies: Waitlist signup endpoint (implied, not explicitly specified in Endpoint Specifications — Needs clarification).
- Permissions/roles: Public, unauthenticated.
- Edge cases: None documented beyond standard form validation.
- Source: Product Foundation/Product Vision, Product Foundation/Product Roadmap, UX/Design System, UX/Navigation.
1.2 Public Offer Discovery / Browse
- Description: Browsable, filterable list of live offers — the entry point for creators (and, per the AI-agent doc, for machine consumption of public product data).
- User goal: Find an offer/product worth promoting.
- Main user actions: Filter by category (digital/physical), commission-rate range, niche; sort by newest, highest commission, most applications (popularity proxy).
- Expected frontend behavior: No dedicated search engine for MVP — structured DB filtering/sorting only. Public, no auth required to view. All prices/commissions shown in PKR.
- Important states: loading, empty ("no live offers match these filters"), error.
- Relevant screens: Public/Creator Offer Discovery list, Public Offer detail page.
- API/backend dependencies:
GET /offers(public, filterable) — renamed fromGET /campaigns2026-08-23. - Permissions/roles: Public read; apply action requires Creator auth.
- Edge cases: Post-MVP AI-assisted semantic matching layers on top of this same filtering, doesn't replace it.
- Source: Technical Architecture/Search Strategy, API/Endpoint Specifications, Business Logic/User Flows.
1.3 Public Offer Detail Page
- Description: The public page for a single offer/product — name, price (PKR), commission rate, merchant,
schema.orgmarkup. - User goal (creator): Decide whether to apply. User goal (buyer via a shared link): Land here or get redirected onward to the merchant's Shopify product page.
- Main user actions: View details; (creator, authenticated) apply.
- Expected frontend behavior: Carries
Product/OfferJSON-LD. This page is informational/discovery, not a checkout entry point — a shared AffiliateLink resolves throughGET /go/:slug, which redirects to the merchant's own Shopify store, not to this page's checkout (there is none). - Important states: loading, not-found/ended offer.
- Relevant screens: Public Offer detail.
- API/backend dependencies:
GET /affiliate-links/:slug(public),GET /go/:slug(public redirect + click logging). - Permissions/roles: Public.
- Edge cases: Offer ended — clicks after end date attribute nothing; clicks before end date still honored within the 30-day window.
- Source: UX/AI Agent & Machine Readability, API/Endpoint Specifications, Business Logic/State Machines.
2. Onboarding & Account Setup
2.1 Role Selection & Signup Branching
- Description: After the unified signup form, the flow branches based on chosen role(s).
- User goal: Get to the correct next step (Offer creation vs. offer browsing) without extra clicks.
- Main user actions: Choose Merchant, Creator, or both.
- Expected frontend behavior: Minimal-field, low-friction form; contextual hiding of irrelevant fields per role (a digital-goods Merchant never sees a shipping field).
- Relevant screens: Register, Role Selection (may be same screen).
- Edge cases: No follower-count floor for Creator eligibility (merit/fit-based, decided).
- Source: Business Logic/User Flows, Business Logic/User Roles, UX/Interaction Patterns.
2.2 Merchant Onboarding: Swich Billing Connect
- Description: Merchant connects Swich as their billing method before any offer can go live — replaces the Paddle card-on-file step (Paddle removed) and the interim plain-bank-details-form default (superseded same-day by the Swich decision).
- User goal: Get set up so periodic billing cycles have a working way to actually charge them.
- Main user actions: Complete Swich's own onboarding/checkout-connect flow (likely an embedded widget or redirect, exact mechanism unconfirmed pending real Swich integration docs).
- Expected frontend behavior: Gate: an Offer cannot go
draft → liveuntil this is complete. Whether this is an embedded Swich widget (like the old Paddle Checkout iframe) or a redirect flow is Needs clarification — Swich's actual integration pattern isn't confirmed yet. - Important states: not started, connected, payment-failed (Swich-reported reason + prompt to update payment method).
- Relevant screens: Merchant Billing Setup / Settings.
- API/backend dependencies:
merchant_profiles.swich_customer_id(new 2026-08-23, replacing bothpaddle_customer_idand the interimbank_account_*fields). - Permissions/roles: Merchant only, own account.
- Edge cases: Needs clarification — the exact retry/escalation policy for a failed billing-cycle charge (the old "3 failed Paddle billing attempts over 3 days" rule needs re-mapping against Swich's own failure-webhook behavior, not yet done). Flagged in MVP Scope's Still-Open Items.
- Source: Product Foundation/MVP Scope, Business Logic/State Machines, Database/Table Specifications, Payments/Money Flow, Payments/Payment Flow.
2.3 Merchant Onboarding: Shopify Store Connect
- Description: Merchant connects their Shopify store via OAuth/app-install — this is what reports sales back to SellVia. Replaces the universal tracking-snippet install entirely (Shopify-only for MVP).
- User goal: Get attribution working so sales are tracked and commissions calculated.
- Main user actions: Click "Connect Shopify Store," authorize the SellVia app in their Shopify admin, confirm the webhook is active.
- Expected frontend behavior: Offer cannot go
draft → liveuntil SellVia verifies the Shopify webhook is registered and active. Also: creating a unique discount code in the merchant's Shopify discount system during offer setup (fallback attribution signal, unchanged in concept from before). This is a simpler frontend step than the old snippet flow — no code to copy-paste, just an OAuth redirect and a confirmation state. - Important states: not connected, connecting (mid-OAuth), connected/verified, connection-failed (with troubleshooting copy — e.g. wrong store, permissions declined).
- Relevant screens: Merchant Offer Setup (Shopify connect step), possibly a dedicated onboarding screen.
- API/backend dependencies: Shopify OAuth flow;
POST /webhooks/shopify-sales(renamed fromPOST /webhooks/merchant-sales2026-08-23). - Permissions/roles: Merchant only, own offers.
- Edge cases: Exact Shopify app-install path (public Shopify App Store listing vs. a private/custom app SellVia distributes directly) is explicitly undesigned — Needs clarification, flagged in MVP Scope's Still-Open Items.
- Source: Payments/Payment Flow, Payments/Money Flow, Business Logic/State Machines, Technical Architecture/Frontend Architecture.
2.4 Creator Onboarding: Swich Payout Setup
- Description: Creator registers as a Swich payout recipient (payee) to receive commission — replaces Paddle seller onboarding entirely, and supersedes the interim plain-bank-details-form default from earlier the same day.
- User goal: Be able to actually get paid once commissions accrue.
- Main user actions: Complete Swich's payee-registration flow — select payout method (bank account, JazzCash, or EasyPaisa) and provide the corresponding details.
- Expected frontend behavior: A Creator approved for an offer but with incomplete Swich payee registration must not get an active AffiliateLink yet — block link activation entirely rather than accruing unpayable commission (unchanged principle from the Paddle-era design). Offering a choice of payout method (not just bank account) is new relative to the interim default, and is a real UX improvement — most Pakistani creators are more likely to have JazzCash/EasyPaisa than a bank IBAN handy.
- Important states: not started, complete, incomplete-blocking-link.
- Relevant screens: Creator Payout Setup / Settings.
- API/backend dependencies:
creator_profiles.swich_payee_id,creator_profiles.payout_method(new 2026-08-23, replacingpaddle_seller_idand the interimbank_account_*fields). - Permissions/roles: Creator only, own account.
- Edge cases: Onboarding-incomplete gate is resolved as hard-block (unchanged). Whether any Pakistani-tax-equivalent form (an FBR-relevant declaration, if any) is collected here is Needs clarification — Swich, like the bank-transfer default before it, is not confirmed to auto-collect this the way Paddle's onboarding did (Swich is a processor, not a Merchant of Record — see Payments/Tax Considerations).
- Source: Edge Cases/User Edge Cases, Technical Architecture/Backend Architecture, Payments/Tax Considerations, Payments/Payout Process.
3. Merchant Module
3.1 Offer Creation & Management (merged with the former "Campaign" concept)
- Description: A Merchant's product listing and its commission-bearing, applicable listing, in one entity — name, price (PKR), category (digital/physical), commission rate, lifecycle status. There is no separate step to "wrap" a product in a campaign; setting the commission rate and publishing are part of the same creation flow.
- User goal: List a product with a commission attached and get it in front of creators, in one pass.
- Main user actions: Create Offer (name, price, category, commission rate), edit Offer, publish (
draft → live), pause, resume, end, archive/soft-delete. - Expected frontend behavior: Minimal required fields; category selection hides irrelevant fields (e.g., no shipping field for digital). No multi-page wizard, and — since Offer absorbed Campaign — one fewer step than the original two-entity design (create Offer, then separately create a Campaign around it).
draft → liveblocked until both gates pass: bank settlement setup complete (§2.2) AND Shopify store connected & verified (§2.3). Editing commission rate mid-flight does not require re-consent from already-approved creators (they keep their locked rate, per approval-time locking); new applicants see the new rate. - Important states: draft, live, paused, ended; empty ("no offers yet"); loading; error; success (created); each gate's pass/fail state visible before publish is attempted.
- Relevant screens: Offers list, Create/Edit Offer, Offer detail.
- API/backend dependencies:
GET /offers,POST /offers,PATCH /offers/:id,PATCH /offers/:id/status(all renamed from/campaigns/...2026-08-23). - Permissions/roles: Merchant (own offers only); Admin (any, for moderation/vetting override).
- Edge cases: Paused offers keep honoring in-flight attribution within the 30-day window, accept no new applications; ended offers stop attributing new clicks immediately but honor pre-end clicks within the window; high-commission/high-risk offers require Admin vetting before going live (thresholds undefined — Needs clarification); product image auto-fetch from a URL is a deferred v2 convenience — manual upload only for MVP.
- Source: Business Logic/Domain Model, Business Logic/State Machines, Business Logic/Business Rules, Database/Table Specifications, Technical Architecture/File Storage, Operations/Admin Panel.
3.2 (Retired — merged into §3.1, 2026-08-23)
The former "Offer Management" and "Campaign Creation & Management" were two separate sections describing a two-entity model. As of the 2026-08-23 revision there is one entity (Offer) and one section (§3.1) — this number is intentionally left as a pointer rather than reused, so cross-references elsewhere in the docs that still say "§3.2" resolve here.
3.3 Application Review
- Description: Merchant reviews creator applications to their offers and approves/rejects.
- User goal: Choose the right creators for the offer.
- Main user actions: View applicant's audience/niche/engagement data (+ AI-generated fit summary), approve, reject.
- Expected frontend behavior: Approval immediately surfaces the generated AffiliateLink to the Creator (real-time-feeling, not delayed-email-only) — described as one of the product's core "trust moments."
- Important states: pending, approved, rejected; empty ("no applications yet"); pending-count indicator.
- Relevant screens: Applications list (per offer), Application review card/detail.
- API/backend dependencies:
POST /offers/:id/applications(creator-initiated),GET /offers/:id/applications,PATCH /applications/:id(approve/reject, triggers AffiliateLink creation) — all renamed from/campaigns/...2026-08-23. - Permissions/roles: Merchant (own offers only); Admin (moderation override).
- Edge cases: Rejected applicants cannot resurrect the old application, only submit a new one; whether merchants see aggregate creator performance platform-wide or only the applicant's own submitted stats is unresolved (Needs clarification); self-dealing applications blocked server-side before reaching this queue.
- Source: Business Logic/State Machines, Business Logic/Permission Matrix, UX/Components, Business Logic/Business Rules.
3.4 Sales Visibility
- Description: Merchant's view of sales reported and attributed to their offers.
- User goal: See what's selling and confirm commissions are calculating correctly.
- Main user actions: View sale list, filter/sort, view acceptance status.
- Expected frontend behavior: Shows
acceptance_status(accepted/rejected). Amounts in PKR. Never served from cache — always live. - Important states: accepted, rejected (flagged for Admin review, not silently dropped), empty, loading.
- Relevant screens: Sales list (Merchant), Sale detail/receipt.
- API/backend dependencies:
GET /sales(scoped to own). - Permissions/roles: Merchant (own only); Admin (any).
- Edge cases: A merchant under-reporting sales is a fraud vector the external-tracking model introduced — flagged/reconciled at the platform level, not something the merchant UI directly exposes.
- Source: API/Endpoint Specifications, Security/Fraud Prevention, Technical Architecture/Caching Strategy.
3.5 Billing (Periodic Merchant Billing — Swich)
- Description: Merchant's billing-cycle history and Swich billing-method management — a Swich-generated invoice/payment-link per cycle, webhook-confirmed, not a Paddle charge and not a manual admin-tracked bank transfer.
- User goal: Understand what's owed and confirm payment goes through smoothly each cycle.
- Main user actions: View billing cycle history/totals, complete payment through Swich when a cycle closes, update billing method.
- Expected frontend behavior: Monthly billing cycles (unchanged cadence). On a cycle closing, SellVia's backend generates a Swich invoice/payment request for the total owed; the merchant completes it through Swich's checkout (card, bank transfer, JazzCash, or EasyPaisa); a Swich webhook confirms it and the cycle flips to
chargedautomatically — no admin manually checking a bank statement. Retry/escalation policy for a failed charge is not yet fully designed (see §2.2's edge case) — the old "3 failed billing attempts → auto-pause" rule needs re-mapping against Swich's own failure-webhook behavior, which isn't confirmed yet. - Important states: open, pending_charge, charged, failed (with a way to see why, from Swich's reported reason, and what to do).
- Relevant screens: Billing Cycles / Billing History, Billing Settings.
- API/backend dependencies:
GET /billing-cycles(scoped to own, now surfacingswich_invoice_id/swich_payment_reference). - Permissions/roles: Merchant (own only).
- Edge cases: Failed billing accumulates rather than losing sales; creator commission for that cycle stays unpaid until resolved (bill-first-then-pay, unchanged principle).
- Source: Payments/Payment Flow, Payments/Money Flow, Business Logic/State Machines, Database/Table Specifications.
3.6 Refund Credit Request
- Description: Merchant requests a billing credit for a sale that was already tracked/billed/paid out, when their own customer got a refund on the merchant's Shopify store.
- User goal: Not be billed for a sale that was refunded to the end customer.
- Main user actions: Submit a credit request for a specific sale, optionally partial.
- Expected frontend behavior: Capped at 5 credits/calendar month; proportional credit for partial refunds; beyond the cap, no further credit (clear messaging why). Amounts in PKR.
- Important states: credits-remaining-this-month counter, submitted, applied-to-next-cycle, cap-reached (disabled state with explanation).
- Relevant screens: Sale detail (Merchant) → Request Refund Credit action; possibly a dedicated Refund Requests list.
- API/backend dependencies: No explicit endpoint named in Endpoint Specifications — Needs clarification ("UI/API for how a merchant actually submits a credit request — not yet designed").
- Permissions/roles: Merchant (own sales only).
- Edge cases: Creator commission is never clawed back regardless — SellVia absorbs the cost within the cap.
- Source: Payments/Refund Handling, Payments/Money Flow.
3.7 Merchant Profile / Business Settings
- Description: Business name, category, and account-level settings.
- User goal: Keep business info accurate.
- Main user actions: Edit business name/profile fields.
- Relevant screens: Merchant Settings / Business Profile.
- API/backend dependencies:
merchant_profilestable (last-write-wins conflict resolution, not event-sourced). - Permissions/roles: Merchant, own profile only.
- Source: Business Logic/Domain Model, Database/Database Design.
4. Creator Module
4.1 Offer Discovery (Authenticated)
- Description: Same underlying discovery/filter system as the public browse page, in-app for logged-in creators applying.
- User goal: Find offers that fit their audience/niche.
- Main user actions: Filter (category, commission range, niche), sort, apply.
- Expected frontend behavior: Post-MVP: AI similarity ranking layered on top of filters (timing unresolved — Needs clarification).
- Important states: loading, empty, already-applied indicator per offer.
- Relevant screens: Creator Discovery/Browse.
- API/backend dependencies:
GET /offers(public endpoint, same as marketing-site browse, called in an authenticated context here). - Permissions/roles: Creator (apply action); public (browse).
- Source: Business Logic/User Flows, Technical Architecture/Search Strategy.
4.2 Application Submission
- Description: Creator applies to a specific offer, with audience info attached.
- User goal: Get approved to promote a product.
- Main user actions: Submit application (audience snippet — niche, audience size, engagement rate).
- Expected frontend behavior: One application per (offer, creator) pair — duplicate attempt returns a clear 409 error, not a generic failure. Rate-limited per Creator account to prevent spam-applying.
- Important states: submitting, submitted/pending, error (duplicate, self-dealing block, rate-limited).
- Relevant screens: Offer detail (Apply action), My Applications list.
- API/backend dependencies:
POST /offers/:id/applications(renamed from/campaigns/:id/applications2026-08-23). - Permissions/roles: Creator only.
- Edge cases: Self-dealing block (own offer, if dual-role); audience/niche data is self-reported and currently unverifiable (open fraud-implication question).
- Source: Business Logic/Business Rules, Database/Constraints, Security/Rate Limiting, Edge Cases/Creator Edge Cases.
4.3 My Applications
- Description: Creator's view of their own application statuses.
- User goal: Track where each application stands.
- Expected frontend behavior: pending / approved / rejected states clearly shown; whether/how a rejection reason is communicated is unresolved (Needs clarification).
- Relevant screens: My Applications list.
- API/backend dependencies: Scoped read of
applications(no dedicated endpoint explicitly named beyond the offer-scoped one — Needs clarification on a creator-facing "my applications across all offers" endpoint). - Permissions/roles: Creator, own only.
- Source: Business Logic/State Machines, Business Logic/Notification Logic.
4.4 My Links (AffiliateLinks)
- Description: The unique trackable link (+ discount code) issued on approval.
- User goal: Get and share the promotional link/code.
- Main user actions: Copy link, copy discount code, share.
- Expected frontend behavior: The "Get Link" moment should feel like a small, clear payoff, given how central it is to the product's trust story. Disclosure-nudge template shown at this moment (fixed legal text, not AI-generated). Only one link per approved application (no regenerating to obscure attribution).
- Important states: link generated/zero clicks yet (calm empty state, not "broken"), active, offer-ended (link stops attributing new activity).
- Relevant screens: My Links list, Link detail (click/cart/purchase timeline).
- API/backend dependencies:
GET /affiliate-links/:slug(public resolution endpoint); link data scoped to the owning creator for the dashboard view. - Permissions/roles: Creator, own links only.
- Source: UX/Components, Business Logic/Domain Model, Business Logic/Business Rules, Payments/Payment Flow.
4.5 Earnings / Wallet
- Description: Running balance of accrued-but-not-yet-paid-out commission, plus payout history.
- User goal: Know how much they've earned and when they'll get paid.
- Main user actions: View balance, view progress toward the payout threshold, view payout history.
- Expected frontend behavior: Balance only includes commissions whose BillingCycle has reached
charged— pre-billing commission is "owed" but not yet in the spendable/displayed wallet balance. Never cached — always live, computed directly from SellVia's own ledger —wallet_balance_centsis authoritative, not synced from Swich's account balance (Swich is the execution rail that moves the money once a payout is due; it doesn't hold SellVia's ledger). All figures in PKR only — the multi-currency conversion-display concern from the earlier USD/EUR/GBP design no longer applies. - Important states: accruing (below threshold), threshold-crossed (payout pending), processing, paid, failed-retrying.
- Relevant screens: Earnings/Wallet dashboard, Payout history detail.
- API/backend dependencies:
GET /payouts(scoped to own);creator_profiles.wallet_balance_cents. - Permissions/roles: Creator, own only.
- Edge cases: No client-facing "trigger payout" action (fully automatic/threshold-based, though "automatic" now means an admin-actioned bank transfer rather than a processor API call — see §3.5); one-time manual below-threshold payout allowed only on account closure (proposed default); a refund after a creator has already been paid is a real, accepted platform loss, never clawed back from the creator. The $50 payout threshold needs re-specifying in PKR — not yet done, flagged as an open item.
- Source: Payments/Wallet Design, Payments/Payout Process, Business Logic/State Machines, Edge Cases/Payment Edge Cases.
4.6 Creator Profile Settings
- Description: Niche, audience size, engagement rate, and payout account status.
- User goal: Keep profile accurate so merchants can evaluate fit.
- Main user actions: Edit niche/audience info.
- Relevant screens: Creator Settings / Profile.
- API/backend dependencies:
creator_profilestable. - Permissions/roles: Creator, own profile only.
- Edge cases: Whether engagement_rate is self-reported vs. platform-calculated is an open fraud-relevant question — Needs clarification before deciding if this field is editable or read-only/derived.
- Source: Business Logic/Domain Model, Edge Cases/Creator Edge Cases.
5. Admin Module
All Admin screens live under a fully separate /admin/* namespace, never exposed in regular Merchant/Creator navigation. Single flat Admin role for MVP (no tiering).
5.1 Moderation Queue
- Description: Flagged sales/applications/accounts from rules-based fraud detection, awaiting human review.
- User goal (Admin): Resolve flags — clear false positives, act on real fraud.
- Main user actions: Review flag reason (velocity, self-referral, conversion outlier, device fingerprinting, merchant under-reporting pattern), clear or act (suspend, reverse a sale, ban).
- Expected frontend behavior: Every action logged to the Audit Log (who, what, outcome).
- Important states: flagged/unreviewed, cleared, actioned.
- Relevant screens: Moderation Queue, Flagged Item detail.
- API/backend dependencies:
GET /admin/flagged. - Permissions/roles: Admin only.
- Source: Operations/Moderation, Security/Fraud Prevention, Business Logic/Permission Matrix.
5.2 Offer Vetting
- Description: High-commission or high-risk offers awaiting approval before going live.
- User goal: Approve/reject before a risky offer reaches creators.
- Main user actions: Approve, reject.
- Relevant screens: Offer Vetting Queue.
- API/backend dependencies:
POST /admin/offers/:id/vet(renamed from/admin/campaigns/:id/vet2026-08-23). - Permissions/roles: Admin only.
- Edge cases: Exact vetting trigger thresholds undefined — Needs clarification.
- Source: Operations/Admin Panel, Business Logic/Business Rules.
5.3 User Management
- Description: View/suspend Merchant or Creator accounts; view a user's history for support/moderation purposes only.
- Main user actions: View user detail, suspend/ban.
- Expected frontend behavior: Suspension instantly revokes the user's sessions.
- Relevant screens: User Management list, User detail.
- API/backend dependencies:
POST /admin/users/:id/suspend. - Permissions/roles: Admin only.
- Edge cases: No formal appeals process designed yet (handled case-by-case via support) — Needs clarification.
- Source: Operations/Admin Panel, Operations/Moderation, Security/Session Management.
5.4 Refund / Dispute Handling
- Description: Manual refund-credit review. Chargeback-evidence submission (originally scoped for Paddle disputes) needs re-scoping against Swich — Swich is a payment processor with its own dispute-handling process for card transactions specifically, but whether it covers bank-transfer/JazzCash/EasyPaisa-settled amounts the same way a card chargeback would is unconfirmed.
- Main user actions: Approve/deny refund credit requests.
- Important states: SellVia absorbs a merchant's first 5 lost disputes (lifetime counter) — this rule was written for a Paddle-chargeback world; whether it still applies as-is under Swich is Needs clarification.
- Relevant screens: Refund/Dispute Handling queue.
- API/backend dependencies: Not explicitly named in Endpoint Specifications — Needs clarification.
- Permissions/roles: Admin only.
- Edge cases: Who submits any dispute evidence, and to whom (SellVia vs. Swich vs. Swich-on-SellVia's-behalf), is unresolved — Needs clarification.
- Source: Payments/Chargebacks, Payments/Refund Handling, Operations/Admin Panel.
5.5 Reconciliation Review
- Description: Surfaces mismatches between internal records and Swich's own transaction records, for manual investigation. (Previously scoped against Paddle's records; the interim bank-transfer default would have had no processor API to reconcile against at all — Swich restores that.)
- Main user actions: Review flagged mismatch, investigate, resolve.
- Important caveat: Reconciliation can verify the billing/payout legs against Swich's transaction records (once that integration exists), but it can no longer independently confirm the underlying sale happened as reported — that trust still rests entirely on Fraud Prevention's Shopify-webhook-reporting checks, unchanged from the external-tracking model generally.
- Relevant screens: Reconciliation Review queue.
- API/backend dependencies: Endpoint not explicitly named — Needs clarification; likely a scheduled job comparing SellVia's ledger against Swich's transaction-list API once that's integrated.
- Permissions/roles: Admin only.
- Source: Payments/Reconciliation, Operations/Admin Panel.
5.6 Waitlist → Beta Invitation Management
- Description: Manages the Private Beta cohort (currently capped 10–25, manually curated for the first cohort, fully automatic/signup-order after). Now implicitly scoped to Pakistani applicants only, since the market is Pakistan-only for MVP.
- Main user actions: Review waitlist, curate/invite first cohort, monitor automatic invitations thereafter.
- Relevant screens: Waitlist Management.
- Permissions/roles: Admin only.
- Edge cases: Beachhead niche/vertical within Pakistan (beyond the geography resolution itself) still undecided — Needs clarification.
- Source: Product Foundation/Product Roadmap, Operations/Admin Panel.
5.7 At-Risk New Users View
- Description: Accounts that hit the 48-hour churn threshold without completing their core activation action (Merchant: publish first offer; Creator: submit first application).
- User goal: Give the founder/Admin visibility into who's stalling, distinct from the fraud queue.
- Relevant screens: At-Risk Users view (within Admin Panel).
- API/backend dependencies:
activation_nudgestable. - Permissions/roles: Admin only.
- Source: Analytics/Activation, Aha Moment & Churn Signals, Operations/Admin Panel.
5.8 Founder AI Command Console
- Description: Founder-only natural-language interface over the entire Admin surface — every tool wraps an existing, already-permission-checked Admin API endpoint; never raw DB access.
- User goal: Query/act on admin data without navigating multiple screens.
- Main user actions: Ask a question (read, executes directly), issue a write command (requires explicit confirmation, every time, no exceptions), request a product-change spec (drafted only, never auto-executed/deployed).
- Expected frontend behavior: Fail-closed on ambiguity — asks for clarification rather than guessing. Every AI-console action logged with
initiated_via: ai_console. - Important states: answering, awaiting-confirmation (for write actions), executed, clarification-needed.
- Relevant screens: AI Command Console (chat-style interface).
- Permissions/roles: Admin/Founder only.
- Edge cases: Whether this ships MVP or post-MVP is an explicit open call — Needs clarification.
- Source: Operations/Founder AI Command Console, Operations/Live Production Access for Support (Command Console), Database/Audit Log Design.
5.9 Support Tooling (Console-Assisted)
- Description: Ticket context lookup and per-feature playbook retrieval, used by the founder/Admin when handling support requests.
- Main user actions: Pull a user's recent activity in one view, retrieve the relevant support playbook.
- Relevant screens: Likely part of User Management detail or the AI Command Console, not necessarily a separate screen — Needs clarification on whether this needs dedicated UI.
- Permissions/roles: Admin only.
- Source: Operations/Live Production Access for Support (Command Console), Operations/Per-Feature Support Playbooks, Operations/Support Tiers.
5.10 Admin Analytics (Marketplace Health, P&L, Unit Economics)
- Description: Founder/Admin dashboards for marketplace health, funnels, time-to-payout, monthly P&L, unit economics, AI/token cost. All monetary figures in PKR.
- Main user actions: View KPI trends, review the automated monthly P&L report, review per-feature AI cost.
- Important states: finalized vs. draft P&L report (recommend a "finalized" flag so historical reports don't silently change).
- Relevant screens: Admin/Founder Dashboard (marketplace health + funnels), Monthly P&L report, Unit Economics view.
- API/backend dependencies:
monthly_pnl_reports,ai_usage_events,infra_coststables;get_pnl(month)console tool.monthly_pnl_reports.paddle_fees_centsis renamedswich_fees_cents— Swich's own transaction fees (rate unconfirmed pending real signup) are a real cost line, unlike the near-zero cost the interim bank-transfer default would have had. - Permissions/roles: Admin only.
- Source: Analytics/Dashboards, Analytics/KPIs, Analytics/Automated Monthly P&L, Analytics/Unit Economics (Revenue vs Cost per User), Analytics/AI Token Usage Tracking.
6. Shared Dashboard Analytics (Merchant & Creator)
6.1 Merchant Analytics
- Description: Per-merchant offer performance: clicks, conversion, sales, spend; exportable reports. All figures in PKR.
- Expected frontend behavior: Simple charts, no data-viz flourishes ("clarity over excitement"); heavy/slow exports run as async jobs (notification on completion, not a spinner).
- Relevant screens: Merchant Dashboard home, Offer performance detail, Export flow.
- API/backend dependencies:
POST /jobs/export,GET /jobs/:id. - Permissions/roles: Merchant, own data only.
- Source: Analytics/Dashboards, Technical Architecture/Async Job Pattern & Idempotency.
6.2 Creator Analytics
- Description: Per-creator link performance: impressions/clicks/sales, earnings trend toward the payout threshold.
- Relevant screens: Creator Dashboard home.
- Permissions/roles: Creator, own data only.
- Source: Analytics/Dashboards.
7. Customer Support (User-Facing)
7.1 Support Contact
- Description: In-app support link/contact form for logged-in Merchants/Creators; email support otherwise.
- User goal: Get help when something's wrong (payout delay, rejected application, suspected double charge, disputed clawback).
- Expected frontend behavior: Clear, specific error/status copy so common cases (e.g., normal Swich settlement/payout processing window) don't look like failures. Exact expected window under Swich is Needs clarification — the original "2–7 day" figure assumed Paddle's own rail and hasn't been re-confirmed against Swich's.
- Relevant screens: Support/Help contact form or link (likely footer/nav-level, not a full dashboard section).
- Permissions/roles: Any authenticated user.
- Edge cases: No formal SLA — founder-handled through Private Beta.
- Source: Operations/Customer Support Flows, Operations/Support Tiers.
7.2 Account Deletion Request
- Description: User-initiated account deletion with a 14-day cancellable grace period.
- User goal: Delete their account/data.
- Main user actions: Request deletion, cancel within grace period.
- Expected frontend behavior: Clear confirmation step naming what happens (PII anonymized, financial-chain skeleton retained, sessions revoked, product images removed immediately with placeholders shown on any referencing offer).
- Important states: requested/counting-down, cancelled, processing, completed.
- Relevant screens: Account Settings → Delete Account flow.
- API/backend dependencies: Async deletion job (Async Job Pattern).
- Permissions/roles: Any authenticated user, own account only.
- Source: Security/Data Retention Policy Engine.
7.3 Data Disclosure Notices
- Description: Plain-language notices at the point of data collection (signup, before bank details are collected, before AI-matching use of profile data) — not buried in a ToS.
- Expected frontend behavior: Short, contextual, timed notices woven into the relevant flow (signup form, bank-details step, profile-completion step for creators).
- Relevant screens: Embedded in Signup, Bank Details Setup, Creator Profile Settings — not a standalone screen.
- Source: Security/Data Inventory & Disclosure.
Feature-Level "Needs Clarification" Summary
For quick reference, every open item flagged above:
- Admin role's full formal scope (used broadly throughout but never explicitly ratified).
- Waitlist signup endpoint not explicitly specified.
- Exact retry/escalation policy for a failed Swich billing-cycle charge (§2.2/§3.5) — the old Paddle "3 failed attempts" rule needs re-mapping against Swich's own failure-webhook shape, not yet confirmed.
- Exact Shopify app-install path — public App Store listing vs. private/custom app (§2.3).
- Application-rejection notification content/whether a reason is shown.
- Real-time vs. digest cadence for "sale made" / merchant notifications.
- Exact merchant "milestone reached" thresholds.
- Whether merchants see platform-wide aggregate creator performance or only per-applicant stats.
- High-commission/high-risk offer vetting thresholds.
- UI/API for merchant refund-credit request submission.
- Whether the Paddle-era "SellVia absorbs first 5 lost disputes" rule still applies as-is under Swich, and who submits any dispute evidence to whom (§5.4).
- Formal account-suspension appeals process.
- Timing of AI-based creator↔offer matching (MVP vs. post-MVP).
- Whether engagement_rate is self-reported or platform-calculated.
- Whether Founder AI Command Console ships MVP or post-MVP.
- Whether support-ticket-context tooling needs dedicated UI or lives inside User Management/AI Console.
- The $50 payout threshold needs re-specifying in PKR (§4.5).
- Swich's exact API shapes, pricing, and MVP-scale onboarding requirements — nothing here is confirmed, it's all a working draft pending a real signup/integration conversation (§2.2, §2.4, §3.5, §5.10 — every Swich mention across this doc).
- Expected Swich settlement/payout window to communicate in support copy (§7.1).
- Whether an FBR-relevant tax form/declaration needs collecting at Creator onboarding (§2.4) — Swich, like the interim bank-transfer default before it, is not a Merchant of Record and doesn't auto-collect this.
- Beachhead niche/vertical within Pakistan (geography itself is resolved; category focus within it is not).
Resolved since the last revision (2026-08-07), no longer open:
Whether Offer needs its own entity vs. one-campaign-per-offer— resolved: no Campaign entity at all.Merchant Paddle requirement post-reversal— moot, Paddle removed.Exact UX for the tracking-snippet install step— resolved: Shopify OAuth/webhook connect, not a snippet.Lime-as-text WCAG AA contrast— resolved: verified compliant, and Gray 02 (the actual failure) corrected.Payment processor— resolved same day: Swich, replacing the brief interim manual-bank-transfer default.
Still outstanding, unrelated to the 2026-08-23 revision:
- Alt-text field missing from product image schema.
Cross-References
- Screens implementing these features:
SCREEN_INVENTORY.md - Navigation/routes these features live at:
SITE_MAP.md
References
- Tax Considerations· Payments
- Authentication· Security
- Session Management· Security
- API Authentication· API
- User Roles· Business Logic
- Navigation· UX
- User Edge Cases· Edge Cases
- Business Rules· Business Logic
- Notification Logic· Business Logic
- Async Job Pattern & Idempotency· Technical Architecture
- Interaction Patterns· UX
- Components· UX
- Copy Guidelines· UX
- Error Responses· API
- Error Handling & Logging Pipeline· Infrastructure & DevOps
- Accessibility· UX
- Security Checklist· Security
- AI Agent & Machine Readability· UX
- AI Services· Technical Architecture
- MVP Scope· Product Foundation
- Tenant Isolation Audit· Security
- Product Vision· Product Foundation
- Product Roadmap· Product Foundation
- Design System· UX
- Search Strategy· Technical Architecture
- Endpoint Specifications· API
- User Flows· Business Logic
- State Machines· Business Logic
- Table Specifications· Database
- Money Flow· Business Logic
- Payment Flow· Payments
- Frontend Architecture· Technical Architecture
- Backend Architecture· Technical Architecture
- Payout Process· Payments
- Domain Model· Business Logic
- File Storage· Technical Architecture
- Admin Panel· Operations
- Permission Matrix· Business Logic
- Fraud Prevention· Security
- Caching Strategy· Technical Architecture
- Refund Handling· Payments
- Database Design· Database
- Constraints· Database
- Rate Limiting· Security
- Creator Edge Cases· Edge Cases
- Wallet Design· Payments
- Payment Edge Cases· Edge Cases
- Moderation· Operations
- Chargebacks· Payments
- Reconciliation· Payments
- Activation, Aha Moment & Churn Signals· Analytics
- Founder AI Command Console· Operations
- Live Production Access for Support (Command Console)· Operations
- Audit Log Design· Database
- Per-Feature Support Playbooks· Operations
- Support Tiers· Operations
- Dashboards· Analytics
- KPIs· Analytics
- Automated Monthly P&L· Analytics
- Unit Economics (Revenue vs Cost per User)· Analytics
- AI Token Usage Tracking· Analytics
- Customer Support Flows· Operations
- Data Retention Policy Engine· Security
- Data Inventory & Disclosure· Security