98 lines
4.2 KiB
Markdown
98 lines
4.2 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Working principles
|
|
|
|
1. Don't assume. Don't hide confusion. Surface tradeoffs.
|
|
2. Minimum code that solves the problem. Nothing speculative.
|
|
3. Touch only what you must. Clean up only your own mess.
|
|
4. Define success criteria. Loop until verified.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Run tests
|
|
pytest -q # all tests
|
|
pytest tests/test_threshold.py # single file
|
|
pytest -k test_name # single test
|
|
|
|
# Lint and type check
|
|
tox -e lint # flake8 over hbd/ and tests/
|
|
tox -e mypy # mypy over hbd/
|
|
|
|
# Install for development
|
|
pip install -e ".[all,dev]"
|
|
|
|
# Run server
|
|
python -m hbd.server.cli serve -c .hb.yaml -f -v
|
|
|
|
# Generate a password hash
|
|
hbd passwd <username>
|
|
```
|
|
|
|
Tests live in `tests/` (pytest, imported as a package). A second directory `test/` contains only TLS fixtures (`.pem` files), not test code.
|
|
|
|
Line length: 111 characters (`black`, `flake8`, both configured).
|
|
|
|
## Architecture
|
|
|
|
The system has two components: `hbc` (client) and `hbd` (server), both in the `hbd` Python package.
|
|
|
|
```
|
|
hbd/
|
|
common/ # proto.py (encode/decode), utils.py
|
|
client/ # hbc: plugins/, main.py, config.py, plugin.py
|
|
server/ # hbd: all server modules
|
|
```
|
|
|
|
### Server module map
|
|
|
|
| Module | Role |
|
|
|---|---|
|
|
| `cli.py` | Argument parsing, entry point, daemon startup |
|
|
| `main.py` | Asyncio runtime: starts UDP, HTTP, WebSocket; pickle save/load |
|
|
| `hbdclass.py` | `Host` and `Connection` domain objects; DNS queue |
|
|
| `udp.py` | UDP datagram listener; processes `HTB` and `PLG` messages; sets/resets overdue timers |
|
|
| `http.py` | aiohttp web server; all REST API routes (`/api/0/`) and page routes |
|
|
| `ws.py` | WebSocket broadcast to connected dashboard clients |
|
|
| `notify.py` | Notification dispatch (Pushover, email, Mattermost, Matrix, Signal, SMS); `eventlog()` is the single choke-point for all alert events |
|
|
| `threshold.py` | Threshold evaluation against plugin metrics; state transitions (OK/WARNING/CRITICAL/UNKNOWN) |
|
|
| `monitor.py` | Timer cleanup on shutdown (reachability is event-driven via timers in `udp.py`, not polled) |
|
|
| `data.py` | Shared in-memory message ring buffer |
|
|
| `journal.py` | JSONL message journal with size-based rotation |
|
|
| `users.py` | Session management, password hashing (PBKDF2), role checks |
|
|
| `config.py` | Config loading and defaults |
|
|
| `configio.py` | Config file read/write via `ruamel.yaml` (preserves comments) |
|
|
| `settings.py` | Settings sections for the web UI settings page |
|
|
| `dns.py` | `nsupdate` integration for dynamic DNS |
|
|
| `oauth.py` | OAuth2 login (Gitea) |
|
|
|
|
### Key data flows
|
|
|
|
**Heartbeat received:** `udp.py` decodes the `HTB` datagram → updates `Connection` state in `hbdclass.py` → resets overdue asyncio timer → broadcasts via `ws.py` → `notify.py` fires connectivity alerts on state change.
|
|
|
|
**Plugin data received:** `udp.py` decodes `PLG` datagram → stores on `Host` → `threshold.py` evaluates against configured thresholds → `notify.py` fires threshold alerts on state transitions.
|
|
|
|
**State persistence:** `Host.hosts` dict + `data.msgs` ring + active sessions are pickled every 5 minutes and on clean shutdown. Asyncio timers are stripped before pickling (`Connection.__getstate__`).
|
|
|
|
**Config reload:** SIGHUP → `configio.py` re-reads YAML → live-updates hosts, thresholds, users, notification channels. Port/cert/pickle/journal changes require a full restart.
|
|
|
|
### Client plugin system
|
|
|
|
Plugins in `hbd/client/plugins/` subclass `InfoPlugin` (collected once, on demand) or `MonitorPlugin` (periodic). `initialize()` returns `False` to self-disable. Data is sent as `PLG` UDP messages.
|
|
|
|
`hbc_mini.py` (scripts/) and `hbc_mini.c` (scripts/c/) are standalone single-file clients with no external dependencies.
|
|
|
|
### Protocol
|
|
|
|
All UDP messages: `!<ID>: <zlib-compressed key=value payload>`. Encoding in `hbd/common/proto.py`. Lists/dicts encoded as JSON with `@` prefix; booleans as `1`/`0`.
|
|
|
|
### Web UI
|
|
|
|
Jinja2 templates in `hbd/server/templates/`. Static assets in `hbd/server/static/`. Live pages (`/live`, `/plugins`) use WebSocket connections for real-time push.
|
|
|
|
### CI
|
|
|
|
Gitea Actions workflow at `.gitea/workflows/release.yml`.
|