Guard / foldkit-guard

Agents

An agent should not be offered, or attempt, what the server would refuse. foldkit-guard/agent reads may from the row the Model holds, for a foldkit-agent capability's authorize and available:

ts
import { Agent } from 'foldkit-agent'
import { GuardAgent } from 'foldkit-guard/agent'

const TodoAgent = Agent.forApplication(App).withPrincipal(G.Principal)
// The Todo an id names, read through `Row` from the client's Model.
const todo = Remote.select(Remote.at(Data, App.model.remote), Row)

TodoAgent.expose(Message, {
  RequestedArchive: {
    description: 'Archive a todo',
    authorize: GuardAgent.authorize(Archive.key, ({ input, model }) => todo(input.id).read(model)),
    available: GuardAgent.available(Archive.key, model => todo(model.selected).read(model)),
  },
})

App and Message are the client application's: its Model holds Remote's store at remote and the selected todo's id at selected, and Message has a RequestedArchive with the todo's id.

  • Row selects may. A row not read yet, or whose read failed, refuses: there is no answer to go on. One being read again answers as it last did. A refusal its rule explained is the agent's error message.
  • available is for a capability over a row the Model alone names (the one selected): a visitor is then not offered it at all.
  • withPrincipal(G.Principal) makes the agent's principal the server's type.
  • It is the agent's gate, not the check: the Message's mutation is checked on the server, under the same principal.