### 📱 PERSON A — Web App (Customer-Facing) #### Functional Requirements - **WEB-FR-1**: User registration (email + password) with email verification - **WEB-FR-2**: Login / logout - **WEB-FR-3**: Password reset flow - **WEB-FR-4**: Display the event's card offering — name, description, price, expiration date - **WEB-FR-5**: Checkout flow via Stripe (EUR) - _Open item: single card per order, or multiple?_ - **WEB-FR-6**: On confirmed payment (via Stripe webhook), trigger card/QR generation (calls shared backend) - **WEB-FR-7**: Send confirmation email with QR code attached/embedded (via transactional email service) - **WEB-FR-8**: "My Cards" account page — shows purchase history, card status (unused/used/expired), QR re-download button - **WEB-FR-9**: Basic account settings page (update email/password) #### Non-Functional Requirements - **WEB-NFR-1**: HTTPS only - **WEB-NFR-2**: GDPR-compliant — privacy policy, consent checkbox at registration, data retention/erasure process - **WEB-NFR-3**: No raw card/payment data stored — Stripe handles PCI compliance, you only store payment references - **WEB-NFR-4**: Responsive design (mobile browser support, since users will pull up emails on phones too, though the QR itself is scanned by the admin's phone, not theirs) #### Open Items for This Side 1. Multi-card orders — yes/no, and if yes, does each card need a separate recipient email field? 2. Refund/cancellation flow — in scope for v1 or not? 3. Any requirement to resend the QR email if a user loses it (vs. just downloading from account page)? --- ### 📷 PERSON B — Android Scanner App (Admin-Facing) #### Functional Requirements - **APP-FR-1**: Single admin login (one hardcoded/managed admin role — no multi-account complexity) - **APP-FR-2**: Camera-based QR scanning (use a standard library — e.g., ML Kit or ZXing) - **APP-FR-3**: On scan, send token to backend validation endpoint - **APP-FR-4**: Display result clearly and immediately: - ✅ **Valid** → show card owner name + card type, mark as used - ❌ **Already Used** → show when it was originally used - ❌ **Expired** → show expiration date - ❌ **Not Found** → invalid/forged code - **APP-FR-5**: Local on-device scan log (timestamp + result) for admin's own reference during the event - **APP-FR-6**: Manual entry fallback (in case camera/QR fails to scan — type in code manually) #### Non-Functional Requirements - **APP-NFR-1**: Requires internet connectivity to validate (confirm: acceptable, or do you need offline fallback?) - **APP-NFR-2**: Fast response time — scan-to-result should feel instant (sub-1s ideally) since there may be a line of people - **APP-NFR-3**: Simple, high-contrast UI readable in bright outdoor daylight or dark event lighting - **APP-NFR-4**: Since it's single-admin/single-device, no need to handle concurrent scan conflicts — backend validation is still atomic, but app itself doesn't need sync logic #### Open Items for This Side 1. **Offline fallback** — if there's no signal at the venue, what happens? Worth deciding now since it affects architecture (native online-only call vs. local cache + sync). 2. Does the admin need to _undo_ an accidental valid scan (e.g., mis-scan, wrong card)? 3. Any requirement to see a running count (e.g., "142 checked in") during the event? --- ### 🔗 SHARED — Backend Contract (Both of you depend on this) This is the glue between your two apps — worth agreeing on before you start building independently, since a mismatch here is the most likely source of integration pain later. - **API-1**: `POST /api/orders` — creates order, integrates Stripe checkout - **API-2**: Stripe webhook handler — on payment success, generates Card record + signed QR token, triggers email - **API-3**: `POST /api/cards/validate` — takes scanned token, returns `{status: valid|used|expired|not_found, owner_name, card_type, used_at?}`, atomically updates status if valid - **API-4**: `GET /api/users/me/cards` — for the web app's "My Cards" page - **API-5**: Shared **Card** data model: `id, unique_token (signed), user_id, card_type, status, purchased_at, expires_at, used_at` - **API-6**: Auth — separate token/role for admin scanner vs. customer web sessions **Recommendation:** whoever owns the backend (or whoever's building it jointly) should nail down the exact JSON shape of `API-3`'s response first, since that's the contract Person B's UI directly renders.