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

+12 -12
View File
@@ -2,13 +2,13 @@
``PushBackend`` interface with two implementations:
- ``FcmBackend``: FCM HTTP v1 via ``httpx`` + a Firebase service account
(``ANDROID_FCM_SERVICE_ACCOUNT``), or a legacy server key
(``ANDROID_FCM_SERVER_KEY``).
(``IRIS_FCM_SERVICE_ACCOUNT``), or a legacy server key
(``IRIS_FCM_SERVER_KEY``).
- ``NtfyBackend``: publishes to ``NTFY_TOPIC`` on ``NTFY_SERVER_URL``
(default ``https://ntfy.sh``) via ``httpx``; the app's listener
subscribes to the topic.
Selected by ``ANDROID_PUSH_BACKEND`` (``fcm`` default, ``ntfy`` fallback).
Selected by ``IRIS_PUSH_BACKEND`` (``fcm`` default, ``ntfy`` fallback).
Fired when a frame has no live subscriber; the data payload drives a silent
sync on the device (docs/08-push.md).
@@ -120,7 +120,7 @@ class FcmBackend(PushBackend):
self._sa = sa
return sa
except Exception:
logger.warning("android: FCM service account unreadable: %s", self._sa_path)
logger.warning("iris: FCM service account unreadable: %s", self._sa_path)
self._sa_failed = True
return None
@@ -151,7 +151,7 @@ class FcmBackend(PushBackend):
claims, sa["private_key"], algorithm="RS256", headers=headers
)
except Exception:
logger.warning("android: FCM JWT mint failed", exc_info=True)
logger.warning("iris: FCM JWT mint failed", exc_info=True)
return None
try:
resp = await client.post(
@@ -163,11 +163,11 @@ class FcmBackend(PushBackend):
timeout=_HTTP_TIMEOUT_S,
)
except Exception:
logger.warning("android: FCM token exchange failed", exc_info=True)
logger.warning("iris: FCM token exchange failed", exc_info=True)
return None
if resp.status_code != _HTTP_OK:
logger.warning(
"android: FCM token exchange HTTP %s: %s",
"iris: FCM token exchange HTTP %s: %s",
resp.status_code, resp.text[:200],
)
return None
@@ -236,12 +236,12 @@ class FcmBackend(PushBackend):
headers={"Authorization": f"Bearer {auth}"},
)
except Exception:
logger.warning("android: FCM send failed (network)", exc_info=True)
logger.warning("iris: FCM send failed (network)", exc_info=True)
return False
if resp.status_code >= _HTTP_ERROR_MIN:
# 404 NOT_FOUND = stale/invalid registration token.
logger.warning(
"android: FCM send HTTP %s: %s", resp.status_code, resp.text[:200]
"iris: FCM send HTTP %s: %s", resp.status_code, resp.text[:200]
)
return False
return True
@@ -313,11 +313,11 @@ class NtfyBackend(PushBackend):
url, content=text.encode("utf-8"), headers=headers
)
except Exception:
logger.warning("android: ntfy publish failed (network)", exc_info=True)
logger.warning("iris: ntfy publish failed (network)", exc_info=True)
return False
if resp.status_code >= _HTTP_ERROR_MIN:
logger.warning(
"android: ntfy publish HTTP %s: %s", resp.status_code, resp.text[:200]
"iris: ntfy publish HTTP %s: %s", resp.status_code, resp.text[:200]
)
return False
return True
@@ -332,7 +332,7 @@ def build_push_backend(
ntfy_server_url: str | None = None,
ntfy_auth_token: str | None = None,
) -> PushBackend:
"""Select the backend by name (``ANDROID_PUSH_BACKEND``; fcm default)."""
"""Select the backend by name (``IRIS_PUSH_BACKEND``; fcm default)."""
if (name or "").strip().lower() == "ntfy":
return NtfyBackend(
topic=ntfy_topic, server_url=ntfy_server_url, auth_token=ntfy_auth_token