1 Users Teams and Access
mitosis edited this page 2026-09-02 08:56:51 +00:00

Bring people onto the platform and scope exactly what they can touch. This page covers registration, teams as permission sets, the operator/admin split, and the restricted machine accounts to copy when you need a bot.

Registration

Registration is open. New users sign up at https://git.open-platform.sh/user/sign_up. Sign-up uses an image CAPTCHA and internal accounts only — no external auth. Every new user can create organizations. Everything they create is private by default.

Note: for an invite-only instance, set the Forgejo switch DISABLE_REGISTRATION. The platform works in either mode.

Add a person to an org

Membership flows through teams. A user is in an org because they are on one of its teams.

UI: open the org page → Teams in the sidebar → pick a team → Add Team Member. The URL shape is https://git.open-platform.sh/org/<org>/teams/<team-name> — for example https://git.open-platform.sh/org/homestead/teams/owners.

API (the same calls the platform itself uses):

# find the team id
curl -s https://git.open-platform.sh/api/v1/orgs/<org>/teams?limit=50 -H "Authorization: token $TOKEN"
# add the member (422 = already a member; retry on 5xx only)
curl -X PUT https://git.open-platform.sh/api/v1/teams/<team_id>/members/<username> -H "Authorization: token $TOKEN"

To grant one repo instead of a whole org, use repo Settings → Collaborators, or PUT /api/v1/repos/{org}/{repo}/collaborators/{username} with {"permission": "read"|"write"|"admin"}.

Note: org membership is not repo permission. Authorization checks run against repo-level permission (owner | admin | write | read | none). Teams and collaborator grants confer that permission. This rule is the keystone of the access model.

Teams are permission sets

Every org has a built-in Owners team with full control. Every other team carries a level — read, write, or admin. A team can narrow that level to specific repo units (repo.code, repo.issues, repo.packages, ...) with per-unit overrides.

The platform's own pattern is the sharpest example. Each org gets a registry-writers team. The team can push container images and Helm charts, and it can touch nothing else:

{
  "permission": "read",
  "units": ["repo.packages"],
  "units_map": { "repo.packages": "write" },
  "includes_all_repositories": true,
  "can_create_org_repo": false
}

The units_map keeps the team from carrying any repo permission. Package-write is only delegatable through an org team — that is why every app is org-owned. Copy this shape for any narrow grant:

  1. Pick the unit.
  2. Map only that unit to write in units_map.
  3. Keep the base permission at read.

Operator vs admin

The platform separates two hats by construction. Nobody wears both at once.

The operator is a normal user. The operator is not a site admin and has zero access to the system repos in the platform org (open-platform/*). The operator is Owner of every product org. The operator steers the fleet through three surfaces: labels (agent-work, ultracode), the /flow/:org API, and mission-control issues on their own <login>/fleet repo.

The admin is plat — the platform's root. plat is the Forgejo site admin and the Owner of the platform's own org, open-platform, which holds the platform-altering repos: open-platform/agents, open-platform/mcp, open-platform/gitops, open-platform/mitosis, open-platform/app-template, and open-platform/ci-runner. The org is public (the template must be visible to anyone who clicks "Use this template"; the seed repo is what a stranger clones), and plat is the only identity that writes to it. The dispatcher runs as plat. Log into plat only for admin duties; everyone else — including you — works from their own account and orgs.

Warning: never make an operator a site admin. Product work never needs admin. Platform changes never ride an operator account.

To make someone an operator:

  1. Add their login to the dispatcher env var PLAT_OPERATORS.
  2. Add them to the Owners team of the product orgs.
  3. Create their <login>/fleet repo.

See Steering the Fleet for the day-to-day work of the operator seat.

Machine users: the restricted-bot model

When automation needs a credential, mint a restricted user with the narrowest token scope that works. A restricted user (Forgejo restricted: true) sees only what it is explicitly granted. The table shows two live examples to copy.

Bot Access Token scope
ci-bot write on open-platform/mitosis; read on gitops/agents/mcp/app-template and a few others write:repository,write:issue
registry-bot-<org> member of that org's registry-writers team only write:package only

The platform derives each registry-bot password on demand and stores none. Agents get no user account at all. Each agent run pushes with a per-run SSH deploy key scoped to one repo. The platform deletes the key when the run exits. An agent cannot write outside its assigned repo. The Security Model page explains why this design holds.

What a new member sees

The platform is private-first. A new member sees their own orgs and repos, the public seed repos on /explore, and nothing else. Every org and app repo is born private (DEFAULT_ORG_VISIBILITY=private, DEFAULT_PRIVATE=private). Other tenants' work stays invisible unless a team or collaborator grant says otherwise.

The first stop after sign-up is Build Your First App. For app credentials, Secrets and Config shows the self-serve channel. Secrets go in repo settings, never in issues or comments.