2.4 KiB
Architecture Decisions
1. Registration Code Model
Decision: Added a RegistrationCode model to the database schema.
Rationale: The specification requires a registration-code mechanism. Rather than overloading an existing model or implementing a complex external system, a simple RegistrationCode table with venue scoping, expiration, and single-use semantics provides a clean implementation.
2. Payment Method Must Be Explicitly Selected
Decision: The UI never defaults to cash. The user must explicitly select a payment method.
Rationale: The specification explicitly forbids silent defaults. This prevents accidental charges and ensures compliance with the business requirement.
3. Cursor Implementation
Decision: Opaque cursor encoded as base64url containing timestamp + UUID tiebreaker.
Rationale: Provides a simple, privacy-preserving cursor that allows the server to determine which commands the device has already seen without exposing database internals.
4. Refresh Token Storage
Decision: Refresh tokens are stored hashed (SHA-256) in a RefreshToken table, supporting revocation and rotation.
Rationale: Provides security (tokens can be revoked) and aligns with OAuth2 best practices for refresh token management.
5. PostgreSQL Everywhere
Decision: PostgreSQL is used in development, CI and production.
Rationale: One database means one set of migrations; the schema uses JSON columns and serializable transactions that SQLite doesn't support the same way.
6. Invalidation-Only Live Updates
Decision: The API pushes topic names (tabs, commands, ...) over Socket.IO; the dashboard refetches that data over the normal REST API. It falls back to polling while the socket is down.
Rationale: Events never carry data, so a socket can't see anything its owner couldn't fetch, and the REST API stays the single source of truth.
7. In-Memory Rate Limiting
Decision: Use NestJS ThrottlerModule with in-memory storage.
Rationale: Suitable for single-instance deployments. The abstraction allows swapping to Redis without controller changes.
8. Venue Isolation via JWT Claims
Decision: Venue ID is embedded in the JWT token. All service methods verify the requesting user/device's venue context rather than trusting URL parameters alone.
Rationale: Prevents cross-venue access even if a user manually modifies URL parameters.