oficina / meet Public
Findings on the Meet spec, revision 1
GPT-6 via codex exec, read-only, against CODEX-REVIEW-BRIEF-MEET.md, reviewing commit 3836222. Verbatim.
R1-1 — P1 — §4.3: Waiting-room isolation is incomplete. Waiting guests already have room streams. The table restricts who sends chat and share, but broadcasts them without restricting recipients. Likewise, leave permits a waiting guest to trigger a room-wide gone: a message other than knock reaches members before admission. Evidence: message table.
Correction: Specify recipients for every message. Chat, sharing state, admitted-peer announcements and rosters go only to admitted peers. Waiting-peer departures update members’ admission queues only. Test that a waiting stream receives no call content.
R1-2 — P1 — §§4.1–4.3: Server-generated from does not establish peer ownership or room isolation. The spec never defines how a tab identifies itself across its stream and POSTs, how that identifier binds to its authenticated actor, or whether to must identify an admitted peer in the URL’s room. Random peer IDs are disclosed in rosters; they cannot serve as credentials. Checking only the sender’s standing leaves cross-room targeting and peer impersonation unspecified. Evidence.
Correction: Bind each peer to its room and authenticated actor, define the stream/POST association, reject conflicting registrations, and resolve every target inside that room. Construct the outbound envelope server-side; preserve only the opaque payload.
R1-3 — P2 — §4.3: Admission bypasses the four-peer cap. With one admitted member, four guests can queue because admitted count remains below four. The member can then admit all four: only join checks capacity. This requires no race. Concurrent admissions introduce another bypass. Evidence: join and admit.
Correction: Check capacity atomically whenever a peer transitions into admitted state. Rejoining an existing admitted peer must not consume another slot. Test queued guests and concurrent admissions.
R1-4 — P2 — §§4.2–4.3: Bounded queues do not bound memory. Waiting peers and streams have no count limit. Only chat has a byte limit; an admitted peer can submit arbitrarily large signalling payloads. A bounded number of unbounded payloads remains unbounded memory. Sheets supplies a 64-message buffer, not a room admission policy or payload-size limit. Meet hub; Sheets hub.
Correction: Define request-size limits before decoding, per-type limits, signalling rates, and waiting-peer/subscriber limits per actor and room.
R1-5 — P1 — §§2, 3.2, 4.2: Live authorization can continue using obsolete standing. The hub stores member or guest and admission state. Request checks do not explain how those values change, or how an already-open stream stops receiving after grant expiry or loss of access. A removed member with an older guest grant could remain marked as a member. The future roster copy also lacks an explicit freshness requirement.
A locally stored guest grant is authoritative, not cached authorization: doctrine §5.2 expressly permits it. The defect is treating previously established standing as current authority. Meet; doctrine §§5.2–5.3.
Correction: Define promotion, removal, grant expiry and stale-roster transitions, including stream termination and hub updates. Preserve valid individual grants without preserving member privileges. State the limit of server enforcement over already-established P2P connections.
R1-6 — P1 — §8.1: Agent reach is not constrained after its operator loses membership. Membership is checked when minting an agent token, but the API contract never requires checking the operator’s current reach. An unrevoked token could continue listing, creating or ending meetings after its operator becomes a non-member. Discussion 4 explicitly binds an agent to its operator’s reach “and no more.” Meet principals; discussion 4.
Correction: Check token revocation and current operator authorization on every API request. Add removal and stale-roster tests.
R1-7 — P2 — §§3.2, 7.1: The reused sign-in flow cannot preserve the return path as described. Rastrillo’s Begin consumes address and force; successful admission redirects to one configured SignedInPath. Neither it nor Docs’ sign-in page preserves a per-attempt return value. Changing the two allowlist gates alone sends an outsider back to /, without minting the meeting grant. Docs auth; Rastrillo admission.
Correction: Design the continuation mechanism explicitly, including its binding to the sign-in attempt. Accept only a canonical /j/<valid-token> destination; reject extra path segments, query/fragment additions and encoded path ambiguities. Revalidate the capability after authentication. Test the complete emailed-link round trip.
R1-8 — P2 — §§3.2, 7.1: Opening sign-in exposes a shared mail-budget denial of service. The inherited limiter allows 20 attempts per IP and five per address per 15 minutes. Its IP key uses RemoteAddr; the code explicitly notes that behind the platform edge this becomes a shared budget. An outsider can exhaust that budget and prevent members or invited guests signing in. Removing Docs’ gate also opens unsolicited sign-in mail to arbitrary addresses. Limiter; proxy limitation.
Correction: Specify mail-volume controls and a trusted client-address strategy, preserving forced magic-link handling. Test budget exhaustion through the deployed proxy shape. Distinguish uniform responses across membership status from rate-limit and invalid-address responses.
R1-9 — P2 — §§3.4, 4.1, 4.3: Routine stream renewal has no coherent reconnect transition. Every five minutes the stream closes and the client posts join again. The table says a guest join becomes waiting, so an admitted guest can require readmission at every renewal. A full room can reject its own reconnecting participant. Meanwhile, §4.1 tells peers to react to a second join, although join is upstream-only; peers receive peer. Evidence.
Correction: Define idempotent resume within the 30-second grace period, replacement-stream ownership, admission preservation and the actual downstream event. Specify recovery after lost and process restart. Test these transitions with shortened timers.
R1-10 — P2 — §§4.3, 5.1, 5.3–5.4: Permanent offerer ordering does not support the later media operations. If the higher-ID peer adds a screen track, it needs renegotiation but has no message requesting an offer from the lower-ID peer. If both sides instead offer on negotiationneeded, simultaneous sharing or credential renewal contradicts the claim that both never offer. restartIce() marks negotiation needed; it does not complete an exchange. Meet ordering; WebRTC negotiation.
Correction: Adopt collision-safe negotiation or specify an explicit offer-request protocol. The three-hour credential and 2½-hour renewal margin are valid against relay §2; define repeated renewal, failed renewal and resumption after suspended timers. Test higher-ID sharing and simultaneous restart/share operations before declaring slices 3 and 4 complete.
R1-11 — P2 — §§5.2, 7.3: Three platform-contract claims are inaccurate. The relay contract supplies URLs in console order, explicitly without a placement-first promise; Meet says nearest region first. The contract forbids assumptions about schemes, while Meet only defines stun: and turn: handling. Finally, relay enable does not require a unit route: socket-backed exec routes and qualifying TCP-address routes are supported too. Evidence: carlos/platform@relay-stun-turn-spec, relay design §2 and §5, enable step 3; Meet ICE, deployment.
Correction: Preserve console order, define handling of supported secure schemes and invalid configuration, and describe a unit route as Meet’s choice.
R1-12 — P2 — §§0.1, 5.6: The server-in-the-media-path change starts with TURN, not the SFU. Stage 4a TURN forwards encrypted media through a platform process. The spec delays its qualification until stage 4b, making “media never touches the server” misleading once slice 3 uses TURN. This does not violate the fixed egress ruling; the platform is an allowed recipient. Evidence: relay design §3, relay sockets and metering; Meet privacy claim.
Correction: Distinguish the Meet application process, the TURN relay carrying encrypted packets, and the future SFU. Put that distinction in the relay introduction immediately.
R1-13 — P2 — §0.1: The stated test does not establish the database/WAL/log guarantee. A post-checkpoint SQLite grep says nothing about earlier WAL contents or logs. The server receives plaintext chat and signalling containing codecs and candidate addresses; opacity to the hub is not a prohibition on logging. Capability URLs create a separate exposure explicitly excluded from ruling 16’s database-only guarantee. Meet test claim; WebRTC information exposure; doctrine token-at-rest branch, §4.1.
Correction: Define which logs the claim covers, prohibit sensitive payload and capability logging, and test success and error paths against captured logs and WAL. State transient signalling visibility separately from at-rest confidentiality.
R1-14 — P2 — §§0.3, 5.5: The network floor makes guarantees ICE does not provide. Host candidates identify physical or virtual interfaces, including globally reachable addresses. They can connect across networks; conversely, client isolation or firewalls can prevent same-network connectivity. “Same network and nowhere else” is false in both directions. An ICE failure also does not establish that TCP-443-only restrictions caused it. Meet floor; RFC 8445 §5.1.1.1.
Correction: Describe the requirement as direct reachability between exposed host candidates, usually available on a permissive LAN. Present restrictive networks as a possible failure cause, not a diagnosis.
R1-15 — P2 — §2: The persistence model contradicts both the scaffold and the promised attendance record. The scaffold has only Note/notes, no persons or users table. The proposed schema also cannot record who attended and when: members create no guest-grant row, grants can belong to people who never attend, and no departure time is stored. Finally, persisted admitted_at contradicts “admission state” existing only in memory. Scaffold models; proposed model.
Correction: Make person creation and auth/session schemas explicit slice-1 work. Decide whether attendance is retained; either provide its model and retention or remove that promise. Separate admission audit fields from current admission authority.
R1-16 — P2 — §§3.3, 9, 12: The scriptless exception is broader than necessary and incompletely routed. The holding-page fallback is sufficiently described to render, but direct navigation to /m/{sqid} has no equivalent fallback. §3.3 calls holding the only script-dependent page, while §9 exempts both pages. Updating PRODUCT.md does not resolve the binding AGENTS.md requirement, and that update is postponed until slice 6. Scriptless contract; repository rule.
Correction: Limit the exception to browser media participation. Specify useful server-rendered output and management navigation on both URLs. Align the repository convention when slice 2 introduces the exception.
R1-17 — P2 — §§3.1, 3.4: Destructive actions lack their required confirmation pages. Replacing a link revokes all existing links; ending a meeting disconnects everyone. Neither action has a specified confirmation-page URL, despite the repository requiring one and mandating ui/confirm-form. Actions; mandatory convention.
Correction: Add scriptless confirmation GETs and guarded mutation POSTs in slice 1, with the required component.
R1-18 — P2 — §8.2: Link replacement cannot satisfy the API’s show-once rule. The API says creation is “the only time” it returns a token, then provides a replacement-link operation. Since only the hash persists, a replacement whose token is not returned is unusable and unrecoverable. Evidence.
Correction: Return the newly minted token once from both creation and replacement. Define replacement failure and retry behavior explicitly.
R1-19 — P2 — §§12–13: The browser-test precedent is wrong, and the gates do not prove the later slices. Calendar documents its chromedp test as stalled at about:blank; its working gate uses Playwright. Meet’s proposed screen-share assertion proves only a label, not a received display track or renegotiation. Asserting an ICE list does not test renewal. Slice 2 specifies two browsers, while §13 substitutes two tabs, which ordinarily share authentication. Calendar’s recorded limitation; Meet gates.
Correction: Establish a working browser driver first; use isolated identities; verify received screen media, stop-sharing, reconnects and accelerated repeated renewal. Assign these gates to their owning slices rather than relying on the final deploy slice.
R1-20 — P2 — §7.3: The current release target does not stamp the build probe. make release supplies only -s -w; Rastrillo’s BuildVersion defaults to dev. The claimed version-stamped release and meaningful /api/version deployment verification therefore require a scaffold change the slices do not identify. Makefile; framework probe contract.
Correction: Include version stamping explicitly in slice 6 and verify that the built binary reports the intended revision.
R1-21 — P3 — §§2, 7.1: Extraction provenance is miscounted. Calendar’s sealer already comes from Sheets and explicitly identifies the third app as the extraction trigger; Meet calls itself the second. Calendar also already contains the same sign-in implementation family, so counting only Docs, Slides and Meet understates the copies. Sealer provenance; Calendar auth.
Correction: Correct the consumer counts and cite the existing extraction trigger without inventing a new one.
Verification limit: the supplied dumps do not include rastrillo/rastrillo discussion 17 or oficina/suite discussion 5. Their attribution remains unverified; that is not evidence that either citation is wrong.
Verdict: request changes.