oficina / meet Public

docs: Codex round 1 fixes for slice 6 (S6-1..S6-13)

Applies Codex round 1's thirteen findings against README.md,
AGENTS.md, PRODUCT.md and the spec, plus a review-record update.

S6-1: README's Deploying section enumerates every deploy setting,
which five refuse startup on and which two default instead
(MEET_ZONE to UTC, CARLOS_RELAY to no relay).
S6-2: README and AGENTS.md state the `carlos apps build-probe`
prerequisite the deploy-wait guarantee depends on, and the
X-Carlos-Version fallback when it is absent.
S6-3: README, PRODUCT.md and spec §9 name the chat panel and the
live admission controls as script-gated alongside browser media
participation; §15.18 notes the widening.
S6-4: README and PRODUCT.md say `CGO_ENABLED=0 make ci` and name all
three CGO_ENABLED=1 exceptions (make race, native-test's meetcore
sub-step, the native Apple bindings), matching AGENTS.md.
S6-5: README says the platform supplies CARLOS_SMTP_FROM too, which
MEET_SMTP_FROM optionally overrides.
S6-6: spec §0.2's rows 3, 6, 9 and 15 and the two paragraphs below
the table cite section/ruling only now, dropping the doctrine
restatements; PRODUCT.md's actor sentence likewise; ruling 16's
provenance kept.
S6-7: spec §8.4 gains a 2026-09-14 amendment recording the shipped
native milestone and its browser-approval handoff; PRODUCT.md's two
native-client citations point at it.
S6-8: README's relay paragraph quotes join.html's same-network
floor sentence verbatim.
S6-9: PRODUCT.md says "five destructive confirmation pairs"; spec
§9 says "every confirm page (five)".
S6-10: README distinguishes a legacy meeting's first Share (mints a
new recoverable invitation) from every retrieval after.
S6-11: README and PRODUCT.md describe the agent rate limit as one
request a second sustained with a burst of 60, not a flat 60/minute.
S6-12: README's canary `instances create` carries --app/--account
and states the environment bundle must already exist.
S6-13: README and PRODUCT.md link to spec §15.18 as the disposition
of record; the platform-124, no-Estilo-tag and credits-branch-canary
claims are attributed to dated records rather than presented as
independently verified.

Also adds the Codex round 1 disposition block to
docs/superpowers/reviews/2026-09-14-slice-6-record.md, replacing
CODEX_ROUNDS_PLACEHOLDER (a fresh placeholder follows for later
rounds), and resolves that file's now-stale carried item on §9's
confirm-page count.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CzvnuKhLzudvq7jZ7SvVt2
Paul Campbell pushed by paul@keymail.dev 2a6eee4546babdaa1975aebdbff91055ef22e018 parent c22cae7
5 files changed, +371 −106
  • AGENTS.md +10 −5
  • PRODUCT.md +52 −36
  • README.md +77 −44
  • docs/superpowers/reviews/2026-09-14-slice-6-record.md +188 −0
  • docs/superpowers/specs/2026-09-07-meet-design.md +44 −21

CI passed — run details

diff --git a/AGENTS.md b/AGENTS.md
index 2617dbb..b7ab6b0 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -85,11 +85,16 @@ by the framework, outside app middleware.
`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, promotes and
-waits until `/api/version` serves it. A migration applied under an
-earlier filename fails at boot; otherwise migrations never re-run.
-Every deploy, and every relay config change, restarts the instance and
-drops live calls — no drain exists. The wait can time out before
+--target linux-arm64 releases/meet-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
+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
+actually changed. A migration applied under an earlier filename fails
+at boot; otherwise migrations never re-run. Every deploy, and every
+relay config change, restarts the instance and drops live calls — no
+drain exists. The wait can time out before
hand-over — check `/api/version` before retrying. See the README's
Deploying section for the canary recipe.
diff --git a/PRODUCT.md b/PRODUCT.md
index 10dfc17..fffc52e 100644
--- a/PRODUCT.md
+++ b/PRODUCT.md
@@ -17,7 +17,7 @@
## Platform
Web, plus native Mac and iPhone/iPad clients over the same server
-contracts (spec §8.4, `native/README.md`).
+contracts (spec §8.4's 2026-09-14 amendment, `native/README.md`).
## Users
@@ -75,17 +75,22 @@ a captured-logger test, not merely asserted (§0.1).
- **Routes today** (`internal/meet/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); four confirm/POST pairs; 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 one named exception: browser media participation.**
- 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
+ (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 same exception;
+ 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
@@ -122,10 +127,13 @@ deliberately not here" below for the full, cited list.
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).
-- **`make race`** for any change to `internal/meet/hub` or the stream —
- the one place `CGO_ENABLED=1` is allowed, for a test binary only.
- **`make browser`** needs UDP, which the Claude Code bash sandbox
- blocks (`AGENTS.md`).
+- **`CGO_ENABLED=0 make ci` is the server's cgo-free gate; three things
+ run under `CGO_ENABLED=1`, none of them shipped.** `make race`, for
+ any change to `internal/meet/hub` or the stream; `make native-test`'s
+ own `meetcore` race sub-step; and the native Apple bindings
+ (`native/go.mod`), the one place real cgo bridges Go to Objective-C
+ (`AGENTS.md`). **`make browser`** needs UDP, which the Claude Code
+ bash sandbox blocks (`AGENTS.md`).
## Brand Commitments
@@ -135,10 +143,10 @@ deliberately not here" below for the full, cited list.
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. No tag exists (`git ls-remote --tags` on `oficina/estilo`
- was empty on 2026-09-14); consumed at a pseudo-version, already
- adopted by the Home integration on main. **[inferred — confirm]** the
- exact commit at any later date.
+ 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
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).
@@ -162,7 +170,10 @@ deliberately not here" below for the full, cited list.
testimonials, benchmarks, pricing, usage numbers, launch date, press,
or a production promotion from this slice — edge
(`meet.oficina.works`) is promoted by hand by Paul, separately from
- documentation (slice 6 plan, "What slice 6 was").
+ 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
@@ -185,7 +196,7 @@ deliberately not here" below for the full, cited list.
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. **Every write names its real actor**, `person:<id>` or `agent:<id>`
+5. **Actors are `person:<id>` or `agent:<id>`, never fabricated**
(§7.2, doctrine ruling 9).
## Accessibility & Inclusion
@@ -197,11 +208,12 @@ 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**, and it is exact: reaching a camera and
-another browser needs script; 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).
+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 Meet
spec or `AGENTS.md`. **[inferred — confirm]**: Docs states "WCAG 2.2 AA,
@@ -210,11 +222,13 @@ and this file does not assume it does.
## What is deliberately not here
-- **Scriptless media** — the one named exception to the scriptless
- floor: reaching a camera and another browser needs script; 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 same exception in the same words).
+- **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 Meet's own.** ICE servers come from the
platform relay, present or not at all — never a server Meet names
itself (suite ruling 6, §5.2, §5.5).
@@ -223,10 +237,11 @@ and this file does not assume it does.
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 (60/min) 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).
+ 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
@@ -239,7 +254,8 @@ and this file does not assume it does.
- **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, `native/README.md`).
+ 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
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 c8101f5..53753fb 100644
--- a/README.md
+++ b/README.md
@@ -8,16 +8,20 @@ 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, start time,
-standing, floor notice, the paragraph that says what needs script, and
-a member's navigation with scripts off (spec §9).
+the room — and, once a call exists, the room's two other script-only
+parts: the chat panel and the live admission queue with its Admit
+controls. Both pages still render their title, start time, standing,
+floor notice, the paragraph that says what needs script, and a
+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
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. When
+can find a working path straight between them, which the holding
+screen states plainly above the join button: "This team's Meet 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
process never receives a media packet at all. With the relay on, a
@@ -53,9 +57,12 @@ 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). A member can retrieve the current invitation
again from the holding screen or the room with Share (`POST
-/m/{sqid}/share`); replacing a link revokes every live one. Chat is
-fanned out live to admitted peers and never stored (spec §6). Screen
-share adds a second tile per sharer
+/m/{sqid}/share`). On a meeting whose only link predates the
+2026-09-12 sharing update, the first Share mints a new recoverable
+invitation alongside the old, still-valid one rather than opening it;
+every Share after that retrieves the same recoverable one. Replacing a
+link revokes every live one. 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).
@@ -69,8 +76,8 @@ 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).
+step. Requests are limited per agent to one a second sustained, with a
+burst of 60 (spec §8, §15.17).
## Native apps
@@ -81,17 +88,21 @@ the Mac app with `make native-mac`. See `native/README.md` and
## 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
+`CGO_ENABLED=0 make ci` (vet, gofmt, tests, migration check) is the
+one gate a runner and a push share; `ci` itself does not set the
+variable, so the runner and every push must. Three things ship or run
+under `CGO_ENABLED=1`, each isolated from the server: `make race`
+builds a server test binary, never a release, for any change to
+`internal/meet/hub` or the signalling stream; `make native-test`'s own
+`meetcore` race sub-step does the same for the shared Go core; and the
+native Mac and iPhone/iPad bindings under `native/` bridge Go to
+Objective-C with real cgo, isolated in `native/go.mod` and built with
+`make native-mac`. `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.
+call then fails with `frames` stuck at 0. `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
@@ -101,36 +112,56 @@ 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`,
-checked against the build probe on `/api/version`. `--account` is a
+which waits until `/api/version` reports it — but only once a build
+probe is configured for the app: `carlos apps build-probe --app meet
+--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
+`X-Carlos-Version` instead, which can report the new version adopted
+before the running process has actually changed. `--account` is a
global flag; `carlos ship` uploads only, while `carlos deploy` is ship,
-promote and wait until the URL serves the version (its own help text).
-Building for your own architecture and shipping that uploads fine and
-fails to exec on the instance.
-
-Secrets — `MEET_INSTANCE_KEY`, `MEET_DEK` (32 base64 bytes) and
-`MEET_SMTP_PASS` — go through `carlos secrets`; the rest go through
-`carlos env`. Mail reads `MEET_SMTP_*` with `CARLOS_SMTP_*` as a
-per-variable fallback, so `carlos email enable` covers everything but
-`MEET_SMTP_FROM`. `carlos relay enable --app meet` 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 database that
-already applied a migration file under an earlier name 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.
+promote and wait (its own help text). Building for your own
+architecture and shipping that uploads fine and fails to exec on the
+instance.
+
+These are the settings a deploy needs (`config.go`, `standing.go`).
+Five refuse startup when empty outside `-env development`:
+`MEET_ORIGIN` (the external origin, scheme included);
+`MEET_INSTANCE_KEY`; `MEET_DEK` (base64 of exactly 32 decoded bytes,
+not 32 base64 characters); `MEET_ALLOWED_ADDRESSES` (comma-separated,
+non-empty — this is the team); and mail, `MEET_SMTP_*` or the
+platform's `CARLOS_SMTP_*`. Two are optional, each with its own
+default rather than a refusal: `MEET_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 —
+`MEET_INSTANCE_KEY`, `MEET_DEK` and `MEET_SMTP_PASS` — go through
+`carlos secrets`; the rest go through `carlos env`. Mail reads
+`MEET_SMTP_*` with `CARLOS_SMTP_*` as a per-variable fallback; the
+platform supplies a sender too
+(`CARLOS_SMTP_FROM`), which `MEET_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
+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
+database that already applied a migration file under an earlier name
+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
refused it ("invalid host, an instance host is one DNS label followed
-by .bds.oncarlos.com" — 2026-09-10, filed as platform discussion #124,
-still open). The recipe actually used: `carlos instances create --host
+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
-slice2` — the environment bundle carries `MEET_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>
+slice2`. The `slice2` environment bundle must already exist, created
+separately, carrying `MEET_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`.
## Where things are written down
@@ -139,4 +170,6 @@ 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.
+conventions the code is held to. Spec §15.18 is the disposition of
+record for what slice 6 delivered, deferred (the acknowledgements
+page) and declined (the Estilo theme pin, the production promotion).
diff --git a/docs/superpowers/reviews/2026-09-14-slice-6-record.md b/docs/superpowers/reviews/2026-09-14-slice-6-record.md
new file mode 100644
index 0000000..93f82b3
--- /dev/null
+++ b/docs/superpowers/reviews/2026-09-14-slice-6-record.md
@@ -0,0 +1,188 @@
+# Meet slice 6 — the record
+
+Branch `slice/6-deploy`, `9225ec2..HEAD` (this commit; started on main
+`9225ec2`, tag `v0.1.0`). Spec: `docs/superpowers/specs/2026-09-07-meet-design.md`,
+revision 9 (§15.18 carries this slice's dispositions). Plan:
+`docs/superpowers/plans/2026-09-14-meet-slice-6-deploy.md`.
+
+Slice 6 is the programme's closing slice (spec §12 item 6) and is
+documentation only: `README.md`, `PRODUCT.md`, a Deploying section in
+`AGENTS.md`, the *Consumed suite rulings* commit (`fa875c7`, the hash
+suite Appendix A.6 points at) and the spec amendments that commit and
+the review made. No file under `internal/`, `cmd/`, `native/`,
+`meetcore/` or `protocol/` changed. The ledger is
+`.superpowers/sdd/2026-09-14-meet-slice-6-deploy/` (gitignored; this
+file is its substance).
+
+---
+
+## 1. Rulings and decisions
+
+- **The slice was re-scoped against main as it is on 2026-09-14, not
+ as the programme imagined it on 2026-09-09.** Between slice 5
+ (`a283c53`, 2026-09-11) and this slice, other sessions landed Home
+ sign-in (§7.1.1), the shared Estilo day theme and brand, the
+ invitation `Share` route (the 2026-09-12 amendment), and the native
+ Mac, iPhone and iPad apps. The plan's "What slice 6 was, and what it
+ is now" table is the disposition of each programme item; §12 item 6
+ and §15.18 restate it in the spec.
+- **The acknowledgements page is not built here.** `oficina/meet`
+ discussion 10, branch `feat-open-source-credits` (`117b6e4`,
+ `bbc126e`), carries a shared Estilo credits page with a runtime
+ dependency inventory and its freshness gate, Fable-approved and
+ verified live on the overnight canary. Building a second one would
+ be the duplication the programme forbids.
+- **The Estilo theme pin.** The programme's condition was a tagged
+ release; `git ls-remote --tags` on `oficina/estilo` is empty on
+ 2026-09-14. The theme is nevertheless adopted on main at an indirect
+ pseudo-version (`go.mod`), brought in by the Home integration.
+ Recorded as: condition unmet, adoption done by another route,
+ nothing changed here.
+- **No deploy from this slice.** The change is documentation. Edge
+ (`meet.oficina.works`) is promoted by hand by Paul (`651cff2` on
+ 2026-09-12), with discussion 14's web UI work queued behind a live
+ check. A redeploy would drop live calls for nothing; a queued
+ promotion is never announced as live (programme §5). The domain was
+ attached before this slice.
+- **Copy review is waived** for this round by Paul's steering on
+ `oficina/suite` discussion 5. README and PRODUCT.md prose is
+ catalogued here (§3) rather than reviewed.
+- **Writers did not commit.** Three writers worked concurrently in one
+ worktree on disjoint files; the controller committed each set. The
+ index is the shared resource, not the files.
+- **Every behavioural claim is verified against the code on the
+ branch and cites its source.** The whole-branch review's finding was
+ that the writers verified the documents against the code but not the
+ code's documents against the documents: four spec sentences on main
+ asserted things about "the README" that the README, once it existed,
+ did not say (§0.1/§5.6's encryption sentence, §5.5's TCP-443 cause
+ and "first paragraph", §3.2's residue). All four now hold, and the
+ fix wave swept every spec sentence naming README, AGENTS.md or
+ PRODUCT.md (twelve remaining, all true).
+- **The two meanings of "floor".** §5.5's floor is "no relay"; §9's is
+ the scriptless floor. §12 item 6 now says which goes where (the
+ scriptless sentence in the README's first paragraph, the relay
+ paragraph carrying §5.5's sentence second); §15.18 notes the two
+ senses.
+- **Platform facts stated from this project's own deploys**, not from
+ the platform source: `carlos canary` composed a host the console
+ refused (platform discussion 124, open); the recipe used is
+ `carlos instances create --host <name>-meet.bds.oncarlos.com
+ --channel canary/<name> --environment <name>` then `carlos deploy
+ --channel …`, with the environment bundle mandatory because a canary
+ without one serves `MEET_ORIGIN` for the main host and refuses
+ sign-in while GETs look healthy. The release command is `carlos
+ deploy --app meet --account oficina --channel edge --version <sha>
+ --target linux-arm64 releases/meet-linux-arm64` after `make release
+ VERSION=<sha>`; the deploy wait can time out before the hand-over
+ while the instance serves the new version a minute later.
+- **Ruling 16** stays cited as on the doctrine's
+ `worktree-worktree-token-at-rest` branch, not doctrine main (whose
+ rulings run 1 to 15 at `1ac4323`, revision 8, confirmed current by
+ `ls-remote` on 2026-09-14), as amended by the 2026-09-12 sharing
+ update for invitation tokens; agent credentials remain hash-only and
+ shown once.
+
+---
+
+## 2. Per-task review dispositions
+
+Three writing tasks (Sonnet) in parallel, then one whole-branch review
+(Opus) and one fix wave, then Codex rounds.
+
+- **Task 1, README and AGENTS.md** (`93f1c2e`): 106 lines, the two
+ paragraphs first. Flagged and acted on: spec §11 still listed a
+ native client as not built (`aa9b227`). Flagged and initially left,
+ then closed by the review: §5.5's "first paragraph" cross-reference;
+ `MEET_SMTP_PASS` as a secret.
+- **Task 2, PRODUCT.md** (`e684b97`): impeccable product schema 1 in
+ `oficina/docs`' shape with the unattended-writing disclaimer; "What
+ is deliberately not here" carries the scriptless exception spec §9
+ asked for.
+- **Task 3, the consumed-rulings commit** (`fa875c7`): §0.2's 4/12 row
+ consumes the home's assertions through §7.1.1 with the allowlist as
+ membership authority; a ruling-16 row as amended; §12 item 6
+ annotated; §15.18 added. Revision line left at 9, following what
+ §15.13 to §15.17 did.
+- **Whole-branch review** (`e684b97`): verdict **merge with named
+ fixes**, W6-1 to W6-15, all applied in `bf3b86b` and `c22cae7`
+ (reflow), plus the handoff's spec sweep, the two-floors
+ disambiguation, §15.11's stale "until slice 3, or until a drain
+ exists" (no drain exists; every deploy drops live calls) and
+ `token_sealed` added to §2.1's `meeting_links` columns. Roughly
+ sixty behavioural claims were traced to file and line and found
+ correct; the fifteen findings were the remainder.
+
+**Codex round 1** (independent, static, scope `9225ec2..c22cae7`):
+verdict **request changes** — thirteen findings, S6-1 through S6-13.
+All applied in one commit (`.superpowers/sdd/2026-09-14-meet-slice-6-deploy/fix-wave-report.md`,
+round-1 section):
+
+- **S6-1 — P2, deployment settings undocumented. Fixed:** README's Deploying section enumerates every required setting and which refuse startup outside `-env development`.
+- **S6-2 — P2, the deploy-wait guarantee had an unstated prerequisite. Fixed:** README and AGENTS.md now state the `carlos apps build-probe` prerequisite and the `X-Carlos-Version` fallback it stands in for.
+- **S6-3 — P2, the scriptless exception was narrower than shipped. Fixed:** README, PRODUCT.md and spec §9 now name the chat panel and the live admission controls as script-gated too, alongside browser media participation; §15.18 notes the widening.
+- **S6-4 — P2, the cgo claims didn't match the Makefile. Fixed:** README and PRODUCT.md now say `CGO_ENABLED=0 make ci` and name `make race`, `make native-test`'s `meetcore` sub-step, and the native Apple bindings as the three `CGO_ENABLED=1` cases, none of them shipped.
+- **S6-5 — P2, the SMTP fallback description was backwards. Fixed:** README now says the platform supplies `CARLOS_SMTP_FROM` too, which `MEET_SMTP_FROM` optionally overrides.
+- **S6-6 — P2, suite restatements remained under §0.2. Fixed:** rows 3, 6, 9 and 15 and the two paragraphs below the table cite section and ruling number only now; PRODUCT.md's actor sentence likewise; ruling 16's off-main provenance kept as before.
+- **S6-7 — P2, PRODUCT.md cited a section that denies native clients shipped. Fixed:** spec §8.4 gained a 2026-09-14 amendment recording the shipped milestone (`v0.1.0` at `9225ec2`) and the browser-approval handoff (`86ed9f3`); PRODUCT.md's two native-client citations now point at that amendment.
+- **S6-8 — P2, the shipped same-network sentence was missing from the README. Fixed:** the relay paragraph now quotes `join.html`'s floor sentence verbatim.
+- **S6-9 — P2, the route inventory undercounted confirmation pairs. Fixed:** PRODUCT.md now says "five destructive confirmation pairs"; spec §9 now says "every confirm page (five)".
+- **S6-10 — P3, Share's legacy behavior was omitted. Fixed:** README now distinguishes a legacy meeting's first Share (mints a new recoverable invitation alongside the old one) from every retrieval after.
+- **S6-11 — P3, "60 requests a minute" obscured the permitted burst. Fixed:** README and PRODUCT.md now say "one request a second sustained, with a burst of 60".
+- **S6-12 — P2, the canary creation command relied on undocumented app/account defaults. Fixed:** README's `instances create` now carries `--app meet --account oficina` and states the named environment bundle must already exist, created separately.
+- **S6-13 — P3, disposition coverage and external-state attribution were incomplete. Fixed:** README and PRODUCT.md now link to spec §15.18 as the disposition of record for the three deferred/declined items; the platform-124, no-Estilo-tag and credits-branch-canary claims are now attributed to dated records rather than presented as independently verified current state.
+
+CODEX_ROUNDS_PLACEHOLDER
+
+---
+
+## 3. Carried items, and where they go
+
+- **The acknowledgements page.** Discussion 10's branch
+ `feat-open-source-credits`, not yet on main. **Destination: that
+ branch's owner**; when it merges, the README's "Where things are
+ written down" section should gain the credits page's path (one
+ line).
+- **The Estilo theme tag.** No tagged release exists; the pseudo-version
+ pin stays until one does. **Destination: oficina/estilo.**
+- **The production promotion of main's head.** Edge serves `651cff2`;
+ main is at `9225ec2` plus this slice. `9225ec2` changed native code
+ only; this slice changes documents only. **Destination: Paul**, who
+ is promoting by hand while discussion 14's web UI work is queued.
+- **Unauthenticated flood control on `/api/v1`** (from slice 5).
+ **Destination: carlos/platform**, unchanged.
+- **Platform discussion 124** (`carlos canary` and the one-label host).
+ Open. The README carries the recipe that works. **Destination:
+ carlos/platform.**
+- **Spec §9's "four confirm pages" is five** (remove, takeover,
+ replace-link, end, revoke-agent). **Resolved in Codex round 1
+ (S6-9):** §9 now says "every confirm page (five)" and PRODUCT.md
+ says "five destructive confirmation pairs".
+- **Copy catalogue** (copy review waived): the README's and
+ PRODUCT.md's prose are the new user-facing text this slice adds;
+ neither is an app string. Nothing in `internal/meet/templates`
+ changed.
+- **The ledger's process note.** A writer's flag should become a task,
+ not a paragraph: two of the three task reports flagged the right
+ problems (W6-3, W6-6) in their "not corrected" sections and the
+ controller took them as recorded rather than as work.
+
+---
+
+## 4. Deploying this slice
+
+Nothing to deploy. No binary, migration, template, client or
+configuration changed. When main is next promoted, the README's
+Deploying section is the recipe, and the `carlos deploy` wait note in
+§1 applies.
+
+---
+
+## 5. The gates, and how to run them
+
+| Gate | Command | This slice |
+|---|---|---|
+| CI | `CGO_ENABLED=0 make ci` | Green on every commit of the branch; remote CI passed on `e684b97` and `c22cae7`. Markdown cannot fail it; it is run so the branch's head is known green. |
+| Race | `make race` | Not run: no change under `internal/meet/hub` or the stream. |
+| Browser | `make browser` (sandbox off) | Not run: no page, template or client file changed. The last run on a shipping head is slice 5's, 31 of 31 on `4f896c2`. |
+| Native | `make native-test` | Not run: nothing under `native/`, `meetcore/` or `protocol/` changed. |
diff --git a/docs/superpowers/specs/2026-09-07-meet-design.md b/docs/superpowers/specs/2026-09-07-meet-design.md
index 911f834..0523d0e 100644
--- a/docs/superpowers/specs/2026-09-07-meet-design.md
+++ b/docs/superpowers/specs/2026-09-07-meet-design.md
@@ -89,20 +89,18 @@ This app cites the suite sharing doctrine (`oficina/suite`,
| Ruling | Used for |
|---|---|
| 1, 5 | One instance per team; the first deploy is the **lone shape** (§7.1). |
-| 3 | Authorization is asked per request and never cached. Standing (member, guest, neither) is derived at each request and re-derived on every hub tick (§2.3). |
+| 3 | §2.3: standing (member, guest, neither) is derived at each request and re-derived on every hub tick. |
| 4, 12 | The home now mints assertions; Meet consumes them through `home/connect`'s bridge, resolving to the existing person and re-checking membership on every request, while the allowlist remains the membership authority throughout (§7.1.1). |
-| 6 | No product-wide egress. Meet never names a STUN or TURN server of its own; ICE servers come from the platform (§5.2) or there are none (§5.5). |
-| 9 | Every write names its real actor: a member, a guest who signed in, or an agent (§8). |
-| 15 | Three rungs plus a read-only link. A meeting link is a capability to obtain a **guest grant at sign-in**, the `granted` rung, and never a way into a room without a name (§3). Ruled for Meet on `oficina/suite` discussion 3, Paul, 2026-09-06. |
+| 6 | §5.2, §5.5: Meet never names a STUN or TURN server of its own; ICE servers come from the platform, or there are none. |
+| 9 | §8: a member, a guest who signed in, or an agent. |
+| 15 | §3: a meeting link is a capability to obtain a **guest grant at sign-in**, the `granted` rung, and never a way into a room without a name. Ruled for Meet on `oficina/suite` discussion 3, Paul, 2026-09-06. |
| 16 | The token at rest (§3.1), as amended by the 2026-09-12 sharing update at the top of this file: invitation tokens are hash-indexed with a sealed copy so a member can share the current one again; agent credentials stay hash-only and shown once (§15.17). Ruling 16 is on the doctrine's `worktree-worktree-token-at-rest` branch (suite discussion 2), not on main on 2026-09-14; Meet adopts it early so it never has the Docs defect that produced it. |
-Doctrine §5.2 is also relied on: a guest grant held by the instance is
-authoritative for that grant, which is why §2 stores it and does not
-ask anyone.
+Doctrine §5.2 is also relied on, for §2: a guest grant is stored, not
+asked for.
-Also consumed: `oficina/suite` discussion 4 (agents as their own
-principal, on behalf of a person, bound to the operator's reach and no
-more) for the drive surface (§8); the CARLOS media roadmap
+Also consumed: `oficina/suite` discussion 4, for the drive surface
+(§8); the CARLOS media roadmap
(`carlos/platform`,
`docs/superpowers/specs/2026-09-07-media-platform-roadmap-design.md`,
merged at 8291cb2) and the stage 4a relay spec
@@ -978,6 +976,19 @@ A thin adapter over §8.2, deferred until a consumer asks by name.
### 8.4 Native clients
+**2026-09-14 amendment.** The SwiftUI Mac, iPhone and iPad apps this
+section specifies shipped on `main` (`native/`, `meetcore/`,
+`protocol/`, tag `v0.1.0` at `9225ec2`), closing the authentication gap
+the bullets below name with a browser-approval hand-off
+(`native/README.md`): a five-minute, one-use authorization bound to a
+proof secret held only by the app; approving in the browser creates an
+ordinary framework session, no cookie copied and no new bearer type
+introduced. The production handoff endpoints were deployed in
+`86ed9f3`. This supersedes the closing paragraph's "version one does
+not ship a native client" below; the rest of this section, written
+before that milestone, otherwise stands as the contract the shipped
+apps speak.
+
Ruling 15: a native app is the next client after the browser, and
nothing in Meet's server contracts may assume the browser. Concretely,
in version one:
@@ -1004,14 +1015,19 @@ until an OpenAPI document earns its place.
## 9. The scriptless floor
-The exception is **browser media participation** and nothing wider:
-reaching a camera and another browser needs script. Every other screen
-works with scripts off, including the meeting list, creating a meeting,
-seeing and copying a link, all four confirm pages, sign-in and
-continuation, the `/welcome` page, the agent token page, and the server-rendered
-parts of the holding screen and the room (§3.3, §3.4): title, start
-time, standing, floor sentence, the paragraph that says what needs
-script, and navigation to everything that does not.
+The exception is **browser media participation**: reaching a camera
+and another browser needs script. Inside a room that exists, script
+also gates the chat panel (`chat.html`'s whole panel is rendered
+`hidden` until script un-hides it, because a Send button with no
+script behind it would be a lie, §6, §10) and the admission queue's
+Admit controls (`room.js`), since neither can do anything before a
+call does. Every other screen works with scripts off, including the
+meeting list, creating a meeting, seeing and copying a link, every
+confirm page (five), sign-in and continuation, the `/welcome` page,
+the agent token page, and the server-rendered parts of the holding
+screen and the room (§3.3, §3.4): title, start time, standing, floor
+sentence, the paragraph that says what needs script, and navigation to
+everything that does not.
`AGENTS.md`'s line "screens work with JavaScript disabled" gains, in
slice 2, the one exception in those words, so the binding file and the
@@ -2160,6 +2176,12 @@ floor" is the no-relay condition, and §9's "The scriptless floor" is
the JavaScript exception; item 6's bullet above now names each rather
than leaving the bare word to carry both.
+§9's exception was also corrected here, on Codex round 1: browser
+media participation was never the only script-gated part of a room —
+the live admission controls have needed script since slice 2 and the
+chat panel since slice 4 — and §9, the README and `PRODUCT.md` now say
+so rather than "and nothing wider."
+
- **Delivered.** `README.md`, with the scriptless floor sentence and
the relay paragraph first. `PRODUCT.md`. `AGENTS.md`'s deploy notes.
§0.2 above, refreshed against doctrine main `1ac4323`, still
@@ -2171,9 +2193,10 @@ than leaving the bare word to carry both.
- **Deferred, not duplicated.** The acknowledgements page lives on
`oficina/meet` discussion 10, branch `feat-open-source-credits`
(`117b6e4`, `bbc126e`): a shared Estilo credits page with a runtime
- dependency inventory, Fable-approved, verified live on the overnight
- canary, not yet merged to main. Building a second one here would be
- the duplication the programme forbids.
+ dependency inventory. As recorded on that branch's own review, it is
+ Fable-approved and was verified live on the overnight canary, not
+ yet merged to main — not independently reverified here. Building a
+ second one here would be the duplication the programme forbids.
- **Declined: the Estilo theme pin.** The programme's condition for
pinning was a tagged release; `git ls-remote --tags` against
`oficina/estilo` is empty on 2026-09-14, so no tag exists and no pin