oficina / meet Public

Move the docs and migration namespace to Calls

The migration namespace becomes "calls". Applied migrations are recorded
under it, so this would orphan an existing database — but the CARLOS app
is being recreated with a fresh one, and rastrillo's migration check
confirms models and migrations still agree.

Living docs take the new name, including the carlos app in the deploy
instructions and the release artifact, which the Makefile's APP variable
now produces as releases/calls-linux-arm64.

Dated records are left as written. The superpowers plans, reviews and the
2026-09-07 design spec describe what was decided and done at the time, and
rewriting them would make the history claim something it did not say. The
design spec instead carries a dated rename note in the same style as its
existing supersession notes, so the spec cannot quietly drift into
disagreeing with the code. PRODUCT.md's Brand Commitments row now states
the current name and keeps ruling 2's choice of oficina/meet as the record
of that decision rather than overwriting it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 3f981e3a1c782500df1f294fed3fd7123958abed parent 252c200
11 files changed, +74 −63
  • AGENTS.md +4 −4
  • PRODUCT.md +17 −15
  • README.md +21 −21
  • design/oficina-icons/INTEGRATION.md +4 −4
  • design/oficina-icons/README.md +2 −2
  • docs/superpowers/specs/2026-09-07-meet-design.md +9 −0
  • internal/calls/migrations.go +1 −1
  • native/DESIGN.md +3 −3
  • native/README.md +9 −9
  • native/VERIFICATION.md +3 −3
  • native/architecture.md +1 −1

CI failed — run details

diff --git a/AGENTS.md b/AGENTS.md
index ba89001..d658e1c 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,4 +1,4 @@
-# meet
+# calls
A [rastrillo](https://github.com/rastrilloorg/rastrillo) app. Read the
framework's own SKILL.md (repo root, or in the module cache) before
@@ -86,10 +86,10 @@ by the framework, outside app middleware.
## Deploying
`make release VERSION=<sha>` builds and stamps the artifact; `carlos
-deploy --app meet --account oficina --channel edge --version <sha>
---target linux-arm64 releases/meet-linux-arm64` ships and promotes it,
+deploy --app calls --account oficina --channel edge --version <sha>
+--target linux-arm64 releases/calls-linux-arm64` ships and promotes it,
waiting until `/api/version` serves it — but only once `carlos apps
-build-probe --app meet --account oficina /api/version` has been run
+build-probe --app calls --account oficina /api/version` has been run
for the app (set on the flagship app since 2026-09-09); a new app or
account needs that first, or the wait watches `X-Carlos-Version`
instead, which can report the version adopted before the process has
diff --git a/PRODUCT.md b/PRODUCT.md
index b2616f9..8bcf8f6 100644
--- a/PRODUCT.md
+++ b/PRODUCT.md
@@ -11,7 +11,7 @@
> 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 Meet spec's §1; a
+> be corrected, not trusted. A bare "ruling N" is the Calls spec's §1; a
> doctrine ruling is always written "suite ruling N".
## Platform
@@ -41,7 +41,7 @@ no target size.
## Product Purpose
-Meet is **video calling for one Oficina team**: a member makes a
+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
@@ -53,7 +53,7 @@ a captured-logger test, not merely asserted (§0.1).
## Positioning
-1. **The claim is made per process, not once** (§0.1): Meet's own
+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
@@ -119,7 +119,7 @@ deliberately not here" below for the full, cited list.
**Binding technical constraints:**
-- **Media never touches Meet's own process** (§0.1); no handler accepts
+- **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`).
@@ -139,17 +139,19 @@ deliberately not here" below for the full, cited list.
## Brand Commitments
-- **Name:** Meet, `amadan.net/oficina/meet`, first served at
- `calls.oficina.works` (preamble; ruling 2 chose `oficina/meet` over
- `oficina/conferencia`). Built beside Docs, Calendar, Slides and the
- suite doctrine, consuming a decision made there rather than restating
- it (preamble, §0.2).
+- **Name:** Calls, `amadan.net/oficina/calls`, served at
+ `calls.oficina.works`. Renamed from Meet 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 Meet's contribution to Estilo** — "one
+- **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
@@ -217,9 +219,9 @@ 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 Meet
+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 Meet,
+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
@@ -231,8 +233,8 @@ and this file does not assume it does.
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 Meet's own.** ICE servers come from the
- platform relay, present or not at all — never a server Meet names
+- **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
@@ -258,7 +260,7 @@ and this file does not assume it does.
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 Meet does not record who was
+ **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.
diff --git a/README.md b/README.md
index e035d72..de3ee1e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-# Meet
+# Calls
-Meet is video calling for one team. A member makes a meeting, now or
+Calls 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
@@ -16,14 +16,14 @@ member's 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
+Calls 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, which the holding
-screen states plainly above the join button: "This team's Meet has no
+screen states plainly above the join button: "This team's Calls has no
relay yet. Calls usually connect only between people on the same
network." Enabling or changing the relay restarts the instance. When
the relay is in the path it forwards DTLS-SRTP packets encrypted
-between the browsers, so it carries bytes it cannot read; Meet's own
+between the browsers, so it carries bytes it cannot read; Calls' own
process never receives a media packet at all. With the relay on, a
call that still fails says "could not connect, even through the
relay" and offers retry; it does not diagnose the network. One known
@@ -106,14 +106,14 @@ against what it is meant to be running.
## Deploying
-Meet deploys as a CARLOS unit route. Build the artifact first — `make
-release VERSION=<sha>` produces `releases/meet-linux-arm64`, stamped
+Calls deploys as a CARLOS unit route. Build the artifact first — `make
+release VERSION=<sha>` produces `releases/calls-linux-arm64`, stamped
with the version `/api/version` will report (`strings -a
-releases/meet-linux-arm64 | grep -cx <sha>` confirms the stamp) — then
-deploy it: `carlos deploy --app meet --account oficina --channel edge
---version <sha> --target linux-arm64 releases/meet-linux-arm64`,
+releases/calls-linux-arm64 | grep -cx <sha>` confirms the stamp) — then
+deploy it: `carlos deploy --app calls --account oficina --channel edge
+--version <sha> --target linux-arm64 releases/calls-linux-arm64`,
which waits until `/api/version` reports it — but only once a build
-probe is configured for the app: `carlos apps build-probe --app meet
+probe is configured for the app: `carlos apps build-probe --app calls
--account oficina /api/version`, set on the flagship app since
2026-09-09. A new app or account needs that command run once before
the wait means anything; without it `carlos deploy` watches
@@ -134,14 +134,14 @@ platform's `CARLOS_SMTP_*`. Two are optional, each with its own
default rather than a refusal: `CALLS_ZONE` (an IANA zone, defaulting
to UTC when unset) and `CARLOS_RELAY` (empty means no relay, §5.5 —
only a *malformed* value refuses startup), delivered by `carlos relay
-enable --app meet` rather than set by hand. Secrets —
+enable --app calls` rather than set by hand. Secrets —
`CALLS_INSTANCE_KEY`, `CALLS_DEK` and `CALLS_SMTP_PASS` — go through
`carlos secrets`; the rest go through `carlos env`. Mail reads
`CALLS_SMTP_*` with `CARLOS_SMTP_*` as a per-variable fallback; the
platform supplies a sender too
(`CARLOS_SMTP_FROM`), which `CALLS_SMTP_FROM` can optionally override,
so `carlos email enable` alone is enough to send mail. `carlos relay
-enable --app meet` turns on the platform relay. Every deploy, and
+enable --app calls` turns on the platform relay. Every deploy, and
every relay change, restarts the instance and drops every live call —
no drain exists, so deploy outside meeting hours. Migrations apply
once each at boot (`msg=migrate` in the log) and are never re-run; a
@@ -150,25 +150,25 @@ fails at boot rather than silently diverging. The deploy wait can time
out before the hand-over while the instance then serves the new
version a minute later — check `/api/version` before retrying.
-Canary a build on its own host: `carlos canary --app meet --name
-slice2` composed `slice2.meet.bds.oncarlos.com`, and the console
+Canary a build on its own host: `carlos canary --app calls --name
+slice2` composed `slice2.calls.bds.oncarlos.com`, and the console
refused it ("invalid host, an instance host is one DNS label followed
by .bds.oncarlos.com") — as recorded on 2026-09-10 in platform
discussion #124, open as of that record. The recipe actually used:
-`carlos instances create --app meet --account oficina --host
-slice2-meet.bds.oncarlos.com --channel canary/slice2 --environment
+`carlos instances create --app calls --account oficina --host
+slice2-calls.bds.oncarlos.com --channel canary/slice2 --environment
slice2`. The `slice2` environment bundle must already exist, created
separately, carrying `CALLS_ORIGIN` for the canary host; without it
sign-in refuses on the canary while GETs look healthy. Then `carlos
-deploy --account oficina --app meet --channel canary/slice2 --host
-slice2-meet.bds.oncarlos.com --version <sha>
-releases/meet-linux-arm64`.
+deploy --account oficina --app calls --channel canary/slice2 --host
+slice2-calls.bds.oncarlos.com --version <sha>
+releases/calls-linux-arm64`.
## 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
+in `docs/superpowers/reviews/`. `PRODUCT.md` covers what Calls is for
and what it deliberately leaves out; `AGENTS.md` covers the
conventions the code is held to. Spec §15.18 is the disposition of
record for what slice 6 delivered, deferred (the acknowledgements
diff --git a/design/oficina-icons/INTEGRATION.md b/design/oficina-icons/INTEGRATION.md
index 1b27ee9..a71f019 100644
--- a/design/oficina-icons/INTEGRATION.md
+++ b/design/oficina-icons/INTEGRATION.md
@@ -2,7 +2,7 @@
The approved set is wired into browser favicons (SVG and PNG), Apple touch
icons and visible app branding for Oficina Home, Docs, Sheets, Slides,
-Calendar, Meet and Memoria. Home's six app rows have the matching icons;
+Calendar, Calls and Memoria. Home's six app rows have the matching icons;
Mail and Files keep their existing entries because no artwork was approved
for them. Product names remain visible and the adjacent images have empty
alt text. All assets are served locally, without JavaScript or a CDN.
@@ -32,7 +32,7 @@ uses its legacy page; the signed-in app listing is present on the paired Home
preview deployment. Changing Home's identity/directory topology is separate
from deploying these assets.
-Meet's icons ship with `codex/iphone-and-mirrored-preview`, including the Mac
+Calls' icons ship with `codex/iphone-and-mirrored-preview`, including the Mac
Dock/Finder resources, iPhone asset catalog and packaged Lucide licenses.
The Mac and signed iPhone builds are installed locally. See
`native/VERIFICATION.md` for native test coverage and acceptance limits.
@@ -45,8 +45,8 @@ The Mac and signed iPhone builds are installed locally. See
disabled. All branding images loaded, with no horizontal overflow or
missing requests. These are local visual checks, not deployed-canary
acceptance. Evidence: `/private/tmp/oficina-icons-evidence/<app>/`.
-- Meet, Calendar, Slides and Memoria `make ci` passed; Estilo `make test`
- passed. Meet and Calendar's real-browser gates passed.
+- Calls, Calendar, Slides and Memoria `make ci` passed; Estilo `make test`
+ passed. Calls and Calendar's real-browser gates passed.
- Docs' Go packages passed after adjusting the existing label test for the
decorative image. Its release test needs GNU realpath on PATH and a short
TMPDIR for macOS Unix-socket limits; it passed with both supplied.
diff --git a/design/oficina-icons/README.md b/design/oficina-icons/README.md
index 2ce163e..8e81dd6 100644
--- a/design/oficina-icons/README.md
+++ b/design/oficina-icons/README.md
@@ -14,7 +14,7 @@ Open `preview.png` or `preview.svg` to compare the family and small sizes.
| Sheets | table | `#168049` |
| Slides | presentation | `#C45B16` |
| Calendar | calendar-days | `#CB3F50` |
-| Meet | video | `#087F8C` |
+| Calls | video | `#087F8C` |
| Memoria | book-search | `#7C3FC8` |
`svg/` contains opaque square 1024-unit masters. `png/` contains 16, 32,
@@ -23,7 +23,7 @@ provide rounded corners; the rounded tiles in the preview are illustrative.
The Lucide canvas occupies 70% of each tile, with the original 2-unit white
stroke. Use visible product names alongside launcher icons.
-Edit `icons.json`, then from the Meet repository root run:
+Edit `icons.json`, then from the Calls repository root run:
```sh
node design/oficina-icons/generate.mjs --render
diff --git a/docs/superpowers/specs/2026-09-07-meet-design.md b/docs/superpowers/specs/2026-09-07-meet-design.md
index 336ce60..67a4798 100644
--- a/docs/superpowers/specs/2026-09-07-meet-design.md
+++ b/docs/superpowers/specs/2026-09-07-meet-design.md
@@ -1,5 +1,14 @@
# 🤖 Meet — design
+**2026-09-16 rename:** the app is now **Calls**, module
+`amadan.net/oficina/calls`, served at `calls.oficina.works`. Every "Meet"
+below should be read as "Calls"; the body is left as written because it
+records what was designed on 2026-09-07, and ruling 2's choice of
+`oficina/meet` stands as the record of that decision. The route grammar is
+unchanged — `/m/{sqid}` and `/meetings/{sqid}` keep their paths, and
+"meeting" remains the domain noun. `PRODUCT.md`'s Brand Commitments hold
+the current name.
+
**2026-09-12 sharing update:** Paul's request for Share in the meeting view
supersedes the invitation-token show-once rule below (§3.1 / ruling 16).
Members may retrieve a current invitation via `POST /m/{sqid}/share`.
diff --git a/internal/calls/migrations.go b/internal/calls/migrations.go
index 502f68b..23bdaa7 100644
--- a/internal/calls/migrations.go
+++ b/internal/calls/migrations.go
@@ -23,7 +23,7 @@ var migrationFS embed.FS
// model, or `rastrillo migration new <name>` to write one by hand.
// Migrations apply at boot and are never re-run or reversed: never
// edit one that has shipped, add a new one instead.
-var Schema = migrate.MustFromFS(migrationFS, "meet")
+var Schema = migrate.MustFromFS(migrationFS, "calls")
// BootSchema is everything applied at boot, in order — this app's own
// Schema plus every framework subsystem's — and it is what App() below
diff --git a/native/DESIGN.md b/native/DESIGN.md
index 59ea5c9..39b5a43 100644
--- a/native/DESIGN.md
+++ b/native/DESIGN.md
@@ -1,6 +1,6 @@
-# Meet native design
+# Calls native design
-The first Oficina native design pass uses Meet's existing teal identity,
+The first Oficina native design pass uses Calls' existing teal identity,
quiet surfaces, clear type hierarchy and native controls. Apple's communication
and productivity apps are references for interaction quality; Oficina retains
its own artwork, wording and colour. Mac and phone share the joining ceremony
@@ -20,7 +20,7 @@ while their call layouts suit the available space.
- Video names sit on an opaque dark label over the image. Microphone and camera
actions use both text and changing symbols, so colour is never the only cue.
- `MeetAppearance` and `CallControl` live in MeetKit for both Apple clients.
- These are Meet presentation choices. General native infrastructure belongs
+ These are Calls presentation choices. General native infrastructure belongs
in Rastrillo Native; Oficina's shared visual components belong in Estilo as
subsequent apps establish what they need in common.
diff --git a/native/README.md b/native/README.md
index da39c14..c7c6b7a 100644
--- a/native/README.md
+++ b/native/README.md
@@ -1,6 +1,6 @@
-# Meet native apps
+# Calls native apps
-The SwiftUI Mac and iPhone apps use the same Meet server and shared Go core.
+The SwiftUI Mac and iPhone apps use the same Calls server and shared Go core.
## Build and run
@@ -8,12 +8,12 @@ Requires macOS 14+, Xcode, Go 1.26 and network access for pinned dependencies.
```sh
make native-mac
-open native/build/Meet.app
+open native/build/Calls.app
```
-Paste a meeting or invitation URL. Meet opens your default browser for the
-existing Home/Meet sign-in. Open the emailed link normally, compare the code in
-the browser with the app, and confirm **Sign in to Meet app**. The app continues
+Paste a meeting or invitation URL. Calls opens your default browser for the
+existing Home/Calls sign-in. Open the emailed link normally, compare the code in
+the browser with the app, and confirm **Sign in to Calls app**. The app continues
automatically; choose **Join meeting** and allow camera/microphone access.
Creating and ending meetings, and replacing invitations, stay on the web for this milestone.
@@ -50,7 +50,7 @@ The iPhone target, device builds and Safari tests are described in
platform capture/UI portions are separate from the Go protocol implementation.
- `native/apple/Sources/MeetMac`: SwiftUI app and system-browser authentication host.
- `native/apple/Sources/MeetInterop`: a separate synthetic-media test executable;
- it is not bundled with Meet.app.
+ it is not bundled with Calls.app.
Go Mobile's cgo requirement is isolated in `native/go.mod` and the native build
script. The existing server continues to build with `CGO_ENABLED=0`. WebRTC is
@@ -94,8 +94,8 @@ See [VERIFICATION.md](VERIFICATION.md) for the completed gate record and accepta
### App artwork
The iPhone asset catalog and Mac application resource use the approved Oficina
-Meet icon. Both are generated copies of Estilo's `brand/png/meet-1024.png`;
-update them with `python3 brand/distribute.py meet /path/to/meet` from Estilo.
+Calls icon. Both are generated copies of Estilo's `brand/png/calls-1024.png`;
+update them with `python3 brand/distribute.py calls /path/to/calls` from Estilo.
The Mac derives `MacIcon.png` with rounded corners and transparent padding using
`native/scripts/generate-mac-icon.swift`. Its Finder ICNS and runtime Dock icon
both use that Mac variant; the square master remains unchanged. The Lucide
diff --git a/native/VERIFICATION.md b/native/VERIFICATION.md
index 88c52c5..42c82fb 100644
--- a/native/VERIFICATION.md
+++ b/native/VERIFICATION.md
@@ -10,7 +10,7 @@ Branch: `codex/iphone-and-mirrored-preview`, based on `86ed9f3`.
on iOS 26.5 Simulator (154 seconds). Peers retain media through stream renewal
and leave cleanly. Simulator media uses synthetic video and disables audio.
- Mac app builds, its ad hoc signature verifies, and it is installed and
- relaunched at `/Applications/Meet.app` with the approved icon and license.
+ relaunched at `/Applications/Calls.app` with the approved icon and license.
- iPhone development build signs successfully with the personal development
team and is installed on Paul's iPhone 16 Pro. Initial launch was blocked by
the phone's lock screen; physical launch/permissions and audible audio await
@@ -43,7 +43,7 @@ to the newer `origin/integrate/home-sso-release` at `eee686a`. Working branch:
| `CGO_ENABLED=0 make browser` | Passed all 31 Chromium scenarios; 541 seconds for the browser suite |
| `make native-test` | Passed shared core, bridge and core race tests |
| `make native-mac` | Built the local Mac app with a macOS 14 deployment target |
-| `codesign --verify --deep --strict native/build/Meet.app` | Passed for the ad hoc development signature |
+| `codesign --verify --deep --strict native/build/Calls.app` | Passed for the ad hoc development signature |
| `TestNativeMacCallsBrowser` | Passed member and guest cases; final run 26.49 seconds |
| App launch and opening-window inspection | Passed |
@@ -53,7 +53,7 @@ media counters after repeated three-second stream renewals, preservation of the
native participation ID, and removal of the browser's remote tile after the
native client left. It uses a synthetic native camera implemented only in the
separate `MeetInterop` executable, Chromium's fake media device, and real
-magic-link sessions on an isolated local Meet server. Audio traffic counters do
+magic-link sessions on an isolated local Calls server. Audio traffic counters do
not prove audible microphone/speaker quality.
`TestNativeCoreUsesHomeSessionAndResumesCall` separately runs the shared Go
diff --git a/native/architecture.md b/native/architecture.md
index 91d4b31..765c59f 100644
--- a/native/architecture.md
+++ b/native/architecture.md
@@ -22,5 +22,5 @@ before minting a separate normal framework session. Home subject, method and
authentication time are preserved. A browser URL contains neither the verifier
nor a session token. Request/exchange honor no ambient cookie, forbid redirects
in the client and expose no CORS access. Cancellation stops the app's polling;
-the unconsumed server request expires. This is a Meet session handoff, not an
+the unconsumed server request expires. This is a Calls session handoff, not an
OAuth authorization server or a replacement for Home assertion verification.