The desktop half of the GitHub App relay (github-relay-spec §13 Step 3):
- relay_client.py: extract RelayHub — ONE authenticated cloud socket owns
the transport/read-loop/reconnect watchdog; frames fan out by provider
tag. SlackRelayAdapter becomes its first consumer (public surface
unchanged); GitHubRelayAdapter its second. Also pin the relay tests'
name resolution to a dead loopback port — unstubbed lookups were
reaching slack.com and intermittently blowing the 2s dispatch window.
- github_relay.py: GitHubRelayAdapter — github:owner/repo#N addressing,
installation_id rides source.team_id so the gateway's per-team
allow-list (park → allow & deliver) applies per installation unchanged;
missed/revoked frames handled; send() posts an issue/PR comment with a
minted installation token.
- github_installs.py: github:install:<id> profiles (metadata ONLY — no
token field by design), default pointer + per-installation allow-lists
on the profile; last-removal turns relay off without resurrecting a
stored manual PAT.
- cloud.py: github_installation_token — memory-only ~50-min cache, force
re-mint for the 401 path, never written to the secret store;
per-installation cloud disconnect; managed-connect flow passthrough.
- Managed OAuth callback branch (token-less by design, so it precedes the
access_token check) + gateway hot-add; per-installation disconnect and
status routes; allow-list edits target github:install:<id>.
- Tools: _github_call resolves auth per repo owner — manual PAT wins
untouched, managed profiles mint and re-mint once on 401; new
github_reply + github_review (approval-gated). The §12.5 write ceiling
is enforced by what exists: no push/delete/settings tools on any path.
- github descriptor: two_way + managed.
655 pytest + 23 vitest green; 13 new tests cover install callback,
per-installation allow-lists, hub fan-out, missed/revoked, addressing,
send, token cache/re-mint, tool auth on both paths.
Accounts: each sign-in lands in its own gmail:account:<email> profile;
gmail:default shrinks to the default pointer + filters. A legacy token-bearing
default migrates lazily into one account (no user action). The three gmail
tools take an optional account argument (default fallback), name the mailbox
in results and approval args, and broker refresh targets account-keyed
profiles.
Filters: senders (addr or @domain) and label names, enforced in the DESKTOP
tool layer - matching messages silently omitted from search, a direct fetch
reads like a real 404, no tombstone an agent could probe. The hidden count
rides a _display sidecar on the tool-result message (mirroring source):
persisted for the GUI, stripped from every provider feed, audited as
rule+count, and shown on the tool card / step-group line.
GUI: GmailDetail page (Accounts with Default badge + per-account disconnect,
one-click add, filter chip rows, collapsed Tools); routes for account
disconnect/default and PATCH filters.
/v1/personas/install accepts gallery_slug: fetch the manifest from the
cloud (sign-in required), verify its sha256 against the published hash,
then reuse the exact local-install parser + consent flow — gallery
personas land disabled/unsurfaced pending approval like any third-party
install. GET /v1/cloud/gallery serves cards to the GUI. Install events
fire best-effort as content-free telemetry.
Phase 3 of the cloud platform spec. The sidecar gains the two loopback
routes: GET /auth/callback completes Auth0 PKCE sign-in (started via
POST /v1/cloud/login, which opens the system browser), and
POST /oauth/callback receives the broker's form-POSTed token payload and
writes a connector profile through the managed setup path. Profiles are
field-compatible with manual paste; managed extras (refresh_token,
connection_id) enable broker refresh — hooked into the tools' _profile
choke point so managed tokens renew just before expiry — and best-effort
cloud metadata disconnect.
Sign-in is strictly optional: manual token paste works signed out and
stays available after sign-in (one-click is an addition, never a
replacement). Managed capability ships for gmail + google_calendar;
other providers join with their Phase 4 waves.
GUI: cloud account card on Integrations ▸ Connectors, one-click connect
button on managed connectors when signed in, manual fields always
rendered. Cloud endpoints are config values (cloud_base_url etc.), never
constants. Tests: 18 python + 2 e2e.