Overview
These are the functional requirements in plain language — what customers and administrators can do, split by role.
How to read
Must = shipped and verified by tests. Should = shipped. Planned = designed but not implemented.
Customer Requirements
| ID | Requirement | Status |
|---|---|---|
| FR-01 | Register with email + phone; verify email via hashed token link (24h TTL) | Must |
| FR-02 | Log in from multiple devices; view active sessions; revoke any or all | Must |
| FR-03 | Recover password via email link or 6-digit OTP (15 min TTL, attempt-limited); reset revokes all sessions | Must |
| FR-04 | Manage profile: name, password change, email change (link, 24h TTL), phone change (6-digit OTP, 10 min TTL), soft-delete own account | Must |
| FR-05 | Manage an address book (CRUD with default shipping/billing flags, ownership-scoped) used at checkout (address is snapshot into shipments) | Must |
| FR-06 | Browse products with filtering, search, sorting, pagination; browse categories; list products per category — customer visibility = non-deleted product with ≥1 ACTIVE variant | Must |
| FR-07 | View a product's variants — pick size/color/barcode/dimensions with live availability and computed final_price; see ordered images per product and per variant with exactly-one-primary invariant | Must |
| FR-08 | Maintain a single lazily-created server-side cart: add variants (merge-on-duplicate), update quantities, remove lines, clear — all four mutations advisory-locked alongside checkout | Must |
| FR-09 | Check out in one transaction: owned address, optional coupon (uppercased), shipping rules, guarded stock reservation, mock payment (PaymentGateway interface), immutable order_items + shipments snapshots, cart clear — under pg_advisory_xact_lock | Must |
| FR-10 | Apply coupons honoring validity window, global limit, per-user limit, minimum order value, and max-discount cap — quota restored on pre-fulfillment cancel, kept on post-fulfillment refund | Must |
| FR-11 | View order history and order detail with immutable snapshots of prices, discounts, SKUs, and variant attributes; filtered by status, sorted by placement date | Must |
| FR-12 | Write one live review per product (with images), edit or delete it; list own reviews — purchase-gate implemented behind REVIEWS_REQUIRE_PURCHASE (off) | Should |
| FR-13 | Upload review/product images directly to ImageKit with server-signed short-lived HMAC params; URLs re-validated for host/folder/extension | Should |
Administrator Requirements
| ID | Requirement | Status |
|---|---|---|
| FR-14 | Full catalog CRUD: products, nested variants, product/variant images with primary-flag management | Must |
| FR-15 | Manage categories and assign/unassign products | Must |
| FR-16 | Manage inventory per variant: adjust quantity_on_hand/reorder_level, create manual reservations, commit/release stock via the FSM | Must |
| FR-17 | Transition orders through an explicit allowedTransitions FSM (pending → confirmed → processing → shipped → delivered → cancelled/returned → refunded) with automatic side effects (shipment row, stock commit/release, payment status, coupon quota) under SELECT … FOR UPDATE | Must |
| FR-18 | Moderate reviews; manage coupons with coupon_usages inspection and history | Must |
| FR-19 | Manage users: list, suspend/activate; role changes (customer ↔ admin) require SUPER_ADMIN; last SUPER_ADMIN protected | Must |
| FR-20 | Manage admin accounts (/admin/admins — SUPER_ADMIN only) and transfer SUPER_ADMIN via CLI | Must |
| FR-21 | View stats dashboard (/admin/stats), analytics — overview, coupons, and P&L expenses ledger (/admin/analytics) — and the append-only audit log (/admin/audit), all SUPER_ADMIN unless noted | Should |
| FR-22 | Download financial PDFs — P&L Statement, Expenses, Revenue by `month | quarter |
| FR-23 | Issue and audit signed ImageKit upload params (/uploads/imagekit-auth + /admin/products/uploads/imagekit-auth) | Should |
Behavior That Matters
- Checkout is all-or-nothing — stock validation, price/
Decimalcomputation, coupon redemption (global/per-user limits + max-discount cap), order +order_items/shipmentssnapshot creation, payment recording, and cart deletion succeed together or not at all under one advisory lock. - Overselling is impossible — reservation uses guarded
UPDATE … WHERE available >= qty, not check-then-write; cart mutations are also advisory-locked so races degrade to clean404s. - Order history never lies — later catalog/address edits can't rewrite
order_items(price/SKU/attributes) orshipments(address copy). - Every privileged mutation is audited — actor, action, entity, request body (redacted), prev/diff, IP, UA — append-only
audit_logs.
Out of Scope (Current Version)
- Real payment gateway (Paymob integration is designed as tracked tasks; MockPaymentGateway only today).
- SMS delivery — the interface exists, sending is stubbed.
- Review purchase verification — implemented behind
REVIEWS_REQUIRE_PURCHASE, currently off. - Multi-origin CORS support.
Why it matters
Every gap is a documented decision with a task number — not an undocumented surprise.