Module render

Module render 

Source
Expand description

Where a component renders — the Mode A / Mode B decision, and what it costs to be wrong.

docs/05-tier-lowering.md §5.1 gives two rendering modes over one source:

Mode A — thinMode B — local
view runs onserverclient
Wire carriesDOM patchesdata patches (state diffs)
Optimistic UInoyes — the same fold runs locally, reconciled by seq

The row that decides everything is the second one. Mode A sends the browser a rendering of the state; Mode B sends it the state. Everything below follows from taking that literally.

§The rule: a Mode B page may not be a function of who is asking

A view has the shape (state, session) -> Html. If it reads who the session is, it renders a different page for different actors from the same state — which is to say it is filtering, scoping or hiding by identity. Running that view on the client requires giving the client the state it filters, so every actor receives what the filter was removing. The page would still look right. That is the worst kind of wrong.

So a component whose view reads the session’s identity is refused Mode B, and the refusal names the reason rather than a rule. What is left is exactly the class §5.1 and docs/10-decisions.md D5 describe as Mode B’s: pages that are the same function of the same state for everybody — editors, typeaheads, drag-and-drop, anything single-user or public.

§Which half of the session, and why the distinction is structural

Session carries three fields and they are not one kind of thing. actor and claims say who is asking and are what an identity provider verified; path says where they are and is the client’s own statement about itself. The argument above is entirely about the first pair: a page that renders by route is not hiding anything from the browser it is running in, because that browser chose the route and already holds the state.

So the refusal is decided by SessionUse, which reads the view’s own code and asks which fields of a Session it can observe. The coarser fact — whether the page is per_session at all — is still what §3.8’s fanout analysis and §5.3’s shared cut use, and it is still true of a page that reads only the route: two people on two routes see two pages, so the operators below the session are theirs. Eligibility and fanout are different questions, and this is where they stopped being the same answer.

§Optimism is a property of what crosses, not of a component

“The browser applies the expected event to its local copy speculatively — legitimate because it runs the same pure fold the server runs” (D5). That is only available to a client that holds the value the fold is of. A client holding a projection — a session’s filtered list, say — could not apply an event to it without a second, different fold that no program writes. So optimism is not an extra feature layered on Mode B; it is the same fact stated twice, and this module reports it as one decision with two consequences.

§And the rule that points the other way

§3.7 asks for one more thing of a guess: that the page can say it is one. “Signal[T] carries a freshness dimension (confirmed | pending(n)) that UI code can render ("saving…") — staleness is typed, not pretended away.” freshness() is that dimension, and it is the only thing here a server cannot answer: what a server renders is what it has recorded, so its answer is Confirmed at every position of every log. So a page reading it is refused Mode A (B0518) exactly as a page reading presence is refused Mode B — the two rules are the same rule about two facts that live on opposite sides of the wire.

Structs§

Decision
How one component renders, and what follows from it.

Enums§

Mode
Where a component’s view runs.
NoOptimism
Why a Mode B client may not guess.
SessionUse
What a view can observe about the Session it is handed.
Why
Why a component renders where it does.

Constants§

ROUTE_FIELD
The field of a Session that says where rather than who.