# Crussell — Overview

**Last Updated:** May 2026
**Status:** Local development — not yet in production

---

## What is Crussell?

Crussell is a full-stack booking platform built for a UK-based sole-trader nail artist. It handles the complete customer journey: browsing services, checking availability, booking appointments, managing profiles, and exporting calendar data. Admins manage the schedule, approve bookings, handle walk-ins and call-ins, and track customer relationships.

The business operates exclusively in the UK (Europe/London timezone). Cloudflare geo-blocking prevents non-UK access. No automatic timezone conversion is performed — times shown are actual salon times.

---

## Tech Stack

| Layer | Technology |
|-------|-----------|
| **Backend** | Go 1.25, chi router, PostgreSQL driver (pgx) |
| **Frontend** | SvelteKit 5 (static adapter SPA), Svelte 5 runes ($state, $bindable, $effect), Tailwind CSS, shadcn-svelte, bits-ui |
| **Database** | PostgreSQL 17 with custom ID generation, partial indexes, GDPR functions |
| **DAV** | SabreDAV (PHP 8.2-FPM) for CardDAV/CalDAV contact and calendar sync |
| **Storage** | S3/R2 abstraction — RustFS in dev, Cloudflare R2 in prod (build tags) |
| **Proxy** | Nginx (static frontend + API reverse proxy + DAV proxy) |
| **Containerisation** | Docker Compose (postgres, backend, sabredav, nginx) |
| **Testing** | Go test with shared test database, TestMain per package, TRUNCATE CASCADE between tests |

---

## Architecture

```mermaid
flowchart TD
    User([Customer])
    Admin([Admin])

    subgraph Docker[Docker Compose Stack]
        subgraph NGINX[Nginx :80/:443]
            Static[Static Frontend Build]
            Proxy[API Proxy → Backend:8080]
            DAVProxy[DAV Proxy → SabreDAV]
        end

        subgraph Backend[Go + Chi :8080]
            Router[chi Router]
            Auth[JWT Middleware]
            Handlers[API Handlers]
        end

        subgraph Database[PostgreSQL :5432]
            DB[(Users / Bookings<br/>Payments / Services<br/>Scheduling)]
        end

        subgraph DAV[SabreDAV :9000]
            CardDAV[(vCard Contacts)]
            CalDAV[(Calendar Events)]
        end
    end

    subgraph External[External Services]
        S3[S3/R2 Storage]
        Gmail[Gmail SMTP]
        SquareAPI[Square API]
    end

    User -->|HTTPS| NGINX
    Admin -->|HTTPS| NGINX
    Static --> User
    Proxy --> Router
    Router --> Auth
    Auth --> Handlers
    Handlers --> DB
    Handlers --> DAV
    Handlers --> S3
    Handlers -.->|TODO| Gmail
    Handlers -.->|TODO| SquareAPI
```

---

## Key Features

### Authentication & Identity
- JWT authentication (HS256, 30-day expiry) with auto-refresh
- User registration with input validation (names, UK phone, email, age 16+)
- Password hashing with bcrypt
- Role-based access: `unverified_email`, `verified_email`, `admin`, `guest`, `affiliate`
- Refresh token with role-change detection (forces re-login if role changed)
- Email verification and password reset endpoints (backend ready, frontend not wired)
- Guest/disposable accounts for one-off bookings

### Booking System
- Three booking flows: self-service (customer), walk-in (admin), call-in (admin)
- Service eligibility filtering (age requirements + patch test validation)
- Slot reservation system with 4 TTL types (user: 1h, anonymous: 10min, walk-in: 5min, call-in: 1h)
- Anonymous reservation cap (50 per 10-minute rolling window)
- Auto-status transitions: confirmed → in_progress → completed
- Booking edit requests (customers can request reschedule, admin approves/denies)
- Admin booking service editing with overlap detection and price/duration overrides
- Idempotency keys for booking deduplication

### Scheduling
- Default weekly working hours (Mon-Fri, closed Sat/Sun)
- Exceptional schedule groups (holiday periods, special hours)
- Time blockers (admin-defined unavailable periods, plus slot reservations)
- Available hours calculation accounting for bookings, blockers, and gaps

### Customer Features
- Profile management with profile picture upload (cropper, separate S3 bucket)
- Loyalty stamps display
- Booking history with cancel/reschedule
- Calendar export (.ics download)
- Portfolio browsing with tag/category filtering

### Admin Features
- Today page (/today): current/next appointment, today's grid, pending approvals
- Admin dashboard (/admin): services CRUD, user management, bookings list, scheduling
- Walk-in booking wizard (3-step) with slot reservation
- Call-in booking wizard (4-step) with slot reservation
- User modal: profile, booking history, customer relationship data (spend, visits, top services), patch test recording, loyalty/referrals, privacy/consent
- Booking modal: view details, approve/cancel
- Approval modal for pending bookings
- Portfolio image upload with tag management
- Discount campaign management (time-based and milestone campaigns)
- Admin notification system (pull-based, acknowledgment)

### Deposit System
- Simplified tracking: `deposits_required` integer (0-3) on users table
- 24-hour late cancellation rule: < 24h without forgiveness = no-show + 3 deposits
- Per-cancellation forgiveness option
- Deposit reduction by 1 when booking completes with payment
- Admin can bypass deposit checks (`enforce_deposits: false`)
- Guest bookings bypass deposit checks entirely

### Data & Compliance
- GDPR anonymization: guest PII scrubbed 6 months after booking start_time
- Registered user account deletion via `anonymize_user()` SQL function
- GDPR data export function (`export_all_user_data()`) — not yet wired to endpoint
- VAT/tax export functions (`get_vat_return_data()`, `export_sales_transactions()`) — not yet wired
- Image metadata stripping (EXIF/GPS removed on upload)
- Partial unique email index: guests can share emails, registered users cannot

### Integrations
- CardDAV: profile photos synced to SabreDAV contacts (vCard PHOTO field)
- CalDAV: ready for calendar event sync
- S3/R2: portfolio image storage (RustFS dev, Cloudflare R2 prod)
- Square: placeholder only (payment integration pending)

---

## Booking Flows

| Flow | Who | Entry Point | Reservation TTL |
|------|-----|-------------|-----------------|
| **Self-Service** | Customer | `/book` → BookingFlow wizard → `POST /api/bookings` | 1h (logged-in) / 10min (anonymous) |
| **Walk-In** | Admin | Admin panel → WalkInBooking → `POST /api/admin/bookings/reserve` → WalkInCreateModal | 5min |
| **Call-In** | Admin | Admin panel → CallInBooking → `POST /api/admin/bookings/reserve` → BookingCreateModal | 1h |

All flows integrate with holiday/exceptional hours and time blockers.

---

## Quick Links

- [[User Manual]] — Customer-facing journeys: booking, account management, portfolio
- [[Admin Manual]] — Admin workflows: today page, booking management, user management, scheduling
- [[Technical Manual]] — Architecture, API reference, database schema, key systems
- [[Future Work - Gap Backlog]] — Prioritised backlog of remaining work

---

## Test Coverage

**306/308 tests passing** across 10+ test packages.

| Package | Coverage Area |
|---------|--------------|
| `handlers/auth` | Authentication (login, register, refresh, verification) |
| `handlers/bookings` | User booking flow, guest bookings, reservations, edit requests, discounts |
| `handlers/admin` | Admin bookings, today view, users, services |
| `handlers/scheduling` | Working hours, exceptional groups, available hours, time blockers |
| `handlers/services` | Service eligibility (age + patch test filtering) |
| `handlers/user` | User profile, guest creation, loyalty |
| `handlers/portfolio` | Image upload, listing, tags, filters |
| `handlers/notifications` | Admin notifications (GET, acknowledge) |
| `handlers/handlers_test.go` | Common handler tests |
| `bookings_test.go` | Main booking integration tests |

### Test Infrastructure
- TestMain per package — schema migration runs once per package
- TruncateTables() between tests — TRUNCATE CASCADE, ~60% faster than DROP+CREATE
- Shared test database — tests run sequentially (`-p 1`)
- Test tokens use fixed secret: `test-secret-key-for-testing-only`
- Fixtures auto-generate unique emails
- All test files use `//go:build test` build tag

---

## Seed Data Summary

Running `local-dev-2.sh` creates:

| Resource | Count |
|----------|-------|
| Users | 20 (1 admin, 19 regular) |
| Services | 12 (10 standard + 2 requiring patch tests) |
| Past Bookings | 18 |
| Today's Bookings | 4 |
| Tomorrow's Bookings | 5 |
| Upcoming Bookings | 16 |
| Guest Bookings | 3 |
| Total Bookings | 43 |
| Payments | 22 completed bookings |
| Time Blockers | 3 |
| Schedule Groups | 3 |
| Cancellations | 1 |
