The checkpoint moves after the page is committed
The other order loses a page on a crash and reports success for it. A 2,000-item sync failing at 1,900 used to restart at zero; the unit became a page, and the rule did not move.
One class per source, describing itself in a record the permission layer can actually reason about — so the gate understands send:email without knowing whether the app behind it is Gmail, Apple Mail or something you wired up yourself.
The manifest is read off the class, never hand-maintained beside it. That distinction is not pedantry: it is why the declared capabilities stayed true while hand-maintained lists elsewhere drifted.
ConnectorManifest ├── connector_id · display_name · provider · version ├── auth method, and the lifecycle state of each connection ├── capabilities frozenset[Capability] ← the whole security surface ├── resources what kinds of thing it holds ├── sync strategy · incremental · resumable · cursor kind ├── events webhook | polling | none, and the dedup key ├── health supported? cost? └── limits requests/interval · concurrency · page size
A capability is a verb applied to a kind of thing — read:email, send:email, read:repository. It says what can be done, not what the app is called, so one gate reasons across all of them.
| tier | means | what the gate does |
|---|---|---|
READ | Answers a question | No approval |
WRITE | Changes something at the vendor, reversibly | The risk tier decides |
DESTRUCTIVE | No inverse exists | Always asks. Never grantable |
OUTBOUND | Reaches a person who is not you | Needs a permitted recipient |
connector declares capability → action registry names the capability it needs → permissions.check() evaluates risk + recipient → approval card, or a standing grant → connector executes
The other order loses a page on a crash and reports success for it. A 2,000-item sync failing at 1,900 used to restart at zero; the unit became a page, and the rule did not move.
Sweeping one deletes the tail of a mailbox because a sync hit its own budget. The absence of an item is not evidence it was deleted.
Storage once keyed on the connector alone, which baked “provider equals account” into the schema. Connections, checkpoints, identity and provenance are all per account now — two mailboxes no longer fight.
403, 400, 401 and 404 are each a reason not to try again. The bounded loop is what stops a rate limit becoming a ban.
Where there is no connector there is usually a protocol, and where there is no protocol there is a browser. A tool reached over MCP is gated by the same chain as a built-in one — and it is grantable per server:tool, because that is a stable, comparable, revocable key in a way an argument blob never is.
The outbound guard re-checks where the request actually landed, because following a redirect is how that check gets bypassed.
Not a guess the UI makes. A source that cannot report is shown as unknown rather than green.
A credential found on the machine lets us offer a source. It never marks it connected.
Free while it is in beta. Bring your own model — or run a local one and never leave the machine.
Join the waitlist→