diff --git a/README.md b/README.md index 0e863ec..83e29b5 100644 --- a/README.md +++ b/README.md @@ -1,257 +1,470 @@ # SmoothSchedule - Multi-Tenant Scheduling Platform -A production-ready multi-tenant SaaS platform for resource scheduling and orchestration. +A production-ready multi-tenant SaaS platform for resource scheduling, appointments, and business management. -## ๐ŸŽฏ Features +## Features -- โœ… **Multi-Tenancy**: PostgreSQL schema-per-tenant using django-tenants -- โœ… **8-Tier Role Hierarchy**: From SUPERUSER to CUSTOMER with strict permissions -- โœ… **Modern Stack**: Django 5.2 + React 18 + Vite -- โœ… **Docker Ready**: Complete production & development Docker Compose setup -- โœ… **Cloud Storage**: DigitalOcean Spaces (S3-compatible) for static/media files -- โœ… **Auto SSL**: Let's Encrypt certificates via Traefik reverse proxy -- โœ… **Task Queue**: Celery + Redis for background jobs -- โœ… **Real-time**: Django Channels + WebSockets support -- โœ… **Production Ready**: Fully configured for deployment +- **Multi-Tenancy**: PostgreSQL schema-per-tenant using django-tenants +- **8-Tier Role Hierarchy**: SUPERUSER, PLATFORM_MANAGER, PLATFORM_SALES, PLATFORM_SUPPORT, TENANT_OWNER, TENANT_MANAGER, TENANT_STAFF, CUSTOMER +- **Modern Stack**: Django 5.2 + React 19 + TypeScript + Vite +- **Real-time Updates**: Django Channels + WebSockets +- **Background Tasks**: Celery + Redis +- **Auto SSL**: Let's Encrypt certificates via Traefik +- **Cloud Storage**: DigitalOcean Spaces (S3-compatible) +- **Docker Ready**: Complete Docker Compose setup for dev and production -## ๐Ÿ“š Documentation +## Project Structure -- **[PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md)** - **Manual step-by-step production deployment** (start here for fresh deployments) -- **[QUICK-REFERENCE.md](QUICK-REFERENCE.md)** - Common commands and quick start -- **[PRODUCTION-READY.md](PRODUCTION-READY.md)** - Production deployment status -- **[DEPLOYMENT.md](DEPLOYMENT.md)** - Comprehensive deployment guide -- **[CLAUDE.md](CLAUDE.md)** - Development guide and architecture +``` +smoothschedule2/ +โ”œโ”€โ”€ frontend/ # React + Vite + TypeScript +โ”‚ โ”œโ”€โ”€ src/ +โ”‚ โ”‚ โ”œโ”€โ”€ api/ # API client and hooks +โ”‚ โ”‚ โ”œโ”€โ”€ components/ # Reusable UI components +โ”‚ โ”‚ โ”œโ”€โ”€ hooks/ # React Query hooks +โ”‚ โ”‚ โ”œโ”€โ”€ pages/ # Page components +โ”‚ โ”‚ โ””โ”€โ”€ types.ts # TypeScript interfaces +โ”‚ โ”œโ”€โ”€ nginx.conf # Production nginx config +โ”‚ โ””โ”€โ”€ Dockerfile.prod # Production frontend container +โ”‚ +โ”œโ”€โ”€ smoothschedule/ # Django backend +โ”‚ โ”œโ”€โ”€ config/ # Django settings +โ”‚ โ”‚ โ””โ”€โ”€ settings/ +โ”‚ โ”‚ โ”œโ”€โ”€ base.py # Base settings +โ”‚ โ”‚ โ”œโ”€โ”€ local.py # Local development +โ”‚ โ”‚ โ””โ”€โ”€ production.py # Production settings +โ”‚ โ”œโ”€โ”€ smoothschedule/ # Django apps (domain-based) +โ”‚ โ”‚ โ”œโ”€โ”€ identity/ # Users, tenants, authentication +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ core/ # Tenant, Domain, middleware +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ users/ # User model, MFA, auth +โ”‚ โ”‚ โ”œโ”€โ”€ scheduling/ # Core scheduling +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ schedule/ # Resources, Events, Services +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ contracts/ # E-signatures +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ analytics/ # Business analytics +โ”‚ โ”‚ โ”œโ”€โ”€ communication/ # Notifications, SMS, mobile +โ”‚ โ”‚ โ”œโ”€โ”€ commerce/ # Payments, tickets +โ”‚ โ”‚ โ””โ”€โ”€ platform/ # Admin, public API +โ”‚ โ”œโ”€โ”€ docker-compose.local.yml +โ”‚ โ””โ”€โ”€ docker-compose.production.yml +โ”‚ +โ”œโ”€โ”€ deploy.sh # Automated deployment script +โ””โ”€โ”€ CLAUDE.md # Development guide +``` -## ๐Ÿš€ Quick Start +--- -### Local Development +## Local Development Setup + +### Prerequisites + +- **Docker** and **Docker Compose** (for backend) +- **Node.js 22+** and **npm** (for frontend) +- **Git** + +### Step 1: Clone the Repository ```bash -# Start backend (Django in Docker) +git clone https://github.com/your-repo/smoothschedule.git cd smoothschedule +``` + +### Step 2: Start the Backend (Django in Docker) + +```bash +cd smoothschedule + +# Start all backend services docker compose -f docker-compose.local.yml up -d -# Start frontend (React with Vite) -cd ../frontend -npm install -npm run dev +# Wait for services to initialize (first time takes longer) +sleep 30 -# Access the app -# Frontend: http://platform.lvh.me:5173 -# Backend API: http://lvh.me:8000/api +# Run database migrations +docker compose -f docker-compose.local.yml exec django python manage.py migrate + +# Create a superuser (optional) +docker compose -f docker-compose.local.yml exec django python manage.py createsuperuser ``` -See [CLAUDE.md](CLAUDE.md) for detailed development instructions. - -### Production Deployment - -For **fresh deployments or complete reset**, follow [PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md) for manual step-by-step instructions. - -For **routine updates**, use the automated script: +### Step 3: Start the Frontend (React with Vite) ```bash -# Deploy to production server (code changes only) -./deploy.sh poduck@smoothschedule.com +cd ../frontend + +# Install dependencies +npm install + +# Start development server +npm run dev ``` -See [PRODUCTION-READY.md](PRODUCTION-READY.md) for deployment checklist and [DEPLOYMENT.md](DEPLOYMENT.md) for detailed steps. +### Step 4: Access the Application -## ๐Ÿ—๏ธ Architecture +The application uses `lvh.me` (resolves to 127.0.0.1) for subdomain-based multi-tenancy: + +| URL | Purpose | +|-----|---------| +| http://platform.lvh.me:5173 | Platform admin dashboard | +| http://demo.lvh.me:5173 | Demo tenant (if created) | +| http://lvh.me:8000/api/ | Backend API | +| http://lvh.me:8000/admin/ | Django admin | + +**Why `lvh.me`?** Browsers don't allow cookies with `domain=.localhost`, but `lvh.me` resolves to 127.0.0.1 and allows proper cookie sharing across subdomains. + +### Local Development Commands + +```bash +# Backend commands (always use docker compose) +cd smoothschedule + +# View logs +docker compose -f docker-compose.local.yml logs -f django + +# Run migrations +docker compose -f docker-compose.local.yml exec django python manage.py migrate + +# Django shell +docker compose -f docker-compose.local.yml exec django python manage.py shell + +# Run tests +docker compose -f docker-compose.local.yml exec django pytest + +# Stop all services +docker compose -f docker-compose.local.yml down + +# Frontend commands +cd frontend + +# Run tests +npm test + +# Type checking +npm run typecheck + +# Lint +npm run lint +``` + +### Creating a Test Tenant + +```bash +cd smoothschedule +docker compose -f docker-compose.local.yml exec django python manage.py shell +``` + +```python +from smoothschedule.identity.core.models import Tenant, Domain + +# Create tenant +tenant = Tenant.objects.create( + name="Demo Business", + schema_name="demo", +) + +# Create domain +Domain.objects.create( + domain="demo.lvh.me", + tenant=tenant, + is_primary=True, +) + +print(f"Created tenant: {tenant.name}") +print(f"Access at: http://demo.lvh.me:5173") +``` + +--- + +## Production Deployment + +### Prerequisites + +- Ubuntu/Debian server with Docker and Docker Compose +- Domain name with DNS configured: + - `A` record: `yourdomain.com` โ†’ Server IP + - `A` record: `*.yourdomain.com` โ†’ Server IP (wildcard) +- SSH access to the server + +### Quick Deploy (Existing Server) + +For routine updates to an existing production server: + +```bash +# From your local machine +./deploy.sh user@yourdomain.com + +# Or deploy specific services +./deploy.sh user@yourdomain.com nginx +./deploy.sh user@yourdomain.com django +``` + +### Fresh Server Deployment + +#### Step 1: Server Setup + +SSH into your server and install Docker: + +```bash +ssh user@yourdomain.com + +# Install Docker +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh +sudo usermod -aG docker $USER + +# Logout and login for group changes +exit +ssh user@yourdomain.com +``` + +#### Step 2: Clone Repository + +```bash +cd ~ +git clone https://github.com/your-repo/smoothschedule.git smoothschedule +cd smoothschedule +``` + +#### Step 3: Configure Environment Variables + +Create production environment files: + +```bash +mkdir -p smoothschedule/.envs/.production + +# Django configuration +cat > smoothschedule/.envs/.production/.django << 'EOF' +DJANGO_SECRET_KEY=your-random-secret-key-here +DJANGO_DEBUG=False +DJANGO_ALLOWED_HOSTS=yourdomain.com,*.yourdomain.com + +DJANGO_ADMIN_URL=your-secret-admin-path/ +FRONTEND_URL=https://platform.yourdomain.com +PLATFORM_BASE_URL=https://platform.yourdomain.com + +REDIS_URL=redis://redis:6379/0 +CELERY_BROKER_URL=redis://redis:6379/0 + +# DigitalOcean Spaces (or S3) +DJANGO_AWS_ACCESS_KEY_ID=your-access-key +DJANGO_AWS_SECRET_ACCESS_KEY=your-secret-key +DJANGO_AWS_STORAGE_BUCKET_NAME=your-bucket +DJANGO_AWS_S3_ENDPOINT_URL=https://nyc3.digitaloceanspaces.com +DJANGO_AWS_S3_REGION_NAME=nyc3 + +# SSL +DJANGO_SECURE_SSL_REDIRECT=True +DJANGO_SESSION_COOKIE_SECURE=True +DJANGO_CSRF_COOKIE_SECURE=True + +# Cloudflare (for wildcard SSL) +CF_DNS_API_TOKEN=your-cloudflare-api-token +EOF + +# PostgreSQL configuration +cat > smoothschedule/.envs/.production/.postgres << 'EOF' +POSTGRES_HOST=postgres +POSTGRES_PORT=5432 +POSTGRES_DB=smoothschedule +POSTGRES_USER=smoothschedule_user +POSTGRES_PASSWORD=your-secure-database-password +EOF +``` + +#### Step 4: Build and Start + +```bash +cd ~/smoothschedule/smoothschedule + +# Build all images +docker compose -f docker-compose.production.yml build + +# Start services +docker compose -f docker-compose.production.yml up -d + +# Wait for startup +sleep 30 + +# Run migrations +docker compose -f docker-compose.production.yml exec django python manage.py migrate + +# Collect static files +docker compose -f docker-compose.production.yml exec django python manage.py collectstatic --noinput + +# Create superuser +docker compose -f docker-compose.production.yml exec django python manage.py createsuperuser +``` + +#### Step 5: Verify Deployment + +```bash +# Check all containers are running +docker compose -f docker-compose.production.yml ps + +# View logs +docker compose -f docker-compose.production.yml logs -f + +# Test endpoints +curl https://yourdomain.com/api/health/ +``` + +### Production URLs + +| URL | Purpose | +|-----|---------| +| https://yourdomain.com | Marketing site | +| https://platform.yourdomain.com | Platform admin | +| https://*.yourdomain.com | Tenant subdomains | +| https://api.yourdomain.com | API (if configured) | +| https://yourdomain.com:5555 | Flower (Celery monitoring) | + +### Production Management Commands + +```bash +ssh user@yourdomain.com +cd ~/smoothschedule/smoothschedule + +# View logs +docker compose -f docker-compose.production.yml logs -f django + +# Restart services +docker compose -f docker-compose.production.yml restart + +# Run migrations +docker compose -f docker-compose.production.yml exec django python manage.py migrate + +# Django shell +docker compose -f docker-compose.production.yml exec django python manage.py shell + +# Database backup +docker compose -f docker-compose.production.yml exec postgres pg_dump -U smoothschedule_user smoothschedule > backup.sql +``` + +--- + +## Architecture ### Multi-Tenancy Model ``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ PostgreSQL Database โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ public (shared schema) โ”‚ -โ”‚ โ”œโ”€ Tenants โ”‚ -โ”‚ โ”œโ”€ Domains โ”‚ -โ”‚ โ”œโ”€ Users โ”‚ -โ”‚ โ””โ”€ PermissionGrants โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ tenant_demo (schema for Demo Company) โ”‚ -โ”‚ โ”œโ”€ Appointments โ”‚ -โ”‚ โ”œโ”€ Resources โ”‚ -โ”‚ โ””โ”€ Customers โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ tenant_acme (schema for Acme Corp) โ”‚ -โ”‚ โ”œโ”€ Appointments โ”‚ -โ”‚ โ”œโ”€ Resources โ”‚ -โ”‚ โ””โ”€ Customers โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +PostgreSQL Database +โ”œโ”€โ”€ public (shared schema) +โ”‚ โ”œโ”€โ”€ Tenants +โ”‚ โ”œโ”€โ”€ Domains +โ”‚ โ”œโ”€โ”€ Users +โ”‚ โ””โ”€โ”€ PermissionGrants +โ”œโ”€โ”€ demo (tenant schema) +โ”‚ โ”œโ”€โ”€ Resources +โ”‚ โ”œโ”€โ”€ Events +โ”‚ โ”œโ”€โ”€ Services +โ”‚ โ””โ”€โ”€ Customers +โ””โ”€โ”€ acme (tenant schema) + โ”œโ”€โ”€ Resources + โ”œโ”€โ”€ Events + โ””โ”€โ”€ ... ``` ### Role Hierarchy -| Role | Level | Access Scope | -|---------------------|----------|---------------------------| -| SUPERUSER | Platform | All tenants (god mode) | -| PLATFORM_MANAGER | Platform | All tenants | -| PLATFORM_SALES | Platform | Demo accounts only | -| PLATFORM_SUPPORT | Platform | Tenant users | -| TENANT_OWNER | Tenant | Own tenant (full access) | -| TENANT_MANAGER | Tenant | Own tenant | -| TENANT_STAFF | Tenant | Own tenant (limited) | -| CUSTOMER | Tenant | Own data only | +| Role | Level | Access | +|------|-------|--------| +| SUPERUSER | Platform | All tenants (god mode) | +| PLATFORM_MANAGER | Platform | All tenants | +| PLATFORM_SALES | Platform | Demo accounts only | +| PLATFORM_SUPPORT | Platform | Can masquerade as tenant users | +| TENANT_OWNER | Tenant | Full tenant access | +| TENANT_MANAGER | Tenant | Most tenant features | +| TENANT_STAFF | Tenant | Limited tenant access | +| CUSTOMER | Tenant | Own data only | -### Masquerading Matrix - -| Hijacker Role | Can Masquerade As | -|--------------------|----------------------------------| -| SUPERUSER | Anyone | -| PLATFORM_SUPPORT | Tenant users | -| PLATFORM_SALES | Demo accounts (`is_temporary=True`) | -| TENANT_OWNER | Staff in same tenant | -| Others | No one | - -**Security Rules:** -- Cannot hijack yourself -- Cannot hijack SUPERUSERs (except by other SUPERUSERs) -- Maximum depth: 1 (no hijack chains) -- All attempts logged to `logs/masquerade.log` - -## ๐Ÿ“ Project Structure +### Request Flow ``` -smoothschedule/ -โ”œโ”€โ”€ config/ -โ”‚ โ””โ”€โ”€ settings.py # Multi-tenancy & security config -โ”œโ”€โ”€ core/ -โ”‚ โ”œโ”€โ”€ models.py # Tenant, Domain, PermissionGrant -โ”‚ โ”œโ”€โ”€ permissions.py # Hijack permission matrix -โ”‚ โ”œโ”€โ”€ middleware.py # Masquerade audit logging -โ”‚ โ””โ”€โ”€ admin.py # Django admin for core models -โ”œโ”€โ”€ users/ -โ”‚ โ”œโ”€โ”€ models.py # Custom User with 8-tier roles -โ”‚ โ””โ”€โ”€ admin.py # User admin with hijack button -โ”œโ”€โ”€ logs/ -โ”‚ โ”œโ”€โ”€ security.log # General security events -โ”‚ โ””โ”€โ”€ masquerade.log # Hijack activity (JSON) -โ””โ”€โ”€ setup_project.sh # Automated setup script +Browser โ†’ Traefik (SSL) โ†’ nginx (frontend) or django (API) + โ†“ + React SPA + โ†“ + /api/* โ†’ django:5000 + /ws/* โ†’ django:5000 (WebSocket) ``` -## ๐Ÿ” Security Features - -### Audit Logging - -All masquerade activity is logged in JSON format: - -```json -{ - "timestamp": "2024-01-15T10:30:00Z", - "action": "HIJACK_START", - "hijacker_email": "support@smoothschedule.com", - "hijacked_email": "customer@demo.com", - "ip_address": "192.168.1.1", - "session_key": "abc123..." -} -``` - -### Permission Grants (30-Minute Window) - -Time-limited elevated permissions: - -```python -from core.models import PermissionGrant - -grant = PermissionGrant.create_grant( - grantor=admin_user, - grantee=support_user, - action="view_billing", - reason="Customer requested billing support", - duration_minutes=30, -) - -# Check if active -if grant.is_active(): - # Perform privileged action - pass -``` - -## ๐Ÿงช Testing Masquerading - -1. Access Django Admin: `http://localhost:8000/admin/` -2. Create test users with different roles -3. Click "Hijack" button next to a user -4. Verify audit logs: `docker-compose exec django cat logs/masquerade.log` - -## ๐Ÿ“Š Admin Interface - -- **Tenant Management**: View tenants, domains, subscription tiers -- **User Management**: Color-coded roles, masquerade buttons -- **Permission Grants**: Active/expired/revoked status, bulk revoke -- **Domain Verification**: AWS Route53 integration status - -## ๐Ÿ› ๏ธ Development - -### Adding Tenant Apps - -Edit `config/settings.py`: - -```python -TENANT_APPS = [ - 'django.contrib.contenttypes', - 'appointments', # Your app - 'resources', # Your app - 'billing', # Your app -] -``` - -### Custom Domain Setup - -```python -domain = Domain.objects.create( - domain="app.customdomain.com", - tenant=tenant, - is_custom_domain=True, - route53_zone_id="Z1234567890ABC", -) -``` - -Then configure Route53 CNAME: `app.customdomain.com` โ†’ `smoothschedule.yourhost.com` - -## ๐Ÿ“– Key Files Reference - -| File | Purpose | -|------|---------| -| `setup_project.sh` | Automated project initialization | -| `config/settings.py` | Multi-tenancy, middleware, security config | -| `core/models.py` | Tenant, Domain, PermissionGrant models | -| `core/permissions.py` | Masquerading permission matrix | -| `core/middleware.py` | Audit logging for masquerading | -| `users/models.py` | Custom User with 8-tier roles | - -## ๐Ÿ“ Important Notes - -- **Django Admin**: The ONLY HTML interface (everything else is API) -- **Middleware Order**: `TenantMainMiddleware` must be first, `MasqueradeAuditMiddleware` after `HijackUserMiddleware` -- **Tenant Isolation**: Each tenant's data is in a separate PostgreSQL schema -- **Production**: Update `SECRET_KEY`, database credentials, and AWS keys via environment variables - -## ๐Ÿ› Troubleshooting - -**Cannot create tenant users:** -- Error: "Users with role TENANT_STAFF must be assigned to a tenant" -- Solution: Set `user.tenant = tenant_instance` before saving - -**Hijack button doesn't appear:** -- Check `HIJACK_AUTHORIZATION_CHECK` in settings -- Verify `HijackUserAdminMixin` in `users/admin.py` -- Ensure user has permission per matrix rules - -**Migrations fail:** -- Run shared migrations first: `migrate_schemas --shared` -- Then run tenant migrations: `migrate_schemas` - -## ๐Ÿ“„ License - -MIT - -## ๐Ÿค Contributing - -This is a production skeleton. Extend `TENANT_APPS` with your business logic. - --- -**Built with โค๏ธ for multi-tenant SaaS perfection** +## Configuration Files + +### Backend + +| File | Purpose | +|------|---------| +| `smoothschedule/docker-compose.local.yml` | Local Docker services | +| `smoothschedule/docker-compose.production.yml` | Production Docker services | +| `smoothschedule/.envs/.local/` | Local environment variables | +| `smoothschedule/.envs/.production/` | Production environment variables | +| `smoothschedule/config/settings/` | Django settings | +| `smoothschedule/compose/production/traefik/traefik.yml` | Traefik routing config | + +### Frontend + +| File | Purpose | +|------|---------| +| `frontend/.env.development` | Local environment variables | +| `frontend/.env.production` | Production environment variables | +| `frontend/nginx.conf` | Production nginx config | +| `frontend/vite.config.ts` | Vite bundler config | + +--- + +## Troubleshooting + +### Backend won't start + +```bash +# Check Docker logs +docker compose -f docker-compose.local.yml logs django + +# Common issues: +# - Database not ready: wait longer, then restart django +# - Missing migrations: run migrate command +# - Port conflict: check if 8000 is in use +``` + +### Frontend can't connect to API + +```bash +# Verify backend is running +curl http://lvh.me:8000/api/ + +# Check CORS settings in Django +# Ensure CORS_ALLOWED_ORIGINS includes http://platform.lvh.me:5173 +``` + +### WebSockets disconnecting + +```bash +# Check nginx has /ws/ proxy configured +# Verify django is running ASGI (Daphne) +# Check production traefik/nginx logs +``` + +### Multi-tenant issues + +```bash +# Check tenant exists +docker compose exec django python manage.py shell +>>> from smoothschedule.identity.core.models import Tenant, Domain +>>> Tenant.objects.all() +>>> Domain.objects.all() +``` + +--- + +## Additional Documentation + +- **[CLAUDE.md](CLAUDE.md)** - Development guide, coding standards, architecture details +- **[DEPLOYMENT.md](DEPLOYMENT.md)** - Comprehensive deployment guide +- **[PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md)** - Step-by-step manual deployment + +--- + +## License + +MIT