Files
sultan/CLAUDE.md
T
br 9861c25949 init des architektur beschreibenden MD...
noch kein code, nur REadme, ai.agent md s
2026-09-29 22:45:38 +02:00

3.9 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Instruktionen

Lies die .ai/*.md Files. Diese liefern den Context für die App, die hier entstehen soll. Maßgeblich ist aktuell .ai/sultan-system-architecture.md (Netzwerk-, Sicherheits-, Daten- und Anwendungsmodell inkl. SQL-Schema, Event-Format und Referenz-Compose-Files). Bei Widersprüchen zwischen diesem File und der Spec gilt die Spec.

Projektstatus

Greenfield: Es existiert noch kein Go-Code, kein go.mod, keine Build-/Test-Toolchain. Build-, Lint- und Test-Befehle hier ergänzen, sobald sie existieren.

Big Picture

Sultan ersetzt manuell gepflegtes Ingress-Routing (z. B. Nginx Proxy Manager): Backends deklarieren ihr Routing selbst (Traefik-Labels an Docker-Containern oder Drop-ins in /etc/sultan.d/*.conf für Bare-Metal/LAMP), ein Agent meldet das an einen zentralen Server, und Traefik auf dem Ingress-Knoten pollt daraus seine Konfiguration.

Single Binary in Go mit drei Subcommands:

  • sultan server – Registry, Stream-Hub (hält Agent-Verbindungen im RAM, Dead-Node-Timeout 90s), Policy-Engine, Traefik-HTTP-Provider
  • sultan agent – Watcher (Docker Events API auf traefik.*-Labels bzw. inotify auf /etc/sultan.d), State-Serializer (injiziert LAN- oder NetBird-IP 100.64.x.y als Backend-Ziel), Transport mit Reconnect + exponentiellem Backoff
  • sultan token – CLI für Schlüssel, Enrollment-Tokens, Lizenzausstellung

Ports / Endpunkte des Servers:

  • :8443 (TLS) – Control Plane, ausschließlich ausgehend vom Agent (NAT/CGNAT/DS-Lite-tauglich). Persistenter Stream (HTTP/2 oder SSE), 45s-Keepalive, Events werden sofort gepusht. Enrollment: POST /api/v1/enroll.
  • 127.0.0.1:8080 – GET /v1/traefik-config (Traefik pollt alle 2–5s; flache Labels aller aktiven Nodes → verschachteltes Traefik-JSON) und GET /metrics/checkmk (Checkmk Local-Check-Format).

Sicherheitsmodell (Kerninvarianten):

  • Server-TLS-Zertifikat self-signed (ECDSA P-256), Agent pinnt den SHA256-Fingerprint per TOFU in known_servers.
  • Agent-Keys (Ed25519) werden nur lokal erzeugt und verlassen den Host nie; Enrollment tauscht Public Key + einmaligen Token gegen Mandanten-Zuordnung und signierten Capability-Lease. Danach ist jeder Heartbeat mit node.key signiert.
  • Jeder Agent-Payload wird serverseitig gegen die Mandanten-Policy geprüft: Hosts in Host(...)-Regeln müssen in allowed_domains stehen (sonst ablehnen + Audit-Log), Routen über max_routes werden verworfen.
  • Lizenzen (license.json) sind mit dem Ed25519-Server-Master-Key signiert.

Stream-Events (JSON: event_id, timestamp, type, node_id, payload): service_state (Agent→Server, vollständiger Label-Snapshot, nicht Delta), node_command (re_enroll/drain/maintenance), lease_renew, error.

Persistenz: SQLite unter <data-dir>/sultan.db (Default /var/lib/sultan), Tabellen tenants, nodes, enrollment_tokens (Tokens nur als Hash gespeichert).

Policy/Lizenzablauf: Mandanten-Status steuert das generierte Routing – Zahlungsverzug → Router auf Bezahlseite (402), Backend down/service_down → Statusseite 503 mit Retry-After: 60. Checkmk-Schwellen: WARN bei 30, CRIT bei 14 Tagen Restlaufzeit, bei Ablauf Umleitung auf Landingpage.

Bekannte Unstimmigkeiten in der Spec

Vor der Implementierung mit dem User klären statt raten:

  • Token-Präfix: sltn_token_... (Abschnitt 3.2) vs. sltn_enroll_... (Compose-Beispiel 7.2).
  • Tenant-Status: Schema kennt active/suspended_payment/quarantined, Abschnitt 6.2 setzt expired.
  • Stream-Transport ist offen: HTTP/2 oder SSE (SSE wäre nur Server→Agent; bidirektionale Events brauchen dann einen Rückkanal).
  • Einige URLs in JSON/YAML-Blöcken der Spec sind durch Copy-Paste als Markdown-Links verstümmelt ("[http://...](http://...)") – die nackte URL ist gemeint.