fix: read federation key live on each request and check PUT sync response

Bug 1 (auth.py): AuthMiddleware.dispatch() was using self.federation_key
(set once at startup) for Bearer token validation. If the key was generated
or rotated via POST /api/federation/generate-key after startup, the old
(often empty) value caused all federation auth to silently return 401.

Fix: import load_federation_key from muxplex.settings and call it fresh on
every non-exempt, non-cookie request. Also adds a warning log when a Bearer
token is received but no key is configured on this server.

Bug 2 (main.py): _sync_settings_with_remotes() discarded the PUT response,
silently swallowing 401/500 errors from the remote sync endpoint.

Fix: capture the PUT response as put_resp. Handle 409 (Conflict = remote is
newer) with a debug log; raise_for_status() for any other non-2xx so errors
propagate to the outer except and are logged as warnings.

Tests:
- test_dispatch_calls_load_federation_key_live: pattern test confirming
  load_federation_key() is called inside dispatch()
- test_dispatch_does_not_use_stale_self_federation_key_for_bearer: pattern
  test confirming self.federation_key is gone from the live bearer check
- test_sync_put_response_calls_raise_for_status: pattern test confirming
  raise_for_status() is called on the PUT response in the sync function
- Updated existing bearer tests to monkeypatch load_federation_key so they
  are isolated from any real key file on disk
This commit is contained in:
Brian Krabach
2026-04-08 22:39:03 -07:00
parent c4ff5c618f
commit d541612843
4 changed files with 91 additions and 10 deletions
+6 -1
View File
@@ -148,12 +148,17 @@ async def _sync_settings_with_remotes(
},
"settings_updated_at": local_ts,
}
await http_client.put(
put_resp = await http_client.put(
f"{url}/api/settings/sync",
json=payload,
headers=headers,
timeout=5.0,
)
if put_resp.status_code == 409:
# Remote is newer — let the next sync cycle pull.
_log.debug("Settings sync push to %s: 409 (remote is newer)", url)
else:
put_resp.raise_for_status()
# If equal: no action.
except Exception as exc:
_log.warning("Settings sync with %s failed: %s", url, exc)