Add QR pairing (terminal QR, in-app scanner, iris://pair deep link)
CI / Kotlin tests (android host + desktop) (push) Successful in 8m5s
CI / Gateway plugin tests (push) Successful in 9m47s

This commit is contained in:
ARIA committed 2026-08-22 22:43:13 +02:00
1 parent 27dc7917f2
commit 7a6d922d12
63 files changed
+2073 -630

No files matched your search

+13 -13
View File
@@ -199,9 +199,9 @@ class HttpServer:
from gateway.status import acquire_scoped_lock
lock_key = f"http:{host}:{port}"
if not acquire_scoped_lock("android", lock_key):
if not acquire_scoped_lock("iris", lock_key):
logger.warning(
"android: HTTP port %s:%s in use by another profile; server disabled",
"iris: HTTP port %s:%s in use by another profile; server disabled",
host,
port,
)
@@ -218,18 +218,18 @@ class HttpServer:
ctx.load_cert_chain(self._adapter.http_cert, self._adapter.http_key)
httpd.socket = ctx.wrap_socket(httpd.socket, server_side=True)
except Exception as e:
logger.warning("android: HTTP server disabled (bind %s:%s failed: %s)", host, port, e)
logger.warning("iris: HTTP server disabled (bind %s:%s failed: %s)", host, port, e)
self._release_lock()
return
self._httpd = httpd
self._thread = threading.Thread(
target=httpd.serve_forever, name="android-http", daemon=True
target=httpd.serve_forever, name="iris-http", daemon=True
)
self._thread.start()
self.enabled = True
scheme = "https" if (self._adapter.http_cert and self._adapter.http_key) else "http"
logger.info("android: HTTP server listening on %s://%s:%s", scheme, host, self.bound_port)
logger.info("iris: HTTP server listening on %s://%s:%s", scheme, host, self.bound_port)
async def stop(self) -> None:
"""Stop serving and unblock all subscribers."""
@@ -261,7 +261,7 @@ class HttpServer:
from gateway.status import release_scoped_lock
if self._lock_key:
release_scoped_lock("android", self._lock_key)
release_scoped_lock("iris", self._lock_key)
self._lock_key = None
# ── Subscriber registry ───────────────────────────────────────────────
@@ -307,7 +307,7 @@ class HttpServer:
except queue.Full:
# Slow subscriber: drop it. The client reconnects with
# Last-Event-ID and catches up from the outbox.
logger.info("android: dropping slow HTTP subscriber %s", s.device_id)
logger.info("iris: dropping slow HTTP subscriber %s", s.device_id)
s.closed.set()
self._remove_sub(s)
return sent
@@ -331,7 +331,7 @@ class HttpServer:
and self._adapter.allowed_users
and device_id not in self._adapter.allowed_users
):
logger.warning("android: http rejected: device %s not allowlisted", device_id)
logger.warning("iris: http rejected: device %s not allowlisted", device_id)
_send_json(handler, 401, {"error": "device not allowed"})
return None
with contextlib.suppress(Exception):
@@ -436,7 +436,7 @@ class HttpServer:
try:
await dispatch.dispatch_frame(self._adapter, frame, device_id)
except Exception:
logger.warning("android: HTTP dispatch failed for %s", frame.type, exc_info=True)
logger.warning("iris: HTTP dispatch failed for %s", frame.type, exc_info=True)
finally:
# Pop our sink entry (a newer request from the same device may
# have replaced it). If the HTTP response was already sent
@@ -478,7 +478,7 @@ class HttpServer:
ntfy_topic,
)
except Exception:
logger.warning("android: device registry upsert failed", exc_info=True)
logger.warning("iris: device registry upsert failed", exc_info=True)
sub = _Subscriber(device_id=device_id, kind="sse")
# Register BEFORE the replay so a frame appended in between is
# fanned out to us (and de-duped by cursor below) instead of lost.
@@ -494,7 +494,7 @@ class HttpServer:
# lifecycle is the primary "is the device connected?" signal
# for debugging flaky links — a gap here is invisible at the
# gateway's default log level.
logger.info("android: SSE stream opened: %s (cursor=%d)", device_id, cursor)
logger.info("iris: SSE stream opened: %s (cursor=%d)", device_id, cursor)
# 1. Catch-up from the outbox (id = cursor; the envelope also
# carries the cursor for the app's push dedupe).
max_cursor = cursor
@@ -532,7 +532,7 @@ class HttpServer:
# Last-Event-ID and catches up from the outbox).
reason = "client-gone"
finally:
logger.info("android: SSE stream closed: %s (%s)", device_id, reason)
logger.info("iris: SSE stream closed: %s (%s)", device_id, reason)
self._remove_sub(sub)
@staticmethod
@@ -735,7 +735,7 @@ class _Handler(BaseHTTPRequestHandler):
server: _ThreadingHTTPD
def log_message(self, fmt: str, *args: Any) -> None: # noqa: A003
logger.debug("android http: " + fmt, *args)
logger.debug("iris http: " + fmt, *args)
# ── Routing ───────────────────────────────────────────────────────────