Docs/Lanes Link/Connections/Scopes and permissions

Scopes and permissions

The two different things called scope, how to narrow one instantly and widen the other, and what can and cannot be set per connection.

Two different things get called "scope", they are enforced in different places, and confusing them is how people end up granting more than they meant to.

Where it livesChanging it
What the vendor grantedthe vendor's consent screenwidening needs a browser, narrowing needs a reconnect
What your agent may spendyour policy file, on your machineinstant, both directions

The first is a ceiling. The second is where you actually work.

Which scopes a given provider asks for, and which it deliberately does not, is on that provider's own page. Every provider has one.

What your agent may spend

Connecting grants a read bundle. Everything after that is policy, and policy is local:

console
$ lanes link policy list --profile personal
$ lanes link policy deny gmail.send --profile personal --workspace local
$ lanes link policy allow 'drive.*' --profile personal --workspace local

Rules are glob patterns over capability names. Two properties matter:

A deny always beats an allow, whatever the order in the file. There is no precedence puzzle to reason about, and no way to accidentally re-grant something by adding a rule below.

An absent policy grants nothing. The default is deny, so a capability nobody wrote a rule for is not reachable. connect writes one rule per provider, which is why a fresh connection works at all.

A rule can also expire, with expires_at, for access you want to hand out for an afternoon.

Bundles

A bundle is a named group of capabilities: read and write are the two you will see. For providers built on an HTTP specification they are derived from the method, so GET and HEAD land in read and the mutating verbs land in write, with nobody curating a list that could quietly drift from what the API does.

Granting one is how you widen without naming twenty capabilities:

console
$ lanes link connect gmail --add write --profile personal --workspace local

Widening what the vendor granted

This is the one that cannot happen locally. If the vendor never granted it, no policy rule conjures it, and the endpoint has nothing to spend.

console
$ lanes link connect <connection> --add <bundle> --profile personal --workspace local

That reopens the browser, because a wider grant is the vendor's decision and yours, not ours. Some scopes are marked broad, and connect stops and asks for an explicit yes before requesting one rather than sliding it in with the rest.

Narrowing what the vendor granted

Reduce the bundles and reconnect. A vendor with a revocation endpoint has the old grant revoked as part of it; where there is none, the grant stays live at the vendor until you remove the app in their account settings, and the page for that provider says so.

Denying the capability locally is the faster half of this and takes effect at once. Do both when the point is to remove access rather than to stop using it.

Scopes are not set per connection

Worth stating plainly, because the shape of the CLI suggests otherwise.

Policy rules name capabilities, never connections. Every account of a provider inside one profile is governed identically. If you have two Gmail connections in personal, denying gmail.send denies it for both. There is no rule that reaches one and not the other.

That is deliberate rather than missing. A rule that named a connection would be a rule whose meaning changed when you relabelled one, and policy that silently re-points is worse than policy that cannot express something.

Granularity comes from profiles. A profile is the unit of separation, so the way to give one agent a narrower view is to give it a narrower profile:

console
$ lanes link profile add reading --profile-default false
$ lanes link connect gmail --profile reading --workspace local
$ lanes link policy deny 'gmail.send' 'gmail.users.messages.trash' --profile reading --workspace local

Register that profile with the agent you want held back, and the wider one with the agent you trust. Nothing in reading can see what personal holds, which is the same isolation the built-ins get.

Seeing what an agent actually has

console
$ lanes link status --profile personal --workspace local
$ lanes link tools --profile personal --workspace local

status lists every connection and what it makes reachable. tools is the exact list an agent would be handed right now. If the count your client shows disagrees with tools, your client is stale and wants reconnecting, not repolicying.

Everything is recorded either way

A refused call is an audit entry, not a silent no-op. lanes link audit tail --denied-only is how you find out that a policy is narrower than the work needs, or that an agent is reaching somewhere you did not expect. See the audit log.


Next: every provider for the scopes each one asks for, or Capabilities for why a capability is a tool, a resource, or a prompt.