One read for a page of targets, not one per target. Thirty rows asking individually is ninety round trips through NUI, which is the thing the batched shape exists to avoid.
A target absent from the reply is a target with no reactions; it does not have to be
echoed back as an empty summary. That is a promise about the transport only — the store
fills the omission in as NO_REACTIONS rather than passing it on, so absence never reaches
a caller as an answer. ReactionStore.load is where that half is written down.
Promise<unknown> rather than Promise<void>: these are usually a facet call handed
straight through, and a facet answers with whatever the server echoed. Demanding
Promise<void> would make every app write a .then(() => {}) to discard a value this
store already ignores — the next load is what the counts come from, not the echo.
How one app's reactions actually reach its server. Supplied by the app; the store never names a route, a table, or an identity of its own.
That split is the whole point. Blabber reacts to
mica_blabber_dmsas an account through the sharedaccountsfacet; a future consumer may react to its own rows as a citizenid through a service of its own. Neither of those is a property of "a reaction" — the batched read, the optimistic toggle and the rollback are, and this file owns exactly those.react/unreactare two members rather than onetoggle(targetId, emoji, on), so an app writes two literal facet calls. A computed action name is invisible toserver/__tests__/routes.test.ts, which cross-references every layer by scanning for literals — and a route it cannot see is reported as dead weight.