refactor: companion FrameServer and related (substantive only, no Black)

Reapply refactor from ce8381a (replace monolithic FrameServer with thin
pymc_core subclass, re-export constants, SQLite persistence hooks) while
preserving pre-refactor whitespace where patch applied cleanly. Remaining
files match refactor commit exactly. Diff vs ce8381a is whitespace-only.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
agessaman
2026-02-21 15:35:47 -08:00
parent 22e337a707
commit c2f8a2e3cd
57 changed files with 4385 additions and 4922 deletions
+2 -6
View File
@@ -1,9 +1,5 @@
from .jwt_handler import JWTHandler
from .api_tokens import APITokenManager
from .jwt_handler import JWTHandler
from .middleware import require_auth
__all__ = [
'JWTHandler',
'APITokenManager',
'require_auth'
]
__all__ = ["JWTHandler", "APITokenManager", "require_auth"]
+9 -14
View File
@@ -1,8 +1,8 @@
import secrets
import hmac
import hashlib
from typing import Optional, List, Dict
import hmac
import logging
import secrets
from typing import Dict, List, Optional
logger = logging.getLogger(__name__)
@@ -11,18 +11,14 @@ class APITokenManager:
def __init__(self, sqlite_handler, secret_key: str):
self.db = sqlite_handler
self.secret_key = secret_key.encode('utf-8')
self.secret_key = secret_key.encode("utf-8")
def generate_api_token(self) -> str:
return secrets.token_hex(32)
def hash_token(self, token: str) -> str:
return hmac.new(
self.secret_key,
token.encode('utf-8'),
hashlib.sha256
).hexdigest()
return hmac.new(self.secret_key, token.encode("utf-8"), hashlib.sha256).hexdigest()
def create_token(self, name: str) -> tuple[int, str]:
plaintext_token = self.generate_api_token()
token_hash = self.hash_token(plaintext_token)
@@ -43,7 +39,6 @@ class APITokenManager:
logger.info(f"Revoked API token ID {token_id}")
return deleted
def list_tokens(self) -> List[Dict]:
return self.db.list_api_tokens()
+7 -6
View File
@@ -1,4 +1,5 @@
import logging
import cherrypy
logger = logging.getLogger("HTTPServer")
@@ -40,10 +41,10 @@ def check_auth():
cherrypy.request.user = {
"username": payload.get("sub"),
"client_id": payload.get("client_id"),
"auth_type": "jwt"
"auth_type": "jwt",
}
return
# Check for JWT token in query parameter (for EventSource/SSE)
# EventSource doesn't support custom headers, so we use query param
query_token = cherrypy.request.params.get("token")
@@ -54,7 +55,7 @@ def check_auth():
cherrypy.request.user = {
"username": payload.get("sub"),
"client_id": payload.get("client_id"),
"auth_type": "jwt_query"
"auth_type": "jwt_query",
}
# Remove token from params to avoid exposing it in logs
del cherrypy.request.params["token"]
@@ -69,15 +70,15 @@ def check_auth():
cherrypy.request.user = {
"token_id": token_info["id"],
"token_name": token_info["name"],
"auth_type": "api_token"
"auth_type": "api_token",
}
return
# No valid authentication found
logger.warning(f"Unauthorized access attempt to {cherrypy.request.path_info}")
raise cherrypy.HTTPError(401, "Unauthorized - Valid JWT or API token required")
# Register the tool
cherrypy.tools.require_auth = cherrypy.Tool('before_handler', check_auth)
cherrypy.tools.require_auth = cherrypy.Tool("before_handler", check_auth)
logger.info("CherryPy require_auth tool registered")
+10 -13
View File
@@ -1,10 +1,12 @@
import jwt
import logging
import time
from typing import Dict, Optional
import logging
import jwt
logger = logging.getLogger(__name__)
class JWTHandler:
def __init__(self, secret: str, expiry_minutes: int = 15):
self.secret = secret
@@ -14,21 +16,16 @@ class JWTHandler:
now = int(time.time())
expiry = now + (self.expiry_minutes * 60)
payload = {
'sub': username,
'exp': expiry,
'iat': now,
'client_id': client_id
}
token = jwt.encode(payload, self.secret, algorithm='HS256')
payload = {"sub": username, "exp": expiry, "iat": now, "client_id": client_id}
token = jwt.encode(payload, self.secret, algorithm="HS256")
logger.info(f"Created JWT for user '{username}' with client_id '{client_id[:8]}...'")
return token
def verify_jwt(self, token: str) -> Optional[Dict]:
try:
payload = jwt.decode(token, self.secret, algorithms=['HS256'])
payload = jwt.decode(token, self.secret, algorithms=["HS256"])
return payload
except jwt.ExpiredSignatureError:
logger.warning("JWT token expired")
+28 -27
View File
@@ -1,6 +1,7 @@
import cherrypy
from functools import wraps
import logging
from functools import wraps
import cherrypy
logger = logging.getLogger(__name__)
@@ -10,56 +11,56 @@ def require_auth(func):
@wraps(func)
def wrapper(*args, **kwargs):
# Skip authentication for OPTIONS requests (CORS preflight)
if cherrypy.request.method == 'OPTIONS':
if cherrypy.request.method == "OPTIONS":
return func(*args, **kwargs)
# Get auth handlers from global cherrypy config (not app config)
jwt_handler = cherrypy.config.get('jwt_handler')
token_manager = cherrypy.config.get('token_manager')
jwt_handler = cherrypy.config.get("jwt_handler")
token_manager = cherrypy.config.get("token_manager")
if not jwt_handler or not token_manager:
logger.error("Auth handlers not configured")
raise cherrypy.HTTPError(500, "Authentication not configured")
# Try JWT authentication first
auth_header = cherrypy.request.headers.get('Authorization', '')
if auth_header.startswith('Bearer '):
auth_header = cherrypy.request.headers.get("Authorization", "")
if auth_header.startswith("Bearer "):
token = auth_header[7:] # Remove 'Bearer ' prefix
payload = jwt_handler.verify_jwt(token)
if payload:
# JWT is valid
cherrypy.request.user = {
'username': payload['sub'],
'client_id': payload['client_id'],
'auth_type': 'jwt'
"username": payload["sub"],
"client_id": payload["client_id"],
"auth_type": "jwt",
}
return func(*args, **kwargs)
else:
logger.warning("Invalid or expired JWT token")
# Try API token authentication
api_key = cherrypy.request.headers.get('X-API-Key', '')
api_key = cherrypy.request.headers.get("X-API-Key", "")
if api_key:
token_info = token_manager.verify_token(api_key)
if token_info:
# API token is valid
cherrypy.request.user = {
'username': 'api_token',
'token_name': token_info['name'],
'token_id': token_info['id'],
'auth_type': 'api_token'
"username": "api_token",
"token_name": token_info["name"],
"token_id": token_info["id"],
"auth_type": "api_token",
}
return func(*args, **kwargs)
else:
logger.warning("Invalid API token")
# No valid authentication found
logger.warning(f"Unauthorized access attempt to {cherrypy.request.path_info}")
cherrypy.response.status = 401
cherrypy.response.headers['Content-Type'] = 'application/json'
return {'success': False, 'error': 'Unauthorized - Valid JWT or API token required'}
return wrapper
cherrypy.response.headers["Content-Type"] = "application/json"
return {"success": False, "error": "Unauthorized - Valid JWT or API token required"}
return wrapper