docs: update CLAUDE.md with scaffold state and add Dragonfly to docker-compose

Documents current implementation status, Dragonfly session cache conventions,
and adds the Dragonfly service to the local dev compose stack.
This commit is contained in:
2026-04-21 20:34:06 +02:00
parent 5ae8744214
commit dbd7706e85
2 changed files with 42 additions and 1 deletions

View File

@@ -1,6 +1,21 @@
# Campaign Manager — CLAUDE.md
This project is in the **architecture/design phase**. No implementation code exists yet. The source of truth is `campaign_manager_design_v7.md`. `Symbiotes Documentation.md` is the TaleSpire platform API reference.
Scaffold complete — implementation in progress. The source of truth for the design is `campaign_manager_design_v7.md`. `Symbiotes Documentation.md` is the TaleSpire platform API reference. `NEXT_STEPS.md` is the canonical implementation roadmap (9 phases).
## Current State
Full project scaffold is in place as of 2026-03-10. All directories, configs, and stub files exist.
| Layer | Status |
|---|---|
| backend/campaign-service | Health endpoint live; auth routes stubbed (most return 501); `POST /auth/refresh` has a dev stub that issues a real JWT but has no DB session persistence |
| backend/content-service | Health endpoint only; all other routes stubbed |
| backend/common | `AppResult` error type, `issue_access_token` JWT helper |
| symbiote | All views scaffolded (Login, GroupList, GroupDetail, CharacterSheet, RollHistory); TS API events wired in `main.ts`; `store.ts` and `api.ts` exist |
| web | All SvelteKit routes scaffolded; API proxy endpoints exist (auth, campaign, content) |
| rulesets | `types.ts`, `dsa5e/index.ts`, `generic/index.ts` scaffolded |
**Next priority:** auth end-to-end (register → login → refresh → logout) in campaign-service. See `NEXT_STEPS.md`.
---
@@ -25,6 +40,7 @@ Three clients, one backend:
| DB queries | sqlx | Compile-time checked SQL, no ORM |
| Database | PostgreSQL 16 | JSONB for sheet_data; strong relational integrity |
| Auth | JWT + argon2id | argon2id preferred over bcrypt for new code |
| Cache / Sessions | Dragonfly (Redis-compatible) | Refresh token sessions + auth rate limiting; available in ITSH cluster |
| Object Storage | S3-compatible (Cloudflare R2) | Portrait images and .cmchar exports; keeps k8s pods stateless |
| Hosting | Kubernetes (no PVC) | Stateless pods; all persistence in Postgres + S3 |
@@ -164,6 +180,17 @@ Plugins live in a `rulesets/` directory. Adding one = dropping in a file + regis
- JWT access tokens: 15-minute lifetime. Refresh tokens: 30-day lifetime, **single-use with rotation**.
- Rate limit on auth endpoints: 10 req/min per IP.
### Dragonfly (Cache / Sessions)
Connection: `redis://<dragonfly-name>:6379` (standard Redis protocol). Use the `redis` crate in Rust.
| Use | Key pattern | TTL |
|---|---|---|
| Refresh token sessions | `rt:<token_id>``user_id` | 30 days |
| Auth rate limiting | `rl:auth:<ip>` → request count | 60 s sliding window |
Refresh token flow: on `POST /auth/refresh`, look up `rt:<token_id>` in Dragonfly; delete it (single-use); issue new pair and write new `rt:<new_token_id>`. On `POST /auth/logout`, delete `rt:<token_id>`. This replaces the dev stub that had no session persistence.
### Sync Strategy
- **`TS.sync`** — lightweight broadcast to all clients on the same board running the same Symbiote. Use for transient state (e.g. initiative announcements). No backend needed.
@@ -234,7 +261,13 @@ campaign-manager/
lib/
backend/ # Rust + Axum
campaign-service/migrations/ # sqlx migrations for cm_users + cm_campaign DBs
content-service/migrations/ # sqlx migrations for cm_content DB
common/ # Shared AppResult, JWT helpers
rulesets/ # Shared ruleset plugins (plain TS — imported by both frontends)
scripts/
ci-local.sh # Local CI: pnpm install, builds, cargo fmt/check, docker compose config
NEXT_STEPS.md # 9-phase implementation roadmap
```
---

View File

@@ -57,6 +57,14 @@ services:
networks:
- internal
dragonfly:
image: docker.io/dragonflydb/dragonfly:latest
restart: unless-stopped
networks:
- internal
ulimits:
memlock: -1
networks:
dev-infra:
external: true