Aller au contenu

DOCS

Policies

Sveda does not store your users. Your app keeps the role. The embed token carries a policy name. The runtime enforces it.

Three layers

Role lives in the host app. Policy is a named entry under policies in sveda.yaml. Capability is what the token is allowed to advertise and call on each turn.

Mint and enforce

POST /sveda/embed/token accepts policy and optional grants. Unknown policy names return 422. Tokens without a policy stay unrestricted. GET /sveda/embed/config returns capabilities for the UI; the token is what the runtime enforces.

Where each piece lives

  • Role — your app (Spatie, Django groups, an AD group). Sveda never reads that name.
  • Policy — a named entry under policies in sveda.yaml. The name is what the host sends as policy when it mints a token.
  • Capability — what that token may advertise and call. Enforced on every turn.

The host maps the signed-in user to a policy name when it mints the token. A browser cannot change that by substituting an email: the session user comes from the host, and the token is HMAC-signed.

Policy document

Globs are only *, prefix*, and *suffix. max_mode is read < write < delete. When a policy is set, omitted web and code are denied. An empty allow list means no tools of that class. Tokens with no policy keep the previous unrestricted behavior.

policies:
  reader:
    web: false
    code: false
    mcp:
      allow: ["tickets.*"]
      domains: ["tickets"]
      max_mode: read
    client:
      allow: []
  agent:
    web: true
    code: false
    mcp:
      allow: ["*"]
      max_mode: delete
    client:
      allow: ["*"]

Tools with MCP mode delete (for example delete_post ) need max_mode: "delete" and the tool name in mcp.allow or the model never sees them. Chat confirmation is separate — see tool confirmation.

Optional grants on mint can only tighten the named policy. An unknown policy name returns 422. Which rows a tool may touch stays in the host tool handler.

Mint

POST /sveda/embed/token
x-sveda-host-key: $SVEDA_EMBED_HOST_API_KEY

{
  "visitor_id": "user-42",
  "policy": "reader"
}

GET /sveda/embed/config returns capabilities so the widget can hide controls. The runtime still filters tools from the token.

Host mapping

host.policyUsing((user) => (user.role === 'agent' ? 'agent' : 'reader'))

host.resolveToolsUsing((user) =>
  user.role === 'agent' ? [searchPosts, createPost, updatePost] : [searchPosts],
)
SvedaClient::host()->policyUsing(
    fn ($user) => $user->hasRole('agent') ? 'agent' : 'reader',
);

End-user web and mobile clients receive the short-lived embed token. They must not hold SVEDA_EMBED_HOST_API_KEY.

Livrez un copilot ce week-end.

Installez le client JS. Lancez sveda-server à côté de l’hôte. Streamez le premier tour.

Commencer