fix: federation remoteId must be integer index, not URL string

- fetch_remote now accepts index i from enumerate() and sets remote_id: int = i
  instead of remote.get("id", url), which fell back to the URL string
- asyncio.gather uses enumerate(remote_instances) to pass the integer index
- federation_connect route: remote_id type changed from str to int; FastAPI
  now validates path param at framework level, simplifying the handler body
- Update test_federation_sessions_includes_remote_failure_status to expect
  integer 0 (not the legacy 'remote-1' id field string)
- Update test_federation_connect_returns_404_for_non_integer_remote_id: now
  expects 422 (FastAPI schema validation) instead of 404
- Add test_federation_sessions_remote_id_is_integer_index verifying remoteId
  is 0 for first remote and 1 for second
This commit is contained in:
Brian Krabach
2026-04-01 20:22:45 -07:00
parent a07e5b5383
commit 463cbf4cb3
2 changed files with 105 additions and 13 deletions
+6 -10
View File
@@ -892,12 +892,12 @@ async def federation_sessions(request: Request) -> list[dict]:
# Fetch remote sessions concurrently
http_client: httpx.AsyncClient = request.app.state.federation_client
async def fetch_remote(remote: dict) -> list[dict]:
async def fetch_remote(i: int, remote: dict) -> list[dict]:
"""Fetch /api/sessions from a remote instance, returning session dicts or a status entry."""
url: str = remote.get("url", "")
key: str = remote.get("key", "")
remote_name: str = remote.get("name", url)
remote_id: str = remote.get("id", url)
remote_id: int = i
try:
resp = await http_client.get(
f"{url.rstrip('/')}/api/sessions",
@@ -937,7 +937,7 @@ async def federation_sessions(request: Request) -> list[dict]:
]
remote_results: list[list[dict]] = await asyncio.gather(
*(fetch_remote(remote) for remote in remote_instances)
*(fetch_remote(i, remote) for i, remote in enumerate(remote_instances))
)
all_sessions: list[dict] = list(local_sessions)
@@ -969,7 +969,7 @@ async def federation_generate_key() -> dict:
@app.post("/api/federation/{remote_id}/connect/{session_name}")
async def federation_connect(
remote_id: str, session_name: str, request: Request
remote_id: int, session_name: str, request: Request
) -> dict:
"""Proxy a connect POST to a remote instance to spawn its ttyd.
@@ -981,16 +981,12 @@ async def federation_connect(
"""
settings = load_settings()
remotes = settings.get("remote_instances", [])
try:
idx = int(remote_id)
if idx < 0 or idx >= len(remotes):
raise IndexError
remote = remotes[idx]
except (ValueError, IndexError):
if remote_id < 0 or remote_id >= len(remotes):
raise HTTPException(
status_code=404,
detail=f"Remote instance '{remote_id}' not found",
)
remote = remotes[remote_id]
remote_url: str = remote.get("url", "").rstrip("/")
remote_key: str = remote.get("key", "")