# CLAUDE.md

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

## Project Overview

ajet-chat is a Clojure monorepo for a team messaging platform (Slack-like). Early stage — module skeletons exist but most code is stubbed out.

## Repository Structure

Monorepo with `:local/root` deps linking modules:

- **shared/** — Common DB layer (next.jdbc + HoneySQL), EventBus (NATS via jnats), API client SDK, schemas, protocols
- **auth-gw/** — Auth gateway: http-kit edge proxy, session/token validation, routing (has PG access)
- **api/** — Stateless REST API: all data reads/writes to PG, publishes events to NATS
- **web-sm/** — Web session manager: Hiccup + Datastar SSE for browsers (NATS + API, no PG)
- **tui-sm/** — TUI session manager: SSE for terminal clients (NATS + API, no PG)
- **cli/** — Terminal client: CLI (one-shot) + TUI (interactive via clojure-tui)
- **mobile/** — Mobile client (deferred, placeholder only)

**Dependency matrix:**
```
              PG    NATS   API(HTTP)
API           yes   pub    —
Auth GW       yes   —      —
Web SM        —     sub    yes (internal)
TUI SM        —     sub    yes (internal)
CLI           —     —      yes (external, via Auth GW)
```

## Common Commands

### Task Runner (Babashka)

Preferred way to run tasks — `bb` wraps `clj` commands and manages Docker infra automatically.

```bash
bb tasks                  # List all available tasks

# Development
bb dev                    # Start dev infra + nREPL (all modules)
bb infra:dev              # Start dev Docker infra only
bb infra:dev:stop         # Stop dev Docker infra

# Testing
bb test                   # All tests (starts test infra)
bb test:unit              # Unit tests only (no Docker needed)
bb test:integration       # Integration tests (starts test infra)
bb test:e2e               # E2E tests (starts test infra)

# Per-module testing
bb test:shared            # All shared tests
bb test:shared:unit       # Shared unit tests only
bb test:api               # All API tests
bb test:api:unit          # API unit tests only
bb test:auth-gw           # All auth-gw tests

# Per-module bb.edn (from module directory)
cd shared && bb test:unit # Delegates to root bb.edn

# Build & Deploy
bb build api              # Build uberjar for a module
bb clean api              # Clean module artifacts (or bb clean for all)
bb prod                   # Start production stack (docker compose)
bb prod:stop              # Stop production stack
bb prod:logs              # Tail production logs

# Database
bb db:reset-test          # Drop & recreate test DB schema
```

### Running Services (REPL-driven)

```bash
# Via bb (recommended)
bb dev                    # nREPL with all modules + dev infra

# Via clj directly
clj -A:dev:api:web-sm:tui-sm:auth-gw   # Single REPL with all modules
clj -M:dev:api                          # Individual service REPL
```

Services expose `(start!)` / `(stop!)` / `(reset!)` in their REPL namespaces.

### Testing (Kaocha)

```bash
# Via bb (recommended — manages Docker infra automatically)
bb test:unit              # Unit tests — no Docker needed
bb test:integration       # Integration — starts Docker automatically
bb test                   # All tiers

# Via clj directly (legacy — requires manual Docker management)
clj -M:test/base:test/unit          # Unit tests
clj -M:test/base:test/integration   # Integration tests
clj -M:test -m kaocha.runner        # All tests (using unified :test alias)
```

Docker infra for integration tests: `docker compose -f docker-compose.test.yml up -d`

### Architecture Diagram

```bash
typst compile architecture.typst architecture.png
```

## Architecture

**Request flow:** Internet → nginx (TLS, prod only) → Auth Gateway → service (API / Web SM / TUI SM)

**Key pattern — data vs events separation:**
- All persistent data reads/writes go through the **API** (stateless REST, only service with PG access besides Auth GW)
- Real-time events flow via **NATS** pub/sub (community-scoped subjects)
- **Session managers** hold live client connections, subscribe to NATS for events, fetch full data from API via HTTP. No direct PG connection.
- SMs publish ephemeral events (typing indicators) directly to NATS — bypasses API for latency

**Auth Gateway** is a Clojure http-kit proxy that does its own DB reads/writes for session validation, then routes authenticated requests to internal services.

## Tech Stack

- All server modules: Clojure 1.12, http-kit 2.8, reitit 0.7, Ring 1.13
- Data: PostgreSQL (next.jdbc + HoneySQL) — API + Auth GW only
- Events: NATS (io.nats/jnats) — API publishes, SMs subscribe
- Web: Hiccup 2.0 + Datastar SDK (web-sm)
- CLI: shared API client SDK (babashka http-client) + clojure-tui (local dep at `../../clojure-tui`)
- Files: MinIO (S3-compatible)

## Conventions

- **PostgreSQL everywhere** — same DB in dev and prod, no SQLite. Dev infra runs in Docker.
- **HoneySQL maps** for all queries — avoid raw SQL strings
- **Migratus** for schema migrations
- **NATS** for all event pub/sub — community-scoped subjects (`chat.events.{community-id}`), DM subjects (`chat.dm.{channel-id}`)
- **MinIO** (S3-compatible) for file storage — same API as AWS S3
- **UUIDs** for all entity IDs (`java.util.UUID/randomUUID`)
- **EventBus protocol**: `publish!`, `subscribe!`, `unsubscribe!` — backed by NATS
- **SSE** for all server→client streaming (web + TUI), HTTP POSTs for client→server signals

## Namespace Conventions

```
ajet.chat.shared.*    — shared/src/
ajet.chat.api.*       — api/src/
ajet.chat.web.*       — web-sm/src/
ajet.chat.tui-sm.*    — tui-sm/src/
ajet.chat.auth-gw.*   — auth-gw/src/
ajet.chat.cli.*       — cli/src/
```
