# CLAUDE.md

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

## Project Overview

RoadWave is a geo-localized audio social network for road users (drivers, pedestrians, tourists). Users listen to audio content (podcasts, audio guides, ads, live radio) based on their geographic location and interests.

**Tech Stack**:
- Backend: Go 1.21+ with Fiber framework
- Mobile: Flutter (see [ADR-014](docs/adr/014-frontend-mobile.md))
- Database: PostgreSQL 16+ with PostGIS extension
- Cache: Redis 7+ with geospatial features
- Auth: Zitadel (self-hosted IAM)
- Data Access: sqlc for type-safe SQL code generation
- Streaming: HLS protocol with Opus codec

## Monorepo Structure

This is a monorepo organized as follows:

```
/backend          → Go backend API (modular monolith)
/mobile           → Flutter mobile app
/features         → Shared BDD Gherkin features (test specs)
/docs/adr         → Architecture Decision Records
/shared           → Shared code and API contracts
/docker           → Docker configuration files
```

**Important**: BDD test features (`.feature` files) are shared in `/features`, but each component implements its own step definitions:
- Backend step definitions: `backend/tests/bdd/`
- Mobile step definitions: `mobile/tests/bdd/`

See [ADR-016](docs/adr/016-organisation-monorepo.md) for monorepo organization rationale.

## Backend Architecture

**Modular monolith** with clear module separation ([ADR-012](docs/adr/012-architecture-backend.md)):

```
backend/internal/
├── auth/         # JWT validation, Zitadel integration
├── user/         # User profiles, interest gauges
├── content/      # Content CRUD, metadata
├── geo/          # Geospatial search, recommendation algorithm
├── streaming/    # HLS generation, transcoding
├── moderation/   # Content moderation, reporting workflow
├── payment/      # Mangopay integration
└── analytics/    # Listening metrics, interest gauge evolution
```

**Module pattern**: Each module follows `handler.go` → `service.go` → `repository.go`.

**Database access**: Uses `sqlc` ([ADR-013](docs/adr/013-orm-acces-donnees.md)) for type-safe Go code generation from SQL queries. This allows writing complex PostGIS spatial queries while maintaining compile-time type safety.

## Development Commands

**IMPORTANT**: Always use `docker compose` (not `docker-compose`) as per user preferences.

All commands must be run from the **monorepo root**:

### Development
```bash
make init              # Initialize project (install tools, setup .env)
make dev               # Start backend with hot reload (Air)
make docker-up         # Start all services (API, PostgreSQL, Redis, Zitadel, Adminer)
make docker-down       # Stop all Docker services
make docker-logs       # Show Docker logs
```

Services after `make docker-up`:
- API: http://localhost:8080
- Zitadel: http://localhost:8081
- Adminer: http://localhost:8082

### Testing

**Test Strategy** ([ADR-015](docs/adr/015-strategie-tests.md)):
- Unit tests: Testify (80%+ coverage target)
- Integration tests: Testcontainers (for PostGIS queries)
- BDD tests: Godog/Gherkin (user stories validation)

```bash
make test              # Run all tests (unit + integration + BDD)
make test-unit         # Unit tests only (fast, ~30s)
make test-integration  # Integration tests with Testcontainers
make test-bdd          # BDD tests with Godog (Gherkin features)
make test-coverage     # Generate coverage report (coverage.html)
```

**Running a single test**:
```bash
cd backend
go test -v -run TestFunctionName ./path/to/package
```

**Running a single BDD feature**:
```bash
godog run features/path/to/feature.feature
```

### Database

```bash
make migrate-up                      # Apply all migrations
make migrate-down                    # Rollback last migration
make migrate-create name=add_users   # Create new migration
make migrate-version                 # Show current migration version
make sqlc-generate                   # Generate Go code from SQL queries
```

**After modifying SQL queries** in `backend/queries/*.sql`, always run `make sqlc-generate` to regenerate Go code.

### Build & Code Quality

```bash
make build             # Build production binary (backend/bin/api)
make lint              # Run golangci-lint
make format            # Format Go code (gofmt)
make deps              # Download and tidy Go dependencies
make clean             # Clean build artifacts
```

### Documentation

```bash
make docs-serve        # Generate BDD docs and serve MkDocs (http://localhost:8000)
make bdd-docs          # Same as docs-serve
make docs-pdf          # Generate PDF of all documentation
make docs-clean        # Remove generated docs and PDF
```

## Working with sqlc

When adding or modifying database queries:

1. Write SQL query in `backend/queries/*.sql`:
```sql
-- name: GetContentNearby :many
SELECT id, title, ST_Distance(location, $1::geography) as distance
FROM contents
WHERE ST_DWithin(location, $1::geography, $2)
ORDER BY distance
LIMIT $3;
```

2. Run code generation:
```bash
make sqlc-generate
```

3. Use generated type-safe Go code:
```go
contents, err := q.GetContentNearby(ctx, location, radius, limit)
```

## Writing BDD Tests

BDD features use Gherkin syntax ([ADR-007](docs/adr/007-tests-bdd.md)):

1. Write feature in `/features/<domain>/<feature>.feature`
2. Implement step definitions in `backend/tests/bdd/` for API testing
3. Run with `make test-bdd`

Example feature:
```gherkin
Feature: Geolocalised recommendation

  Scenario: Tourist near a monument
    Given a user with "tourism" interest at 80%
    And a GPS position 100m from the Eiffel Tower
    When the system calculates recommendations
    Then the audio guide "Histoire de la Tour Eiffel" is in first position
```

## Key Architectural Decisions

All technical decisions are documented in Architecture Decision Records (ADRs) in `/docs/adr/`:

- [ADR-001](docs/adr/001-langage-backend.md): Backend language (Go)
- [ADR-002](docs/adr/002-protocole-streaming.md): Streaming protocol (HLS)
- [ADR-005](docs/adr/005-base-de-donnees.md): Database (PostgreSQL + PostGIS)
- [ADR-008](docs/adr/008-authentification.md): Authentication (Zitadel)
- [ADR-012](docs/adr/012-architecture-backend.md): Backend architecture (modular monolith)
- [ADR-013](docs/adr/013-orm-acces-donnees.md): Data access (sqlc)
- [ADR-016](docs/adr/016-organisation-monorepo.md): Monorepo organization

**When making architectural decisions**, check if there's an existing ADR or create a new one following the established pattern.

## Recommendation Algorithm

Core feature combining geolocation and interest matching:

- **Geographic priority**: GPS point > city > department > region > country
- **Interest gauges**: Dynamic scores per category (automobile, travel, music, etc.)
- **Combined scoring**: Distance + interest matching
- **Cache**: Redis geospatial for performance (`GEORADIUS`)

The algorithm is implemented in `backend/internal/geo/` and uses PostGIS functions like `ST_DWithin`, `ST_Distance`.

## Common Patterns

### Module Structure
Each backend module follows this pattern:
```
internal/modulename/
├── handler.go      # HTTP handlers (Fiber routes)
├── service.go      # Business logic
├── repository.go   # Database access (sqlc generated code)
└── models.go       # Domain models (if needed)
```

### Error Handling
Use the custom error package in `backend/pkg/errors/` for consistent error handling across the application.

### Configuration
Environment variables are loaded via `backend/pkg/config/`. Development config is in `backend/.env` (copied from `.env.example` during `make init`).

## PostGIS Spatial Queries

Example patterns for geospatial operations:

```sql
-- Find content within radius
WHERE ST_DWithin(location::geography, ST_MakePoint($lon, $lat)::geography, $radius_meters)

-- Calculate distance
SELECT ST_Distance(location::geography, ST_MakePoint($lon, $lat)::geography) as distance

-- Order by proximity
ORDER BY location <-> ST_MakePoint($lon, $lat)::geography
```

## Testing with Testcontainers

Integration tests that require PostGIS use Testcontainers to spin up a real PostgreSQL+PostGIS instance:

```go
// backend/tests/integration/geo_test.go
// Uses testcontainers to validate complex spatial queries
```

This ensures PostGIS queries work correctly without mocking.

## Authentication Flow

Zitadel handles authentication ([ADR-008](docs/adr/008-authentification.md)):
- Self-hosted on OVH (France data sovereignty)
- OAuth2 PKCE for mobile apps
- JWT validation in backend using zitadel-go SDK
- Shares PostgreSQL database with RoadWave (separate schema)

## Performance Targets

See [TECHNICAL.md](TECHNICAL.md) for detailed metrics:
- API latency p99: < 100ms
- Audio start time: < 3s
- Target availability: 99.9%
- Concurrent connections/server: 100K+
