Files
chat-app/CLAUDE.md
kappa 554c578345 Initial commit: Anvil Lounge chat application
- React frontend with Vite + TypeScript
- Cloudflare Worker backend with Durable Objects
- AI-powered chat moderation via OpenAI
- WebSocket-based real-time messaging
- XSS prevention, rate limiting, input validation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:17:27 +09:00

87 lines
3.5 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Real-time chat application with AI-powered moderation. Korean-language community chat ("Anvil Lounge") with an AI bot host (방장) that moderates conversations, answers questions, and provides weather/documentation lookups.
## Architecture
```
chat-app/
├── frontend/ # React SPA (Vite + TypeScript)
│ └── src/
│ ├── components/ # ChatRoom, MessageList, MessageInput
│ ├── hooks/ # useWebSocket (WebSocket client with reconnection)
│ └── utils/ # sanitize.ts (XSS prevention, markdown→HTML)
└── worker/ # Cloudflare Worker + Durable Object
└── src/
├── index.ts # HTTP router, CORS handling
├── ChatRoom.ts # Durable Object: WebSocket hub, message persistence
├── AIManager.ts # OpenAI integration, moderation, tool calling
├── Context7Client.ts # Documentation lookup API
├── RateLimiter.ts # In-memory rate limiting
└── validation.ts # Zod schemas for message validation
```
### Key Design Patterns
**Durable Objects with Hibernation API**: `ChatRoom` uses `webSocketMessage()`, `webSocketClose()`, `webSocketError()` handlers instead of event listeners. Session data stored via `ws.serializeAttachment()`.
**AI Moderation Flow**: Messages are checked by AI for profanity before broadcast. Detected words are masked (첫 글자 + asterisks). Repeated violations trigger auto-silence via `trackViolation()` → DO storage transaction.
**Storage Patterns**: All DO storage operations use transactions for atomicity and retry logic with jitter for resilience.
## Development Commands
```bash
# Root-level (npm workspaces)
npm run dev:worker # Start worker dev server (wrangler)
npm run dev:frontend # Start Vite dev server (localhost:5173)
npm run build:worker # Build worker
npm run build:frontend # Build frontend (tsc + vite)
npm run deploy:worker # Deploy to Cloudflare Workers
npm run deploy:frontend # Deploy to Cloudflare Pages
# Type checking
cd worker && npx tsc --noEmit
cd frontend && npx tsc --noEmit
# Worker secrets
wrangler secret put OPENAI_API_KEY
```
## API Endpoints
| Endpoint | Description |
|----------|-------------|
| `GET /api/rooms/:roomId/websocket` | WebSocket upgrade for chat |
| `GET /api/rooms/:roomId/users` | List users in room |
| `GET /api/health` | Health check |
## WebSocket Message Types
**Client → Server**: `{ type: "message", content: string }` or `{ type: "rename", name: string }`
**Server → Client**: `message`, `join`, `leave`, `userList`, `history`, `error`
## Configuration Alignment
Frontend `config.ts` and backend `validation.ts` must stay in sync:
- `maxMessageLength`: 2000 characters
- `maxUserNameLength`: 50 characters
## Security Considerations
- XSS prevention: `sanitize.ts` uses DOMPurify + custom URL validation (`isUrlSafe()`) to block encoded `javascript:` attacks
- API key redaction: `sanitizeErrorForLogging()` in AIManager.ts strips credentials from error logs
- CORS: Strict origin allowlist in `index.ts` (includes Pages preview deployments)
- Input validation: All WebSocket messages validated with Zod schemas before processing
## External Services
- **OpenAI API**: Chat completions with function calling (weather, docs, hosting info, silence user)
- **Open-Meteo API**: Weather data (no API key required)
- **Context7 API**: Documentation lookup for technical questions