Files
orca/cloud
Neil 568567f7ad relay: director edge cohort for the relay edge (dark by default) (#39362)
* feat(relay): director edge override for moving hosts to the relay edge (dark by default)

Directors with ORCA_RELAY_EDGE_CELL_URL seed an existing-only 'edge' cell (registered
with the admission selector so deploy workflows carry it) and answer a host cohort
(hash bucket, allow/deny lists, region scope) on the edge before the reserve and
database lanes. The epoch rises only on a cell change; a host still holding units on
its old cell is told to retry. Phone resolve and the invite move answer edge rows
without moving anything; old cells answer WRONG_CELL to phones of moved hosts.
Unset URL keeps today's behaviour.

* feat(relay): director pushes host data to the relay edge on a move and takes it back before any move away

With ORCA_RELAY_EDGE_ADMIN_SIGNING_KEY set (its own key, never the assignment lease key), a move
onto the edge pushes the host's relay_devices and a location hint under the row lock and commits
only after the edge accepts; an edge holding a newer epoch is re-minted above once. Before any
lane may re-place an edge row, the director exports (refused while the desktop is connected; the
edge freezes the host), replaces the host's Postgres devices, places it as today, then fences the
edge with the new cell and epoch. Idle regional rehome skips edge rows. Unset key: unchanged.

* fix(relay): a deferred edge move keeps the host on today's path instead of a 503 loop

A host still holding old-cell units (a pairing invite holds one for its 10 min TTL) or whose push
the edge did not take now stays where it is and moves on a later ask. 503 stays for a held row
lock and for a desktop still connected to the edge on the way out.

* relay: director refuses an edge URL without the edge admin key

The deployed edge keeps host data in its objects; without the key the director could
not push it and hosts would land on an edge holding none of their devices.

* relay: edge cohort by account (ORCA_RELAY_EDGE_ALLOW_USERS)

Every host of a listed account (relay token sub) joins the edge cohort, in any region;
a denied host still stays off. For the team's own accounts before any share rollout.

* relay: edge modules follow main's relay module moves

* relay: satisfy the changed-lines lint gate in the edge cohort code

Braces on every if, T[] arrays, type aliases, one ternary, and a justified max-lines header on
edge-relay.ts. No behaviour change: relay unit 845 passed.

* relay: move edge cohort config and row helpers to edge-relay-cohort.ts

Keeps edge-relay.ts under the 300-line limit without a max-lines disable. Code moved verbatim;
edge-relay.ts re-exports what other modules import. Relay unit 845 passed.
2026-11-07 18:40:06 -08:00
..

Orca Relay

The relay that connects the Orca mobile app to a desktop host. Phones and desktops never talk to each other directly: each opens an outbound WebSocket to a relay cell, the relay pairs the two sessions, and it splices frames between them. A director assigns hosts to cells and coordinates migrations; cells carry the user connections.

This directory is an independent pnpm workspace inside the Orca monorepo. Run its commands from cloud/, not the repository root. The source is covered by the repository's root MIT license.

The 2026-10-21 security review records dependency/container scans, remaining upstream advisories, CI coverage, and the validation required before rolling out the updated images and host pins.

Packages

  • packages/relay-contract: the wire contract shared by the relay, the desktop app, and the mobile app (frame shapes, close codes, admission budgets, splice state machine).
  • apps/relay: the relay server. The same image runs as a director or a cell depending on ORCA_RELAY_ROLE.
  • apps/relay-fence-broker: a private, IAM-only service that owns the durable mutation lease, the Terraform checkout, and the narrow Compute mutation used when a registered target is superseded. The workflow that calls it holds read and invoke rights only, never those mutation permissions.
  • apps/push and packages/push-contract: the mobile push gateway that holds the APNs key and sends to phones through APNs and FCM, and its wire contract. Deployment and operations are owned by the private stablyai/orca-cloud repository.
  • packages/connector-contract: the connector wire contract (experimental).

Mobile push gateway

apps/push is a separate Cloud Run service from the relay. Phones never hold an Orca credential for it: the desktop host authenticates with the same X25519 key it uses for the relay, answering an encrypted challenge to mint a 24 hour session, then registers each paired phone's native push token and asks the gateway to push. The gateway queues each event as its own notification, enforces per-host quotas and request limits, and retires a registration as soon as Apple or Google reports the token unregistered. Provider push is the only ordinary mobile OS-banner path. The notification socket is retained only for live dismissal and reconnect tray reconciliation; it never creates or recovers banners. Desktop notification categories remain authoritative. Each delivery is persisted as one notification event. Before deploying an incompatible queue format, stop all older push gateway revisions and clear only unpublished push delivery fixtures; no queue preservation or migration is required. FCM notification messages are inherently collapsible while offline and have a small concurrent collapse-key budget, so every pending alert is not guaranteed.

Storage follows the relay pattern: PostgreSQL in production, SQLite for tests and local development. Configure it with ORCA_PUSH_PUBLIC_URL, ORCA_PUSH_FCM_PROJECT_ID, ORCA_PUSH_DATABASE_URL, the three APNs variables (ORCA_PUSH_APNS_KEY, ORCA_PUSH_APNS_KEY_ID, ORCA_PUSH_APPLE_TEAM_ID, all three or none), and optionally ORCA_PUSH_APNS_TOPIC. The FCM credential comes from the runtime service account, so no key material is configured for Android. See push gateway operations for deployment and recovery.

Logging is aggregate counters only. Tokens, notification titles, notification bodies, and full host fingerprints never reach a log line.

Deployment configuration

The relay runtime and wire contracts are public. Production and staging Terraform, backend configuration, operator tools, runbooks, broker image assembly, and deployment workflows live in the private stablyai/orca-cloud repository. That repository pins an immutable public source revision and combines it with its deployment configuration.

Cloud Verify here builds and tests public runtime code, audits dependencies, scans relay and push images, and checks for secrets without cloud credentials. Private CI also validates Terraform, scans the SQL proxy and broker, and runs deployment contracts.

Local development

cd cloud
pnpm install
pnpm build
pnpm test

pnpm test runs the SQLite-backed suites. Tests that need PostgreSQL run only when ORCA_RELAY_TEST_POSTGRES_URL points at a disposable PostgreSQL 16 or 17 database, for example:

docker run --rm -d --name orca-relay-pg -e POSTGRES_HOST_AUTH_METHOD=trust \
  -e POSTGRES_DB=orca_relay_test -p 55440:5432 postgres:16-alpine
ORCA_RELAY_TEST_POSTGRES_URL=postgres://postgres@127.0.0.1:55440/orca_relay_test \
  pnpm --filter @orca-cloud/relay test
docker rm -f orca-relay-pg

Configuration is read from environment variables validated in apps/relay/src/config.ts. ORCA_RELAY_ASSIGNMENT_SIGNING_KEY (at least 32 bytes) is the only required value; everything else has a local default.