Uwierzytelnienie agenta
MCP server https://mcp.mdiv.pl/api/mcp akceptuje dwie metody uwierzytelnienia:
- OAuth 2.1 + PKCE — preferowane dla agentów AI działających w imieniu użytkownika (Claude Desktop, Cursor, ChatGPT z MCP). Wymagany
code_challenge_method=S256; wartośćplainjest odrzucana zgodnie z RFC. Authorization endpoint:https://moje.mdiv.pl/oauth/authorize. Dynamic Client Registration:https://moje.mdiv.pl/api/oauth/register(RFC 7591). - Personal API Token — format
mpt_<64hex>(96 bitów entropii). Wystawiany ręcznie przez klienta na https://moje.mdiv.pl/account/api-tokens. Przekazywany w nagłówkuAuthorization: Bearer mpt_….
Tokeny są przechowywane na serwerze jako bcrypt hash — nigdy w plaintext. Wartość tokena jest pokazywana jednokrotnie, w momencie wystawienia. Klient może w dowolnym momencie unieważnić token przez panel.
Granularne scope'y (33)
Każdy token (OAuth lub PAT) ma przypisany podzbiór z 33 scope'ów. Lista domen: websites, domains, databases, email, dns, ssl, apps, jobs, packages, files, backups, commerce, profile, offline_access. Każda domena ma rozdziały :read / :write / :delete.
Zasady wzajemnego implikowania:
:writeimplies:read— token zdatabases:writemoże też czytać.:deleteNIE jest implikowany przez:write. Aby usunąć zasób, agent musi mieć osobny scope:delete.- Wszystkie scope'y są opt-in — domyślnie pusty token nie pozwala na nic.
Pełna lista i mapowanie tool→scope: zobacz stronę /dla-agentow-ai oraz /.well-known/mcp.json.
Tier system
Niezależnie od scope'ów tokena, każde konto klienta ma flagę ai_deploy ustawianą przez administratora mDiv:
| Tier | Co wolno |
|---|---|
none | Default. Wszystkie operacje AI Deploy → 403 AI_DEPLOY_NOT_ENABLED. |
sandbox | Wyłącznie read-only narzędzia. install_*, delete_*, set_dns_records → 403 AI_DEPLOY_TIER_TOO_LOW. |
beta | Pełen zakres ops. Limit 500 mutujących wywołań na konto na dzień. |
full | Bez ograniczeń ponad fizyczne limity pakietu. |
Klient zaczyna od sandbox. Awans po 1–2 tygodniach testów następuje po pisemnej zgodzie klienta i analizie logów. Globalny kill switch (AI_DEPLOY_GLOBALLY_DISABLED) pozwala wyłączyć AI Deploy dla wszystkich kont w razie incydentu po stronie mDiv.
Two-step delete pattern
Każda destrukcyjna operacja (delete_*, w fazie 1 obejmuje tylko delete_domain; kolejne resource'y są dokładane stopniowo) wymaga dwóch wywołań:
preview_delete_domain({ domain_id })→{ preview_token, impact: { subdomains, ssl_certs, email_domains, warning }, expires_at }. Agent musi pokazać użytkownikowi poleimpacti czekać na potwierdzenie.delete_domain({ domain_id, preview_token, confirm: true})→{ deleted: true }.
Token preview ma trzy zabezpieczenia:
- Bound do (user_id, resource_type, resource_id). Agent NIE może podsunąć użytkownikowi tokenu wystawionego dla innego zasobu lub innego konta — server odrzuca z
PREVIEW_TOKEN_OWNERSHIP_MISMATCH/PREVIEW_TOKEN_RESOURCE_MISMATCH. - Single-use — po pierwszym użyciu token jest invalidated.
- TTL 10 minut. Po wygaśnięciu:
PREVIEW_TOKEN_EXPIRED.
Brak preview_token w destruktywnym wywołaniu zwraca PREVIEW_TOKEN_MISSING; brak confirm: true → CONFIRMATION_REQUIRED. Wzór jest progresywnie wdrażany na kolejne typy zasobów.
Idempotency-Key
Wszystkie mutating endpointy (POST, PUT, PATCH, DELETE) honorują nagłówek Idempotency-Key z UUID v4 dostarczonym przez klienta.
- Replay z tym samym body w oknie 24h → cached response z nagłówkiem
Idempotent-Replay: true. - Replay z innym body →
409 IDEMPOTENCY_KEY_REUSED. - Niepoprawny format klucza →
400 IDEMPOTENCY_KEY_INVALID. - Endpointy zwracające one-time secrets (
create_database, wystawienie PAT, wystawienie OAuth tokena) nie cache'ują body odpowiedzi. Replay re-executes handler — sekret nie jest wyciekany przez cache.
Rate limit
Per-token sliding window 60 sekund. Limity są bardziej restrykcyjne dla operacji o dużym koszcie infrastrukturalnym:
- Default: 60 req/min na token.
- Install ops (
install_wordpress,request_ssl): 5 req/min. Każda taka operacja uruchamia pipeline instalacji / certyfikacji, więc agresywne pollowanie nie ma zastosowania.
Po wyczerpaniu: 429 RATE_LIMITED z nagłówkami X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After. Agent powinien respektować Retry-After — ignorowanie skutkuje pauzą tokena.
Audit log
Każde wywołanie MCP (read i write) jest zapisywane w niezmienialnym audit logu po stronie mDiv. Wpis zawiera:
- token_id (sha256 hash; nigdy plaintext token)
- user_id, oauth_client_id (jeśli OAuth)
- tool name, scope wymagany, request body (PII redacted)
- resource_type, resource_id
- response status, error code
- IP, user-agent, timestamp z dokładnością do milisekundy
- idempotency_key, preview_token (jeśli użyty)
Klient ma prawo wglądu w log dotyczący swojego konta przez panel moje.mdiv.pl/account/audit-log. Retention: 12 miesięcy. Logi wyższego ryzyka (delete, install, token issuance) — 24 miesiące. Po retencji są anonimizowane (token_id i IP zerowane), reszta zostaje dla statystyk.
Anomaly detection
Audit log jest analizowany w czasie zbliżonym do rzeczywistego. Wykrywane anomalie (przykładowe progi):
- Seria
delete_*w krótkim oknie (≥3 w 60s) — token pauzowany do potwierdzenia administratora. set_dns_recordsnadpisujący dotychczasowe rekordy krytyczne (MX, SPF, DKIM) — wymaga potwierdzenia mailowego klienta.- Nagła zmiana lokalizacji geograficznej źródła requestów (IP geo) — email do klienta z linkiem „nie poznaję tej aktywności → zablokuj token".
- Próba enumeracji zasobów innych klientów (np. używanie cudzych UUID) — natychmiastowa blokada tokena i alert do administratora.
Polityka jest ewolucyjna: nowe sygnały są dopisywane bez zmiany API. Reguły obecne w produkcji są opisane w changelogu AI Deploy.
Weekly summary email
Każdy klient z ai_deploy ≠ none dostaje w poniedziałek rano podsumowanie poprzedniego tygodnia:
- liczba wywołań agregowana per scope i per tool
- lista zmian write (utworzone domeny, bazy, instalacje, SSL)
- lista zmian destrukcyjnych (delete_*) z timestamp
- aktywne tokeny i daty ich ostatniego użycia
- flagowane anomalie (jeśli były)
- link do panelu wyłączania AI Deploy lub zwężenia zakresu tokenów
Subskrypcję można wyłączyć w panelu, ale alerty bezpieczeństwa (anomalie, blokady tokenu) są zawsze wysyłane — nie da się ich wyciszyć.
Izolacja danych między klientami
Każde wywołanie MCP jest filtrowane przez kontekst user_id wyciągnięty z tokena. Backend wykonuje autoryzację na poziomie zapytania SQL — nawet znajomość UUID domeny / bazy / website innego klienta nie pozwala na jego wyświetlenie.
Audit log waliduje, że resource.user_id == token.user_id przy każdej operacji. Próba użycia cudzego UUID kończy się 404 NOT_FOUND (nie 403 — nie ujawniamy istnienia zasobu) oraz wpisem w log anomaly detection (sekcja 8).
Bazy danych klientów żyją w odseparowanych instancjach MariaDB / PostgreSQL z dedykowanymi userami. Pliki na shared hostingu są chronione przez open_basedir + chroot per-user.
Szyfrowanie i transport
In transit:wszystkie endpointy MCP, OAuth i panel klienta wymuszają HTTPS (HSTS, TLS 1.3, certyfikaty Let's Encrypt z auto-renew). Połączenia HTTP są przekierowywane 301 i nie obsługują żadnych endpointów aplikacyjnych.
At rest: hashe haseł użytkowników w argon2id; tokeny (PAT, OAuth access/refresh) w bcrypt; preview tokeny w pamięci z TTL 10 min (Redis z encryption at rest na woluminie).
Backupy: codzienne, szyfrowane (AES-256) przed zapisaniem na zdalnym storage. Klucz nigdy nie jest na maszynie backupowanej.
Sekrety w response body (np. hasło DB z create_database): zwracane jeden raz, przez Streamable HTTP, nie zapisywane w logach ani audit (audit zapisuje tylko fakt wywołania, nie zawartość response).
Incident response & disclosure
Zgłoszenie podatności: security@…. Akceptujemy szyfrowane zgłoszenia (PGP key dostępny pod /.well-known/security.txt). Czas pierwszej odpowiedzi: do 24h w dni robocze.
Disclosure: 90-dniowy coordinated disclosure od daty potwierdzenia podatności. Zgłaszający otrzymuje credit (chyba, że poprosi o anonimowość). Hall of fame dla researcherów na dedykowanej stronie po launchu publicznym (Q3 2026).
Powiadomienia o naruszeniach danych: w przypadku incydentu dotyczącego danych osobowych (RODO) klienci są informowani mailem oraz w panelu w ciągu 72h od stwierdzenia. Plan komunikacji incydentu obejmuje także: szczegółowy post-mortem na blogu mDiv, listę dotkniętych kont, kroki naprawcze i zalecenia dla klientów.
Kontakt operacyjny AI Deploy: ai-deploy@… lub formularz kontaktowy.