# Mirka Loyalty — Scan-to-Earn Workflow Architecture

## Purpose
This document describes the initial hardware-free scan-to-earn flow for Mirka Loyalty. The cashier scans a short-lived customer QR code using a smartphone camera, enters the eligible purchase amount, and submits the transaction.

## Confirmed operating model
- One central customer app for Android and iOS.
- Merchant and platform administration use web portals.
- Cashier uses an authenticated smartphone browser or cashier interface.
- No dedicated POS terminal, QR scanner, card reader, or other special hardware is required.
- The initial flow is independent of the merchant's existing POS. The cashier manually enters the eligible purchase amount.
- Because the flow is not integrated with the merchant POS, Mirka Loyalty records the declared purchase amount but cannot independently verify that payment occurred or that the amount matches the POS receipt.

## Transaction sequence
1. Customer signs in and opens the QR screen.
2. The customer app requests a QR token from the backend.
3. The backend creates a cryptographically random, short-lived, single-use token. Store only a hash of the token.
4. Cashier signs in and selects an authorized business and branch.
5. Cashier scans the customer's QR using the phone camera.
6. The backend validates the token and returns only the minimum customer and membership details needed to award loyalty.
7. Cashier enters the eligible purchase amount and submits the earn transaction with an idempotency key.
8. Backend validates cashier permissions, business and branch access, active customer membership, token status, currency, purchase amount, and loyalty rules.
9. Backend calculates stamps server-side. Never trust a stamp count submitted by the client.
10. In one atomic database transaction, consume the QR token, create the transaction record, append the stamp-ledger entry, update any cached balance, and write an audit event.
11. Customer app displays the confirmation and updated loyalty history.

## Security and integrity requirements
- QR token should have at least 128 bits of cryptographic randomness; 256 bits is preferred.
- Token lifetime should be short (for example, 60–120 seconds) and configurable.
- A token must be single-use and invalidated atomically when redeemed.
- Never place phone number, email, database ID, balance, or other personal data in the QR payload.
- Do not use a permanent QR code as transaction authorization.
- Do not log raw QR tokens.
- Rate-limit token issuance and QR resolution.
- Use an idempotency key to prevent duplicate awards after retries.
- Use database locking and atomic transactions to prevent concurrent token reuse.
- Resolve tenant/business context from the authenticated cashier's membership, not an untrusted business ID supplied by the client.
- Validate branch access for every transaction.
- Verify the customer has an active membership in the same business.
- Cashiers receive only the minimum customer data needed for the transaction.
- Customer accounts can view only their own transactions.
- Use HTTPS for all hosted authentication and API traffic before real customer data is processed.

## Permissions
Suggested permissions:
- `loyalty.transaction.create`
- `loyalty.transaction.reverse`
- `loyalty.program.manage`
- `loyalty.reward.redeem`

Default cashier role should be able to create eligible earn transactions only. Reversal, reward configuration, and program management should require separately granted permissions.

## Ledger and audit policy
- Treat the stamp ledger as append-only.
- Do not silently edit or delete an awarded transaction.
- Correct mistakes using a compensating reversal entry with a reason.
- Record actor, business, branch, action, transaction reference, timestamp, and reversal reason where applicable.

## Proposed API endpoints
- `POST /api/v1/customer/qr-tokens`
- `GET /api/v1/customer/business-memberships`
- `GET /api/v1/customer/loyalty/transactions`
- `GET /api/v1/cashier/branches`
- `POST /api/v1/cashier/qr-scans/resolve`
- `POST /api/v1/cashier/loyalty/transactions`

## Important limitation of manual amount entry
Without POS integration, a cashier can enter an incorrect amount or award stamps without a verified sale. Mitigations for the first release can include transaction limits, cashier audit logs, manager review, receipt reference fields, and exception reports. POS integration can be considered later.

## Suggested initial configuration
- QR token lifetime: 90 seconds (configurable).
- One token: one successful earn transaction.
- Currency: configured per business/branch.
- Stamp calculation: server-side, based on the active loyalty program.
- Amount limits and eligibility: configurable by the business within platform policy.
