diff --git a/muxplex/main.py b/muxplex/main.py index 9f8254a..07fe54e 100644 --- a/muxplex/main.py +++ b/muxplex/main.py @@ -71,6 +71,7 @@ from muxplex.settings import ( load_settings, patch_settings, ) +from muxplex.identity import load_device_id from muxplex.ttyd import kill_orphan_ttyd, kill_ttyd, spawn_ttyd, TTYD_PORT # --------------------------------------------------------------------------- @@ -865,16 +866,17 @@ async def put_settings_sync(payload: SettingsSyncPayload): @app.get("/api/instance-info") async def instance_info() -> dict: - """Return this instance's display name and version. + """Return this instance's display name, device identity, and version. Public endpoint (no auth required) — used by remote instances to - discover peer names and verify reachability. + discover peer names, device identity, and verify reachability. """ settings = load_settings() # Read fresh so the UI reflects key-file changes without requiring a restart. fed_key = load_federation_key() return { "name": settings["device_name"], + "device_id": load_device_id(), "version": app.version, "federation_enabled": bool(fed_key), } diff --git a/muxplex/tests/test_api.py b/muxplex/tests/test_api.py index e7082d3..e019e0a 100644 --- a/muxplex/tests/test_api.py +++ b/muxplex/tests/test_api.py @@ -1294,6 +1294,26 @@ def test_instance_info_federation_enabled_true_when_key_exists( ) +def test_instance_info_includes_device_id(client, tmp_path, monkeypatch): + """GET /api/instance-info includes device_id as a non-empty string.""" + import muxplex.identity as identity_mod + import muxplex.settings as settings_mod + + monkeypatch.setattr(settings_mod, "SETTINGS_PATH", tmp_path / "settings.json") + monkeypatch.setattr(identity_mod, "IDENTITY_PATH", tmp_path / "identity.json") + + response = client.get("/api/instance-info") + assert response.status_code == 200 + data = response.json() + assert "device_id" in data, f"Response must include 'device_id' key, got: {data}" + assert isinstance(data["device_id"], str), ( + f"device_id must be a string, got: {type(data['device_id'])}" + ) + assert data["device_id"] != "", ( + f"device_id must be a non-empty string, got: {data['device_id']!r}" + ) + + # --------------------------------------------------------------------------- # POST /api/sessions (create new session) # ---------------------------------------------------------------------------