Files
HermesMessages/CLAUDE.md
Hanzo_dev 798bd14312 feat: initial commit — HermesMessages SaaS platform
Backend (FastAPI + Python 3.12):
- Multi-tenant auth with JWT: login, register, refresh, Meta OAuth
- Business & BusinessConfig management
- WhatsApp webhook with HMAC signature verification
- Bot engine powered by Claude AI
- Calendar availability with Redis caching
- Reservations CRUD with status management
- Dashboard analytics (stats, agenda, peak hours)
- Billing & plan management
- Admin panel with platform-wide stats
- Async bcrypt via asyncio.to_thread
- IntegrityError handling for concurrent registration race conditions

Frontend (React 18 + Vite + Tailwind CSS):
- Multi-step guided registration form with helper text on every field
- Login page with show/hide password toggle
- Protected routes with AuthContext
- Dashboard with stats cards, bar chart, and daily agenda
- Reservations list with search, filters, and inline status actions
- Calendar with weekly view, slot availability, and date blocking
- Config page: business info, schedules, bot personality
- Billing page with plan comparison and usage bar

Design system:
- Bricolage Grotesque + DM Sans typography
- Emerald primary palette with semantic color tokens
- scale(0.97) button press feedback, ease-out animations
- Skeleton loaders, stagger animations, prefers-reduced-motion support
- Accessible: aria-labels, visible focus rings, 4.5:1 contrast

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 09:49:41 -05:00

5.1 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Multi-tenant SaaS platform for automating WhatsApp Business reservations via an AI-powered bot. Businesses (restaurants, clinics, salons) connect their WhatsApp and a Claude-powered bot handles bookings conversationally.

Repository Structure

hermesmessages/
├── backend/     # FastAPI API — Python 3.12+
├── frontend/    # (in progress)
└── database/    # docker-compose.yml (PostgreSQL + Redis)

Tech Stack

Layer Technology
Language Python 3.12+
Framework FastAPI
Database PostgreSQL + SQLAlchemy (async) + Alembic
Cache Redis
Validation Pydantic v2
Auth JWT
AI Claude API (claude-sonnet-4-20250514)
Testing Pytest

Common Commands

All backend commands run from backend/:

# Start local services
cd database && docker-compose up -d

# Install dependencies
cd backend && pip install -r requirements.txt

# Run development server
cd backend && uvicorn app.main:app --reload

# Run migrations
cd backend && alembic upgrade head

# Generate new migration
cd backend && alembic revision --autogenerate -m "description"

# Run tests
cd backend && pytest

# Run a single test file
cd backend && pytest tests/test_calendar.py

Backend Architecture

Module Structure

backend/
├── app/
│   ├── main.py
│   ├── core/                    # Config & infrastructure
│   │   ├── config.py            # pydantic-settings
│   │   ├── database.py          # async PostgreSQL
│   │   ├── redis.py
│   │   ├── security.py          # JWT, hashing
│   │   ├── dependencies.py      # get_current_business, require_admin
│   │   └── errors.py            # global exception handler
│   ├── modules/
│   │   ├── auth/
│   │   ├── business/
│   │   ├── whatsapp/
│   │   ├── bot_engine/
│   │   ├── calendar/
│   │   ├── reservations/
│   │   ├── notifications/
│   │   ├── dashboard/
│   │   ├── billing/
│   │   └── admin/
│   └── shared/
├── alembic/
│   └── versions/0001_initial.py
└── requirements.txt

Each module contains: router.py, service.py, models.py, schemas.py, and optionally dependencies.py.

Module Data Flow

WhatsApp webhook → Bot Engine → Calendar → Reservations → Notifications
                       ↑
                 Business Config

Critical Business Logic

Multi-tenancy Rule

business_id is always extracted from the JWT token — never from the request body or path params. All queries must filter by business_id from the token. Exception: the WhatsApp webhook resolves business_id via whatsapp_phone_number_id (no JWT on webhook calls).

Availability Calculation (calendar/service.py)

  1. Fetch BusinessConfig for the business
  2. Check if date is in open_days and not in blocked_dates
  3. Generate all time slots using open_time, close_time, slot_duration
  4. Query confirmed+pending reservations for that day
  5. Filter slots where existing count < max_per_slot
  6. Cache result in Redis with 5-minute TTL
  7. Invalidate cache when a reservation is created, updated, cancelled, or deleted

WhatsApp Webhook (whatsapp/router.py)

  • GET /whatsapp/webhook — Meta verification (return hub.challenge)
  • POST /whatsapp/webhook — Validate X-Hub-Signature-256, dispatch to bot engine via BackgroundTasks, respond 200 immediately

Bot Engine (bot_engine/service.py)

  1. Load/create ConversationContext from Redis (TTL: 30 min, key: conv:{business_id}:{phone})
  2. Build system prompt with: assistant name/tone, available slots, collected data, language instruction
  3. Call Claude API — response must be JSON with action: collect_more | create_reservation | cancel
  4. If create_reservation → call reservations/service.py::create_reservation, clear context
  5. If cancel → clear context
  6. Send reply via WhatsApp Graph API
  7. Save updated context to Redis

Key Models

  • Business — tenant record with Meta/WhatsApp credentials, plan (free|basic|pro), status (trial|active|suspended)
  • BusinessConfigopen_days (list of 0-6 ints), open_time/close_time, slot_duration (minutes), max_per_slot, blocked_dates (PostgreSQL ARRAY columns)
  • Reservationstatus: pending|confirmed|cancelled|no_show, source: whatsapp|manual, time_end computed from slot_duration
  • Userrole: owner|admin, meta_user_id for Facebook OAuth

Environment Variables

Defined in backend/.env.example:

DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/hermesmessages
REDIS_URL=redis://localhost:6379
SECRET_KEY=
META_APP_ID=
META_APP_SECRET=
META_WEBHOOK_VERIFY_TOKEN=
ANTHROPIC_API_KEY=
ENVIRONMENT=development|production

Access Control

  • All endpoints require JWT except GET/POST /whatsapp/webhook and /auth/*
  • /admin/* routes require role: admin (enforced via require_admin dependency)