Why streaming is the hard part#
Modern providers stream answers token by token, and users expect text to appear immediately. A restore step that buffered the whole response would turn every chat into a wait. The Salus restore design works inline instead: it holds back only a small window of the stream — enough to recognize a Salus token even when the provider's chunking splits it in half — resolves the mapping, and releases restored text continuously. The stream stays live; the added delay is a bounded hold-back, not a full-response buffer.
Where this runs today: Salus Desktop restores streamed responses inline in exactly this way. The Salus API's first lane is synchronous text — your application detokenizes a complete response — with streaming restore following as the API surface matures.
This is also why the engine sits in the response path architecturally: something with vault access has to see the stream before the caller does, or restoration cannot happen at all.
Restore is an authorization, not a find-and-replace#
This is the contract: turning a token back into a value is a governed act, separate from tokenization. The credential that identifies your tenant does not by itself authorize seeing restored values — every detokenize operation carries an asserted principal for the requesting user or service, from a component you configure and trust, and fails closed when authorization cannot be established. The result is that "reversible" means reversible for authorized paths.
When restoration cannot happen#
If the vault is unreachable or a mapping is missing, the default is conservative: a response marked for restore is held, and the caller sees a visible failure rather than an answer with unresolved tokens standing in for values it was promised. Behavior is configurable per data class — a low-risk surface can be allowed to deliver-with-tokens plus an alert — but the principle stands: open never means raw, and silent substitution failures are not an option.