Visitor access
The SDK tells you whether a visitor may act. Your app has to enforce that answer on every data and side-effect path.
const grant = await demo.verify(identity, "invoice.create");
await withVisitor(runtimeDb, grant, async (tx, resourceId) => {
// Reads and writes are scoped by row-level security.
});
// On any path that would leave your infrastructure:
denyExternalEffect("send-email");Checking a grant
Verification checks the project key, visitor token, session state, expiry, and whether the demo or session has been reset or unpublished since. Reset invalidates old identities. Don’t cache positive answers for long, and deny access if Trylane can’t be reached.
Row-level security
The PostgreSQL helper sets a transaction-local resource and switches to a non-owner role. Enable and force row-level security on your tables with policies that match that resource. No endpoint may skip the visitor wrapper.
Blocking side effects
Run the demo deployment without production provider credentials, refuse external effects in code, and restrict outbound network access at the hosting level. The manifest declares this policy; it doesn’t enforce network isolation for you.
Transport and secrets
HTTPS is required except on a local development loopback. Handoff codes last 30 seconds and work once. Cookies must be HttpOnly, Secure and SameSite. Trylane stores only a hash of your project key.
See every step from the visitor’s side.
Try the Ledger example