Security & Architecture
Tenant isolation, payment integrity and how the system behaves when the internet drops.
Last updated 7 October 2026
1. Tenant isolation
Gym records carry a tenant identifier. API views must explicitly scope reads and writes to the authenticated gym and enforce role permissions; the base model does not automatically filter every query. Isolation is checked by tenant and permission tests.
2. Tenant identity is never taken from the client
A tenant identifier supplied in a request header is never trusted. The tenant is resolved from the authenticated session, so forging a header does not grant cross-tenant access.
3. Payment integrity
A payment moving to 'initiated' is not a payment. Online memberships extend only after the gateway payment is cryptographically verified, through checkout verification or a signed webhook. Desk payments are recorded separately with staff authorization. Webhooks are consumed idempotently, so a gateway retry cannot double-extend a membership or duplicate a ledger entry.
4. Access token design
Check-in codes are HMAC tokens that regenerate every 15 seconds, each code opens the gate once, and a second entry on the same membership within a configurable window is refused to prevent pass-back. Entry is decided on the server from the membership's paid status, never by the app.
5. Offline behaviour
If the member's phone is offline, the app shows a code from a short batch the server issued in advance, and those codes are single-use and time-limited like any other. The server still decides entry, so an expired or lapsed membership is refused either way.
6. No hard deletes on money or attendance
Financial transactions, attendance corrections and red-list contact history are soft-deleted with the acting user and timestamp recorded. Nothing that could be disputed later is destroyed.
7. Keeping slow work away from the gate
Meal-photo analysis has its own time limit and its own daily cap, and a slow or failed AI answer is reported to you rather than retried in a loop. It never stands between a member and the gate: check-in and payment confirmation do not wait on it.