Guard / foldkit-guard
Who is asking
Authentication decides who is asking; guards only read it. Give the handlers
G.Principal instead of a principal, and each call reads it, so one handler
set answers every request, and whatever authenticates a request provides it:
const handlers = RemoteServer.handlers(backend.server, G.Principal)
// per request: `body` is what it sent, and authentication resolved `principal`
RemoteServer.answer(handlers, body).pipe(Effect.provideService(G.Principal, principal))A live hub shares a re-read between subscribers with one principal. Two
requests by one person each decode a principal of their own, so give the hub
Policy.keyOf, which names a principal by every field, as JSON keeps it (a
set, a bigint, a date included; a visitor too), and they share one:
const hub = yield* RemoteServer.liveHub([...backend.server.entities.values()], {
key: Policy.keyOf,
})Two principals with one key are read as the first of them, so a key that
named only the person (G.key) would read a request made after their
projects changed as an older request's claims; Policy.keyOf changes with
any field. On the client, a cache snapshot is scoped by the person
(RemotePersistence's scope: G.key(user)), and a sign-in or sign-out is
Remote.forget (forget on a domain made with Remote.make), since every
fact the cache holds was read as someone.