Groups and access
Decide who can open an app, see exactly why each answer came out that way, and take access back.
Access is decided per app, per person, at the moment they ask. Nothing is cached into a person's session and left there, so the answer can change without anyone signing out and back in.
People and groups
Everyone who can sign in belongs to your team. People lists them; the person who owns the team and anyone running it can open every app, which is why they never appear in an app's rules.
A group is a named set of people — family, friends, beta-testers.
Someone can be in several. Grant a group access to an app once, and after that
you manage the app by moving people in and out of the group rather than by
editing the app.
The three ways to grant access
You can give one app's access to a person directly, to a group, or to a role in the team. Use a direct grant for an exception; use a group for anything you will do twice.
Each grant carries a role, which travels through to the app so it can tell an admin from a member. When several grants match the same person, the highest role among them wins.
Deny wins
A grant can also be a deny, and a deny beats every allow that matches. That is how you exclude one person from one app without dismantling the group access everyone else depends on. There is no ordering to reason about and no precedence to configure: if anything denies, the answer is no.
The full order the platform works through, first answer wins:
- Is this app switched off, or is the request for a different app? No.
- Has the person, their session, or the app's access been revoked? No.
- Does the session belong to this person, and is it still current? If not, no.
- Is the person banned? No.
- Are they in the team that owns this app? If not, no.
- Do they own or run the team? Yes, as an admin.
- Does anything deny them? No.
- Does anything allow them? Yes, at the highest role that matched. Otherwise no.
Signing up
Each app decides what happens when someone signs in successfully but is not in the team yet:
- Closed — they are shown a page saying whoever runs the app can let them in, and the attempt is recorded so you can see it.
- Invite only — they get in only by accepting an invitation sent to their verified address. Anything else about the invitation being wrong — expired, already used, a different address, a different team — fails the same way.
- Open — they join the team as a member on first sign-in.
Neither refusal page names the app, the person, or which of the two happened. Someone who was removed yesterday and a complete stranger see the same words.
Invitations
An invitation adds someone to the team when they accept, and can place them in groups at the same moment. It grants nothing before acceptance, and it cannot give someone a single app on its own — that is what the group placement is for. If no group opens the app you are inviting them to, the dashboard tells you so before you send it, because otherwise the person joins the team and still cannot open the thing they were invited to.
Ways in that are not accounts
An app that is walled off can also be opened without an account at all. All three appear on the app's Access screen, with how often each has been used, and any of them can be turned off there.
- Shared password — one password for the app. Rotating it invalidates every session it created.
- Share link — a signed link a visitor redeems for a session. Each redemption creates one session; an optional expiry, a maximum number of uses, or revoking the link decide whether it can be redeemed again.
- Bypass token for CI — a header a build job sends. It authorizes a request and normally leaves no cookie behind.
Rotating any of them issues a new secret and retires the old one in one step. The secret itself is shown once, at creation or rotation, and is never retrievable afterwards — the screens that list these grants are not given the stored value in the first place.
Protect an app covers how each of these behaves in front of a real app.
Why someone has access
The Access screen answers with the reason, not just the verdict: the direct grant, the group that carried it, the team role, or the deny that stopped it. Every person in the team is listed with their current answer, so "who can open this" is a thing you read rather than a thing you work out.
If two grants would give the same person conflicting roles and neither is higher, the screen says the role is unsettled instead of picking one quietly.
History
History records changes as they are made, newest first, with who did it and what it affected. It is append-only. Grants, denies, Group edits, invitations, and rotations all land there, whether they came from the dashboard, the HTTP API, or an agent using the MCP tools.
A few moments that are not changes land there too: somebody getting into a walled-off app with a shared password, a share link, or a bypass token; somebody asking to be let in; somebody being turned away, and why; an invitation being accepted; somebody joining the team on first sign-in; and somebody agreeing to let an app see who they are.
Full sign-in and visit history is not recorded yet. There is no row for every sign-in and no row for every page somebody opens, so History answers "what changed, and who first got in" rather than "where has this person been".
Taking access back
Removing someone from a group, denying them, banning them, or ending their session all take effect on a walled-off app in under a minute. The change is pushed out as soon as it is made, and a scheduled check every sixty seconds covers the case where the push did not arrive — so a minute is the worst case, not the usual one.
Apps that hold their own tokens are a different shape. Those tokens are good for at most fifteen minutes, and access is re-checked when they are next refreshed, so removal there lands within that window rather than within a minute.
Nothing here is instant, and nothing pretends to be. What is guaranteed is the bound: under a minute for a walled-off app, and within the token lifetime for an app holding its own. If a removal has to be provably complete before you do something else, wait out the window rather than assuming the push arrived first.