Added Additional Scaffolds for API Endpoint Domains

This commit is contained in:
2025-10-27 21:38:57 -06:00
parent 3772ea2e4a
commit 215a054979
20 changed files with 886 additions and 72 deletions

View File

@@ -1,11 +1,4 @@
"""API service adapters for the Borealis Engine runtime.
Stage 3 of the migration introduces blueprint registration that mirrors the
behaviour of :mod:`Data.Server.server` by delegating to the existing domain
modules under ``Data/Server/Modules``. Each adapter wires the Engine context
into the legacy registration helpers so routes continue to function while
configuration toggles control which API groups are exposed.
"""
"""API service adapters for the Borealis Engine runtime."""
from __future__ import annotations
import datetime as _dt
@@ -15,10 +8,9 @@ import sqlite3
import time
from dataclasses import dataclass, field
from pathlib import Path
import os
from typing import Any, Callable, Iterable, Mapping, Optional, Sequence
from flask import Blueprint, Flask, jsonify, request
from flask import Blueprint, Flask, jsonify
from Modules.auth import jwt_service as jwt_service_module
from Modules.auth.dpop import DPoPValidator
@@ -29,11 +21,12 @@ from Modules.enrollment.nonce_store import NonceCache
from Modules.tokens import routes as token_routes
from ...server import EngineContext
from .authentication import register_auth
DEFAULT_API_GROUPS: Sequence[str] = ("tokens", "enrollment")
DEFAULT_API_GROUPS: Sequence[str] = ("auth", "tokens", "enrollment")
_SERVER_SCOPE_PATTERN = re.compile(r"\b(?:scope|context|agent_context)=([A-Za-z0-9_-]+)", re.IGNORECASE)
_SERVER_AGENT_ID_PATTERN = re.compile(r"\bagent_id=([^\s,]+)", re.IGNORECASE)
_SERVER_SCOPE_PATTERN = re.compile(r"\\b(?:scope|context|agent_context)=([A-Za-z0-9_-]+)", re.IGNORECASE)
_SERVER_AGENT_ID_PATTERN = re.compile(r"\\bagent_id=([^\\s,]+)", re.IGNORECASE)
def _canonical_server_scope(raw: Optional[str]) -> Optional[str]:
@@ -104,7 +97,7 @@ def _make_service_logger(base: Path, logger: logging.Logger) -> Callable[[str, s
prefix_parts.append(f"[CONTEXT-{resolved_scope}]")
prefix = "".join(prefix_parts)
with path.open("a", encoding="utf-8") as handle:
handle.write(f"[{timestamp}] {prefix} {msg}\n")
handle.write(f"[{timestamp}] {prefix} {msg}\\n")
except Exception:
logger.debug("Failed to write service log entry", exc_info=True)
@@ -187,64 +180,11 @@ def _register_enrollment(app: Flask, adapters: LegacyServiceAdapters) -> None:
_GROUP_REGISTRARS: Mapping[str, Callable[[Flask, LegacyServiceAdapters], None]] = {
"auth": register_auth,
"tokens": _register_tokens,
"enrollment": _register_enrollment,
}
LEGACY_APP_CACHE: Optional[Flask] = None
def _load_legacy_app(context: EngineContext) -> Flask:
global LEGACY_APP_CACHE
if LEGACY_APP_CACHE is not None:
return LEGACY_APP_CACHE
os.environ.setdefault("BOREALIS_DATABASE_PATH", context.database_path)
if context.tls_cert_path:
os.environ.setdefault("BOREALIS_TLS_CERT", context.tls_cert_path)
if context.tls_key_path:
os.environ.setdefault("BOREALIS_TLS_KEY", context.tls_key_path)
if context.tls_bundle_path:
os.environ.setdefault("BOREALIS_TLS_BUNDLE", context.tls_bundle_path)
try:
from Data.Server import server as legacy_server # Local import to avoid heavy import when unused
except ImportError as exc:
raise RuntimeError("Legacy server module is unavailable; cannot enable fallback proxy.") from exc
LEGACY_APP_CACHE = legacy_server.app
return LEGACY_APP_CACHE
def _register_legacy_proxy(app: Flask, context: EngineContext) -> None:
try:
legacy_app = _load_legacy_app(context)
except RuntimeError as exc:
context.logger.warning("Legacy API fallback disabled: %s", exc)
return
blueprint = Blueprint("legacy_api_bridge", __name__)
methods = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]
@blueprint.route("/api", defaults={"path": ""}, methods=methods)
@blueprint.route("/api/<path:path>", methods=methods)
def _legacy_passthrough(path: str):
legacy_context = legacy_app.request_context(request.environ)
legacy_context.push()
try:
request_path = request.path or f"/api/{path or ''}"
context.logger.info(
"Engine API routed to legacy handler: %s %s",
request.method,
request_path,
)
response = legacy_app.full_dispatch_request()
finally:
legacy_context.pop()
return response
app.register_blueprint(blueprint)
context.logger.info("Engine registered legacy API fallback proxy.")
def _register_core(app: Flask, context: EngineContext) -> None:
"""Register core utility endpoints that do not require legacy adapters."""
@@ -279,5 +219,3 @@ def register_api(app: Flask, context: EngineContext) -> None:
continue
registrar(app, adapters)
context.logger.info("Engine registered API group '%s'.", group)
_register_legacy_proxy(app, context)