Architecture Overview
GlamB is built using the Modular Monolith pattern on Rails 8.1+.
Domains are organized in /app/ by folder; in the future each can be extracted into a separate Rails Engine.
Layers
┌─────────────────────────────────────────────────────────┐
│ Presentation: REST API v1 · Hotwire · ActionCable │
├─────────────────────────────────────────────────────────┤
│ Application: Controllers · Services · Serializers │
│ Pundit Policies · Query Objects │
├─────────────────────────────────────────────────────────┤
│ Domain (11 engines — Phase 1: folders in /app/): │
│ core · catalog · scheduling · booking · payments │
│ reviews · notifications · analytics · crm · admin │
│ favorites │
├─────────────────────────────────────────────────────────┤
│ Infrastructure: PostgreSQL 16 · Redis 7 · SolidQueue │
│ MinIO (S3) · ActionCable │
├─────────────────────────────────────────────────────────┤
│ External: Stripe · Twilio · SendGrid · Google Maps │
│ Firebase FCM · Cloudflare CDN │
└─────────────────────────────────────────────────────────┘
Authorization
Pundit RBAC. Every protected endpoint calls authorize or policy_scope.
| Policy | Resource |
|---|---|
SalonPolicy | Salon CRUD and service management |
AppointmentPolicy | Appointments with role-based access |
ApplicationPolicy | Base class, deny all by default |
Error Handling
All errors are centralized in BaseController via rescue_from:
| Exception | HTTP | When |
|---|---|---|
DomainErrors::NotFound | 404 | Resource not found |
DomainErrors::Unauthorized | 401 | Invalid password / token |
DomainErrors::ValidationError | 422 | Model/parameter validation failed |
DomainErrors::Forbidden | 403 | Insufficient permissions |
ActiveRecord::RecordNotFound | 404 | AR find |
Pundit::NotAuthorizedError | 403 | Pundit |
JwtSignature::TokenExpiredError | 401 | Expired token |
JwtSignature::TokenInvalidError | 401 | Invalid token |