Phase 2: EVE SSO auth + read-only account tools
Add PKCE OAuth2 login against EVE SSO with an encrypted, auto-refreshing token store, driven by `familiar login` / `status` / `logout` CLI commands. The MCP server gains authenticated account tools: - account_status, get_wallet, get_skills, get_skill_queue - get_location, get_clones, get_assets (paginated) ESI client extended with Bearer auth and X-Pages pagination. 51 tests (auth + account mocked), coverage 88%. Client id/callback/scopes are env-overridable; refresh token Fernet-encrypted on disk. Closes #7 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
11 files changed
+796
-11
No files matched your search
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import json
|
||||
from collections.abc import Callable
|
||||
|
||||
import httpx
|
||||
@@ -9,6 +11,17 @@ import pytest
|
||||
|
||||
from familiar import esi
|
||||
|
||||
|
||||
def make_jwt(claims: dict) -> str:
|
||||
"""Build a fake JWT (header.payload.signature) whose payload is `claims`.
|
||||
|
||||
Only the payload segment is ever decoded by familiar, so the header and
|
||||
signature can be arbitrary.
|
||||
"""
|
||||
payload = base64.urlsafe_b64encode(json.dumps(claims).encode()).rstrip(b"=").decode()
|
||||
return f"header.{payload}.signature"
|
||||
|
||||
|
||||
Handler = Callable[[httpx.Request], httpx.Response]
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user