Authorization
Every private route checks the access token first, then the role, then ownership of the record. Gallery bytes require a further check of publication and access status.
Roles
| Role | May do |
|---|---|
| Unauthenticated visitor | Read the public catalog and start a checkout for a new or logged-out booking flow. |
CUSTOMER | Read and act on their own bookings, orders, galleries, ratings, referral code, and reward balance. |
ADMIN | Approve bookings, manage the catalog, upload and publish galleries, approve or revoke access, manage reward policies, and read audit logs. MFA is required in production. |
The photographer uses ADMIN. There is no second staff role in this edition.
Ownership
Customer queries include customer_id equal to the access token sub in the database filter, not only in the UI. A customer who guesses another gallery id receives the same not-found response used for a missing id, so the API does not reveal that the other gallery exists.
An administrator acts through /admin routes. Those routes write audit_logs with the actor, the action, and the resource id.
Gallery rule
A published gallery remains private until access is approved. The download and preview handlers refuse the request unless all of the following are true:
- The caller is the gallery's customer, or the caller is an administrator on the admin preview route.
publication_statusisPUBLISHED. Archived and draft galleries are not downloadable by the customer.access_statusisAPPROVED.- The photo status is
READY.
The handler then asks object storage for a URL that expires in 5 minutes. Revoking access changes access_status and appends a review row. The next request does not receive a URL. URLs already issued expire on their own.
This check lives in the galleries module and is called for every content request. A route that returns a storage key to the browser is a defect.
Booking decisions
POST /admin/bookings/{id}/decision requires ADMIN, MFA, a booking in PENDING_APPROVAL, and an order in PAID. The decision and the refund job, when rejecting, commit together.
Reward spending
A customer can redeem only their own ledger balance, and only up to the service subtotal of their own order. The lock and the ledger insert are the authorization against double spending. A client-supplied discount larger than the balance is reduced to the balance or rejected. This edition rejects the request so the customer sees the smaller total and submits again.