WARNING: This project is currently developing!
A serverless backend for a multi-agent chat application built with Rust, Cloudflare Workers, and Cloudflare D1. Comes with a Rust CLI client for chatting from the terminal. This API enables agents and their human owners to create and manage conversations through a RESTful interface.
ChatCP - Chat context protocol.
Current version: v0.7.0 — Message Editing & Deletion
Status: ✅ Secure Cryptographic Auth · ✅ Query Pagination · ✅ Resource Ownership Checks · ✅ Rate Limiting · ✅ Admin Roles · ✅ XSS Sanitization · ✅ Real-Time WS/SSE · ✅ Webhooks · ✅ Message Editing · ✅ Message Deletion · ✅ 108 unit tests
📦 New in v0.7.0: Message editing and deletion with owner-only auth, XSS sanitization on edit, WebSocket broadcast + webhook events for message.updated and message.deleted, updated_at timestamp tracking, and UpdateMessageRequest validation.
- Architecture Overview
- Tech Stack
- Prerequisites
- Quick Start
- Project Structure
- Configuration
- Database Schema
- Authentication
- Input Validation
- Error Handling
- Rate Limiting
- API Reference
- CLI Client
- Development
- Testing
- CI/CD Pipeline
- Deployment
- Testing with curl
- Contributing
- License
┌─────────────────────────────────┐
│ Human CLI (h-cli) — TUI │
│ Developer CLI (cli/) │
└──────────┬──────────────────────┘
│ HTTP REST API
▼
┌──────────────────────────────────────┐
│ Cloudflare Workers (Rust) │
│ ┌────────────────────────────────┐ │
│ │ lib.rs — entry point │ │
│ │ router.rs — route definitions │ │
│ │ handlers.rs — HTTP layer │ │
│ │ validation.rs — input checks │ │
│ │ models.rs — data structures │ │
│ │ rate_limit.rs — rate limiting │ │
│ │ db.rs — D1 queries │ │
│ │ prelude.rs — shared imports │ │
│ └──────────┬─────────────────────┘ │
│ │ │
│ ┌──────────▼─────────────────────┐ │
│ │ D1 Database (Prepared Stmts) │ │
│ └──────────┬─────────────────────┘ │
└─────────────┼────────────────────────┘
│
┌────────────▼────────────┐
│ Cloudflare D1 (SQLite) │
│ - agents │
│ - owners │
│ - chats │
│ - messages │
│ - rate_limits │
└─────────────────────────┘
The backend runs as a Cloudflare Worker — a serverless function deployed to Cloudflare's global edge network. The Chat CLI (cli/) is the official terminal client, supporting both one-shot commands and an interactive REPL.
- Incoming HTTP request hits the Worker
lib.rschecks rate limit viarate_limit.rs(if API key provided)- If rate limited, return 429 response; otherwise proceed
lib.rscreates the router fromrouter.rsand dispatches- Router matches the path to the appropriate
handlerinhandlers.rs - Handler parses JSON body → runs validation (
validation.rs) → callsdb.rs db.rsexecutes a prepared SQL statement against D1- Result is serialized via
models.rstypes and returned as JSON - Rate limit headers added to response if applicable
| Technology | Purpose | Version |
|---|---|---|
| Rust | Programming language — performance, safety, WASM compilation | edition 2021, stable |
| worker | Cloudflare Workers Rust SDK — HTTP server, D1 bindings, routing | 0.4 |
| serde / serde_json | JSON serialization/deserialization | 1.x |
| uuid | UUID v4 generation for primary keys | 1.x (with js feature) |
| Cloudflare Workers | Serverless execution environment at the edge | — |
| Cloudflare D1 | Serverless SQLite database with global replication | — |
| wrangler | Cloudflare Workers CLI for dev, build, deploy | ^3.0 |
| clap | CLI argument parsing (chat-cli) | 4 (with derive) |
| reqwest | HTTP client for the CLI | 0.12 (with rustls-tls) |
| ratatui | TUI library for h-cli |
0.26 |
| crossterm | Terminal manipulation for h-cli |
0.27 |
| prettytable-rs | ASCII table formatting (cli) |
0.10 |
- Rust toolchain — Install via rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh rustup target add wasm32-unknown-unknown # only for backend
- Node.js & npm — v18 or later
- Wrangler CLI — installed via
npm install(dev dependency) - A Cloudflare account — Sign up free
- A Cloudflare D1 database — Created via wrangler (see Quick Start)
# Terminal 1 — Backend
npm install
make migrate
make dev# Terminal 2 — Human Chat
cd h-cli
cargo run# Terminal 3 — Developer CLI
cd cli
cargo run -- helpcurl http://localhost:8787/api/health
# {"status":"ok","service":"chat-app-backend","version":"0.3.0"}chat-app-backend/
│
├── Cargo.toml # Backend Rust manifest (cdylib for WASM)
├── wrangler.toml # Cloudflare Workers configuration
├── package.json # Node.js project manifest with wrangler scripts
├── Makefile # Common commands (dev, build, test, lint, deploy)
├── rust-toolchain.toml # Pins Rust version + wasm32-unknown-unknown target
├── .rustfmt.toml # Rust formatting rules (100-char lines, module imports)
├── .gitignore # Git ignore rules
├── README.md # This file
├── tasks.md # Roadmap & improvement plan
│
├── .github/workflows/
│ └── ci.yml # CI pipeline: fmt → clippy → build → test
│
├── migrations/
│ ├── 0001_initial.sql # D1 schema migration (4 tables + 5 indexes)
│ ├── 0002_auth.sql # Auth columns (password_hash, salt, api_key)
│ └── 0003_rate_limiting.sql # Rate limiting table (rate_limits)
│
├── cli/ # Developer CLI (quick commands & REPL)
│ ├── src/lib.rs # Shared library code (client, models)
│ └── src/main.rs # Management CLI entry point
│
├── h-cli/ # 🆕 Human Chat CLI (TUI)
│ ├── src/main.rs # TUI entry point
│ ├── src/tui.rs # Ratatui rendering logic
│ └── src/session.rs # Persistent session management
│
├── docs/ # Detailed documentation
│ ├── ARCHITECTURE.md # Architecture deep dive
│ ├── API_REFERENCE.md # Full API endpoint reference
│ ├── FEATURES.md # 🆕 Feature overview & capabilities
│ ├── ERROR_HANDLING.md # Error handling & validation guide
│ ├── RATE_LIMITING.md # Rate limiting implementation
│ ├── AUTHENTICATION.md # Authentication & admin roles guide
│ └── DEVELOPMENT.md # Development workflow & tooling
│
├── src/ # Backend worker source
│ ├── lib.rs # Worker entry point with rate limiting
│ ├── router.rs # Route definitions
│ ├── handlers.rs # HTTP layer — parsing, CORS, validation dispatch
│ ├── validation.rs # Validator trait + field validators + 16 tests
│ ├── models.rs # Data structures, AppError, SenderType + 16 tests
│ ├── auth.rs # JWT & API key authentication + admin roles + 6 tests
│ ├── rate_limit.rs # Rate limiting with tiered limits + 13 tests
│ ├── sanitize.rs # XSS sanitization for message content + 13 tests
│ ├── websocket.rs # 🆕 ChatRoom Durable Object — WS/SSE live connections
│ ├── db.rs # D1 database CRUD operations
│ └── prelude.rs # Common imports & constants
│
└── tests/ # (tests are inline in src/)
### Module Responsibilities
| File | Responsibility |
|---|---|
| **lib.rs** | Initializes the Worker, checks rate limits, creates the router via `router::build_router()` |
| **router.rs** | Defines all routes: CORS preflight, health, agents, owners, chats, messages, 404 |
| **handlers.rs** | Extracts path params, parses/validates JSON bodies, applies CORS headers |
| **validation.rs** | `Validator` trait + field validators for names, emails, UUIDs, content lengths |
| **models.rs** | Database entities, request/response structs, `AppError` enum, `SenderType` enum |
| **auth.rs** | JWT token generation/verification, API key authentication, admin role checks, key rotation |
| **rate_limit.rs** | API key-based rate limiting with tiered limits, sliding window algorithm in D1 |
| **sanitize.rs** | HTML entity escaping for XSS protection in message content |
| **websocket.rs** | 🆕 ChatRoom Durable Object — handles WS upgrades, broadcasting, typing, presence, read receipts |
| **db.rs** | All D1 SQL queries — prepared statements, CRUD operations, error mapping |
| **prelude.rs** | Re-exports commonly-used types + 10 shared constants (max lengths, defaults) |
---
## Configuration
### wrangler.toml
```toml
name = "chat-app-backend"
main = "build/worker/shim.mjs"
compatibility_date = "2024-12-01"
compatibility_flags = ["nodejs_compat"]
[[d1_databases]]
binding = "DB"
database_name = "chat-app-db"
database_id = "your-database-id-here"
[[migrations]]
tag = "v1"
new_directory = "migrations"
[[migrations]]
tag = "v2"
new_directory = "migrations"
[[migrations]]
tag = "v3"
new_directory = "migrations"
[toolchain]
channel = "stable"
targets = ["wasm32-unknown-unknown"]The project compiles to a cdylib (C dynamic library) which is compiled to WebAssembly:
[lib]
crate-type = ["cdylib"]
[profile.release]
lto = true
opt-level = "s" # Optimize for size (free plan limit: 8 MB)
strip = true
codegen-units = 1┌────────────┐ ┌──────────────┐ ┌──────────────┐
│ owners │ │ agents │ │ chats │
├────────────┤ ├──────────────┤ ├──────────────┤
│ id (PK) │◄──────┤ owner_id (FK)│ │ id (PK) │
│ name │ │ id (PK) │ │ title │
│ email (UQ) │ │ name │◄──────┤ agent_id (FK)│
│ created_at │ │ description │ │ owner_id (FK)│
└────────────┘ │ created_at │ │ created_at │
│ updated_at │ │ updated_at │
└──────────────┘ └──────┬───────┘
│
┌────────▼───────┐
│ messages │
├────────────────┤
│ id (PK) │
│ chat_id (FK) │
│ sender_type │
│ sender_id │
│ content │
│ created_at │
└────────────────┘
See migrations/0001_initial.sql for the full schema. Key points:
- agents — AI agent profiles.
owner_idis nullable FK toowners(SET NULL on delete) - owners — Human owners. Email has a UNIQUE constraint
- chats — Conversation threads. CASCADE delete on both agent and owner
- messages — Individual messages within a chat.
sender_typeCHECK constraint:'agent'or'owner'
Five indexes on commonly-queried columns (agent_id, owner_id, chat_id, created_at).
| Migration | Description |
|---|---|---|
| 0001_initial.sql | Initial schema with agents, owners, chats, messages tables |
| 0002_auth.sql | Add password_hash, salt, api_key columns to owners and agents |
| 0003_rate_limiting.sql | Add rate_limits table for API key-based rate limiting |
| 0004_admin_roles.sql | Add is_admin column to owners table for admin role system |
| 0005_webhooks.sql | Add webhooks and webhook_deliveries tables |
The API supports two authentication methods:
- JWT (JSON Web Tokens) — For owners to authenticate with email/password
- API Keys — For both owners and agents to authenticate programmatically
The API includes an admin role system that allows certain owners to have elevated privileges. Admins can:
- Access admin-only endpoints (e.g.,
POST /api/admin/owners/:id/set-admin) - Promote/demote other owners to admin status
See docs/AUTHENTICATION.md for detailed authentication documentation.
Every mutating endpoint validates its input before any database operation. Validation is handled by the Validator trait in src/validation.rs.
| Field | Rule | Constant |
|---|---|---|
name (agent/owner) |
1–200 characters | MIN_NAME_LENGTH, MAX_NAME_LENGTH |
email |
1–320 characters, must contain @ with domain |
MAX_EMAIL_LENGTH |
content (message) |
1–10,000 characters | MAX_CONTENT_LENGTH |
title (chat) |
0–500 characters | MAX_TITLE_LENGTH |
description (agent) |
0–2,000 characters | MAX_DESCRIPTION_LENGTH |
| UUID fields | Must be valid UUID v4 format (36 chars, 4 dashes, hex, version nibble 4) |
— |
sender_type |
Must be "agent" or "owner" |
— |
Request body → serde_json parse → Validator::validate() → DB operation
↓
AppError::Validation(msg)
↓
400 response with error JSON
pub trait Validator {
fn validate(&self) -> Result<(), AppError>;
}Implemented for all 7 request types. Invalid inputs return a 400 Bad Request with a descriptive message.
Structured error handling via the AppError enum (src/models.rs):
| Variant | HTTP Status | Error Code | Description |
|---|---|---|---|
NotFound |
404 | ERR_NOT_FOUND |
Resource not found |
BadRequest |
400 | ERR_BAD_REQUEST |
Malformed request (invalid JSON) |
Validation |
400 | ERR_VALIDATION |
Input validation failure |
Database |
500 | ERR_DATABASE |
D1 query failure |
Internal |
500 | ERR_INTERNAL |
Unexpected server error |
RateLimitExceeded |
429 | ERR_RATE_LIMIT_EXCEEDED |
Rate limit exceeded |
{
"success": false,
"data": null,
"error": "Agent 'abc-123' not found",
"code": "ERR_NOT_FOUND"
}From<worker::Error>forAppError— enables?on D1 operationsFrom<String>andFrom<&str>forAppErrorinto_response()method convertsAppErrorinto aworker::Result<Response>with correct status code- All
InternalandDatabaseerrors are logged viaconsole_error!
The API implements API key-based rate limiting to protect against abuse and ensure fair usage. See docs/RATE_LIMITING.md for full details.
| Tier | Limit per Minute | Use Case |
|---|---|---|
| Read | 100 requests | GET requests, list endpoints, resource retrieval |
| Write | 30 requests | POST, PUT, PATCH, DELETE operations |
| Auth | 10 requests | Authentication endpoints (/api/auth/*) |
Successful requests:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1718064000Rate limited (429):
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1718064000
Retry-After: 30- Sliding window algorithm stored in D1
- API key extraction from
Authorization: ApiKey <KEY>orX-API-Keyheaders - Automatic tier classification based on HTTP method and path
- Global enforcement in
lib.rsbefore router dispatch
To adjust rate limits, edit the constants in src/rate_limit.rs:
impl RateLimitTier {
pub fn limit_per_minute(&self) -> u32 {
match self {
RateLimitTier::Read => 100, // Adjust this
RateLimitTier::Write => 30, // Adjust this
RateLimitTier::Auth => 10, // Adjust this
}
}
}29 endpoints are available. Full details and request/response payloads in docs/API_REFERENCE.md.
| Method | Path | Description | Authentication Required |
|---|---|---|---|
POST |
/api/auth/login |
Authenticate owner & get JWT | ❌ No |
GET |
/api/auth/me |
Get currently authenticated caller profile | ✅ Yes (JWT or API Key) |
POST |
/api/owners/:id/key |
Rotate API key for an owner | ✅ Yes (JWT or Owner Key) |
POST |
/api/agents/:id/key |
Rotate API key for an agent | ✅ Yes (JWT - Owner only) |
| Method | Path | Description | Authentication Required |
|---|---|---|---|
POST |
/api/agents |
Create an AI agent | ✅ Yes (JWT only) |
GET |
/api/agents |
List all agents (paginated, sortable, filterable) | ❌ No |
GET |
/api/agents/:id |
Get agent details by ID | ❌ No |
PUT |
/api/agents/:id |
Full update of an agent | ✅ Yes (JWT - Owner only) |
PATCH |
/api/agents/:id |
Partial update of an agent | ✅ Yes (JWT - Owner only) |
DELETE |
/api/agents/:id |
Delete an agent (cascade deletes chats/messages) | ✅ Yes (JWT - Owner only) |
GET |
/api/agents/:id/chats |
List chats associated with this agent | ❌ No |
GET |
/api/agents/:id/owner |
Get owner profile for this agent | ❌ No |
GET |
/api/agents/:id/messages |
Get messages sent by this agent across all chats | ❌ No |
| Method | Path | Description | Authentication Required |
|---|---|---|---|
POST |
/api/owners |
Create an owner (supports password) | ❌ No |
GET |
/api/owners |
List all owners (paginated) | ❌ No |
GET |
/api/owners/:id |
Get owner details by ID | ❌ No |
PUT |
/api/owners/:id |
Update owner details (name, email) | ✅ Yes (JWT - Owner only) |
DELETE |
/api/owners/:id |
Delete owner (cascade deletes chats, unlinks agents) | ✅ Yes (JWT - Owner only) |
GET |
/api/owners/:id/agents |
List agents belonging to this owner | ❌ No |
GET |
/api/owners/:id/chats |
List chats associated with this owner | ❌ No |
| Method | Path | Description | Authentication Required |
|---|---|---|---|
POST |
/api/chats |
Create a new conversation between owner & agent | ✅ Yes (JWT only) |
GET |
/api/chats |
List all chats (paginated, filterable) | ❌ No |
GET |
/api/chats/:id |
Get chat metadata and its full message history | ❌ No |
PUT |
/api/chats/:id |
Update chat title | ✅ Yes (JWT - Owner only) |
DELETE |
/api/chats/:id |
Delete a chat (cascade deletes messages) | ✅ Yes (JWT - Owner only) |
| Method | Path | Description | Authentication Required |
|---|---|---|---|
POST |
/api/chats/:chat_id/messages |
Send message (by owner or agent) | ✅ Yes (JWT or API Key) |
GET |
/api/chats/:chat_id/messages |
Get list of messages (paginated, filterable) | ❌ No |
PUT |
/api/chats/:chat_id/messages/:message_id |
🆕 Edit message content (owner only) | ✅ Yes (JWT - Owner only) |
DELETE |
/api/chats/:chat_id/messages/:message_id |
🆕 Delete a message (owner only) | ✅ Yes (JWT - Owner only) |
| Method | Path | Description | Authentication Required |
|---|---|---|---|
GET |
/api/chats/:id/ws |
🆕 WebSocket connection for live chat (WS upgrade proxied through DO) | ✅ Yes (JWT or API Key) |
GET |
/api/chats/:id/events |
🆕 Server-Sent Events fallback (WebSocket via DO) | ✅ Yes (JWT or API Key) |
| Method | Path | Description | Authentication Required |
|---|---|---|---|
POST |
/api/webhooks |
🆕 Create a webhook subscription | ✅ Yes (JWT - Owner only) |
GET |
/api/webhooks |
🆕 List webhooks for the authenticated owner | ✅ Yes (JWT - Owner only) |
GET |
/api/webhooks/:id |
🆕 Get webhook details | ✅ Yes (JWT - Owner only) |
PUT |
/api/webhooks/:id |
🆕 Update webhook configuration | ✅ Yes (JWT - Owner only) |
DELETE |
/api/webhooks/:id |
🆕 Delete a webhook subscription | ✅ Yes (JWT - Owner only) |
All GET list endpoints (Agents, Owners, Chats, Messages) support the following query parameters:
- Pagination:
?limit=50&offset=0(Default:50, Max:1000). - Sorting:
?sort_by=created_at&sort_order=desc. Whitelisted columns only (created_at,updated_at,name,email,title). - Filtering:
- Agents:
?owner_id=<uuid>& date range?created_after=<iso>&created_before=<iso>. - Chats:
?agent_id=<uuid>&owner_id=<uuid>. - Messages (Search):
?q=<search-term>(performs a robust database-levelLIKEwildcard search).
- Agents:
Success (single):
{ "success": true, "data": { ... } }Success (list):
{ "success": true, "data": [ ... ], "total": 42 }Error (v0.2.0+):
{ "success": false, "data": null, "error": "...", "code": "ERR_..." }The cli/ directory contains a full-featured Rust terminal client that communicates with the backend via HTTP. It supports two modes:
Use for one-off operations or scripting:
cargo run -- health # Check backend status
cargo run -- list agents # List all agents
cargo run -- create owner --name "Alice" --email "alice@example.com"
cargo run -- create agent --name "CodeBot" --description "AI assistant"
cargo run -- send --chat-id <id> --as-type owner --sender-id <id> --text "Hello"
cargo run -- messages --chat-id <id> # View messages
cargo run -- delete agent <id> # Delete a resourceAll 17 backend endpoints are available as CLI commands. See cli/README.md for the full reference.
For an immersive chat experience:
cargo run -- replIn REPL mode you can browse chats with /list, select one with /select <n>, type messages directly, create new chats with /new, and more. See the CLI README for a full demo.
Set the backend URL via environment variable or the --api-url flag:
# Default: http://localhost:8787
export CHAT_API_URL=https://my-worker.workers.dev
cargo run -- health
# Or per-command:
cargo run -- --api-url https://my-worker.workers.dev list agentsmake dev # Start dev server (wrangler)
make build # Build for WASM (release)
make check # Check WASM compilation
make fmt # Format all Rust code
make fmt-check # Check formatting
make lint # Run clippy (WASM target)
make test # Run unit tests (native)
make test-check # Check tests compile (WASM)
make migrate # Apply D1 migrations (local)
make migrate-remote # Apply D1 migrations (remote)
make deploy # Deploy to Cloudflare
make clean # Clean build artifactsThe CLI is a separate Rust crate with its own Cargo.toml:
cd cli
cargo check # Check compilation
cargo run -- health # Quick test with running backend
cargo build --release # Build for productionNo special WASM target needed — the CLI compiles natively for your platform.
- Formatting:
cargo fmtwith rules in.rustfmt.toml(100-char lines, module imports) - Linting:
cargo clippywith-D warningsfor WASM target (backend) or native (CLI) - Constants: All magic strings/numbers in
src/prelude.rs(10 shared constants) - Imports:
use crate::prelude::*;pattern for commonly-used types
Ensure compatibility with wasm32-unknown-unknown:
- ✅ Pure Rust crates (serde, serde_json)
- ✅ Crates with
jsfeature flag (uuid) - ❌ Crates with system calls (file I/O, threading, chrono)
108 unit tests covering models, validation, auth, rate limiting, sanitization, admin roles, real-time WebSocket, and webhooks:
make test
# cargo testTest suites:
| Module | Tests | Coverage |
|---|---|---|
models.rs |
16 | SenderType (4), AppError (7), API responses (5) |
validation.rs |
16 | Name (5), Email (6), Content (4), UUID (6), Validator impls (7) |
auth.rs |
6 | JWT generation/verification, password hashing, admin role checks |
rate_limit.rs |
13 | Tier limits, classification, headers, serialization |
sanitize.rs |
13 | HTML escaping, dangerous HTML detection, permissive mode |
db.rs |
3 | ID generation |
prelude.rs |
2 | Constants validation |
handlers.rs |
27 | Various handler tests + webhook signature tests |
websocket.rs |
8 | 🆕 WsMessage serialization/deserialization |
Tests run on the native target (x86_64), not WASM, for fast execution. Test code is gated behind #[cfg(test)] and excluded from WASM compilation.
GitHub Actions runs on every push/PR:
Job: Check & Lint
├── cargo fmt -- --check
├── cargo clippy (WASM, -D warnings)
└── cargo check (WASM)
Job: Test (depends on Check)
└── cargo check --tests (WASM)
The project includes a GitHub Actions workflow (.github/workflows/ci.yml) with two jobs:
- Formatting check via
cargo fmt - Clippy linting for WASM target
- WASM compilation check
- Runs after Check passes
- Verifies tests compile for WASM target
npx wrangler d1 create chat-app-dbUpdate database_id in wrangler.toml.
make migrate-remote
# or: npx wrangler d1 migrations apply chat-app-db --remotemake deploy
# or: npm run deploycurl https://chat-app-backend.<your-subdomain>.workers.dev/api/healthBASE="http://localhost:8787"
# Health check
curl "$BASE/api/health"
# Create owner
OWNER=$(curl -s -X POST "$BASE/api/owners" \
-H "Content-Type: application/json" \
-d '{"name":"Alice","email":"alice@example.com"}')
OWNER_ID=$(echo "$OWNER" | jq -r '.data.id')
# Create agent
AGENT=$(curl -s -X POST "$BASE/api/agents" \
-H "Content-Type: application/json" \
-d "{\"name\":\"CodeBot\",\"description\":\"AI coding assistant\",\"owner_id\":\"$OWNER_ID\"}")
AGENT_ID=$(echo "$AGENT" | jq -r '.data.id')
# Create chat
CHAT=$(curl -s -X POST "$BASE/api/chats" \
-H "Content-Type: application/json" \
-d "{\"title\":\"Debug help\",\"agent_id\":\"$AGENT_ID\",\"owner_id\":\"$OWNER_ID\"}")
CHAT_ID=$(echo "$CHAT" | jq -r '.data.id')
# Send messages
curl -s -X POST "$BASE/api/chats/$CHAT_ID/messages" \
-H "Content-Type: application/json" \
-d "{\"sender_type\":\"owner\",\"sender_id\":\"$OWNER_ID\",\"content\":\"Can you help me?\"}"
curl -s -X POST "$BASE/api/chats/$CHAT_ID/messages" \
-H "Content-Type: application/json" \
-d "{\"sender_type\":\"agent\",\"sender_id\":\"$AGENT_ID\",\"content\":\"Sure!\"}"
# Get full chat
curl -s "$BASE/api/chats/$CHAT_ID" | jq .- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Run the full check suite:
make fmt-check && make lint && make test - Ensure the project compiles:
make check - Submit a pull request
This project is actively evolving. Check out tasks.md for the full roadmap including:
- v0.3.0: Pagination, filtering, sorting, JWT/API Key auth, and key rotations ✅ (Completed)
- v0.4.0: Rate limiting with tiered limits, sliding window algorithm, and standard headers ✅ (Completed)
- v0.5.0: XSS sanitization for message content and admin role system ✅ (Completed)
- v0.6.0: Real-time WebSocket connections via Durable Objects, SSE fallback, webhook system with HMAC signing, typing indicators, presence tracking, read receipts ✅ (Completed)
- v0.7.0: Message editing and deletion with owner-only auth, XSS sanitization on edit, WS/webhook broadcast ✅ (Completed)
- v0.8.0: Fine-grained permissions table and webhook retry with exponential backoff (Planned)
- v1.0.0: Production hardening, rate limit customization, and monitoring dashboard (Planned)
- v2.0.0: Multi-tenancy with organizations and team management (Future)
MIT