| new file mode 100644 |
| index 0000000..3d7d810 |
| --- /dev/null |
| +++ b/README.md |
| @@ -0,0 +1,106 @@ |
| +# Meet |
| + |
| +Meet is video calling for one team. A member makes a meeting, now or |
| +for later, and sends one link; anyone who follows it sets up their |
| +camera and microphone on a holding screen, waits to be let in if they |
| +are not on the team, and talks in a room of up to four, with chat |
| +beside the call and a screen to share. An agent can also create, |
| +list, relink and end meetings over an API. Every screen works with |
| +JavaScript disabled except browser media participation — the camera |
| +preview and join button on the holding screen, and the call itself in |
| +the room — and both pages still render their title, standing, floor |
| +notice and navigation with scripts off (spec §9). |
| + |
| +ICE servers come from the CARLOS platform relay, delivered as |
| +`CARLOS_RELAY` and minted fresh for each call at `GET /m/{sqid}/ice`; |
| +Meet names no STUN or TURN server of its own (suite ruling 6). With no |
| +relay configured, calls are direct only: two browsers connect when ICE |
| +can find a working path straight between them, and the holding screen |
| +says so. Enabling or changing the relay restarts the instance (spec |
| +§5.2, §5.5, §7.3, §15.13). |
| + |
| +## Sign-in |
| + |
| +Sign-in is a magic link to an address on the team's allowlist |
| +(`MEET_ALLOWED_ADDRESSES`). Following a meeting link gives an outsider |
| +a guest grant at sign-in — never a way into a room without a name — |
| +and the allowlist otherwise gates sign-in exactly as it does for a |
| +member (spec §3, §7.1). An operator can also enable Home sign-in with |
| +all four of `MEET_HOME_ISSUER`, `MEET_HOME_CONSUMER_ID`, |
| +`MEET_HOME_KEYS_BASE64` and `MEET_HOME_DEK_BASE64` — never a partial |
| +set — which links an existing member after a fresh, independent local |
| +sign-in and explicit confirmation; it never creates a person or grants |
| +membership on its own (spec §7.1.1). |
| + |
| +## The room |
| + |
| +The room is a peer-to-peer mesh of up to four admitted participants, |
| +negotiated with the W3C perfect-negotiation pattern over an SSE stream |
| +and a POST signal per peer. A guest waits in a queue until an admitted |
| +member lets them in; removing a participant and ending a meeting each |
| +go through their own confirm page — there is no in-room control that |
| +skips one (spec §3.5). Chat is fanned out live to admitted peers and |
| +never stored (spec §6). Screen share adds a second tile per sharer |
| +(spec §5.4). The room lives in one process's memory, so every deploy |
| +drops every live call (spec §15.11). |
| + |
| +## Agents |
| + |
| +A member mints an agent's bearer token from Settings; it is shown once |
| +and the row after it keeps only its hash. The token works on |
| +`/api/v1` only — never a cookie there, and never a bearer on an HTML |
| +route — for five operations: list meetings, create one, replace its |
| +link, end it, and read one meeting's detail. It cannot join a call |
| +(spec §8). An agent's reach is re-derived from its operator's current |
| +standing on every request, so an operator who leaves the team takes |
| +their agent's reach with them at once, with no separate revocation |
| +step. A limit of 60 requests a minute applies per agent (spec §8, |
| +§15.17). |
| + |
| +## Native apps |
| + |
| +The SwiftUI Mac and iPhone apps use this same server and a shared Go |
| +core (`meetcore/`, `protocol/`); there are no embedded webviews. Build |
| +the Mac app with `make native-mac`. See `native/README.md` and |
| +`native/ios/README.md` for setup, native sign-in and the native gates. |
| + |
| +## Building and gates |
| + |
| +`make ci` (vet, gofmt, tests, migration check) is the one gate a |
| +runner and a push share, and it stays `CGO_ENABLED=0` throughout. |
| +`make race` is the one exception, building a test binary under |
| +`CGO_ENABLED=1` for any change to `internal/meet/hub` or the |
| +signalling stream. `make browser` drives a real call across two real |
| +Chromium contexts, 31 scenarios in about nine minutes; it needs the |
| +Claude Code bash sandbox off, because the sandbox blocks UDP and every |
| +call then fails with `frames` stuck at 0. `make native-test` covers |
| +the shared Go core and the gomobile bridge. `make release |
| +VERSION=<sha>` stamps that version into `/api/version`, so a deploy |
| +can be checked against what it is meant to be running. |
| + |
| +## Deploying |
| + |
| +Meet deploys as a CARLOS unit route: `carlos deploy --app meet |
| +--account oficina`, checked against a build probe on `/api/version`. |
| +Secrets — `MEET_INSTANCE_KEY` and `MEET_DEK` (32 base64 bytes) — go |
| +through `carlos secrets`; mail reads `MEET_SMTP_*` with `CARLOS_SMTP_*` |
| +as a fallback, per variable; `MEET_ORIGIN`, `MEET_ALLOWED_ADDRESSES` |
| +and `MEET_ZONE` go through `carlos env`. `carlos relay enable --app |
| +meet` turns on the platform relay. Every deploy, and every relay |
| +change, restarts the instance and drops every live call, so deploy |
| +outside meeting hours. Migrations apply once each at boot (`msg=migrate` |
| +in the log) and are never re-run; a database that already applied a |
| +migration file under an earlier name fails at boot rather than |
| +silently diverging. The `carlos deploy` wait can time out before the |
| +instance hands over — check `/api/version` again before retrying. The |
| +canary recipe is `carlos instances create` then `carlos deploy |
| +--channel`, because `carlos canary` itself now forms a two-label host |
| +(platform #124). |
| + |
| +## Where things are written down |
| + |
| +The design lives in `docs/superpowers/specs/2026-09-07-meet-design.md`, |
| +the slice plans in `docs/superpowers/plans/`, and each slice's review |
| +in `docs/superpowers/reviews/`. `PRODUCT.md` covers what Meet is for |
| +and what it deliberately leaves out; `AGENTS.md` covers the |
| +conventions the code is held to. |