UI project 4 of 5 · IOS/TheOne/Main/GlobalChat, app/web-platform/app/globalchatStack: SwiftUI + Combine + Core Data; React/Next.js with a transport/store/runtime split
Scope: iOS module 75 Swift files ≈ 9,400 lines · web tier with composer, media, search, webrtc, transport, store
Where this sits. The client half of
GlobalChat. Two independent
implementations of one realtime protocol — which is exactly the situation
where client/server contract discipline stops being theoretical.
One protocol, two independent clientsinteractive
# engineeringsocket open
did the relay ever catch up after the restart?
yeah, lag was the outbox, not Kafka. 40s to drain.✓ acked
so the consumer groups were fine the whole time
The client half of project 2. The web tier splits transport, store and runtime so the socket can drop and reconnect without the UI knowing. The message above goes optimistic first, then reconciles against the server ack.
Separating transport / store / runtime / render is the right decomposition
for a realtime client. The transport dies constantly; the store must survive
it; the render layer should never know a socket exists.
The iOS module — and the correction worth reading
docs/GLOBALCHAT-MODULE-WIRING.md is a wiring record that opens by
retracting three of its own earlier conclusions. That document is a hiring
artifact in its own right:
"I got these wrong first time and they change the picture materially."
"The module was never orphaned — it is load-bearing."GlobalChatServer.swift declares 13 publishers typed with GlobalChatMessage,
GlobalChatReceiptEvent, GlobalChatCallLogEntry and 14 other types —
every one declared only inside this module. There is no second copy. The
module owns model, persistence and view; GlobalChatServer owns transport.
"The module has been attached in production all along."TheOneApp.swift:112 applies .attachGlobalChat(...) — committed, not added
by this work. GlobalChatStore.attach had been subscribed to all 13
publishers and mirroring live traffic into Core Data on every install. The
data layer was wired; only the view layer was never rendered.
"The attach modifier never had a crash."
The earlier claim that nothing injected GlobalChatServer was wrong — "my
grep looked for a variable named server, and it is named chat."
The real gap, once the false ones were cleared, was narrow and specific: the
outbound path, where GlobalChatStore held a private weak var attachedServer.
Publicly correcting your own analysis, naming the grep that misled you, and
then landing a smaller and correct fix is the single most senior-coded
behavior in this entire repository.
Feature surface
Attachments (typed), voice messaging, reactions, edits and deletes, view-once
media, live location, typing indicators, read receipts, search, call log, and
an avatar hexagon treatment migrated across the component set. The dating
variant wraps 18 Dating* components in a DatingChatView facade over the
same GlobalChat engine.
WEB_CHAT_RUNBOOK_AND_GAPS.md carries a WhatsApp feature-parity comparison
(present / partial / missing), and
WEB_CHAT_FEATURE_IMPLEMENTATION_PLAN.md turns the gaps into a phased plan
with code-verified backend status, exact file/wire/store changes, effort
sizing, acceptance criteria, and iOS-parity notes.
Interview surface this opens
Transport / store / render separation in a realtime client
Message ordering, dedupe, and gap-fill after a reconnect
Local persistence (Core Data) as a mirror of a server log
Two clients, one protocol — and how AsyncAPI keeps them honest
Retracting an analysis in writing when the evidence goes the other way