# Dziennik Firm auth.md

> Karty spółek, wydania dzienne, zdarzenia w KRS i teksty redakcji są publiczne: REST API i serwer MCP działają bez rejestracji i bez tokenu. Logowanie (OAuth 2.1) jest potrzebne tylko do listy obserwowanych spółek konkretnego czytelnika.

## Dla kogo

Agenci AI i klienci MCP działający w imieniu konkretnego czytelnika Dziennika Firm (dziennikfirm.pl), który chce, żeby agent pokazał jego obserwowane spółki, dodał spółkę do obserwowanych albo ją usunął. Po zamknięciu każdego wydania czytelnik dostaje e-mail z nowymi wpisami w KRS obserwowanych spółek. Do samych danych nie rejestruj się – wywołuj narzędzia publiczne bez nagłówka `Authorization`.

## Co wymaga tokenu

Serwer MCP <https://dziennikfirm.pl/mcp>:

| Narzędzie | Scope | Co robi |
|---|---|---|
| `list_my_watchlist` | `watchlist:read` | lista obserwowanych spółek czytelnika (nazwa, KRS, status, ostatni wpis, url karty) i stan powiadomień e-mail |
| `watch_company` (`krs`) | `watchlist:write` | dodaje spółkę z bazy Dziennika Firm do obserwowanych (najwyżej 50 na konto) |
| `unwatch_company` (`krs`) | `watchlist:write` | usuwa spółkę z obserwowanych |

Wywołanie tych narzędzi bez tokenu daje `HTTP 401` z nagłówkiem `WWW-Authenticate: Bearer resource_metadata="https://dziennikfirm.pl/.well-known/oauth-protected-resource/mcp", scope="watchlist:read watchlist:write"`. Token z za wąskim zakresem: `HTTP 403`, `error="insufficient_scope"`. Konto czytelnika to jego adres e-mail potwierdzony logowaniem; jeśli go nie ma, powstaje przy pierwszym dodaniu spółki.

## Odkrywanie

1. Metadane zasobu (RFC 9728): <https://dziennikfirm.pl/.well-known/oauth-protected-resource/mcp> (zasób <https://dziennikfirm.pl/mcp>) albo <https://dziennikfirm.pl/.well-known/oauth-protected-resource> (cały serwis).
2. Metadane serwera autoryzacji (RFC 8414): <https://dziennikfirm.pl/.well-known/oauth-authorization-server> – issuer <https://dziennikfirm.pl>, blok `agent_auth`, klucze JWKS <https://dziennikfirm.pl/oauth/jwks.json>.

## Rejestracja

Dwie metody. Obie kończą się tym samym: token dostępu do <https://dziennikfirm.pl/mcp> po zalogowaniu czytelnika linkiem z e-maila i jego zgodzie. Nie ma haseł ani kluczy API.

### 1. OAuth 2.1 z dynamiczną rejestracją (klienci MCP)

1. `POST` <https://dziennikfirm.pl/oauth/register> (RFC 7591, JSON): `redirect_uris` (https albo <http://127.0.0.1>/`localhost`/`[::1]` dla aplikacji natywnych; port loopback może się zmieniać), `client_name`, `token_endpoint_auth_method` (`none` dla klientów publicznych, albo `client_secret_basic`/`client_secret_post`), `grant_types: ["authorization_code","refresh_token"]`. Odpowiedź `201` z `client_id` (i `client_secret`, jeśli klient poufny).
2. Przeglądarka: `GET` <https://dziennikfirm.pl/oauth/authorize?response_type=code&client_id=…&redirect_uri=…&scope=watchlist:read%20watchlist:write&state=…&code_challenge=…&code_challenge_method=S256&resource=https://dziennikfirm.pl/mcp> – PKCE S256 obowiązkowe, `redirect_uri` dokładnie jak przy rejestracji.
3. Czytelnik podaje e-mail, klika link (albo wpisuje 6-cyfrowy kod) i na ekranie zgody widzi nazwę klienta, adres powrotu, zakresy i zasób.
4. Powrót: `redirect_uri?code=…&state=…&iss=` <https://dziennikfirm.pl> (sprawdź `state` i `iss`). Kod działa 3 minuty, raz.
5. `POST` <https://dziennikfirm.pl/oauth/token> (`application/x-www-form-urlencoded`): `grant_type=authorization_code&code=…&redirect_uri=…&code_verifier=…&client_id=…&resource=` <https://dziennikfirm.pl/mcp>.

### 2. Rejestracja agenta (auth.md, `service_auth`)

Gdy agent zna tylko e-mail czytelnika i nie ma przeglądarki z przekierowaniem:

1. `POST` <https://dziennikfirm.pl/oauth/agent/identity> (JSON) `{"type":"service_auth","login_hint":"czytelnik@example.com","client_name":"Nazwa agenta"}`. Przyjmujemy też kształt `{"type":"identity_assertion","assertion_type":"verified_email","assertion":"czytelnik@example.com"}` – adres i tak potwierdza logowanie linkiem. Odpowiedź `200`: `registration_id`, `claim_token` (zwracany raz), `claim_token_expires` (1 h), `post_claim_scopes`, `claim` = `user_code` (6 cyfr), `verification_uri`, `expires_in` (600), `interval` (5).
2. Pokaż czytelnikowi w jednej wiadomości `verification_uri` i `user_code`. Czytelnik otwiera link, loguje się linkiem z e-maila wysłanym na podany adres, sprawdza, o co prosisz, i wpisuje `user_code` na naszej stronie.
3. Odpytuj `POST` <https://dziennikfirm.pl/oauth/token> z `grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=…` nie częściej niż co `interval` sekund. Odpowiedzi: `authorization_pending`, `slow_down`, `expired_token` (nowy kod: `POST` <https://dziennikfirm.pl/oauth/agent/identity/claim> z `{"claim_token":"…","email":"…"}`), `access_denied` (czytelnik odmówił), a po zgodzie standardowa odpowiedź tokenu z `access_token`, `refresh_token`, `scope` i `client_id`.

## Poświadczenia

- `Authorization: Bearer <access_token>` w każdym żądaniu do <https://dziennikfirm.pl/mcp>. Nigdy w adresie URL.
- Access token: JWT RS256 (`typ: at+jwt`), ważny 3600 s, `aud` = zasób, o który prosiłeś (`resource`). Na innym zasobie nie działa.
- Odświeżanie: `grant_type=refresh_token&refresh_token=…` (+ `client_id`/sekret klienta). Każde użycie daje nowy refresh token; ponowne użycie starego unieważnia cały łańcuch. Refresh token żyje 30 dni od ostatniego użycia, łańcuch najwyżej 90 dni.
- Na `HTTP 401` z `error="invalid_token"` odśwież token raz; jeśli `invalid_grant`, zacznij od rejestracji.

## Odwołanie

- Agent: `POST` <https://dziennikfirm.pl/oauth/revoke> (RFC 7009) `token=…&token_type_hint=refresh_token` – odwołanie refresh tokenu kończy cały łańcuch. Zawsze `200`.
- Czytelnik: strona konta https://dziennikfirm.pl/konto/ (po zalogowaniu) albo „Twoje połączone aplikacje” https://dziennikfirm.pl/oauth/aplikacje/ (link przychodzi też w e-mailu po każdym nowym połączeniu). Odwołanie działa od razu, także dla wydanych access tokenów.

## Limity

Serwer MCP i REST: 60 zapytań na minutę z jednego IP (`429`, `Retry-After`). Rejestracje: 10 na godzinę z IP. E-maile logowania: 3 na 15 minut na adres. Token: 60 zapytań na minutę z IP. Kod z e-maila i `user_code`: 5 prób. Obserwowane spółki: najwyżej 50 na konto, 100 zmian listy na dobę.

## Dane i prywatność

Przechowujemy adres e-mail czytelnika, listę obserwowanych spółek, nazwę klienta, zakresy i daty zgody. Tokeny, kody i linki tylko jako skróty HMAC. Dziennik bezpieczeństwa bez adresów e-mail i IP w jawnej postaci, 90 dni. Szczegóły: https://dziennikfirm.pl/polityka-prywatnosci/ (sekcje o obserwowanych spółkach i połączonych aplikacjach). Dokumentacja: https://dziennikfirm.pl/dla-agentow/. Kontakt: redakcja@dziennikfirm.pl.

## English

Company cards, daily editions, KRS events and articles are public: call the MCP server (https://dziennikfirm.pl/mcp) without credentials. Only the reader's own watchlist tools (`list_my_watchlist`, `watch_company`, `unwatch_company`; scopes `watchlist:read`, `watchlist:write`) need an OAuth 2.1 access token from https://dziennikfirm.pl. Either register a client (RFC 7591, <https://dziennikfirm.pl/oauth/register>) and run the authorization code flow with PKCE S256 and `resource=` <https://dziennikfirm.pl/mcp>, or register as an agent with `POST https://dziennikfirm.pl/oauth/agent/identity {"type":"service_auth","login_hint":"<reader e-mail>"}`, show the reader `verification_uri` + `user_code`, and poll <https://dziennikfirm.pl/oauth/token> with `grant_type=urn:workos:agent-auth:grant-type:claim`. The reader signs in with an e-mail link (no passwords) and approves on a consent screen. Access tokens last 3600 s; refresh tokens rotate (reuse revokes the chain). Revoke at <https://dziennikfirm.pl/oauth/revoke>; readers manage access at https://dziennikfirm.pl/konto/.
