Skip to content

feat(oauth): autodetekcja #21 + self-healing proxy discovery (Authorize bez fixu nginksa) - #16

Merged
mpasternak merged 7 commits into
mainfrom
feat-oauth-autodetekcja-proxy
Jul 24, 2026
Merged

feat(oauth): autodetekcja #21 + self-healing proxy discovery (Authorize bez fixu nginksa)#16
mpasternak merged 7 commits into
mainfrom
feat-oauth-autodetekcja-proxy

Conversation

@mpasternak

Copy link
Copy Markdown
Member

Cel

Sprawić, by natywny przycisk „Authorize" w kliencie MCP (Claude Code i pokrewne) działał w trybie --http także na instancjach BPP, które nie mają jeszcze wdrożonego fixu nginksa przepuszczającego /.well-known/ (bpp-deploy #21). Umożliwia to stopniowy rollout tego fixu bez psucia logowania po drodze.

Problem

W trybie HTTP klient robi discovery: 401 → PRM → authorization_serversGET BPP/.well-known/oauth-authorization-server. Na instancji bez #21 nginx oddaje 403 (reguła location ~ /\. na pliki ukryte przechwytuje żądanie przed aplikacją), więc „Authorize" pada — mimo że serwer autoryzacji BPP (/o/authorize|token|register) działa w pełni.

Rozwiązanie: autodetekcja przy starcie + self-healing proxy

W trybie --http bpp-mcp robi jeden probe przy starcie i wybiera tryb na całe życie procesu:

  • PASS-THROUGH (instancja z #21): issuer → BPP, zachowanie jak dotąd — klient idzie po metadane wprost do BPP.
  • PROXY (instancja bez #21, tryb domyślny przy niepewności): bpp-mcp sam wystawia /.well-known/oauth-authorization-server z issuer = własny adres i endpointami → BPP/o/*. „Authorize" działa bez #21.

Po wdrożeniu #21 na daną instancję wystarczy restart jej bpp-mcp — przeskoczy na pass-through.

Zgodność ze specem

PROXY nie jest naginaniem RFC 8414: §3.3 wymaga tylko, by issuer = adres pobrania metadanych (tu: URL bpp-mcp), a endpointy mogą być cross-origin. issuer normalizowany przez AnyHttpUrlbajt w bajt zgodny z tym, co PRM wystawia z AuthSettings (inaczej trailing-slash by je rozjechał). Token BPP jest opaque (brak claimu iss) — nic do walidacji po stronie tokenu.

Weryfikacja

  • 204 testy zielone, ruff czysty. Nowe: test_probe.py (6), test_metadata_proxy.py (3), integracyjne PROXY/PASS-THROUGH + CORS w test_http_auth.py (4), config (2).
  • Live smoke przeciw niezmienionej publikacje.up.lublin.pl (403 na discovery): tryb proxy wybrany poprawnie; dokument AS issuer=http://127.0.0.1:8766/, endpointy .../o/*; PRM authorization_servers=['http://127.0.0.1:8766/'] — zgodne bajt w bajt z dokumentem AS.

Review (FABLE) — naniesione

Gałąź przeszła adwersaryjny review subagentem na modelu FABLE (empirycznie zweryfikowany). Znaleziska naniesione w tym PR:

  • CORS (istotne): dokument AS w PROXY dostał Access-Control-Allow-Origin: * (jak PRM od SDK) — bez tego zdalny klient przeglądarkowy padał na kroku 2 discovery. Potwierdzone na żywo + test.
  • issuer ze ścieżką (istotne → udokumentowane ograniczenie): BPP_MCP_ISSUER_URL musi być gołym originem (klient MCP inaczej buduje URL discovery); jawnie udokumentowane, test przemianowany.
  • removesuffix przy trailing slash (drobne) i docstring probe (nit): poprawione.

Rdzeń (autodetekcja + PROXY dla issuera host:port) FABLE potwierdził jako poprawny, przetestowany i bez regresji — brak blockerów.

⚠️ Pozostaje do potwierdzenia (human-in-the-loop)

Zweryfikowano syntetycznie cały łańcuch protokołu opróc ostatniego kroku: faktyczne kliknięcie „Authorize" w realnym kliencie MCP + logowanie w przeglądarce. To wymaga człowieka i danych do BPP — nie dało się tego wyklikać automatycznie. Analiza speca i live-smoke wskazują na sukces, ale przed mergem warto ten jeden klik wykonać przeciw instancji bez #21 (spike opisany w planie, Task 0).

Dokumenty projektowe

  • Spec: docs/superpowers/specs/2026-07-24-oauth-autodetekcja-proxy-design.md
  • Plan: docs/superpowers/plans/2026-07-24-oauth-autodetekcja-proxy.md

Poza zakresem

Detekcja na żywo/periodyczna (świadomie: stan instancji zmienia się raz, przy deployu), introspekcja tokenu, zmiany w BPP/bpp-deploy.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Wpux2rimQuavKWiaqakxYL

Michał Pasternak and others added 7 commits July 24, 2026 21:23
Design: bpp-mcp w trybie --http probuje instancje przy starcie i wybiera
PASS-THROUGH (issuer->BPP, gdy #21 wdrozony) albo PROXY (bpp-mcp serwuje
wlasne metadane RFC 8414 z issuer=self, endpointy->BPP/o/*, gdy 403).
Umozliwia dzialajacy przycisk Authorize podczas stopniowego rolloutu #21.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wpux2rimQuavKWiaqakxYL
5 taskow TDD + spike empiryczny jako bramka. Self-review zlapal rozjazd
trailing-slash miedzy PRM a dokumentem AS (RFC 8414 §3.3) — issuer
normalizowany przez AnyHttpUrl w obu miejscach.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wpux2rimQuavKWiaqakxYL
probe_instance wykrywa czy instancja wystawia .well-known (PASSTHROUGH)
czy nie (PROXY, default przy niepewnosci). authorization_server_metadata
buduje dokument RFC 8414 z issuer=self (norm. AnyHttpUrl) i endpointami
BPP/o/*. _konwencjonalne rozszerzone o revoke_token.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wpux2rimQuavKWiaqakxYL
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wpux2rimQuavKWiaqakxYL
W trybie --http bpp-mcp probuje instancje przy starcie: PASSTHROUGH gdy
.well-known wystawia poprawne metadane (#21 wdrozony), inaczej PROXY —
dokladamy custom_route serwujaca metadane AS z issuer=self, endpointy
BPP/o/*. Live smoke: proxy wybrany przeciw niezmienionej instancji,
issuer w PRM i dokumencie AS zgodne bajt w bajt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wpux2rimQuavKWiaqakxYL
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wpux2rimQuavKWiaqakxYL
…BLE)

- CORS: dokument AS w trybie PROXY dostaje Access-Control-Allow-Origin: *
  (jak PRM od SDK) — bez tego zdalny klient przegladarkowy padal na kroku 2
  discovery. Potwierdzone na zywo + test.
- issuer: udokumentowane ograniczenie do golego originu (bez sciezki) —
  klient MCP buduje URL discovery inaczej dla issuera ze sciezka; test
  przemianowany, by nie sugerowal wsparcia ktorego nie ma.
- effective_issuer_url: rstrip('/') przed removesuffix (trailing slash).
- docstring probe: doprecyzowany (dokladnie 200, nie dowolne 2xx).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wpux2rimQuavKWiaqakxYL
@mpasternak
mpasternak merged commit d7a8c7d into main Jul 24, 2026
4 checks passed
@mpasternak
mpasternak deleted the feat-oauth-autodetekcja-proxy branch July 24, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant