This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/docs/ICD/teams.md
2026-03-12 10:22:08 +00:00

259 lines
6.9 KiB
Markdown

# Teams & Access Control
### My Teams
```
GET /teams/mine → { "data": [...] }
```
**Auth:** Authenticated user.
Returns teams the current user is a member of (active teams only).
Each team object:
```json
{
"id": "uuid",
"name": "Engineering",
"description": "...",
"is_active": true,
"settings": "{}",
"my_role": "admin|member",
"member_count": 5
}
```
### Team Administration
**Team CRUD (platform admin):**
```
GET /admin/teams → { "data": [...], "total": N, "page": N, "per_page": N }
POST /admin/teams ← { "name", "description" } → { "id", "name" }
GET /admin/teams/:id → team object (unwrapped)
PUT /admin/teams/:id ← { "name"?, "description"?, "is_active"?, "settings"? }
DELETE /admin/teams/:id
```
**Auth:** `RequireAdmin` (platform admin).
`POST` returns `201`. `PUT`/`DELETE` return `{"ok": true}`. `PUT` with
no fields returns `400`. Duplicate name returns `409`.
**Members (admin routes):**
```
GET /admin/teams/:id/members → { "data": [...] }
POST /admin/teams/:id/members ← { "user_id", "role" } → { "id" }
PUT /admin/teams/:id/members/:memberId ← { "role" }
DELETE /admin/teams/:id/members/:memberId
```
**Auth:** `RequireAdmin`.
`role` must be `admin` or `member`. Duplicate membership returns `409`.
**Team-scoped routes** (team admin self-service):
```
GET /teams/:teamId/members
POST /teams/:teamId/members ← { "user_id", "role" }
PUT /teams/:teamId/members/:memberId
DELETE /teams/:teamId/members/:memberId
```
**Auth:** `RequireTeamAdmin`.
Same handlers as admin routes; the `getTeamID()` helper reads either
`:id` or `:teamId`.
**Team Providers:**
```
GET /teams/:teamId/providers → { "data": [...], "allow_team_providers": bool }
POST /teams/:teamId/providers ← { "name", "provider", "endpoint", "api_key", ... }
PUT /teams/:teamId/providers/:id
DELETE /teams/:teamId/providers/:id
GET /teams/:teamId/providers/:id/models → { "models": [...], "provider": "name" }
```
**Auth:** `RequireTeamAdmin`.
`GET` returns provider configs scoped to the team. The `models` endpoint
performs a live query to the upstream provider.
**Team Models:**
```
GET /teams/:teamId/models → { "models": [...] }
```
**Auth:** `RequireTeamAdmin`.
Returns all models available to this team: global admin models with
`visibility IN ('enabled', 'team')` plus live-queried team provider
models with `source` field (`"global"` or `"team"`).
**Team Groups:**
```
GET /teams/:teamId/groups → { "data": [...] }
```
**Auth:** `RequireTeamAdmin`.
Returns groups scoped to this team.
**Team Personas:** See personas.md §Team Personas.
**Team Roles:**
```
GET /teams/:teamId/roles → { "data": {...} }
PUT /teams/:teamId/roles/:role ← RoleConfig object
DELETE /teams/:teamId/roles/:role
```
**Auth:** `RequireTeamAdmin`.
`GET` returns the team's `model_roles` settings map (composite object,
not an array). Initially empty `{}`. Each key is a role name, value is
a `RoleConfig`. `PUT` validates the role name. `DELETE` removes the
override, falling back to the global role definition.
**Team Audit:**
```
GET /teams/:teamId/audit → { "data": [...], "total": N, "page": N, "per_page": N }
GET /teams/:teamId/audit/actions → { "actions": [...] }
```
**Auth:** `RequireTeamAdmin`.
Audit log is scoped to actions performed by team members. Supports
query filters: `?action=`, `?actor_id=`, `?resource_type=`.
**Team Usage:**
```
GET /teams/:teamId/usage → { "totals": {...}, "results": [...] }
```
**Auth:** `RequireTeamAdmin`.
Returns usage against team-owned providers. Supports query params for
date range filtering.
### Groups & Resource Grants
Groups are ACL containers that decouple access from team membership.
A resource grant controls who can see a Persona or KB beyond its base
scope.
**My Groups:**
```
GET /groups/mine → { "data": [...] }
```
**Auth:** Authenticated user.
**Admin Group CRUD:**
```
GET /admin/groups → { "data": [...] }
POST /admin/groups ← { "name", "scope", "team_id"? }
GET /admin/groups/:id → group object (unwrapped)
PUT /admin/groups/:id ← { "name"?, "description"?, "permissions"?, ... }
DELETE /admin/groups/:id
```
**Auth:** `RequireAdmin`.
`POST` returns `201`. Duplicate name returns `409`. Deleting a
system-sourced group (e.g. Everyone) returns `400`.
**Group Members:**
```
GET /admin/groups/:id/members → { "data": [...] }
POST /admin/groups/:id/members ← { "user_id" }
DELETE /admin/groups/:id/members/:userId
```
**Auth:** `RequireAdmin`.
**Resource Grants:**
```
GET /admin/grants/:type/:id → grant object (unwrapped)
PUT /admin/grants/:type/:id ← { "grant_scope", "granted_groups"?: [...] }
DELETE /admin/grants/:type/:id
```
**Auth:** `RequireAdmin`.
`:type` is `persona` or `kb`. `:id` is the resource ID.
Grant scopes:
| `grant_scope` | Visibility |
|---------------|-----------|
| `team_only` | Only the owning team |
| `global` | All authenticated users |
| `groups` | Members of specified groups |
Setting `grant_scope: "groups"` without `granted_groups` returns `400`.
### Permissions
Groups carry fine-grained permissions. Permission resolution:
union of all group permissions + Everyone group permissions.
**List all permissions:**
```
GET /admin/permissions → { "permissions": ["model.use", "kb.read", ...] }
```
**Auth:** `RequireAdmin`.
**Get user's effective permissions:**
```
GET /admin/users/:id/permissions → { "permissions": [...], "user_id": "...", "groups": [...] }
```
**Auth:** `RequireAdmin`.
Returns the resolved permission set and contributing group IDs
(always includes the Everyone group).
**Group permission fields** (set via `PUT /admin/groups/:id`):
```json
{
"permissions": ["model.use", "kb.read", "channel.create"],
"token_budget_daily": 100000,
"token_budget_monthly": 3000000,
"allowed_models": ["claude-sonnet-4-20250514", "gpt-4o"]
}
```
| Field | Type | Description |
|-------|------|-------------|
| `permissions` | string[] | Permission constants granted to members |
| `token_budget_daily` | int/null | Daily token ceiling (NULL = unlimited) |
| `token_budget_monthly` | int/null | Monthly token ceiling (NULL = unlimited) |
| `allowed_models` | string[]/null | Model allowlist (NULL = unrestricted) |
**Everyone group:** System-seeded group (ID `00000000-0000-0000-0000-000000000001`)
whose permissions apply to all authenticated users implicitly (no membership
row needed). Editable by admins, cannot be deleted (`source=system`).
**RequirePermission middleware:** Routes gated by permission check user's
resolved permission set. Returns 403 if the required permission is not present.
See [enums.md](enums.md) for the full permission constant list.