Orders & fulfilment
Storefront Customer Accounts
Indicative price, not an offer: €49–149/month
Generated from docs/plan/paid/storefront-customer-accounts/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
Merged from duplicate proposals: “Storefront Customer Accounts”
A customer authentication and account system for storefronts, enabling password-based login, session management, order history, saved addresses, reorders, and wishlist. Supports customer retention and repeat-purchase visibility.
The problem
No password, no session, no login, no order history, no saved addresses, no reorder, no wishlist. Order lookup is number-plus-email only. Merchants miss repeat-purchase opportunities and customer retention signals.
What it does
- Customer signup with email and password (password strength requirements, hashing via bcrypt)
- Login/logout with session cookies (HttpOnly, Secure, SameSite=Lax)
- Password reset (email link with token, one-time use, 24h expiry)
- Edit profile (name, phone, avatar URL)
- Saved addresses (default shipping/billing, multiple addresses, CRUD)
- View order history (all orders, filter by date, search by order number)
- Reorder (create new cart from prior order line items, repopulate saved address)
- Wishlist (add/remove products, share wishlist link, convert to cart)
- Email notification on order status changes (order placed, shipped, delivered)
- Admin view: customer list, customer detail (profile, order history, lifetime value), edit customer
- Customer account security: account lockout after 5 failed logins, session timeout (30 min default)
- Audit trail: login/logout, password change, address change, profile edit
What it deliberately does NOT do
Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.
- Customer tier/loyalty programs — core does not manage tiers or loyalty points. Reason: paid feature (rewards system).
- Subscription management — core does not support recurring orders or subscriptions. Reason: complex billing; separate paid feature.
- Social login (Google, Facebook) — not included. Reason: OAuth credential management is paid.
- Two-factor authentication (2FA) — not included. Reason: paid security feature.
- Referral links — core does not generate or track referral codes. Reason: paid marketing feature.
- Customer insights (RFM analysis, churn prediction) — not included. Reason: advanced analytics; paid feature.
Data model
New tables: Customer {id, email (unique), passwordHash, name, phone, avatar, createdAt, updatedAt, lastLoginAt, isLocked (bool), lockExpiresAt}; CustomerAddress {id, customerId, type (‘shipping’|‘billing’|‘both’), street, city, postcode, country, isDefault, createdAt}; CustomerSession {id, customerId, token (unique, signed), expiresAt, createdAt, lastActivityAt}; CustomerWishlistItem {id, customerId, productId, addedAt}; CustomerAuditLog {id, customerId, action (‘login’|‘logout’|‘password_changed’|‘address_added’|‘profile_updated’), details, timestamp}. No migration.
API
- POST /api/customers/register
- POST /api/customers/login
- POST /api/customers/logout
- POST /api/customers/password-reset
- PUT /api/customers/password-reset/:token
- GET /api/customers/me
- PUT /api/customers/me
- POST /api/customers/addresses
- PUT /api/customers/addresses/:addressId
- DELETE /api/customers/addresses/:addressId
- GET /api/customers/orders
- GET /api/customers/orders/:orderId
- POST /api/customers/orders/:orderId/reorder
- POST /api/customers/wishlist
- DELETE /api/customers/wishlist/:wishlistItemId
- GET /api/customers/wishlist
- GET /api/customers/wishlist/share/:shareToken
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Customer list: search by email/name, filter by registration date, sort by lifetime value. Customer detail page: profile, order history, wishlist, login history, account status, ability to reset password or unlock. Admin bulk action: send email to customer segment, export customer list (CSV).
The seam — why this is paid
Core owns: basic order fulfillment, order history (orders remain accessible). Paid owns: customer authentication, session management, saved addresses, wishlist, profile management, loyalty/retention features.
Decided PAID (C-140). Requires auth, session, and account infrastructure. Supports retention and repeat-purchase visibility.
Dependencies
- Order/checkout infrastructure (orders must be queryable by customer)
- Email system (password reset, order notifications)
- Settings system (session timeout, password policy, email sender)
- Notification system (order status emails)
Acceptance checks
Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.
- Registering with email=‘test@example.com’ and password=‘SecurePass123!’ creates Customer and allows subsequent login
- Password reset: requesting reset sends email with token; token valid for 24h; after token use, password changes and token invalidated
- Login with invalid password after 5 attempts locks account; lockExpiresAt set to +30 min; login within lockout period returns {error: ‘account_locked’, retryAfter: …}
- Session timeout: if no activity for 30 min, subsequent request returns {error: ‘session_expired’}; customer must log in again
- Logged-in customer can view their own orders via GET /api/customers/orders; unauthenticated user cannot; customer cannot view another customer’s orders
- Reorder: creating reorder from order #123 copies all line items, applies saved address, creates new order #456 with status ‘pending’
- Adding product to wishlist with productId=‘xyz’ creates CustomerWishlistItem; adding same product again is idempotent (no duplicate)
- Shared wishlist link (GET /api/customers/wishlist/share/:token) is viewable without login; contains product list + custom message
- Admin can reset a customer’s password; customer receives email with reset link and must set new password on next login
- Audit log records login at 10:00, logout at 10:35, password_changed at 15:00 with timestamps; no customer email or password is logged
Risks
Password brute-force: attacker tries 1000 passwords/sec; mitigation: account lockout after 5 failures, rate-limit by IP. Session hijacking: session token stolen (XSS, network sniff); mitigation: HttpOnly cookie, Secure flag, SameSite=Lax, short timeout. Email reuse: two customers register with same email; mitigation: unique constraint. Reorder price staleness: product price changed since original order; mitigation: reorder uses current prices, not historical; document clearly.
Commercial context
| Suggested price | €49–149/month |
| Rival anchor | Magento Open Source: full customer accounts, order history, address book ship free. |
The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.
Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full
catalogue and ../../AI-GUIDE.md for how to work on this repository.