Fix CPU HLS streaming (yuv420p) and opt-in middleware for fragments

- Add -pix_fmt yuv420p to multi_res_output.py libx264 path so browsers
  can decode CPU-encoded segments (was producing yuv444p / High 4:4:4).
- Switch silent auth check and coop fragment middlewares from opt-out
  blocklists to opt-in: only run for GET requests with Accept: text/html.
  Prevents unnecessary nav-tree/auth-menu HTTP calls on every HLS segment,
  IPFS proxy, and API request.
- Add opaque grant token verification to L1/L2 dependencies.
- Migrate client CLI to device authorization flow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-25 18:33:53 +00:00
parent 4f49985cd5
commit b788f1f778
5 changed files with 252 additions and 188 deletions

View File

@@ -54,6 +54,77 @@ def get_templates(request: Request) -> Environment:
return request.app.state.templates
async def _verify_opaque_grant(token: str) -> Optional[UserContext]:
"""Verify an opaque grant token via account server, with Redis cache."""
import httpx
import json
if not settings.internal_account_url:
return None
# Check L1 Redis cache first
cache_key = f"grant_verify:{token[:16]}"
try:
r = get_redis_client()
cached = r.get(cache_key)
if cached is not None:
if cached == "__invalid__":
return None
data = json.loads(cached)
return UserContext(
username=data["username"],
actor_id=data["actor_id"],
token=token,
email=data.get("email", ""),
)
except Exception:
pass
# Call account server
verify_url = f"{settings.internal_account_url.rstrip('/')}/auth/internal/verify-grant"
try:
async with httpx.AsyncClient(timeout=5.0) as client:
resp = await client.get(verify_url, params={"token": token})
if resp.status_code != 200:
return None
data = resp.json()
if not data.get("valid"):
# Cache negative result briefly
try:
r = get_redis_client()
r.set(cache_key, "__invalid__", ex=60)
except Exception:
pass
return None
except Exception:
return None
username = data.get("username", "")
display_name = data.get("display_name", "")
actor_id = f"@{username}" if username else ""
ctx = UserContext(
username=username,
actor_id=actor_id,
token=token,
email=username,
)
# Cache positive result for 5 minutes
try:
r = get_redis_client()
cache_data = json.dumps({
"username": username,
"actor_id": actor_id,
"email": username,
"display_name": display_name,
})
r.set(cache_key, cache_data, ex=300)
except Exception:
pass
return ctx
async def get_current_user(request: Request) -> Optional[UserContext]:
"""
Get the current user from request (cookie or header).
@@ -61,11 +132,19 @@ async def get_current_user(request: Request) -> Optional[UserContext]:
This is a permissive dependency - returns None if not authenticated.
Use require_auth for routes that require authentication.
"""
# Try header first (API clients)
# Try header first (API clients — JWT tokens)
ctx = get_user_from_header(request)
if ctx:
return ctx
# Try opaque grant token (device flow / CLI tokens)
auth_header = request.headers.get("Authorization", "")
if auth_header.startswith("Bearer "):
token = auth_header[7:]
ctx = await _verify_opaque_grant(token)
if ctx:
return ctx
# Fall back to cookie (browser)
return get_user_from_cookie(request)