# Minimalne API dla bot-executora (k3s) + auth Ten dokument opisuje **minimalny** zestaw endpointów i zasad bezpieczeństwa dla warstwy **execution plane** (`bot-executor`) i **control plane** (API do sterowania botami) na VPS (k3s). Cel: wysyłać transakcje na Drift **bez wystawiania publicznie** endpointu typu “podpisz i wyślij tx”. Powiązane: - Architektura botów: `doc/bots.md` - DLOB / statsy na VPS: `doc/dlob-services.md` - Topologia: `doc/rpc/README.md` ## Rozdział odpowiedzialności ### `bot-executor` (execution plane, private) - Ma klucze prywatne (tylko tutaj). - Podpisuje i wysyła transakcje na Drift przez prywatny Solana RPC. - Czyta “desired state” z DB (`bot_config`) i zapisuje audyt (`bot_events`) + heartbeat (`bot_state`). - **Nie** przyjmuje z zewnątrz “raw tx do podpisu”. ### Control plane (public/edge, auth) - Ustawianie `bot_config` (mode/target/limity/kill switch). - Odczyt `bot_state` i `bot_events`. - Autoryzacja: tokeny/ACL/WireGuard (zależnie od klienta). Control plane może być zrobiony na dwa sposoby: 1) **Hasura GraphQL** (z rolami i RLS) — szybkie, ale wymaga dopięcia uprawnień. 2) **`trade-api` endpointy** (HTTP) — prostsze do “opiniowania” auth (Bearer token scopes). ## Model danych (minimum) Minimalne tabele (wg `doc/bots.md`): - `bot_config`: desired state (mode, market, limity, kill_switch, strategia) - `bot_state`: heartbeat + ostatni błąd/akcja - `bot_events`: log audytowy (decision/order/panic/error) ## Auth (rekomendacja minimalna) Warstwy: 1) **Sieć**: tylko przez WireGuard / allowlist IP (najprostsze i skuteczne). 2) **Aplikacja**: tokeny + scopes (np. `Authorization: Bearer ...`). 3) (Opcjonalnie) **mTLS/HMAC** service-to-service w klastrze, jeśli chcesz twardsze granice. W tym repo masz już wzorzec tokenów w `api_tokens` + walidacja w `services/api/server.mjs`. ### Scopes (propozycja) - `bots:read` — odczyt `bot_config/state/events` - `bots:write` — zmiana `bot_config` (mode/params/kill switch) - `exec:panic` — wymuszenie panic (jeśli zdecydujesz się na osobny endpoint; zwykle wystarczy `kill_switch=true`) ## Control plane API (HTTP) — propozycja endpointów Te endpointy wystawiaj publicznie (za auth), ale **niech one tylko zmieniają DB**, a nie wysyłają transakcje. ### Konfiguracja bota - `GET /v1/bots` (scope: `bots:read`) - lista botów (id, name, market, mode, kill_switch, updated_at) - `GET /v1/bots/:id` (scope: `bots:read`) - pełny `bot_config` - `POST /v1/bots` (scope: `bots:write`) - tworzy nowy `bot_config` - `PATCH /v1/bots/:id` (scope: `bots:write`) - aktualizacja (np. limity, target exposure, params) ### Kill switch / mode (najczęstsze akcje) - `POST /v1/bots/:id/mode` (scope: `bots:write`) - body: `{ "mode": "off" | "observe" | "trade" }` - `POST /v1/bots/:id/kill-switch` (scope: `bots:write`) - body: `{ "enabled": true | false }` - Executor traktuje `enabled=true` jako “panic” i wykonuje runbook (`cancel_all` + `close_position`) opisany w `doc/bots.md`. ### Status i audyt - `GET /v1/bots/:id/state` (scope: `bots:read`) - heartbeat, last_error, last_action_at - `GET /v1/bots/:id/events?limit=200` (scope: `bots:read`) - ostatnie eventy (decision/order/panic/error) ## `bot-executor` API (private) — minimalne endpointy To API **nie musi być wystawione** poza klaster. Wystarczy Service `ClusterIP`. - `GET /healthz` — liveness (bez auth) - `GET /readyz` — readiness (bez auth; np. czy jest połączenie z RPC + DB) - (Opcjonalnie) `POST /v1/reconcile` — ręczny reconcile (auth tylko wewnętrzny / admin) Zamiast `POST /v1/panic` preferuj sterowanie przez DB (`kill_switch=true`), bo to daje audyt i działa nawet, gdy control plane jest odcięty od samego executora. ## Deployment w k3s (propozycja) - `Deployment/bot-executor`: - env: RPC endpoints (po WG), Hasura URL, market list, itp. - secret: keypair / seed, ewentualnie API tokeny - zasoby: limity CPU/RAM (żeby executor nie “zjadał” node’a) - `Service/bot-executor` (ClusterIP) - brak Ingress (domyślnie) - Monitoring: - `Prometheus` scrape `/metrics` (jeśli dodasz) ## Co z “wysłaniem kontraktu” na Drift? - `bot-executor` robi to przez Drift SDK → Solana RPC (`sendTransaction`). - Control plane **nie** wysyła tx; tylko ustawia desired state.