The server calls.
Clock, injectable for tests.
The current view, then every change.
confirm — the user approves what is shown. Refused for anyone but the user, whatever the schema says.
enter_code — hand the code the person received to the server. The code is never kept.
fill — set a field. A value the user types is confirmed by being theirs; anyone else's is not.
The server says the person is verified (the identity.verified event). Idempotent. Returns whether
this call made the change, so the channel completes exactly once.
Registers the (single) listener told about every change — the channel.
resend — send a fresh code to the same, already-confirmed address.
Seeds values the HOST knows (open inputs). They are unconfirmed — the user still has to approve them.
submit — send the code to the confirmed address.
The channel's GetState snapshot (the descriptor's nouns).
The identity-verification state machine — framework-free, so it is testable without Angular and shared by the channel (which adds the descriptor, events and perception) and the surface (which only renders View$ and sends the user's actions back through the channel).
The invariants it exists to hold:
identity.verifiedevent is what makes a session verified. A successful code submission also applies it, but only as a fallback for a transport without events, and idempotently.