Organizations, projects and teams

Hierarchy

  • Organization (org) — the top level: billing/quotas, members, teams, probes, SSO. Everything else lives inside it.
  • Project — a specific application or service: it has its own DSN, its own issues, its own monitors, and so on.
  • Team — a group of an organization’s members that can be granted access to a subset of projects, without handing out an organization-wide role.

Roles

Roles are assigned at the organization level and apply across all its projects:

RoleCan do
ownerEverything admin can, plus: grant/revoke the owner role for others, remove owners, see the organization’s SSO section (configuring it isn’t gated by the owner role at all, but by a separate “instance administrator” flag — the section is visible to whoever carries that flag too, even for organizations they don’t own), export/delete subjects’ personal data, delete the organization entirely
adminInvite and remove members, change admin/member roles (not owner), manage ingest quotas, create/delete teams, manage probes and project settings (monitors, status pages, maintenance windows)
memberWorks inside the projects they have access to (issues, performance, metrics, uptime, etc.), with no access to the organization’s admin pages

An organization’s last owner cannot be demoted or removed — the system always protects against an organization ending up with no owner.

Instance admin

Separately from organization roles, there’s an instance administrator flag (users.is_instance_admin) — exactly one per instance, unrelated to any role in any organization. It’s assigned automatically to the first user registered on the instance.

The instance administrator configures and removes SSO for organizations — that capability isn’t granted by the owner role, only by this flag (see the roles table above). While other users exist on the instance, the instance administrator’s account cannot be deleted until the role is transferred to one of them — otherwise SSO for every organization would become unreachable to everyone. If the instance administrator is the only user on the instance, they can delete their own account freely: there’s no one to transfer the role to, and the next person to register becomes the administrator automatically.

Transfer the role from the “Instance admin” section on /profile: enter the email of an existing instance user and confirm the transfer. Once confirmed, the role moves to the recipient immediately, and the previous administrator loses access to SSO configuration and the ability to transfer the role again.

Recovery if access to the instance administrator’s account is lost: the administrator’s account still cannot be deleted while other users exist on the instance — but the password can be recovered if that’s all that’s missing.

If only the password is forgotten, two paths:

  • Self-service, when the instance has outgoing email configured (GOTCHA_SMTP_*): the /forgot-password page (“Forgot password?” on /login) emails a link to set a new password to the given address. The link is valid for an hour and single-use; setting a new password through it ends every existing session for that account.

  • Through an operator, when email isn’t configured (in that case /forgot-password says so plainly instead of showing a form that would silently do nothing) or the mailbox itself is also unreachable: the gotcha set-password --email=<address> subcommand sets a new password directly in the database. The password is read from standard input, not a command-line argument — an argument would end up in shell history and the process list. Don’t type the password as a literal in the command either (that also lands in history) — use read -s so it’s neither echoed nor saved:

    read -rs -p 'New password: ' PW && printf '%s\n' "$PW" | gotcha set-password --email=admin@example.com; unset PW
    

    The subcommand itself doesn’t mask input — typing the password directly at its own prompt, bypassing read -s, echoes it to the screen.

If the account is completely unreachable (no way to recover or reset the password — the email itself is gone too, say), an operator with access to the instance database assigns a new administrator directly, in one transaction — BEGIN/COMMIT are required: psql autocommits by default, and without them a typo in the email after the first UPDATE silently leaves the instance with no administrator at all:

BEGIN;
UPDATE users SET is_instance_admin = false WHERE is_instance_admin;
UPDATE users SET is_instance_admin = true WHERE email = '<email>';
COMMIT;

Before COMMIT, verify each UPDATE reported UPDATE 1 — UPDATE 0 on the second command means a typo in the email, and committing in that state leaves the instance with no administrator. The partial unique index one_instance_admin prevents two users from ending up as administrator at once.

Ending someone else’s session

There’s no button, for an owner or admin, that ends another member’s active login session directly — signing out of other devices is self-service only, from the “Sessions” section on /profile (“Sign out of all other devices” ends every session on that account except the one used to click it).

If a member’s device is lost or compromised and you need to act without them, what actually ends every one of their sessions is a password change on that account: it deletes every session row for that user immediately, the same mechanism the recovery paths above rely on. The member can do this themselves once they’re on a device they trust; if they can’t, an operator with access to the instance’s server can force it with gotcha set-password --email=<address> (see above) — an admin or owner without server access has no way to do this through the web app.

Two more actions address a related but different risk, worth doing alongside it:

  • Revoke the project’s ingest keys the device had access to, from project settings — this doesn’t touch a login session at all, but it does stop a key stored on that device from still sending telemetry (allow up to 30 seconds for the revocation to take effect, see Ingest keys).
  • Remove the member from the organization (“Settings” → “Organization” → “Members”) if they shouldn’t have access at all: membership is checked on every request, not cached, so this cuts off every project’s data immediately — even though, if their login session is still valid, they could still sign in to an account that now sees no organization.

Inviting members

The “Settings” → “Organization” → “Members” page (/orgs/{id}/settings, owner/admin only) has a table of current members (email, role, change-role, remove) and an invite form:

  1. Enter the invitee’s email.
  2. Pick a role — member or admin (the owner role cannot be granted through an invite — it can only be assigned to an existing member afterward).
  3. Click “Invite”.

If the server has no SMTP configured, the invite is still created but no email is sent — instead, the page shows a direct invite link once, which you forward to the person manually (it’s not shown again).

Until it is accepted, an invitation is listed under “Awaiting acceptance” on the same page and can be revoked there — mistype an address, and revoking kills the link before a stranger can use it. Accepting removes the invitation from the list and adds the member.

What happens next depends on the instance’s registration mode (GOTCHA_REGISTRATION_MODE, see Configuration):

  • open — self-registration is always open; an invite is just a way to add someone with a specific role right away;
  • invite (default) — self-registration closes once the instance has its first user; joining afterward requires a valid invite link (or OAuth/SSO, if a pending invite exists for that email);
  • closed — self-registration is closed entirely, except for the instance’s very first user.

Teams

The “Settings” → “Organization” → “Teams” page (/orgs/{id}/teams, owner/admin only) lets you group members and grant them access to specific projects without changing their organization-wide role.

Creating a team:

  1. Click the “+” next to the page heading — a “Create team” modal opens.
  2. Enter a Slug (a short identifier, e.g. backend) and a Name (the display name, e.g. “Backend”).
  3. Save.

Each team gets its own card on the page, with two lists and forms underneath. The card heading carries a “Rename” button: it changes the display name without touching members or attached projects. The slug stays as it is — it is used in URLs and in access grants.

Inside the card:

  • Members — a table of current members, an add form with a dropdown (listing only organization members not yet in this team), and a remove button on each row.
  • Projects — a table of attached projects, an attach form with a dropdown (listing only organization projects not yet attached), and a detach button on each row.

Only someone already in the organization can be added to a team; attaching a project to a team doesn’t change what organization owners/admins can see — they already see every project.

Roles and access

Being on a team attached to a project — an operator, in the table below — is what lets a member actually run the monitoring day to day, without promoting them to admin and handing them every other project in the organization along with it. Org owners and admins automatically qualify as operators on every project too, since they already have full access.

ActionViewer (access)Operator (team member)AdminOwner
View issues, performance, uptime, alerts, etc.✓✓✓✓
Change an issue’s or a performance issue’s status✓✓✓✓
Acknowledge an open incident — any of the six sources (hosts, metrics, traces, profiles, SLOs, uptime)—✓✓✓
Monitors: create, edit, pause/resume, delete—✓✓✓
Heartbeat monitor: regenerate the ping token—✓✓✓
Maintenance windows: create, edit, delete—✓✓✓
Status page content: create/edit a page, pick monitors and titles; delete it while unpublished—✓ (a page an operator creates starts unpublished)✓✓
Status page publication: the “Published” toggle, or deleting a page that’s already published——✓✓
Alert rules (new issue / regression / spike)—✓✓✓
Escalations: per-severity notification ladders (“Critical”/“Warning”)—✓✓✓
Storm suppression: dependency edges — create, edit, delete—✓✓✓
Alert channels: create, edit, delete, “Test”—— (sees each channel’s kind and a masked target only, enough to tell channels apart when picking one in a rule)✓✓
Delivery log—✓ (targets masked)✓ (full)✓ (full)
Metric alerts: create, edit and disable, delete—✓✓✓
SLOs: create, delete—✓✓✓
Recipes: turn on a service’s recommended thresholds—✓✓✓
Hosts: project-wide thresholds, environment/role label groups, a per-host threshold override, deleting a host—✓✓✓
Exports: queue and delete an export job—✓ (sees and downloads only their own jobs)✓ (every job in the project)✓ (every job in the project)
Project settings (rename, DSN keys, quotas, sample rate)——✓✓
Create a new project——✓✓
Organization management (members, roles, invites, teams, probes)——✓✓
Delete a project or the organization———✓

“Viewer” here isn’t a role of its own — it’s what CanAccessProject grants to anyone who can already see the project (an org owner/admin, or a plain member on an attached team), before touching the operator predicate at all. In other words, every operator is also a viewer, and every admin and owner is also an operator: the columns are cumulative, not exclusive tiers.

What team membership buys a member, in short: everything about running monitoring day to day on that project’s monitors, maintenance windows, status pages, alert rules, and metric alerts — the operational surface, without an organization-wide role. What still requires admin (or owner): alert channels, because their recipient and secret (a bot token, an SMTP address, a webhook URL) are credentials and personal data, not operational settings; whether a status page is actually public, because that’s a decision about what the organization shows the world, not how monitoring is run; and project settings and everything at the organization level, unchanged from before.

What’s next