From 28e18ff873c9452adb68444ec16aba1bb4abfae7 Mon Sep 17 00:00:00 2001 From: Terra Tauri Date: Sat, 24 Jan 2026 23:29:00 -0800 Subject: [PATCH] docs: add project documentation Add documentation for the hook system and project setup: - README.md with quick start and feature overview - Getting started guide with installation steps - Hook system documentation with examples - Architecture overview - Configuration reference - Protocol support details - Deployment guide - GitHub issue and PR templates - Security policy - Contributing guidelines - Code of conduct --- .github/ISSUE_TEMPLATE/bug_report.md | 54 ++++ .github/ISSUE_TEMPLATE/feature_request.md | 37 +++ .github/PULL_REQUEST_TEMPLATE.md | 14 + CODE_OF_CONDUCT.md | 43 +++ CONTRIBUTING.md | 79 +++++ README.md | 194 ++++++++++++ SECURITY.md | 59 ++++ docs/architecture.md | 263 ++++++++++++++++ docs/cli-client.md | 337 ++++++++++++++++++++ docs/configuration.md | 288 ++++++++++++++++++ docs/deployment.md | 329 ++++++++++++++++++++ docs/getting-started.md | 311 +++++++++++++++++++ docs/hooks.md | 354 ++++++++++++++++++++++ docs/protocol-support.md | 249 +++++++++++++++ 14 files changed, 2611 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 README.md create mode 100644 SECURITY.md create mode 100644 docs/architecture.md create mode 100644 docs/cli-client.md create mode 100644 docs/configuration.md create mode 100644 docs/deployment.md create mode 100644 docs/getting-started.md create mode 100644 docs/hooks.md create mode 100644 docs/protocol-support.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..eebb94f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,54 @@ +--- +name: Bug Report +about: Report a bug to help us improve +title: '[BUG] ' +labels: bug +assignees: '' +--- + +## Bug Description + + + +## Steps to Reproduce + +1. +2. +3. + +## Expected Behavior + + + +## Actual Behavior + + + +## Environment + +- **OS**: [e.g., Ubuntu 22.04, macOS 14] +- **Rust version**: [e.g., 1.75.0] +- **Chattermax version**: [e.g., 0.1.0] +- **XMPP client**: [e.g., Gajim 1.8.0] + +## Configuration + + + +```toml +[server] +domain = "example.com" +``` + +## Logs + + + +``` +Chattermax listening on 0.0.0.0:5222 +... +``` + +## Additional Context + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..ac82575 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,37 @@ +--- +name: Feature Request +about: Suggest an idea for Chattermax +title: '[FEATURE] ' +labels: enhancement +assignees: '' +--- + +## Problem Statement + + + +## Proposed Solution + + + +## Alternatives Considered + + + +## Use Case + + + +## XEP Reference + + + +- XEP-XXXX: [Title](https://xmpp.org/extensions/xep-xxxx.html) + +## Implementation Ideas + + + +## Additional Context + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..b4ab131 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +## Summary + + + +## Test plan + + + +- [ ] `cargo test` passes +- [ ] Manual testing (describe below if applicable) + +## Related issues + + diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..0ae7995 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,43 @@ +# Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior: + +- The use of sexualized language or imagery and unwelcome sexual attention +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information without explicit permission +- Other conduct which could reasonably be considered inappropriate + +## Enforcement Responsibilities + +Project maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project maintainers at me@terratauri.com. All complaints will be reviewed and investigated promptly and fairly. + +All project maintainers are obligated to respect the privacy and security of the reporter of any incident. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.0. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..9f0da75 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,79 @@ +# Contributing to Chattermax + +## Before You Start + +1. Check [open issues](https://github.com/terraboops/chattermax/issues) for existing work +2. For significant changes, open an issue to discuss your approach first +3. Read the [Code of Conduct](CODE_OF_CONDUCT.md) + +## Development Setup + +```bash +git clone https://github.com/terraboops/chattermax.git +cd chattermax +cargo build +cargo test +``` + +Start a dev server: + +```bash +cargo run -- --init-db +cargo run -- --add-user test:test +cargo run +``` + +## Making Changes + +### Branch naming + +``` +feature/xep-0199-ping +fix/roster-subscription-handling +docs/deployment-guide +``` + +### Commit messages + +Use conventional commits: + +``` +feat(muc): add room configuration support +fix(auth): handle empty password in SASL PLAIN +docs: update deployment guide +``` + +### Before submitting + +```bash +cargo fmt +cargo clippy +cargo test +``` + +## Pull Requests + +1. Push your branch +2. Open a PR against `main` +3. Link related issues with `Closes #123` +4. Wait for review + +## Code Style + +- Run `cargo fmt` and `cargo clippy` +- Use `Result` for fallible operations +- Avoid `.unwrap()` except in tests +- Document public APIs with `///` + +## Testing + +```bash +cargo test # all tests +cargo test -p chattermax-core # specific crate +cargo test test_jid_parsing # specific test +cargo test -- --nocapture # with output +``` + +## Questions? + +Open a [discussion](https://github.com/terraboops/chattermax/discussions). diff --git a/README.md b/README.md new file mode 100644 index 0000000..8e20412 --- /dev/null +++ b/README.md @@ -0,0 +1,194 @@ +# Chattermax + +[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE) +[![Rust](https://img.shields.io/badge/rust-1.75%2B-orange.svg)](https://www.rust-lang.org/) +[![XMPP](https://img.shields.io/badge/XMPP-RFC%206120%2F6121-green.svg)](https://xmpp.org/) + +A modern XMPP server written in Rust with a **hook system for AI agent integration**. The same binary also provides a CLI client mode for scriptable XMPP interactions. + +## Features + +### XMPP Server +- Direct messaging (1:1 chat) +- Group channels (MUC - Multi-User Chat) +- User presence (online/offline/away) +- Message archiving with history retrieval +- Service discovery for client capabilities +- TLS encryption support + +### Hook System + +The hook system lets AI agents respond to chat events. Events flow through configurable filters, spawning commands that receive JSON on stdin and reply on stdout. + +```toml +[[hooks]] +name = "ai-assistant" +command = "/usr/local/bin/my-ai-agent" +filters = [ + { field = "type", pattern = "message" }, + { field = "body", pattern = "^@bot\\s+" } +] +``` + +See [Hook System Documentation](docs/hooks.md) for details. + +### CLI Client Mode + +One-shot commands for scripting and automation: + +```bash +# Send a message +chattermax send --to user@example.com --body "Hello!" + +# Set presence +chattermax presence --status online --message "Available" + +# Join a channel +chattermax join --room general@conference.example.com +``` + +## Quick Start + +### Prerequisites + +- Rust 1.75+ (2024 edition) +- SQLite 3.x + +### Build + +```bash +git clone https://github.com/terraboops/chattermax.git +cd chattermax +cargo build --release +``` + +### Run Server + +```bash +# Initialize database +./target/release/chattermax --init-db + +# Create a user +./target/release/chattermax --add-user alice:password + +# Start server +./target/release/chattermax +``` + +The server listens on `0.0.0.0:5222` by default. + +### Connect + +Use any XMPP client with: + +| Setting | Value | +|---------|-------| +| Server | localhost | +| Port | 5222 | +| Username | alice | +| Password | password | + +## Configuration + +```toml +[server] +host = "0.0.0.0" +port = 5222 +domain = "example.com" + +[database] +path = "chattermax.db" + +[tls] +cert_path = "/etc/chattermax/fullchain.pem" +key_path = "/etc/chattermax/privkey.pem" + +# AI agent hook +[[hooks]] +name = "ai-assistant" +command = "/usr/local/bin/my-ai-agent" +filters = [ + { field = "body", pattern = "^@assistant\\s+" } +] +``` + +See [Configuration Reference](docs/configuration.md) for all options. + +## Documentation + +| Document | Description | +|----------|-------------| +| [Getting Started](docs/getting-started.md) | Installation and first steps | +| [Hook System](docs/hooks.md) | AI agent integration guide | +| [CLI Client](docs/cli-client.md) | Command-line client usage | +| [Architecture](docs/architecture.md) | System design and components | +| [Configuration](docs/configuration.md) | All configuration options | +| [Protocol Support](docs/protocol-support.md) | XMPP XEP coverage | +| [Deployment](docs/deployment.md) | Production deployment guide | + +## Tested Clients + +Chattermax targets compatibility with major Android XMPP clients: + +| Client | Platform | Status | +|--------|----------|--------| +| [Conversations](https://conversations.im/) | Android | Primary target | +| [Blabber.im](https://blabber.im/) | Android | Supported | +| [Moxxy](https://moxxy.org/) | Android | Supported | +| [Gajim](https://gajim.org/) | Desktop | Supported | +| [Psi](https://psi-im.org/) | Desktop | Supported | + +## XMPP Protocol Support + +### Required for Android Compatibility + +| XEP | Name | Status | +|-----|------|--------| +| XEP-0030 | Service Discovery | Supported | +| XEP-0045 | Multi-User Chat | Supported | +| XEP-0115 | Entity Capabilities | Planned | +| XEP-0198 | Stream Management | Planned | +| XEP-0280 | Message Carbons | Planned | +| XEP-0313 | Message Archive Management | Supported | + +See [Protocol Support](docs/protocol-support.md) for full details. + +## Current Status + +Chattermax is in **MVP (v0.1.x)** status, suitable for development and testing. + +**Implemented:** +- Core messaging (1:1 and group) +- Message archiving (MAM) +- Service discovery +- SQLite storage + +**In Progress:** +- Hook system for AI agents +- CLI client mode +- TLS encryption + +**Planned:** +- Stream management (XEP-0198) +- Message carbons (XEP-0280) +- Entity capabilities (XEP-0115) +- PostgreSQL support + +## Use Cases + +- **AI Chat Assistants** - Connect LLMs to XMPP via the hook system +- **Chat Bots** - Automate responses using CLI client or hooks +- **Private Messaging** - Self-hosted chat for teams or communities +- **IoT Integration** - Device notifications via XMPP + +## Contributing + +Contributions welcome! See [Contributing Guide](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md). + +## License + +Apache License 2.0. See [LICENSE](LICENSE). + +## Author + +Terra Tauri (me@terratauri.com) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..0c65c94 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,59 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 0.1.x | :white_check_mark: | + +## Reporting a Vulnerability + +We take security vulnerabilities seriously. If you discover a security issue, please report it responsibly. + +### How to Report + +**Do NOT open a public GitHub issue for security vulnerabilities.** + +Instead, please email us at: **me@terratauri.com** + +Include the following information: +- Description of the vulnerability +- Steps to reproduce the issue +- Potential impact +- Any suggested fixes (optional) + +### What to Expect + +I'll respond as quickly as I can. For critical issues, expect a fix within days. I'll coordinate disclosure timing with you. + +### Scope + +The following are in scope for security reports: + +- Authentication bypass +- Authorization flaws +- Remote code execution +- SQL injection +- XML/XXE vulnerabilities +- Denial of service (protocol-level) +- Information disclosure + +### Out of Scope + +- Denial of service via resource exhaustion (expected behavior for MVP) +- Issues in dependencies (report to upstream) +- Social engineering attacks + +## Security Best Practices + +When deploying Chattermax: + +1. **Use a reverse proxy** with TLS (nginx, Caddy) until native TLS is implemented +2. **Run as non-root** user with minimal privileges +3. **Firewall** - Only expose necessary ports +4. **Keep updated** - Apply security patches promptly +5. **Strong passwords** - Enforce strong user passwords + +## Acknowledgments + +We appreciate responsible disclosure and will acknowledge security researchers who help improve Chattermax security. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..27191c7 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,263 @@ +# Architecture Overview + +## Project Structure + +Chattermax follows a modular Rust workspace architecture with three independent crates: + +``` +chattermax/ +├── Cargo.toml # Workspace manifest +├── chattermax.toml # Server configuration +│ +├── chattermax-core/ # Shared XMPP types & parsing +│ └── src/ +│ ├── lib.rs # Library exports +│ ├── error.rs # Error types +│ ├── jid.rs # Jabber ID handling +│ ├── stanza.rs # XMPP stanza definitions +│ └── stream.rs # Stream state & namespaces +│ +├── chattermax-server/ # XMPP server implementation +│ └── src/ +│ ├── main.rs # Entry point & CLI +│ ├── stream.rs # Connection handling +│ ├── session.rs # Session management +│ ├── router.rs # Message routing +│ ├── config.rs # Configuration loading +│ ├── auth.rs # SASL authentication +│ ├── db.rs # SQLite operations +│ ├── xml.rs # XML utilities +│ ├── roster.rs # Contact list (RFC 6121) +│ ├── muc.rs # Multi-User Chat (XEP-0045) +│ ├── mam.rs # Message Archive (XEP-0313) +│ └── disco.rs # Service Discovery (XEP-0030) +│ +└── chattermax-client/ # CLI client (skeleton) + └── src/ + └── main.rs +``` + +## Core Components + +### chattermax-core + +The core library provides fundamental XMPP types shared between server and client: + +| Module | Purpose | +|--------|---------| +| `jid` | Jabber ID parsing and validation (bare, full, domain-only) | +| `stanza` | Message, Presence, and IQ stanza definitions | +| `stream` | XMPP namespace constants and stream state machine | +| `error` | Custom error types for protocol violations | + +### chattermax-server + +The server implementation handles all XMPP protocol operations: + +| Module | Purpose | +|--------|---------| +| `stream` | Async TCP connection handling with XML parsing | +| `session` | Per-connection state (JID binding, stream ID) | +| `router` | Central message routing and session registry | +| `auth` | SASL PLAIN authentication | +| `db` | SQLite persistence with connection pooling | +| `roster` | Contact list management | +| `muc` | Multi-User Chat room support | +| `mam` | Message archive queries | +| `disco` | Service discovery responses | +| `hooks` | External hook execution | + +### chattermax-client + +The CLI client provides one-shot XMPP operations for scripting: + +| Command | Purpose | +|---------|---------| +| `send` | Send a message to a user or room | +| `presence` | Set online/away/offline status | +| `join` | Join a MUC room | +| `leave` | Leave a MUC room | +| `roster` | Manage contacts | +| `listen` | Listen for incoming messages | + +## Hook System + +Hooks let external programs (AI agents, bots, etc.) respond to XMPP events. + +### Architecture + +``` +┌──────────────┐ ┌──────────────┐ ┌──────────────┐ +│ XMPP Event │────▶│ Hook Manager │────▶│ Filters │ +│ (message, │ │ │ │ (regex/glob)│ +│ presence) │ └──────────────┘ └──────┬───────┘ +└──────────────┘ │ + │ Match? + ┌────────────┴────────────┐ + │ Yes No │ + ▼ ▼ + ┌──────────────┐ (skip hook) + │ Spawn Process│ + │ │ + │ stdin: JSON │ + │ stdout: JSON │ + └──────┬───────┘ + │ + ▼ + ┌──────────────┐ + │ Send Reply │ + │ (if any) │ + └──────────────┘ +``` + +### Event Flow + +1. An XMPP event occurs (message received, presence change, etc.) +2. The Hook Manager checks each configured hook's filters +3. For matching hooks, the hook command is spawned as a subprocess +4. The event is serialized as JSON and written to the process's stdin +5. The process writes a JSON response to stdout +6. The server parses the response and takes the specified action (reply, send, etc.) + +### Design Principles + +- **Process Isolation** - Each hook runs in its own process +- **Language Agnostic** - Any executable can be a hook (Python, Node, Rust, shell scripts) +- **Simple Protocol** - JSON on stdin/stdout +- **Timeout Protection** - Hooks are killed after configurable timeout +- **Filter Efficiency** - Events are filtered before spawning processes + +See [Hook System Documentation](./hooks.md) for configuration and examples. + +## Data Flow + +### Connection Lifecycle + +``` +┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ +│ Initial │────▶│ Opened │────▶│Authenticated────▶│ Ready │ +└──────────┘ └──────────┘ └──────────┘ └──────────┘ + │ │ │ │ + │ Stream open SASL PLAIN Resource + │ with features completed bound +``` + +### Message Routing + +``` +┌─────────┐ ┌─────────┐ ┌─────────┐ +│ Sender │────────▶│ Router │────────▶│Recipient│ +│ Session │ │ │ │ Session │ +└─────────┘ └────┬────┘ └─────────┘ + │ + │ If offline + ▼ + ┌─────────┐ + │ Offline │ + │ Queue │ + └─────────┘ +``` + +### Authentication Flow + +``` +Client Server + │ │ + │──── Stream Open ─────────────▶│ + │◀─── Features (SASL) ─────────│ + │ │ + │──── SASL PLAIN ──────────────▶│ + │ │ Verify credentials + │◀─── Success ─────────────────│ + │ │ + │──── Stream Open ─────────────▶│ + │◀─── Features (Bind) ─────────│ + │ │ + │──── Bind Request ────────────▶│ + │◀─── Bound JID ───────────────│ + │ │ + │ Ready for messaging │ +``` + +## Key Design Decisions + +### Async Runtime + +Chattermax uses [Tokio](https://tokio.rs/) for async I/O: +- High concurrency with minimal thread overhead +- Thousands of simultaneous connections +- Non-blocking database operations via `sqlx` + +### Message Routing Architecture + +The `Router` maintains an in-memory session registry mapping bare JIDs to their connected sessions: + +```rust +HashMap> // bare_jid → sessions +``` + +This provides O(1) lookups for message delivery, support for multiple resources per user, and fast presence broadcasting. + +### Database Design + +SQLite was chosen for the MVP due to: +- Zero configuration deployment +- ACID compliance for message durability +- Async support via `sqlx` + +**Schema:** + +| Table | Purpose | +|-------|---------| +| `users` | User credentials (username, password hash) | +| `roster` | Contact relationships and subscriptions | +| `rooms` | MUC room definitions | +| `room_members` | Room occupancy tracking | +| `messages` | Message archive for MAM | +| `offline_messages` | Queue for offline delivery | + +### XML Processing + +XMPP uses XML for all protocol messages. Chattermax handles this with: +- `minidom` for DOM parsing of complete stanzas +- Custom stream header parsing (handles non-well-formed XML in stream opens) +- Incremental parsing from byte streams + +## Extensibility Points + +### Adding New IQ Handlers + +IQ (Info/Query) handlers can be added in `stream.rs`: + +```rust +match iq.payload { + IqPayload::YourNewPayload(data) => { + handle_your_payload(session, iq, data).await + } + // ... +} +``` + +### Adding New XEPs + +1. Define stanza types in `chattermax-core/src/stanza.rs` +2. Add namespace constants to `chattermax-core/src/stream.rs` +3. Implement handler in a new module under `chattermax-server/src/` +4. Wire up the handler in `stream.rs` + +## Current Limitations + +| Limitation | Reason | Future Solution | +|------------|--------|-----------------| +| Single-server only | MVP scope | Federation support | +| No TLS | Implementation pending | STARTTLS negotiation | +| Memory-based MUC state | Simplicity | Database-backed rooms | +| Simple password hashing | MVP scope | Argon2/bcrypt | + +## Related Documentation + +- [Getting Started](./getting-started.md) - Quick start guide +- [Hook System](./hooks.md) - AI agent integration +- [CLI Client](./cli-client.md) - Command-line client usage +- [Configuration](./configuration.md) - Server configuration reference +- [Protocol Support](./protocol-support.md) - XMPP XEP coverage diff --git a/docs/cli-client.md b/docs/cli-client.md new file mode 100644 index 0000000..c597234 --- /dev/null +++ b/docs/cli-client.md @@ -0,0 +1,337 @@ +# CLI Client + +Chattermax includes a command-line client for scriptable XMPP interactions. Use it to send messages, manage presence, and automate chat operations. + +## Table of Contents + +- [Overview](#overview) +- [Authentication](#authentication) +- [Commands](#commands) +- [Scripting Examples](#scripting-examples) +- [Exit Codes](#exit-codes) + +## Overview + +The CLI client provides one-shot commands that connect, perform an action, and disconnect. This makes it ideal for: + +- Sending notifications from scripts +- Cron-based automated messages +- CI/CD pipeline alerts +- Testing and debugging +- Bot prototyping + +## Authentication + +### Login and Store Credentials + +```bash +chattermax login \ + --server example.com \ + --user bot@example.com \ + --password-file /path/to/password +``` + +Credentials are stored in `~/.config/chattermax/credentials.toml`. + +### Inline Credentials + +For scripts, you can pass credentials directly: + +```bash +chattermax send \ + --server example.com \ + --user bot@example.com \ + --password-file /path/to/password \ + --to alice@example.com \ + --body "Hello!" +``` + +### Environment Variables + +```bash +export CHATTERMAX_SERVER=example.com +export CHATTERMAX_USER=bot@example.com +export CHATTERMAX_PASSWORD_FILE=/path/to/password + +chattermax send --to alice@example.com --body "Hello!" +``` + +## Commands + +### send + +Send a message to a user or room. + +```bash +# Direct message +chattermax send --to alice@example.com --body "Hello, Alice!" + +# Group message +chattermax send --to general@conference.example.com --type groupchat --body "Hello, everyone!" + +# Message from file +chattermax send --to alice@example.com --body-file /path/to/message.txt + +# With subject +chattermax send --to alice@example.com --subject "Important" --body "Please read this." +``` + +**Options:** + +| Option | Description | +|--------|-------------| +| `--to ` | Recipient JID (required) | +| `--body ` | Message content | +| `--body-file ` | Read message from file | +| `--type ` | `chat` (default) or `groupchat` | +| `--subject ` | Message subject | + +### presence + +Set your presence status. + +```bash +# Go online +chattermax presence --status online + +# Set away with message +chattermax presence --status away --message "Back in 5 minutes" + +# Go offline +chattermax presence --status offline + +# Extended away +chattermax presence --status xa --message "On vacation" +``` + +**Options:** + +| Option | Description | +|--------|-------------| +| `--status ` | `online`, `away`, `xa`, `dnd`, `offline` | +| `--message ` | Status message | +| `--priority ` | Resource priority (default: 0) | + +### join + +Join a MUC room. + +```bash +# Join with default nickname +chattermax join --room general@conference.example.com + +# Join with custom nickname +chattermax join --room general@conference.example.com --nick "Bot" + +# Join and stay connected (for receiving messages) +chattermax join --room general@conference.example.com --persist +``` + +**Options:** + +| Option | Description | +|--------|-------------| +| `--room ` | Room JID (required) | +| `--nick ` | Nickname in room | +| `--password ` | Room password (if required) | +| `--persist` | Stay connected after joining | + +### leave + +Leave a MUC room. + +```bash +chattermax leave --room general@conference.example.com +``` + +### roster + +Manage contacts. + +```bash +# List contacts +chattermax roster list + +# Add contact +chattermax roster add --jid alice@example.com --name "Alice" + +# Remove contact +chattermax roster remove --jid alice@example.com + +# Show contact details +chattermax roster show --jid alice@example.com +``` + +### listen + +Listen for incoming messages (useful for debugging). + +```bash +# Listen for all messages +chattermax listen + +# Listen with timeout +chattermax listen --timeout 60 + +# Listen and output JSON +chattermax listen --format json + +# Listen to specific room +chattermax listen --room general@conference.example.com +``` + +**Options:** + +| Option | Description | +|--------|-------------| +| `--timeout ` | Exit after N seconds | +| `--format ` | `text` (default) or `json` | +| `--room ` | Only messages from this room | +| `--count ` | Exit after N messages | + +### info + +Get server information. + +```bash +# Server info +chattermax info server + +# Your account info +chattermax info account + +# List available rooms +chattermax info rooms +``` + +## Scripting Examples + +### Daily Standup Reminder + +```bash +#!/bin/bash +# /etc/cron.d/standup-reminder + +0 9 * * 1-5 chatbot /usr/local/bin/chattermax send \ + --to engineering@conference.example.com \ + --type groupchat \ + --body "🌅 Good morning! Time for standup. Please share your updates." +``` + +### CI/CD Notification + +```bash +#!/bin/bash +# notify-deploy.sh + +STATUS=$1 +PROJECT=$2 +VERSION=$3 + +if [ "$STATUS" = "success" ]; then + EMOJI="✅" + MESSAGE="deployed successfully" +else + EMOJI="❌" + MESSAGE="deployment failed" +fi + +chattermax send \ + --to devops@conference.example.com \ + --type groupchat \ + --body "$EMOJI $PROJECT v$VERSION $MESSAGE" +``` + +### System Alert Bot + +```bash +#!/bin/bash +# alert.sh + +THRESHOLD=90 +USAGE=$(df / | tail -1 | awk '{print $5}' | tr -d '%') + +if [ "$USAGE" -gt "$THRESHOLD" ]; then + chattermax send \ + --to admin@example.com \ + --body "⚠️ Disk usage critical: ${USAGE}% on $(hostname)" +fi +``` + +### Interactive Bot (using listen) + +```bash +#!/bin/bash +# simple-bot.sh + +chattermax listen --format json | while read -r event; do + body=$(echo "$event" | jq -r '.body') + from=$(echo "$event" | jq -r '.from') + + case "$body" in + "!ping") + chattermax send --to "$from" --body "pong" + ;; + "!time") + chattermax send --to "$from" --body "$(date)" + ;; + "!help") + chattermax send --to "$from" --body "Commands: !ping, !time, !help" + ;; + esac +done +``` + +### Bulk Message Sender + +```bash +#!/bin/bash +# announce.sh + +MESSAGE=$1 + +while read -r jid; do + chattermax send --to "$jid" --body "$MESSAGE" + sleep 0.5 # Rate limiting +done < contacts.txt +``` + +## Exit Codes + +| Code | Meaning | +|------|---------| +| 0 | Success | +| 1 | General error | +| 2 | Connection failed | +| 3 | Authentication failed | +| 4 | Invalid arguments | +| 5 | Timeout | +| 6 | Permission denied | + +### Checking Exit Codes + +```bash +chattermax send --to alice@example.com --body "Test" + +case $? in + 0) echo "Message sent" ;; + 2) echo "Could not connect to server" ;; + 3) echo "Invalid credentials" ;; + *) echo "Unknown error" ;; +esac +``` + +## Configuration File + +Create `~/.config/chattermax/config.toml` for default settings: + +```toml +[client] +server = "example.com" +user = "bot@example.com" +password_file = "/etc/chattermax/bot-password" + +[defaults] +message_type = "chat" +presence_status = "online" +``` diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..6745cd5 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,288 @@ +# Configuration Reference + +Chattermax is configured via a TOML file. By default, it reads `chattermax.toml` from the current directory. + +## Table of Contents + +- [Configuration File Location](#configuration-file-location) +- [Complete Configuration Example](#complete-configuration-example) +- [Server Section](#server-section) +- [Database Section](#database-section) +- [TLS Section](#tls-section) +- [Hooks Section](#hooks-section) +- [Environment-Specific Examples](#environment-specific-examples) +- [CLI Options](#cli-options) +- [Validation](#validation) + +## Configuration File Location + +Specify a custom configuration file: + +```bash +chattermax -c /etc/chattermax/server.toml +``` + +## Complete Configuration Example + +```toml +[server] +host = "0.0.0.0" +port = 5222 +domain = "example.com" + +[database] +path = "/var/lib/chattermax/chattermax.db" + +[tls] +cert_path = "/etc/chattermax/fullchain.pem" +key_path = "/etc/chattermax/privkey.pem" + +# AI assistant hook +[[hooks]] +name = "ai-assistant" +command = "/usr/local/bin/ai-agent" +timeout = 30 +filters = [ + { field = "type", pattern = "message" }, + { field = "body", pattern = "^@bot\\s+" } +] + +# Message logger hook +[[hooks]] +name = "logger" +command = "/usr/local/bin/chat-logger" +filters = [ + { field = "type", pattern = "message" } +] +``` + +## Server Section + +### `host` + +**Type:** String +**Default:** `"0.0.0.0"` +**Description:** IP address to bind the server to. + +| Value | Description | +|-------|-------------| +| `"0.0.0.0"` | Listen on all interfaces | +| `"127.0.0.1"` | Listen only on localhost | +| `"192.168.1.10"` | Listen on specific interface | + +### `port` + +**Type:** Integer +**Default:** `5222` +**Description:** TCP port for client connections (C2S). + +Standard XMPP ports: +- `5222` - Client-to-Server (unencrypted/STARTTLS) +- `5223` - Client-to-Server (legacy SSL, deprecated) +- `5269` - Server-to-Server (not implemented) + +### `domain` + +**Type:** String +**Default:** `"localhost"` +**Description:** The XMPP domain served by this server. + +This value: +- Becomes the domain part of user JIDs (`user@domain`) +- Must match what clients use to connect +- Should be a valid DNS hostname in production + +**Examples:** +```toml +domain = "localhost" # Development +domain = "chat.example.com" # Production +``` + +## Database Section + +### `path` + +**Type:** String +**Default:** `"chattermax.db"` +**Description:** Path to the SQLite database file. + +**Examples:** +```toml +path = "chattermax.db" # Relative to working directory +path = "/var/lib/chattermax/data.db" # Absolute path +path = "./data/chattermax.db" # Relative subdirectory +``` + +**Notes:** +- The file is created automatically if it doesn't exist +- Parent directories must exist +- Ensure write permissions for the server process + +## TLS Section + +TLS encryption for secure client connections. + +### `cert_path` + +**Type:** String +**Required:** Yes (if TLS enabled) +**Description:** Path to the TLS certificate file (PEM format). + +### `key_path` + +**Type:** String +**Required:** Yes (if TLS enabled) +**Description:** Path to the TLS private key file (PEM format). + +**Example:** +```toml +[tls] +cert_path = "/etc/letsencrypt/live/chat.example.com/fullchain.pem" +key_path = "/etc/letsencrypt/live/chat.example.com/privkey.pem" +``` + +**Notes:** +- TLS is required for Android client compatibility in production +- Use Let's Encrypt for free certificates +- Certificate must include the server domain + +## Hooks Section + +Hooks enable external programs to respond to XMPP events. See [Hook System Documentation](./hooks.md) for detailed examples. + +### Hook Configuration + +Each hook is defined as a `[[hooks]]` entry: + +```toml +[[hooks]] +name = "my-hook" +command = "/path/to/executable" +timeout = 30 +working_dir = "/var/lib/chattermax" +filters = [ + { field = "type", pattern = "message" }, + { field = "body", pattern = "^@bot\\s+" } +] + +[hooks.env] +API_KEY = "secret" +DEBUG = "true" +``` + +### Hook Options + +| Option | Type | Required | Default | Description | +|--------|------|----------|---------|-------------| +| `name` | string | Yes | - | Unique identifier for the hook | +| `command` | string | Yes | - | Path to executable | +| `timeout` | integer | No | 30 | Seconds before killing the process | +| `working_dir` | string | No | Server CWD | Working directory for the command | +| `filters` | array | No | Match all | Conditions for triggering | +| `env` | table | No | - | Environment variables | + +### Filter Options + +| Option | Type | Description | +|--------|------|-------------| +| `field` | string | Event field to match (`type`, `from`, `to`, `body`, `room`) | +| `pattern` | string | Regex pattern to match against | +| `match_type` | string | `regex` (default) or `glob` | + +### Examples + +**AI Assistant (trigger on @bot mentions):** +```toml +[[hooks]] +name = "ai-assistant" +command = "/usr/local/bin/ai-agent" +timeout = 60 +filters = [ + { field = "body", pattern = "^@bot\\s+" } +] +``` + +**Message Logger (all messages):** +```toml +[[hooks]] +name = "logger" +command = "/usr/local/bin/chat-logger" +filters = [ + { field = "type", pattern = "message" } +] +``` + +**Room Welcome (presence in specific room):** +```toml +[[hooks]] +name = "welcome" +command = "/usr/local/bin/greeter" +filters = [ + { field = "type", pattern = "presence" }, + { field = "room", pattern = "general@conference\\.example\\.com" } +] +``` + +## Environment-Specific Examples + +### Development + +```toml +[server] +host = "127.0.0.1" +port = 5222 +domain = "localhost" + +[database] +path = "chattermax.db" +``` + +### Production + +```toml +[server] +host = "0.0.0.0" +port = 5222 +domain = "chat.mycompany.com" + +[database] +path = "/var/lib/chattermax/production.db" + +# [tls] +# cert_path = "/etc/letsencrypt/live/chat.mycompany.com/fullchain.pem" +# key_path = "/etc/letsencrypt/live/chat.mycompany.com/privkey.pem" +``` + +### Docker + +```toml +[server] +host = "0.0.0.0" +port = 5222 +domain = "xmpp.local" + +[database] +path = "/data/chattermax.db" +``` + +## CLI Options + +CLI arguments override configuration file values: + +| Option | Description | +|--------|-------------| +| `-c, --config ` | Configuration file path | +| `--init-db` | Initialize database schema and exit | +| `--add-user ` | Create user and exit | +| `-h, --help` | Show help | +| `-V, --version` | Show version | + +## Validation + +The server validates configuration on startup: +- Host must be a valid IP address +- Port must be between 1 and 65535 +- Domain must be non-empty +- Database path must be writable + +Invalid configuration results in an error message and exit. diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..0d99833 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,329 @@ +# Deployment Guide + +This guide covers deploying Chattermax in various environments. + +## Requirements + +### System Requirements + +| Component | Minimum | Recommended | +|-----------|---------|-------------| +| CPU | 1 core | 2+ cores | +| RAM | 256 MB | 512 MB+ | +| Storage | 100 MB | 1 GB+ (for message archive) | +| OS | Linux, macOS | Linux (Debian/Ubuntu) | + +### Software Requirements + +- SQLite 3.x (usually pre-installed) +- (Optional) Reverse proxy for TLS (nginx, Caddy) + +## Building for Production + +```bash +# Clone repository +git clone https://github.com/terraboops/chattermax.git +cd chattermax + +# Build optimized release binary +cargo build --release + +# Binary location +ls -la target/release/chattermax +``` + +## Linux Server Deployment + +### 1. Create System User + +```bash +sudo useradd -r -s /bin/false chattermax +``` + +### 2. Install Binary + +```bash +sudo mkdir -p /opt/chattermax +sudo cp target/release/chattermax /opt/chattermax/ +sudo chown -R chattermax:chattermax /opt/chattermax +``` + +### 3. Create Data Directory + +```bash +sudo mkdir -p /var/lib/chattermax +sudo chown chattermax:chattermax /var/lib/chattermax +``` + +### 4. Create Configuration + +```bash +sudo mkdir -p /etc/chattermax +sudo tee /etc/chattermax/chattermax.toml << 'EOF' +[server] +host = "0.0.0.0" +port = 5222 +domain = "chat.example.com" + +[database] +path = "/var/lib/chattermax/chattermax.db" +EOF + +sudo chown -R chattermax:chattermax /etc/chattermax +``` + +### 5. Initialize Database + +```bash +sudo -u chattermax /opt/chattermax/chattermax \ + -c /etc/chattermax/chattermax.toml \ + --init-db +``` + +### 6. Create Users + +```bash +sudo -u chattermax /opt/chattermax/chattermax \ + -c /etc/chattermax/chattermax.toml \ + --add-user admin:securepassword +``` + +### 7. Create systemd Service + +```bash +sudo tee /etc/systemd/system/chattermax.service << 'EOF' +[Unit] +Description=Chattermax XMPP Server +After=network.target + +[Service] +Type=simple +User=chattermax +Group=chattermax +WorkingDirectory=/var/lib/chattermax +ExecStart=/opt/chattermax/chattermax -c /etc/chattermax/chattermax.toml +Restart=always +RestartSec=5 + +# Security hardening +NoNewPrivileges=yes +PrivateTmp=yes +ProtectSystem=strict +ProtectHome=yes +ReadWritePaths=/var/lib/chattermax + +[Install] +WantedBy=multi-user.target +EOF +``` + +### 8. Start Service + +```bash +sudo systemctl daemon-reload +sudo systemctl enable chattermax +sudo systemctl start chattermax +sudo systemctl status chattermax +``` + +### 9. View Logs + +```bash +sudo journalctl -u chattermax -f +``` + +## Docker Deployment + +### Dockerfile + +```dockerfile +FROM rust:1.75-slim as builder + +WORKDIR /build +COPY . . +RUN cargo build --release + +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y \ + libsqlite3-0 \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /build/target/release/chattermax /usr/local/bin/ + +RUN useradd -r chattermax +USER chattermax + +EXPOSE 5222 + +ENTRYPOINT ["chattermax"] +CMD ["-c", "/etc/chattermax/chattermax.toml"] +``` + +### Docker Compose + +```yaml +version: '3.8' + +services: + chattermax: + build: . + ports: + - "5222:5222" + volumes: + - ./config:/etc/chattermax:ro + - chattermax-data:/var/lib/chattermax + restart: unless-stopped + +volumes: + chattermax-data: +``` + +### Running with Docker + +```bash +# Build image +docker build -t chattermax . + +# Initialize database +docker run --rm -v chattermax-data:/var/lib/chattermax \ + -v $(pwd)/chattermax.toml:/etc/chattermax/chattermax.toml:ro \ + chattermax --init-db + +# Add user +docker run --rm -v chattermax-data:/var/lib/chattermax \ + -v $(pwd)/chattermax.toml:/etc/chattermax/chattermax.toml:ro \ + chattermax --add-user admin:password + +# Run server +docker run -d --name chattermax \ + -p 5222:5222 \ + -v chattermax-data:/var/lib/chattermax \ + -v $(pwd)/chattermax.toml:/etc/chattermax/chattermax.toml:ro \ + chattermax +``` + +## TLS Termination with Nginx + +Since Chattermax doesn't yet implement TLS, use a reverse proxy: + +### Nginx Configuration + +```nginx +stream { + upstream chattermax { + server 127.0.0.1:5222; + } + + server { + listen 5223 ssl; + proxy_pass chattermax; + + ssl_certificate /etc/letsencrypt/live/chat.example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/chat.example.com/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + } +} +``` + +Clients connect to port 5223 with "Direct TLS" or "Legacy SSL" mode. + +## Firewall Configuration + +### UFW (Ubuntu) + +```bash +sudo ufw allow 5222/tcp comment 'XMPP C2S' +sudo ufw allow 5223/tcp comment 'XMPP C2S TLS' +``` + +### firewalld (RHEL/Fedora) + +```bash +sudo firewall-cmd --permanent --add-service=xmpp-client +sudo firewall-cmd --reload +``` + +## DNS Configuration + +For production, configure SRV records: + +``` +_xmpp-client._tcp.example.com. 86400 IN SRV 5 0 5222 chat.example.com. +``` + +This allows clients to auto-discover the server. + +## Monitoring + +### Health Check + +```bash +# Check if server is listening +nc -zv localhost 5222 + +# Check systemd status +systemctl is-active chattermax +``` + +### Log Analysis + +```bash +# Recent errors +journalctl -u chattermax --since "1 hour ago" | grep -i error + +# Connection count (approximate) +ss -tn state established '( dport = :5222 )' | wc -l +``` + +## Backup + +### Database Backup + +```bash +# Stop server for consistent backup +sudo systemctl stop chattermax +sudo cp /var/lib/chattermax/chattermax.db /backup/chattermax-$(date +%Y%m%d).db +sudo systemctl start chattermax + +# Or use SQLite online backup (no downtime) +sudo -u chattermax sqlite3 /var/lib/chattermax/chattermax.db ".backup /backup/chattermax-$(date +%Y%m%d).db" +``` + +### Automated Backup Script + +```bash +#!/bin/bash +BACKUP_DIR=/backup/chattermax +DB_PATH=/var/lib/chattermax/chattermax.db +DATE=$(date +%Y%m%d-%H%M%S) + +mkdir -p $BACKUP_DIR +sqlite3 $DB_PATH ".backup $BACKUP_DIR/chattermax-$DATE.db" + +# Keep only last 7 days +find $BACKUP_DIR -name "*.db" -mtime +7 -delete +``` + +## Troubleshooting + +### Server won't start + +1. Check configuration syntax: `cat /etc/chattermax/chattermax.toml` +2. Check permissions: `ls -la /var/lib/chattermax/` +3. Check port availability: `ss -tlnp | grep 5222` +4. Check logs: `journalctl -u chattermax -n 50` + +### Clients can't connect + +1. Verify server is running: `systemctl status chattermax` +2. Check firewall: `sudo ufw status` +3. Test connectivity: `nc -zv 5222` +4. Check client TLS settings (disable TLS for direct connection) + +### Performance issues + +1. Check database size: `ls -lh /var/lib/chattermax/chattermax.db` +2. Check connection count: `ss -tn | grep :5222 | wc -l` +3. Check system resources: `htop` or `top` +4. Consider vacuuming database: `sqlite3 chattermax.db "VACUUM;"` diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..274e1e8 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,311 @@ +# Getting Started + +## Prerequisites + +- **Rust 1.75+** (2024 edition support required) +- **SQLite 3.x** (usually pre-installed on most systems) + +### Installing Rust + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +source ~/.cargo/env +``` + +## Building from Source + +### Clone the Repository + +```bash +git clone https://github.com/terraboops/chattermax.git +cd chattermax +``` + +### Build Release Binary + +```bash +cargo build --release +``` + +This produces two binaries: +- `target/release/chattermax` - The XMPP server +- `target/release/chattermax-cli` - CLI client (skeleton) + +### Run Tests + +```bash +cargo test +``` + +## Quick Start + +### 1. Initialize the Database + +```bash +./target/release/chattermax --init-db +``` + +This creates `chattermax.db` with the required schema. + +### 2. Create Users + +```bash +./target/release/chattermax --add-user alice:secretpassword +./target/release/chattermax --add-user bob:anotherpassword +``` + +### 3. Start the Server + +```bash +./target/release/chattermax +``` + +Output: +``` +Chattermax listening on 0.0.0.0:5222 +``` + +### 4. Connect with an XMPP Client + +Use any standard XMPP client: +- [Gajim](https://gajim.org/) (Desktop) +- [Psi](https://psi-im.org/) (Desktop) +- [Conversations](https://conversations.im/) (Android) +- [Converse.js](https://conversejs.org/) (Web) + +**Connection settings:** +| Setting | Value | +|---------|-------| +| Server | localhost | +| Port | 5222 | +| Username | alice | +| Password | secretpassword | +| Domain | localhost | + +**Note:** Disable TLS/SSL in your client settings (or use "unencrypted" mode) as TLS is not yet implemented. + +## Verifying Your Installation + +After starting the server, verify everything is working: + +### Check Server is Listening + +```bash +# Verify port is open +nc -zv localhost 5222 + +# Expected output: +# Connection to localhost 5222 port [tcp/*] succeeded! +``` + +### Test with Telnet (Basic) + +```bash +telnet localhost 5222 +``` + +Type the following (then press Enter): +```xml + +``` + +You should receive a stream response with features. Press `Ctrl+]` then type `quit` to exit. + +### Verify Database + +```bash +# Check database exists and has tables +sqlite3 chattermax.db ".tables" + +# Expected output: +# messages offline_messages room_members rooms roster users + +# Check users were created +sqlite3 chattermax.db "SELECT username FROM users;" +``` + +### Check Logs + +When clients connect, you should see log output from the server indicating connection activity. + +## Configuration + +The server reads configuration from `chattermax.toml`: + +```toml +[server] +host = "0.0.0.0" # Listen on all interfaces +port = 5222 # Standard XMPP C2S port +domain = "localhost" # Your XMPP domain + +[database] +path = "chattermax.db" +``` + +Specify a custom config file: + +```bash +./target/release/chattermax -c /path/to/config.toml +``` + +See [Configuration Reference](./configuration.md) for all options. + +## Basic Usage + +### Sending Messages + +Once connected, you can send messages to other users: + +**To:** `bob@localhost` +**Message:** Hello, Bob! + +### Creating Chat Rooms (MUC) + +Join or create a room by entering: + +**Room JID:** `myroom@muc.localhost` + +The room is created automatically when the first user joins. + +### Viewing Message History + +Chattermax supports MAM (Message Archive Management). Compatible clients can retrieve message history automatically. + +## CLI Client + +Chattermax includes a CLI client for scripting and automation. + +### Send a Message + +```bash +chattermax send \ + --server localhost \ + --user alice@localhost \ + --password-file ~/.chattermax-password \ + --to bob@localhost \ + --body "Hello from the command line!" +``` + +### Set Presence + +```bash +chattermax presence --status online --message "Available" +``` + +### Join a Room + +```bash +chattermax join --room general@muc.localhost --nick "Alice" +``` + +### Listen for Messages + +```bash +# Listen and print messages as JSON +chattermax listen --format json + +# Listen for 60 seconds +chattermax listen --timeout 60 +``` + +See [CLI Client Documentation](./cli-client.md) for full details. + +## Setting Up Hooks + +Hooks let external programs (like AI agents) respond to chat events. + +### Simple Echo Bot + +Create `/usr/local/bin/echo-bot`: + +```bash +#!/bin/bash +read -r event +body=$(echo "$event" | jq -r '.body') +echo "{\"action\": \"reply\", \"body\": \"You said: $body\"}" +``` + +Make it executable: + +```bash +chmod +x /usr/local/bin/echo-bot +``` + +Add to `chattermax.toml`: + +```toml +[[hooks]] +name = "echo" +command = "/usr/local/bin/echo-bot" +filters = [ + { field = "body", pattern = "^!echo\\s+" } +] +``` + +Now any message starting with `!echo` will trigger a reply. + +See [Hook System Documentation](./hooks.md) for AI agent integration examples. + +## CLI Reference + +``` +chattermax [OPTIONS] + +Options: + -c, --config Config file path [default: chattermax.toml] + --init-db Initialize database and exit + --add-user Add user and exit + -h, --help Print help + -V, --version Print version +``` + +## Directory Structure After Setup + +``` +chattermax/ +├── chattermax # Server binary +├── chattermax.toml # Configuration +└── chattermax.db # SQLite database +``` + +## Troubleshooting + +### "Address already in use" + +Another process is using port 5222: + +```bash +# Find the process +lsof -i :5222 + +# Or use a different port in chattermax.toml +``` + +### "Connection refused" from client + +1. Ensure the server is running +2. Check firewall settings +3. Verify the client is connecting to the correct host/port + +### Database errors + +Re-initialize the database: + +```bash +rm chattermax.db +./target/release/chattermax --init-db +``` + +### Authentication failures + +1. Verify the user exists (re-add if needed) +2. Check username matches the domain in config +3. Ensure password is correct + +## Next Steps + +- [Hook System](./hooks.md) - AI agent integration +- [CLI Client](./cli-client.md) - Command-line client usage +- [Configuration Reference](./configuration.md) - Detailed config options +- [Architecture Overview](./architecture.md) - System design +- [Protocol Support](./protocol-support.md) - XMPP feature coverage diff --git a/docs/hooks.md b/docs/hooks.md new file mode 100644 index 0000000..9456130 --- /dev/null +++ b/docs/hooks.md @@ -0,0 +1,354 @@ +# Hook System + +Hooks let external programs respond to XMPP events. Use them to connect AI agents, build bots, log messages, or trigger workflows from chat. + +## How It Works + +Hooks let you: + +- Connect AI/LLM agents to chat +- Build automated response bots +- Log or archive messages externally +- Integrate with external services +- Trigger workflows from chat commands + +## How It Works + +``` +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ XMPP Event │────▶│ Filter │────▶│ Spawn │────▶│ Reply │ +│ arrives │ │ matching │ │ command │ │ sent │ +└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ + │ │ + │ JSON on stdin + │ JSON on stdout + ▼ │ + No match = skip ▼ + Command process +``` + +1. XMPP event occurs (message, presence, etc.) +2. Server checks each hook's filters against the event +3. Matching hooks spawn their configured command +4. Hooks receive events as JSON on stdin +5. Hooks write responses as JSON on stdout +6. Server sends the reply to the appropriate recipient + +## Configuration + +Hooks are configured in `chattermax.toml`: + +```toml +[[hooks]] +name = "ai-assistant" +command = "/usr/local/bin/my-ai-agent" +timeout = 30 +filters = [ + { field = "type", pattern = "message" }, + { field = "body", pattern = "^@bot\\s+" } +] + +[[hooks]] +name = "logger" +command = "/usr/local/bin/chat-logger" +filters = [ + { field = "type", pattern = "message" } +] +``` + +### Hook Options + +| Option | Type | Required | Description | +|--------|------|----------|-------------| +| `name` | string | Yes | Unique identifier for the hook | +| `command` | string | Yes | Path to executable or script | +| `timeout` | integer | No | Seconds before killing the process (default: 30) | +| `filters` | array | No | Conditions that must match (default: match all) | +| `env` | table | No | Environment variables to pass | +| `working_dir` | string | No | Working directory for the command | + +### Filter Options + +| Option | Type | Description | +|--------|------|-------------| +| `field` | string | Event field to match against | +| `pattern` | string | Regex or glob pattern | +| `match_type` | string | `regex` (default) or `glob` | + +### Available Filter Fields + +| Field | Description | Example | +|-------|-------------|---------| +| `type` | Event type | `message`, `presence`, `iq` | +| `from` | Sender JID | `user@example.com` | +| `to` | Recipient JID | `room@conference.example.com` | +| `body` | Message content | `Hello world` | +| `room` | MUC room (if applicable) | `general@conference.example.com` | + +## Event Format + +Events are passed to hooks as JSON on stdin: + +### Message Event + +```json +{ + "type": "message", + "id": "msg-12345", + "from": "alice@example.com/mobile", + "to": "bob@example.com", + "body": "@bot what's the weather?", + "timestamp": "2024-01-15T10:30:00Z", + "thread": null, + "muc": null +} +``` + +### MUC Message Event + +```json +{ + "type": "message", + "id": "msg-67890", + "from": "general@conference.example.com/alice", + "to": "general@conference.example.com", + "body": "@bot help", + "timestamp": "2024-01-15T10:31:00Z", + "thread": null, + "muc": { + "room": "general@conference.example.com", + "nickname": "alice" + } +} +``` + +### Presence Event + +```json +{ + "type": "presence", + "from": "alice@example.com/mobile", + "to": null, + "status": "available", + "show": "chat", + "message": "Ready to chat!", + "timestamp": "2024-01-15T10:00:00Z" +} +``` + +## Response Format + +Hooks respond with JSON on stdout: + +### Send a Reply + +```json +{ + "action": "reply", + "body": "The weather in San Francisco is 65°F and sunny." +} +``` + +### Send to Specific JID + +```json +{ + "action": "send", + "to": "alice@example.com", + "body": "Your scheduled reminder: Team meeting in 15 minutes." +} +``` + +### Send to MUC Room + +```json +{ + "action": "send", + "to": "general@conference.example.com", + "type": "groupchat", + "body": "Announcement: Server maintenance at 10 PM." +} +``` + +### No Response + +```json +{ + "action": "none" +} +``` + +### Multiple Actions + +```json +{ + "actions": [ + { "action": "reply", "body": "Processing your request..." }, + { "action": "send", "to": "admin@example.com", "body": "User requested: weather" } + ] +} +``` + +## Examples + +### Simple Echo Bot + +```bash +#!/bin/bash +# /usr/local/bin/echo-bot + +read -r event +body=$(echo "$event" | jq -r '.body') +echo "{\"action\": \"reply\", \"body\": \"You said: $body\"}" +``` + +```toml +[[hooks]] +name = "echo-bot" +command = "/usr/local/bin/echo-bot" +filters = [ + { field = "body", pattern = "^!echo\\s+" } +] +``` + +### Python AI Assistant + +```python +#!/usr/bin/env python3 +# /usr/local/bin/ai-assistant + +import json +import sys +import openai + +event = json.loads(sys.stdin.read()) +body = event.get("body", "") + +# Strip the @bot prefix +query = body.replace("@bot", "").strip() + +# Call your LLM +response = openai.ChatCompletion.create( + model="gpt-4", + messages=[{"role": "user", "content": query}] +) + +reply = response.choices[0].message.content +print(json.dumps({"action": "reply", "body": reply})) +``` + +```toml +[[hooks]] +name = "ai-assistant" +command = "/usr/local/bin/ai-assistant" +timeout = 60 +filters = [ + { field = "type", pattern = "message" }, + { field = "body", pattern = "^@bot\\s+" } +] +env = { OPENAI_API_KEY = "sk-..." } +``` + +### Message Logger + +```python +#!/usr/bin/env python3 +# /usr/local/bin/chat-logger + +import json +import sys +from datetime import datetime + +event = json.loads(sys.stdin.read()) + +with open("/var/log/chattermax/messages.log", "a") as f: + log_entry = { + "timestamp": datetime.now().isoformat(), + "from": event.get("from"), + "to": event.get("to"), + "body": event.get("body") + } + f.write(json.dumps(log_entry) + "\n") + +# No reply needed +print(json.dumps({"action": "none"})) +``` + +### Room Greeter + +```bash +#!/bin/bash +# /usr/local/bin/room-greeter + +read -r event +status=$(echo "$event" | jq -r '.status') + +if [ "$status" = "available" ]; then + nickname=$(echo "$event" | jq -r '.muc.nickname // .from') + echo "{\"action\": \"reply\", \"body\": \"Welcome, $nickname! Type @help for commands.\"}" +else + echo "{\"action\": \"none\"}" +fi +``` + +## Best Practices + +### Performance + +- Keep hooks fast (< 1 second for interactive responses) +- Use `timeout` to prevent hung processes +- Avoid blocking I/O in hook scripts +- Consider async processing for slow operations + +### Security + +- Validate all input from events +- Don't expose sensitive data in hook scripts +- Use absolute paths for commands +- Run hooks with minimal privileges +- Sanitize user input before passing to shells + +### Reliability + +- Handle JSON parsing errors gracefully +- Always output valid JSON (even for errors) +- Log errors to stderr (not stdout) +- Return `{"action": "none"}` when unsure + +### Error Handling + +```python +#!/usr/bin/env python3 +import json +import sys + +try: + event = json.loads(sys.stdin.read()) + # Process event... + print(json.dumps({"action": "reply", "body": "Success!"})) +except Exception as e: + print(json.dumps({"action": "none"}), file=sys.stdout) + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) +``` + +## Debugging + +Enable hook debugging in configuration: + +```toml +[hooks] +debug = true +log_events = true +log_responses = true +``` + +View hook activity: + +```bash +# Watch hook execution +journalctl -u chattermax -f | grep hook + +# Test a hook manually +echo '{"type":"message","body":"@bot hello"}' | /usr/local/bin/my-hook +``` diff --git a/docs/protocol-support.md b/docs/protocol-support.md new file mode 100644 index 0000000..3a7f27a --- /dev/null +++ b/docs/protocol-support.md @@ -0,0 +1,249 @@ +# XMPP Protocol Support + +This document details the XMPP standards and extensions (XEPs) implemented in Chattermax. + +## Android Client Compatibility + +Chattermax targets compatibility with major Android XMPP clients. These are the XEPs required for a good mobile experience: + +| XEP | Name | Status | Required For | +|-----|------|--------|--------------| +| XEP-0030 | Service Discovery | **Supported** | Client capability detection | +| XEP-0045 | Multi-User Chat | **Supported** | Group channels | +| XEP-0115 | Entity Capabilities | Planned | Efficient capability caching | +| XEP-0198 | Stream Management | Planned | Connection reliability | +| XEP-0280 | Message Carbons | Planned | Multi-device sync | +| XEP-0313 | Message Archive Management | **Supported** | Chat history | + +**Nice-to-have for mobile:** +- XEP-0163 (PEP) - Personal Eventing Protocol +- XEP-0384 (OMEMO) - End-to-end encryption +- XEP-0363 (HTTP File Upload) - File sharing + +**Tested Android clients:** +- [Conversations](https://conversations.im/) - Primary target +- [Blabber.im](https://blabber.im/) +- [Moxxy](https://moxxy.org/) + +## Core Protocol + +### RFC 6120 - XMPP Core + +| Feature | Status | Notes | +|---------|--------|-------| +| Stream negotiation | Supported | Full stream lifecycle | +| Stream features | Supported | Pre/post-auth features | +| SASL authentication | Partial | PLAIN mechanism only | +| Resource binding | Supported | Client-provided or auto-generated | +| Stanza addressing | Supported | Full JID handling | +| Error stanzas | Supported | Standard error conditions | + +### RFC 6121 - XMPP IM + +| Feature | Status | Notes | +|---------|--------|-------| +| Roster management | Supported | Add, update, remove contacts | +| Roster versioning | Not implemented | | +| Presence subscriptions | Supported | Request, approve, deny | +| Presence broadcast | Supported | To roster contacts | +| Message delivery | Supported | Chat and groupchat types | +| Message threads | Passed through | Not processed server-side | + +## Implemented XEPs + +### XEP-0030: Service Discovery + +**Status:** Supported + +Enables clients to discover server capabilities and services. + +**Supported queries:** +- `disco#info` - Server/entity information +- `disco#items` - Available services and rooms + +**Advertised features:** +- `urn:xmpp:mam:2` - Message Archive Management +- `http://jabber.org/protocol/muc` - Multi-User Chat + +### XEP-0045: Multi-User Chat (MUC) + +**Status:** Basic support + +Provides group chat functionality. + +| Feature | Status | +|---------|--------| +| Room creation | Supported (auto-create on join) | +| Room join/leave | Supported | +| Presence broadcast | Supported | +| Groupchat messages | Supported | +| Room persistence | Supported (database) | +| Occupant lists | Supported | +| Nicknames | Supported | +| Room configuration | Not implemented | +| Admin/owner roles | Not implemented | +| Moderation | Not implemented | +| Invitations | Not implemented | +| Room history | Not implemented | + +**Room JID format:** `room@muc.` + +### XEP-0059: Result Set Management (RSM) + +**Status:** Supported + +Enables pagination of large result sets (used with MAM). + +| Feature | Status | +|---------|--------| +| `` limit | Supported | +| `` pagination | Supported | +| `` pagination | Supported | +| `` / `` | Supported | +| `` | Supported | + +### XEP-0191: Blocking Command + +**Status:** Stub only + +Framework exists but blocking is not enforced. + +### XEP-0203: Delayed Delivery + +**Status:** Supported + +Timestamps for delayed/offline messages. + +| Feature | Status | +|---------|--------| +| `` element | Supported | +| Stanza IDs | Supported | + +### XEP-0313: Message Archive Management (MAM) + +**Status:** Supported + +Server-side message archive with query capabilities. + +| Feature | Status | +|---------|--------| +| Archive queries | Supported | +| `with` filter (JID) | Supported | +| `start` filter (date) | Supported | +| `end` filter (date) | Supported | +| RSM pagination | Supported | +| Result metadata | Supported | +| Preferences | Not implemented | +| Archive ID | Supported | + +**Namespace:** `urn:xmpp:mam:2` + +## Authentication + +### SASL Mechanisms + +| Mechanism | Status | Security | +|-----------|--------|----------| +| PLAIN | Supported | Requires TLS in production | +| SCRAM-SHA-1 | Not implemented | Recommended | +| SCRAM-SHA-256 | Not implemented | Recommended | +| EXTERNAL | Not implemented | Certificate auth | +| ANONYMOUS | Not implemented | Guest access | + +**Current flow:** +1. Client sends base64-encoded credentials: `\0username\0password` +2. Server verifies against database +3. Success/failure response + +### TLS/STARTTLS + +**Status:** Supported + +TLS encryption is available via configuration. Required for Android client compatibility. + +```toml +[tls] +cert_path = "/etc/chattermax/fullchain.pem" +key_path = "/etc/chattermax/privkey.pem" +``` + +**Notes:** +- Use Let's Encrypt for free certificates +- Android clients require valid TLS certificates +- For development, use a TLS-terminating reverse proxy + +## Stanza Types + +### Message + +| Type | Status | Description | +|------|--------|-------------| +| `chat` | Supported | One-to-one messages | +| `groupchat` | Supported | MUC messages | +| `headline` | Passed through | Alerts/notifications | +| `normal` | Passed through | Standalone messages | +| `error` | Supported | Error responses | + +### Presence + +| Type | Status | Description | +|------|--------|-------------| +| (none) | Supported | Available | +| `unavailable` | Supported | Offline | +| `subscribe` | Supported | Subscription request | +| `subscribed` | Supported | Approve subscription | +| `unsubscribe` | Supported | Remove subscription | +| `unsubscribed` | Supported | Deny subscription | +| `probe` | Not implemented | Presence check | +| `error` | Supported | Error response | + +### IQ (Info/Query) + +| Type | Status | Description | +|------|--------|-------------| +| `get` | Supported | Request information | +| `set` | Supported | Modify state | +| `result` | Supported | Success response | +| `error` | Supported | Error response | + +## Not Implemented + +These features are not currently implemented: + +### Core Protocol +- Server-to-Server (S2S) federation +- Component protocol (XEP-0114) +- BOSH (XEP-0124) +- WebSocket (RFC 7395) + +### Extensions +- Stream Management (XEP-0198) +- Message Carbons (XEP-0280) +- Chat State Notifications (XEP-0085) +- Message Delivery Receipts (XEP-0184) +- vCards (XEP-0054, XEP-0292) +- PubSub (XEP-0060) +- PEP (XEP-0163) +- Entity Capabilities (XEP-0115) +- Last Activity (XEP-0012) +- Ping (XEP-0199) +- Software Version (XEP-0092) + +## Compliance + +### XMPP Compliance Suites (XEP-0459) + +| Suite | Status | +|-------|--------| +| Core Server 2024 | Partial | +| Core Client 2024 | N/A | +| Advanced Server 2024 | Partial | +| IM Server 2024 | Partial | + +Chattermax is an MVP implementation focused on core messaging functionality. Full compliance suite support is planned for future versions. + +## Version History + +| Version | Changes | +|---------|---------| +| 0.1.0 | Initial release with core messaging, MUC, MAM |