# cloud/cloud_api — Multiplayer REST API

The REST brain of the Bigscreen multiplayer stack. Every time a VR user creates or joins a room, shares their screen, sends a friend request, or a media server comes online, something interesting happens here. `cloud_api` holds the canonical picture of "who is where", backed by Redis for real-time state and DynamoDB for history. It also routes messages to / from media servers and the websocket tier.

**Entry:** [cloud/cloud_api/cloud_api.ts](../../cloud/cloud_api/cloud_api.ts):48 — port `CLOUD_API_SERVER_PORT` or 3002.
**Package:** `bigscreen_cloud_api`.
**Depends on:** [`@bigscreen/lib`](../libraries/lib.md), [`@bigscreen/auth`](../libraries/auth.md), [`@bigscreen/api`](../libraries/api-handlers.md), [`@bigscreen/cloud`](../libraries/cloud-handlers.md).

## Ecosystem View

`cloud_api` sits at the middle of a small cluster of cooperating processes:

```mermaid
flowchart TB
    subgraph Clients
        VR[VR Clients]
        WEB[Website]
        ARDA[Arda SPA]
    end

    CAPI["cloud/cloud_api (:3002)"]
    WSS["cloud/ws_server (:3003)"]
    WORKER["cloud/cloud_worker"]
    MS["cloud/media_server_next"]

    REDIS[("Redis")]
    DDB[("DynamoDB")]
    BCQ[[SQS BigscreenCloud]]
    WOUT[[SQS WebsocketOutbox]]
    WIN[[SQS WebsocketInbox]]

    VR -->|/room, /social, ...| CAPI
    WEB --> CAPI
    ARDA -->|/admin/*| CAPI

    CAPI <--> REDIS
    CAPI --> DDB
    CAPI --> BCQ
    CAPI --> WOUT

    MS -->|HTTP: /api/media-server/message| CAPI

    WORKER <--> BCQ
    WORKER <--> WIN
    WORKER --> REDIS

    WSS <--> WOUT
    WSS <--> WIN
    WSS <-.websocket.-> VR
```

`cloud_api` never speaks WebSockets to users directly — that's `ws_server`'s job. Outbound pushes go through the `WebsocketOutbox` queue. Media-server coordination is split: HTTP ingress from media servers via `/api/media-server/message` (because media servers may live outside AWS and can't reach SQS directly), but outbound commands TO media servers go via SQS.

## Auth Handler Matrix

`cloud_api` spins up **five** auth handlers, one per category of caller. All created at [cloud_api.ts:17-21](../../cloud/cloud_api/cloud_api.ts):

| Handler | `apiName` | Used by |
|---------|-----------|---------|
| `standardAuthHandler` | `cloud-api` | VR clients, website (public endpoints) |
| `adminAuthHandler` | `cloud-admin-api` | Arda staff |
| `mediaServerAuthHandler` | `media-server-api` | media_server_next instances registering / posting heartbeats |
| `websiteAuthHandler` | `website-cloud-api` | website-specific endpoints (e.g. browser info) |
| `hyperbeamAuthHandler` | `hyperbeam-webhook` | Hyperbeam browser-sharing webhooks |

Each has a corresponding middleware (`requiresStandardBearerAuth`, `requiresStandardAccessToken`, `requiresAdminAccessToken`, `requiresMediaServerBearer`, etc.) applied per-route.

## Endpoint Groups

Routes are declared inline in [cloud_api.ts](../../cloud/cloud_api/cloud_api.ts). Main prefixes:

| Prefix | Purpose | Auth handler |
|--------|---------|--------------|
| `/admin/*` | Room stats, room / user admin, media-server admin, screen admin | admin |
| `/room`, `/rooms/*` | Create, join, leave, update, delete rooms; seat assignment; kick | standard |
| `/social/*` | Friend lists, block / unblock, friend requests, social search, history | standard |
| `/screen/*` | Screen creation, screen sharing | standard |
| `/activity/*` | Shared activities (games, co-watching) | standard |
| `/channels/*`, `/channel/:id` | Channel info, join streaming events | standard |
| `/media/join` | Join a shared-media session | standard |
| `/lobby/join` | Join the default lobby | standard |
| `/apps/browser/*` | Browser-sharing (Unity writes, website reads) | standard / website |
| `/hyperbeam/webhook/*` | Hyperbeam session access-control callbacks | hyperbeam |
| `/report/*` | Report user / room (mirror of `apps/api`) | standard |
| `/api/media-server/register` | Media-server registration handshake | mediaServer |
| `/api/media-server/message` | Media-server → cloud command ingestion (HTTP→SQS bridge) | mediaServer |
| `/api/media-server/manifest` | Query current manifest | mediaServer |

## Startup

```mermaid
sequenceDiagram
    autonumber
    participant P as Node process
    participant MQ as MessageQueue
    participant C as Cloud @bigscreen/cloud
    participant MW as media_server_worker
    participant SRV as Express

    P->>MQ: initQueue(BigscreenCloud)
    P->>MQ: initQueue(WebsocketInbox)
    P->>C: Cloud.initialize()
    P->>MW: startMediaServerWorker()
    Note over MW: polls SQS BigscreenCloud<br/>for MediaServer-origin msgs<br/>in-process (NOT cloud_worker)

    alt NETWORK_NAME == "dev"
        P->>C: setInterval(Cloud.checkRoomsIntegrity, 60s)
    end

    P->>SRV: express() + middleware stack
    P->>SRV: register all auth handlers + routes
    P->>SRV: api.listen(3002)
```

There's an in-process worker (`startMediaServerWorker` from [cloud/cloud_api/media_server_worker.ts](../../cloud/cloud_api/media_server_worker.ts)) that polls SQS for media-server messages — this is **distinct** from the separate [`cloud_worker`](./cloud-worker.md) process, which handles a different subset of the same queue. Historical context: the media-server worker used to live in `cloud_worker` and was moved in-process to reduce latency on media-server heartbeats.

## Middleware Stack

```mermaid
flowchart LR
    R[request] --> C1[compression]
    C1 --> C2[bodyParser.urlencoded]
    C2 --> C3[bodyParser.json]
    C3 --> C4[helmet]
    C4 --> C5["CORS (origin: *)"]
    C5 --> C6{route-specific<br/>auth middleware}
    C6 --> H[route handler]
```

CORS is wide-open (`origin: *`) because VR clients speak from anywhere. All security is enforced by the auth stack.

## Room Integrity Checks (dev only)

On networks named `dev`, `cloud_api` runs `Cloud.checkRoomsIntegrity()` every 60 s. This is a diagnostic that walks Redis room keys, flags inconsistencies (orphaned users, rooms without media servers), and logs / repairs them. It's dev-only because the walk can get expensive at production fleet sizes.

## Further reading

- How room-create flows end-to-end → [data-flows.md#2-room-creation](../data-flows.md#2-room-creation)
- How media-server heartbeats land here and propagate → [data-flows.md#3-media-server-heartbeat](../data-flows.md#3-media-server-heartbeat)
- What `Cloud.*` functions actually do → [libraries/cloud-handlers.md](../libraries/cloud-handlers.md)
- WebSocket message delivery → [services/ws-server.md](./ws-server.md)
