oficina / meet Public

Clone
git clone https://amadan.net/oficina/meet

Plain git — no account needed to clone.

Download

Download this file

Product

<!-- impeccable:product-schema 1 -->

> How this file was written. Written unattended, on the same > instruction that produced oficina/docs' PRODUCT.md: every fact > below comes from repository evidence, not an interview — > docs/superpowers/specs/2026-09-07-meet-design.md (revision 9, plus > the 2026-09-10 and 2026-09-12 amendments), AGENTS.md, the slice > records under docs/superpowers/reviews/, native/README.md, and the > shipped code in internal/calls/ on branch slice/6-deploy, main > 9225ec2. Facts are cited to a spec section or a file. A reading > rather than a citation is marked [inferred — confirm] and should > be corrected, not trusted. A bare "ruling N" is the Calls spec's §1; a > doctrine ruling is always written "suite ruling N".

Platform

Web, plus native Mac and iPhone/iPad clients over the same server contracts (spec §8.4's 2026-09-14 amendment, native/README.md).

Users

Primary: a member of one team, making and joining that team's video calls. The instance boundary is the team — one instance per team (preamble; suite ruling 1, 5, §0.2), the "lone shape" until a suite home exists (§7.1). Secondary: an outside guest, admitted with a real identity, never as an anonymous URL holder: every participant signs in, and a meeting link gives an outsider a guest grant, never a way in without a name (ruling 1; suite ruling 15); a guest waits until an admitted member lets them in (ruling 9, §3.3).

Access is a magic link gated by CALLS_ALLOWED_ADDRESSES (internal/calls/config.go), with optional Home sign-in when an operator sets all four CALLS_HOME_* settings (§7.1.1) — Home only links an existing member after independent local sign-in; it never creates a person or grants membership. Unlike Docs' §8.1, the spec states no passkey ruling of its own. [inferred — confirm] the team is assumed small enough that an address allowlist is appropriate; the spec states no target size.

Product Purpose

Calls is video calling for one Oficina team: a member makes a meeting, sends one link, and the people who follow it set up camera and microphone, wait to be let in if not on the team, and talk (preamble). "The instance carries the pages, the sign-in, the signalling and the in-call chat, and never a frame of media" (§0.1) — falsifiable: publish the SQLite file, its WAL, and every log line, and the worst anyone learns is the shape of the team's meetings and who minted what, never a title, chat text, or signalling payload, enforced by a WAL-grep test and a captured-logger test, not merely asserted (§0.1). Since 2026-10-03 the log also holds quality and problem reports under random tags (§15.26): the shape of a call's connections, never which meeting or who.

Positioning

  1. The claim is made per process, not once (§0.1): Calls' own process never touches a media packet; the platform TURN relay forwards encrypted DTLS-SRTP it cannot read; a future platform SFU decrypts to forward and gets its own spec revision when it ships (§5.7).
  2. No relay of its own, by ruling (suite ruling 6, §5.2): present CARLOS_RELAY mints ICE credentials per call; absent means host candidates only, stated before the join button (§5.5).
  3. Two authorities, not one, for a room. Standing (§2.3, computed per request, never stored) decides who may enter; a participation (§2.4, hub state) decides who may continue — an admitted guest keeps talking past its grant's expiry while a member who loses standing is dropped at once (ruling 14).

Operating Context

  • One Go binary per instance, CGO_ENABLED=0, deployed on CARLOS as a unit route (§7.3). Native Apple bindings under native/ are the one place cgo is used, isolated in native/go.mod (AGENTS.md).
  • Routes today (internal/calls/app.go): GET /, POST /meetings; GET /j/{token} (outside the session group); the holding screen and room; signalling (stream, signal, ice); POST /m/{sqid}/share (2026-09-12); five destructive confirmation pairs (remove, takeover, replace invitation, end meeting, revoke agent); Settings and agent tokens; sign-in including optional Home routes; native handoff endpoints; a bearer-only /api/v1/* group (api.go) outside CSRF and the session group. GET /healthz/GET /api/version answer from rastrillo itself, outside app middleware.
  • Scriptless, with browser media participation as the exception, and two script-only parts inside a live room. Reaching a camera and another browser needs script; so, once a call exists, do the chat panel (partials/chat.html renders it hidden until script un-hides it) and the admission queue's Admit controls (room.js). Every other screen — the list, creating a meeting, a link shown once, every confirm page, sign-in, /welcome, the agent token page, the Share page and the Home account-link screens (§7.1.1), and the server-rendered parts of the holding screen and room — works with scripts off (§9; AGENTS.md's UX line carries the media exception; full list below).
  • Nothing stored beyond a meeting's bones. Rooms, peers, admission, chat and presence live in an in-process hub and die with the process (§2.2); a restart drops every live call (§4.5). Stored: persons, meetings (sealed title, internal/calls/seal/), meeting_links (hash-indexed plus a sealed copy for sharing since 2026-09-12), pending_joins (a keyed address fingerprint, never plaintext), guest_grants, agents (a member's minted principal; the token itself is never stored, only its SHA-256) (models.go; §2.1).
  • Quality reports and "Report a problem" go to the log, by Paul's ruling of 2026-10-03 (spec §15.26), which knowingly bends "stores nothing about calls". Collected: every 30 s in a call and at leave, each client's connection numbers per remote peer (bitrate, loss, RTT, jitter, audio concealment and jitter buffer, video freezes and frames, frame size and fps, the encoder's limitation, screen recovery steps), the candidate types and transport of the path (host/srflx/relay, udp/tcp/tls), the notices shown (Reconnecting, can't hear you yet, no sound, sound blocked, screen stalled), app/browser/OS and their versions, and the kind of microphone and speaker (bluetooth, usb, built-in…); all under a random call tag and a random peer tag. When someone presses Send in "Report a problem": their note, and their call diagnostics, which include device names and, on the web, the user agent, with people as peer tags and the meeting scrubbed. Never: names, emails, meeting titles or sqids, peer ids, IP addresses, device names (in quality reports), chat, audio or video. Nothing goes to the database; the log is the only store, kept for the platform's log retention — seven days, or 50 MiB of compressed log per app per box, whichever is first. CALLS_QUALITY_REPORTS=off stops quality reports; a person can stop their own in Settings (apps) or the Devices panel (web).

Capabilities and Constraints

Shipped: meeting creation and listing; a link shown once, replaced or shared via POST /m/{sqid}/share; sign-in with the pending-join exception admitting an outsider only while holding a live link (ruling 12, §3.2); optional Home account-linking (§7.1.1); the holding screen and a P2P mesh room capped at four with perfect negotiation, resume, and a replay ring (§4); relay-minted ICE credentials renewed before deadline (§5.2, §5.3); ephemeral chat and screen share (§6, §5.4); a bearer-token drive surface for agents re-checking operator membership on every request (§8, §15.17); native Mac and iPhone/iPad apps sharing the Go protocol core (native/README.md).

Deliberately not built yet (§11, as amended): see "What is deliberately not here" below for the full, cited list.

Binding technical constraints:

  • Media never touches Calls' own process (§0.1); no handler accepts a media packet. scope.Owned, no bound request body: every user-owned query goes through it, reads and writes alike; a row that isn't yours 404s, never 403s (AGENTS.md).
  • Standing is computed, never cached — every request, every 15-second hub tick (§2.3, §2.4). A shipped migration is never edited. The agent API's rate limit keys on the resolved agent, not the client address, deliberately (§15.17; see below).
  • CGO_ENABLED=0 make ci is the server's cgo-free gate. Two things run under CGO_ENABLED=1 and never ship: make race, for any change to internal/calls/hub or the stream, and make native-test's own callscore race sub-step. The native Mac and iPhone/iPad apps are the one place real cgo does ship — CallsBridge is a binary target CallsKit links (native/apple/Package.swift, native/scripts/build-mac.sh) — while every server release stays CGO_ENABLED=0 (AGENTS.md). make browser needs UDP, which the Claude Code bash sandbox blocks (AGENTS.md).

Brand Commitments

  • Name: Calls, amadan.net/oficina/calls, served at calls.oficina.works. Renamed from Calls on 2026-09-16. Ruling 2 chose oficina/meet over oficina/conferencia (preamble); that ruling stands as the record of what was decided then, and this row is the current name. Built beside Docs, Calendar, Slides and the suite doctrine, consuming a decision made there rather than restating it (preamble, §0.2).
  • The theme is Estilo's, adopted at whatever Estilo holds when each slice lands. As recorded on 2026-09-14 (git ls-remote --tags against oficina/estilo, empty at that check), no tag exists; consumed at a pseudo-version, already adopted by the Home integration on main. [inferred — confirm] the exact commit at any later date.
  • The chat panel is Calls' contribution to Estilo — "one self-contained template partial and one script file so a second app can adopt it," the suite's first chat, built to be taken (§6).
  • Voice: [inferred — confirm]. Copy review was waived for this documentation round (steering on oficina/suite discussion 5), so shipped strings were not checked against a review record.

Evidence on Hand

  • Spec: revision 9 plus the 2026-09-10 and 2026-09-12 amendments, 2100+ lines, six rounds of Codex review (§14). Plans: docs/superpowers/plans/, one programme (slices 2–6) plus a plan per slice. Slice records: docs/superpowers/reviews/, one per slice 2–5 (room, relay, chat/screen-share, drive surface), each an index into the spec's own §15 rulings for that slice.
  • Native: native/README.md, native/DESIGN.md, native/VERIFICATION.md — build, gates, stated acceptance limits (no real-device pass claimed for camera permissions, audio-device switching, sleep/wake, or Home passkeys).
  • What does not exist and must not be invented: customers, testimonials, benchmarks, pricing, usage numbers, launch date, press, or a production promotion from this slice — edge (calls.oficina.works) is promoted by hand by Paul, separately from documentation (slice 6 plan, "What slice 6 was"). The acknowledgements page and the Estilo theme pin are the other two slice-6 items with a disposition rather than a delivery; spec §15.18 is the record for all three.

Product Principles

  1. State the degradation rather than let it be discovered. The no-relay floor says calls usually connect only on the same network (§5.5); §0.3 states what the privacy claim excludes (signalling in flight, a replay ring of up to 32 messages for 30 seconds, a link as a bearer); the mail-budget residue is written down, not claimed away (§3.2).
  2. A verification that cannot distinguish "no" from "I can't see it" is not a verification. The §0.1 claim is enforced by grepping raw SQLite bytes and the WAL and capturing the logger during a real call; make browser asserts a received track by ontrack and frame count, never a label (§13).
  3. Two authorities are named because one would be wrong in some direction (§2.3–§2.4, ruling 14): a single authority either drops an admitted guest at the grant's two-hour mark or lets an expired grant re-enter.
  4. A contract is written for the next client, not the current one. Signalling, /ice and the meeting API are contracts a native client could speak (ruling 15, §8.4); the native apps are that ruling paying off.
  5. Actors are person:<id> or agent:<id>, never fabricated (§7.2, doctrine ruling 9).

Accessibility & Inclusion

AGENTS.md's vendored UI conventions apply: labelled fields with one error envelope, destructive actions on their own confirm-page URL and never a modal (ui/confirm-form — §3.1, §3.5, §4.2), state shown with a text label and not colour alone, and empty states that say what the screen is for.

The scriptless floor is the accessibility constraint this app adds beyond that shared list. Reaching a camera and another browser needs script, and so, once a call exists, do the room's chat panel and its admission-queue Admit controls; nothing else does. With scripts off the holding screen's join button becomes one paragraph saying a call needs JavaScript and everything else on the page works without it (§3.3); the room does the same (§3.4).

No target locale count or WCAG conformance level is stated in the Calls spec or AGENTS.md. [inferred — confirm]: Docs states "WCAG 2.2 AA, no exemptions" for itself; nothing here says the same target binds Calls, and this file does not assume it does.

What is deliberately not here

  • Scriptless media, chat and admission — the exceptions to the scriptless floor: reaching a camera and another browser needs script, and so, once a call exists, do the room's chat panel and its admission-queue Admit controls; every other screen, including the server-rendered parts of the holding screen and the room, works with scripts off (spec §9; AGENTS.md's UX-conventions line carries the media exception in the same words).
  • No STUN or TURN server of Calls' own. ICE servers come from the platform relay, present or not at all — never a server Calls names itself (suite ruling 6, §5.2, §5.5).
  • No SFU, and the room is capped at four admitted peers — not a claimed product limit, the mesh's own (ruling 5), lifted only when a platform SFU that decrypts to forward ships, in its own spec revision, not a quiet cap change (§5.7, §0.3, §11 "rooms above four").
  • No client-address limiter on the drive surface. The agent API's per-agent rate limit (one request a second sustained, burst 60) keys on the resolved agent, not the client address: behind the platform's relay socket every request can share one address, and an address-keyed limiter would let one flood take out every real agent at once (§15.17).
  • No passkeys ruling of its own. Unlike Docs §8.1, the spec states no instance-local-passkey decision. [inferred — confirm].
  • Chat is never stored. A chat message fans out to admitted peers and renders client-side; not replayed to a peer who joins or resumes later, gone with the tab (ruling 8, §6).
  • No recurring meetings, Calendar integration, recording, attendance records, reactions, dial-in, captions, multi-host signalling, push-to-talk, or virtual backgrounds, and no way to deny a knock — a guest who isn't admitted simply waits or leaves (§11).
  • No native client sign-in method of its own — a native client authenticates through the same Home/local sign-in the browser uses, handed off through a five-minute, one-use authorization; no separate bearer or token scheme for native apps (§8.4's 2026-09-14 amendment, native/README.md). No attendance claim, ever: §0.3 says Calls does not record who was in a call or for how long; an earlier revision implied one and the spec dropped the implication rather than building the model. The quality reports of §15.26 show that a call under a random tag happened between two times with so many clients in it, for seven days; never which meeting or who.

---

See also: the design spec, README.md, AGENTS.md, and the slice records under docs/superpowers/reviews/.