feat(auth): granular API token scopes, team binding, and a token modal #87
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/api-token-scoping"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #81
Macht das API-Token-Scoping granular, erzwingt die Team-Beschränkung und ersetzt das Anlege-UI durch ein Modal.
⚠️ Breaking change
Die alten
ai:*-Scopes wurden entfernt. Bestehende AI-Tokens müssen neu erstellt werden (die AI-/MCP-Endpoints verlangen jetzt die neuen Scopes).Scope-Modell (
internal/auth/scopes.go)read,write,write:draft,write:schedule,delete,delete:draft,delete:schedule—writeist Superset vonwrite:draft/write:schedule,deletevondelete:draft/delete:schedule,readunabhängig.Bestätigte Entscheidungen:
Sicherheits-Fix: Team-Bindung
api_tokens.team_idwurde bisher zwar geladen, aber nie durchgesetzt — ein „team-scoped" Token konnte auf alle Teams des Users zugreifen. Jetzt verweigertPrincipalHasTeamAccessjeden fremden Team-Zugriff (auch für Admins), wenn der Token an ein Team gebunden ist.Durchsetzung
read.write:draft/write:schedulebzw.delete:draft/delete:scheduleanhand des Post-Status (in-Handler).read; Write-/Delete-Tools prüfen ihren Scope.400 unknown_scope.Store
api_tokensbekommt einedescription-Spalte (sqlite + postgres, create table +alter … if not exists-Migration).CreateUserAPITokennimmt eine Beschreibung; das Listing liefert nunscopes+description.Frontend
Neues
ApiTokenManager: „+ New Token" öffnet ein Modal (Name, Beschreibung, Team-Auswahl, gruppierte Scope-Checkboxes, Ablaufdatum). Der erzeugte Token wird einmalig in einem Reveal-Modal angezeigt und per Klick in die Zwischenablage kopiert. Die Liste zeigt Beschreibung, Team und Scope-Chips.Tests
auth: Scope-Hierarchie,PrincipalAllows(unscoped=full, OIDC-exempt), Team-Bindungstore(sqlite + postgres): description/scope/team-Roundtrip, neue Spalteapi: Create-Post ohnewrite:schedule→ 403 / mit → 201, team-bound Token auf fremdem Team → 403, Read-Gatemcp: Gate (read) + Write-Tool-Scopego build/vet/test ./...,make test-postgres,pnpm build+lint(0 errors), Locales key-identisch — alles grün.🤖 Generated with Claude Code