Skip to main content

Team structure

TRUSCA models authorization as one Organization, many Teams, and three Roles. Projects belong to teams; roles are granted per team. The structure decides who can scan what, who can dispose approvals, and who sees which projects — so it is worth designing rather than growing by accident. This page helps you choose a team layout that matches how your engineering org actually works.

Audience

super_admin laying out the organization at install time, and team_admin deciding whether their team should split. Familiarity with the RBAC model. RBAC is Role-Based Access Control — permissions attach to roles, not individuals.

The model, in one picture​

Organization (one per deployment)
├── Super Admin — system-wide: all /admin screens, create/delete teams, edit any project
├── Team A
│ ├── Team Admin — manages Team A's membership, settings, policy, API keys; disposes approvals
│ └── Developer — runs scans, triages findings in Team A's projects
└── Team B
└── ...

There is exactly one Organization per deployment. A user can hold a different role in each team — team_admin in one, developer in another — because roles are additive across teams and evaluated per project by the project's owning team. See the full role capabilities table.

A team can also nest other teams under it, to any depth; see Nested groups for how to move one or create a subgroup, and how the permission cascade and the always-on license/gate policy walk each carry a role or a policy down from a parent. The guidance below (roles, visibility, and when to split) applies the same way whether a team sits at the root of the organization or several levels deep.

Choosing roles​

Grant the least role that lets someone do their job:

RoleGive it toNot for
super_adminThe operators who run the deployment — install, upgrade, backup, Trivy DB, org-wide policy.Ordinary engineers. A super-admin can read every team's data.
team_adminA team's tech lead or compliance owner — manages members, team policy, API keys, and disposes approvals.Every engineer on the team.
developerEngineers who scan and triage.Anyone who only needs to read a report — reading is already covered by team membership.
Keep at least two super-admins

The portal refuses to demote or deactivate the last active super_admin, but that guard is a floor, not a plan. Always have a second super-admin so an off-boarding or a forgotten password never locks you out of /admin. See last-super-admin protection.

Grant super_admin sparingly — it is org-wide and bypasses team boundaries. Most compliance leads only need team_admin on the teams they own.

Project visibility: team-only vs org-wide​

Each team carries a default visibility for the projects it creates, set at team creation:

VisibilityWho can see the projectUse when
team_only (default)Members of the owning team onlyThe default. Projects contain findings a team should triage before wider exposure.
org_wideEvery user in the organization (read)A shared platform library, a reference SBOM, or a project whose risk posture the whole org should see.

Visibility governs read exposure, not write. Editing, scanning, and disposing approvals still require a role on the owning team regardless of visibility. Start team_only and promote a project to org_wide deliberately — widening is easy, and you avoid leaking a team's in-progress triage to the whole org by default.

When to split a team​

A team is the unit of ownership, visibility, and policy. Split when those three want to diverge — not merely because the headcount grew:

  • Different policy needs. One group ships a redistributed binary (copyleft is a real risk) and another ships a closed SaaS (copyleft is often fine). A per-team license policy only helps if they are separate teams.
  • Different approval authority. Approvals are disposed by a team_admin of the owning team. If team A must not sign off on team B's conditional-license usage, they need separate teams.
  • Visibility boundaries. A confidential project should not be readable by unrelated engineers. Separate teams keep team_only meaningful.
  • Independent membership churn. Contractors or a partner team you on/off-board on a different cadence belong in their own team, so a membership change never touches your core team.

Reasons not to split: a shared component that several teams consume (make its project org_wide instead), or a need that is really about position in the hierarchy rather than policy, visibility, or approval authority (nest a subgroup under the existing team instead of standing up an unrelated one; see Nested groups). Every extra team is another membership list and policy to keep current; split for a boundary, not for tidiness.

One person, many teams

Because roles are per team, a platform engineer can be team_admin on the shared-infra team and developer on a product team without a second account. Splitting teams does not fragment a person's access — add the membership at the right role instead.

A component shared across teams​

When the same dependency shows up in several teams' projects, each project raises its own approval request — verdicts do not propagate, because the same license can carry different obligations under different distribution models. That is deliberate; see cross-project approvals. If you want one ruling to apply everywhere, either dispose each project's request and reference the originating decision, or encode the verdict as a license override in the org-default policy so every team inherits it.

Verify it worked​

Review the layout you chose:

  1. Every engineer holds the least role that lets them work — developer unless they manage members, policy, or approvals.
  1. At least two active super_admin accounts exist.
  1. New projects default to team_only; any org_wide project is a deliberate choice, not the default.
  1. Teams that need different license policy or different approval authority are actually separate teams, and a person needing access to several teams is added to each at the right role rather than promoted to super_admin.
  1. A shared dependency's approval verdicts are handled per project (or encoded once in the org-default policy) — you are not expecting them to propagate.

See also​