Files
terdut-server/internal/db/migrations/013_oidc_team_groups.sql
T
Niklas Ye 5b4683febf Let each team name its own OIDC group, not a global mapping
Team membership from single sign-on used to come from one env var,
TERDUT_OIDC_GROUP_MAPPINGS, matched against a team by name and creating
the team if none existed. That put the decision in the server's
environment rather than the team's own hands, needed a restart to
change, and let a typo in a team name silently create a stray team.

Each team now carries its own oidc_member_group and oidc_owner_group,
set by its owner (or an administrator) from the Members tab, or PUT
/api/teams/{teamID}/oidc-groups. The "highest role wins" rule
TERDUT_OIDC_GROUP_MAPPINGS used to apply across mappings now applies
across one team's own two fields: being in both makes somebody an
owner. The sync no longer creates a team by name; a group only ever
grants into a team that already exists.

This is a breaking change for anyone already using
TERDUT_OIDC_GROUP_MAPPINGS, deliberately not auto-migrated: an
OIDC-sourced membership is dropped at a user's next sign-in until its
team's owner re-sets the group. The README's OIDC section spells out
the migration and the risk of a visible access gap during it.

TERDUT_OIDC_ADMIN_GROUP and TERDUT_OIDC_ALLOWED_GROUPS are untouched --
only team membership moved. terdut-tui needs no change: it only reads
GET /api/teams and GET /api/teams/{id}/members, and neither response
shape moved.
2026-09-27 11:43:57 +02:00

27 lines
1.5 KiB
SQL

-- Per-team OIDC group configuration, replacing the global
-- TERDUT_OIDC_GROUP_MAPPINGS env var.
--
-- Group -> team -> role used to be one global list an operator set for the
-- whole install, matched against a team by name, and the sync would create
-- the team if no team by that name existed yet. That put the decision of
-- which group controls a team in the server's environment rather than the
-- team's own hands, meant changing it needed an env var edit and a restart,
-- and let a typo in a team name silently create a stray team.
--
-- Each team now names, itself, which group grants membership and which
-- grants ownership. Nullable: most teams need neither. No uniqueness
-- constraint on either column — two teams may legitimately watch the same
-- provider group (a broad team and a narrower one both keyed off overlapping
-- groups is a choice for their owners to make, not one the schema should
-- refuse).
--
-- BREAKING CHANGE, deliberately not auto-migrated: TERDUT_OIDC_GROUP_MAPPINGS
-- stops being read as of this version, and the sync no longer creates a team
-- by name. Every team's group binding must be set again through
-- PUT /api/teams/{teamID}/oidc-groups. Until an owner does that, an
-- OIDC-sourced membership in that team is dropped at that user's next SSO
-- sign-in, the same way any other loss of group access is handled. See the
-- README's OIDC section.
ALTER TABLE teams ADD COLUMN oidc_member_group TEXT;
ALTER TABLE teams ADD COLUMN oidc_owner_group TEXT;