# Security ## Authentication ### Device Tokens - Format: `dev_` + 48 random bytes, base64url-encoded - Stored as SHA-256 hash in database - Raw token returned only once during registration - Expire after 90 days - Revocation immediately invalidates token ### Client Authentication - Passwords hashed with bcrypt (10 rounds) - JWT access tokens (15 minute expiration) - Refresh tokens (30 days) with rotation and revocation; a refresh token works only once - The dashboard keeps both tokens in `SameSite=Lax` cookies (`Secure` over HTTPS). They are readable by the dashboard's JavaScript, so an XSS bug would expose them; the short access token lifetime limits the damage ## Authorization ### Role-Based Access - `admin`: Full access, including users and pairing or unpairing terminals - `manager` (the people running the venue): products and their pictures, stock, tabs, planned customers and reminders. Accounts and tokens with the former role `viewer` are treated as managers - Product pictures are public by id (`GET /images/:imageId`); the id is a SHA-256 hash, so it can't be guessed ### Venue Isolation - Every user and device is scoped to exactly one venue - All service methods validate venue context from authentication - Cross-venue access is blocked at the service layer ## API Security ### Headers - Helmet for security headers - Strict CORS (dashboard origin only) - Body size limits enforced ### Rate Limiting - Login and device registration: 10 requests per minute per client - General: 100 requests per minute per client - Device sync and command acks are not rate limited (they are authenticated by the device token) ### Error Handling - Consistent error format never exposes internals - No secrets in error messages - No stack traces in production ## Audit Trail All sensitive operations are logged: - Command creation, acknowledgement, expiration - Device registration and revocation - Snapshot conflicts - No sensitive data (passwords, tokens) in audit logs