Auth
How people, agents and programs sign in, act for others, and get the grants each call is checked against.
Every call to a Startup answers three questions before it runs: who is acting, for whom, and by what right. The answers stay on the Action.
Who is acting
People sign in with a passkey, an email link or their own single sign-on; the signup Setting in startup.ts picks the default. Agents carry their own credentials and never borrow a person's. Programs hold a key.
curl https: //api.sb/ leaseline.app/ offers \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"A key starts sk_test_ or sk_live_, and the prefix picks the environment. A key acts only in its namespace and scopes, and mints only narrower keys:
npx startup-builder keys create --name ci --scope leaseline.app --expire-in 30dA missing or expired key returns unauthorized. A valid key without the right returns forbidden, naming the grant it lacks.
For whom
An agent acting for a person or the Startup does so under a Mandate: one Verb, within a Limit, until it expires.
import { $ } from 'startup-builder'
await $.Mandate.authorize({ agent: 'agent_1', verb: 'Invoice.refund', limit: 'limit_100_usd' })Every Action records the Worker that acted and the Party it acted for.
By what right
| Grant | Comes from | Declared in |
|---|---|---|
| Permission | A Role | agents/ |
| Entitlement | An accepted Offer | offers/ |
| Persona access | An App | apps/ |
| Mandate | A Party's authorization | Mandate.authorize |
A call over its Limit does not fail. It waits as an Approval for a Worker who may allow or refuse it.
Customers and their teams
A Customer's people sign in to the Startup's App and see only their own Tenant. A Customer that is an Organization connects its own single sign-on and directory. Because every call is checked, MCP shows a Customer exactly what the portal shows.