API · 31 operationer
auth-api
Genererad ur services/auth-api/openapi.json, kontraktsversion 1.0.0. Auth-modell och anropare står i atlasen.
GET /.well-known/jwks.json
Jwks
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | object application/json |
GET /.well-known/openid-configuration
Openid Config
Maskinidentitetsytan — och EN hänvisning vidare (D-71, Task 6). Fälten nedan beskriver `/v1/token/client`: client_credentials, hemlighet i `client_secret_basic`. De är oförändrade sedan tjänsten byggdes, med flit. Auktoriseringsserverns yta (Task 3-5) bor på en ANNAN token-endpoint (SDK:ns `/token`, publika klienter, PKCE), och OIDC-discovery har bara ett `token_endpoint`-fält — att peka om det hade tyst brutit varje integratör som läst det här dokumentet för att nå maskinidentitetsvägen. Alltså: två dokument, ett per yta, och en länk mellan dem i stället för ett dokument som ljuger om någondera. `oauth_authorization_server_metadata` är ingen registrerad OIDC-parameter, men OIDC Discovery 1.0 §3 tillåter ytterligare metadata — samma undantag och samma husform som Task 4:s `resource_indicators_supported` i RFC 8414-dokumentet. Länken sätts BARA när OAuth-ytan faktiskt är rest (`oauth_enabled` är all-or-none). Att peka på ett dokument som svarar 404 vore att byta ut en ofullständig sanning mot en osann.
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | object application/json |
GET /healthz
Healthz
Liveness: process is alive. No deps check.
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | { [nyckel]: string } application/json |
GET /readyz
Readyz
Readiness: process can serve traffic. Checks deps.
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | any application/json |
GET /v1/admin/tenants/{tenant_id}/channel-identities
List Channel Identities
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | ChannelIdentityList application/json |
422 | Validation Error | HTTPValidationError application/json |
DELETE /v1/admin/tenants/{tenant_id}/channel-identities/{channel}/{team_id}/{external_user_id}
Unmap Channel Identity
Ta bort mappningen. Idempotent; `removed` säger om något fanns. Gäller nästa anrop mot `/v1/token/channel`. Redan utfärdade token lever till sin `exp`, av samma skäl som för återkallad delegering.
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
channel | path | string | ja |
team_id | path | string | ja |
external_user_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | ChannelIdentityRemoved application/json |
422 | Validation Error | HTTPValidationError application/json |
PUT /v1/admin/tenants/{tenant_id}/channel-identities/{channel}/{team_id}/{external_user_id}
Map Channel Identity
Mappa kanalkontot till personen med den här e-posten. Idempotent. Samma person igen: ingen ändring, ingen auditrad. Annan person: raden skrivs om och auditas med `previous_user_id`, så en ommappning aldrig ser ut som en första mappning i kedjan.
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
channel | path | string | ja |
team_id | path | string | ja |
external_user_id | path | string | ja |
authorization | header | string | null | nej |
Kropp: ChannelIdentityPut application/json
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | ChannelIdentityOut application/json |
422 | Validation Error | HTTPValidationError application/json |
GET /v1/admin/tenants/{tenant_id}/export
Export Tenant
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string (uuid) | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | TenantExport application/json |
422 | Validation Error | HTTPValidationError application/json |
DELETE /v1/admin/tenants/{tenant_id}/group-mappings
Delete Mapping
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
idp_group | query | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
204 | Successful Response | — |
422 | Validation Error | HTTPValidationError application/json |
GET /v1/admin/tenants/{tenant_id}/group-mappings
List Mappings
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | GroupMappingList application/json |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/admin/tenants/{tenant_id}/group-mappings
Create Mapping
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
authorization | header | string | null | nej |
Kropp: GroupMappingCreate application/json
| Svar | Beskrivning | Kropp |
|---|---|---|
201 | Successful Response | GroupMappingOut application/json |
422 | Validation Error | HTTPValidationError application/json |
GET /v1/admin/tenants/{tenant_id}/role-bindings
List Bindings
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | RoleBindingList application/json |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/admin/tenants/{tenant_id}/role-bindings
Create Binding
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
authorization | header | string | null | nej |
Kropp: RoleBindingCreate application/json
| Svar | Beskrivning | Kropp |
|---|---|---|
201 | Successful Response | RoleBindingOut application/json |
422 | Validation Error | HTTPValidationError application/json |
DELETE /v1/admin/tenants/{tenant_id}/role-bindings/{user_id}
Delete Bindings For User
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
user_id | path | string (uuid) | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
204 | Successful Response | — |
422 | Validation Error | HTTPValidationError application/json |
GET /v1/admin/tenants/{tenant_id}/service-clients
List Service Clients
Tenantens service clients — aldrig `client_secret_hash`, aldrig hemligheten.
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | ServiceClientList application/json |
422 | Validation Error | HTTPValidationError application/json |
DELETE /v1/admin/tenants/{tenant_id}/service-clients/{client_id}/channel
Revoke Channel
Ta tillbaka `token:channel`. Gäller nästa anrop mot `/v1/token/channel`.
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
client_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | ServiceClientOut application/json |
422 | Validation Error | HTTPValidationError application/json |
PUT /v1/admin/tenants/{tenant_id}/service-clients/{client_id}/channel
Grant Channel
Slå på `token:channel` (`P3`, D-146). Idempotent, additivt — samma form och samma gränser som delegeringsrätten ovan.
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
client_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | ServiceClientOut application/json |
422 | Validation Error | HTTPValidationError application/json |
DELETE /v1/admin/tenants/{tenant_id}/service-clients/{client_id}/delegation
Revoke Delegation
Ta tillbaka `token:delegate`. Idempotent. Svarar 200 med den uppdaterade raden och inte 204: en administratör som just tagit tillbaka en rättighet ska se att `delegation_allowed` är `false`, inte behöva lita på det. Återkallandet gäller nästa anrop mot `/v1/token/delegate`. Redan utfärdade delegerade token lever till sin `exp` — de är signerade och inte uppslagsbara, och en spärrlista är en egen mekanism med eget felläge.
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
client_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | ServiceClientOut application/json |
422 | Validation Error | HTTPValidationError application/json |
PUT /v1/admin/tenants/{tenant_id}/service-clients/{client_id}/delegation
Grant Delegation
Slå på `token:delegate` för klienten. Idempotent. Additivt: bara scopet i fråga rörs, resten av listan lämnas som den är.
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
client_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | ServiceClientOut application/json |
422 | Validation Error | HTTPValidationError application/json |
GET /v1/admin/tenants/{tenant_id}/users
List Users
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | UserList application/json |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/admin/tenants/{tenant_id}/users
Invite User
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
authorization | header | string | null | nej |
Kropp: UserInviteRequest application/json
| Svar | Beskrivning | Kropp |
|---|---|---|
201 | Successful Response | UserOut application/json |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/admin/tenants/{tenant_id}/users/{user_id}/enable
Enable User
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
user_id | path | string (uuid) | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
204 | Successful Response | — |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/admin/tenants/{tenant_id}/users/{user_id}/erase
Erase User
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
user_id | path | string (uuid) | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | any application/json |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/admin/tenants/{tenant_id}/users/{user_id}/export
Export User
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
user_id | path | string (uuid) | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | UserExport application/json |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/admin/tenants/{tenant_id}/users/{user_id}/revoke
Revoke User
| Parameter | I | Typ | Krävs |
|---|---|---|---|
tenant_id | path | string | ja |
user_id | path | string (uuid) | ja |
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
204 | Successful Response | — |
422 | Validation Error | HTTPValidationError application/json |
GET /v1/me
Me
| Parameter | I | Typ | Krävs |
|---|---|---|---|
authorization | header | string | null | nej |
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | object application/json |
422 | Validation Error | HTTPValidationError application/json |
GET /v1/oauth/callback
Oauth Callback
Andra benet: användaren är tillbaka från kundens IdP.
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | any application/json |
POST /v1/token/channel
Token Channel
Kanalkonto → plattforms-JWT för personen bakom det (`P3`, D-146). Ett Slack-user-ID är ingen identitet. Rutten slår upp `(kanal, workspace, kanal-användare)` i `auth.channel_identities` och myntar personens token med kanaladaptern som `act`. **Saknas raden är svaret 403 `channel_identity_unmapped` — det finns ingen andra väg** (#208, OWASP ASI03). `tools/checks/check_no_channel_service_fallback.py` fäller syntaktiskt om uppslaget, det hårda felet eller förbudet mot `mint_service` försvinner ur den här funktionen; täckningsgränsen står i vakten. Tillitsmodellen, utskriven: tokenet myntas på anroparens ord plus vår mappning, inte på en IdP-inloggning. Anroparen är en service-client med `token:channel`, samma tillitsnivå som `token:delegate`; skillnaden är att delegeringen får ett verifierat subjekt-token medan kanalvägen får ett kanal-ID adaptern påstår. Mappningen skrivs bara av tenant-admin. Roller, scopes och grupper kommer ur databasen som efter en inloggning (`RoleResolver`), aldrig ur anropet: adaptern kan inte välja dem. Varje nekande skrivs och committas före `raise`; metadata bär BARA `reason`, aldrig kanal-ID eller e-post — det är angriparvalda strängar. Nekandets `tenant_id` är alltid KLIENTENS (`None` för en plattformsklient), aldrig kroppens: samma invariant som `_deny_delegation` motiverar.
| Parameter | I | Typ | Krävs |
|---|---|---|---|
authorization | header | string | null | nej |
Kropp: TokenChannelRequest application/json
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | TokenResponse application/json |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/token/client
Token Client
| Parameter | I | Typ | Krävs |
|---|---|---|---|
authorization | header | string | null | nej |
Kropp: TokenClientRequest application/json
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | TokenResponse application/json |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/token/delegate
Token Delegate
RFC 8693-delegering (P2a, D-101): agenten byter användarens token mot ett där `sub` fortfarande är människan och `act` namnger agenten. Rutten UPPRÄTTHÅLLER ingenting nedströms — den bara utfärdar. Att avvisa anrop utan `act` är P2. Vad den däremot gör är att aldrig utfärda mer än den fick: roller, scopes och grupper kopieras verbatim från subjekt-tokenet och livslängden kapas till dess återstående liv. **Känd gräns — ett subjekt-token med `aud` går inte att delegera.** Verifieraren konstrueras utan `expected_audience`, och `JWTVerifier` är binär i den frågan (D-71): utan deklarerat namn avvisas varje token som BÄR `aud`. Följden är att tokens från OAuth-/RFC 8707-vägen (som sätter `aud` till MCP-resursen) svarar 401 `subject_token_invalid` här, medan tokens från `/v1/token/exchange` (utan `aud`) fungerar. Gränsen är medvetet inte "fixad" genom att skicka en audience till verifieraren — det hade försvagat audience-isoleringen, som är en säkerhetsegenskap, och valet av vilken audience som ska accepteras hör inte hemma i P2a. Låst av `test_subject_token_with_audience_cannot_be_delegated`. Varje nekande skrivs till auditkedjan och COMMITTAS före sitt `raise` (fail-closed) — även de som avvisar själva subjekt-tokenet. Det är just de vägarna en agent som prövar stulna, utgångna, tjänste- eller redan delegerade token går, och en tyst sådan väg lämnar ingen spårbar sondering efter sig. Metadata bär BARA `reason`: aldrig subjekt-tokenet, aldrig dess claims (GDPR first — rutten hanterar legitimationer).
| Parameter | I | Typ | Krävs |
|---|---|---|---|
authorization | header | string | null | nej |
Kropp: TokenDelegateRequest application/json
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | TokenResponse application/json |
422 | Validation Error | HTTPValidationError application/json |
POST /v1/token/exchange
Token Exchange
Kropp: TokenExchangeRequest application/json
| Svar | Beskrivning | Kropp |
|---|---|---|
200 | Successful Response | TokenResponse application/json |
422 | Validation Error | HTTPValidationError application/json |
Scheman
ChannelIdentityList
| Fält | Typ | Krävs |
|---|---|---|
items | ChannelIdentityOut[] | ja |
ChannelIdentityOut
| Fält | Typ | Krävs |
|---|---|---|
channel | string | ja |
created_at | string | ja |
created_by | string | ja |
external_user_id | string | ja |
team_id | string | ja |
user_id | string | ja |
ChannelIdentityPut
Vem kanalkontot är. E-posten är uppslagsnyckel vid skrivning; det som lagras och ekas är vårt `user_id` (`P3`, D-146).
| Fält | Typ | Krävs |
|---|---|---|
email | string | ja |
ChannelIdentityRemoved
| Fält | Typ | Krävs |
|---|---|---|
removed | boolean | ja |
CoverageGap
En store exporten INTE täcker, med ett ärligt skäl. `store` måste vara IDENTISK med namnet i `covered` när en store demoteras (t.ex. `page_truncated_over_500`), så en konsument kan korrelera flytten. Se regel (c) i docs/tenant-export-coverage.md.
| Fält | Typ | Krävs |
|---|---|---|
reason | string | ja |
store | string | ja |
GroupMappingCreate
| Fält | Typ | Krävs |
|---|---|---|
idp_group | string | ja |
roles | "tenant_admin" | "assistant_editor" | "user" | "viewer"[] | ja |
GroupMappingList
| Fält | Typ | Krävs |
|---|---|---|
items | GroupMappingOut[] | ja |
GroupMappingOut
| Fält | Typ | Krävs |
|---|---|---|
created_at | string | ja |
idp_group | string | ja |
roles | string[] | ja |
HTTPValidationError
| Fält | Typ | Krävs |
|---|---|---|
detail | ValidationError[] | nej |
RoleBindingCreate
| Fält | Typ | Krävs |
|---|---|---|
roles | "tenant_admin" | "assistant_editor" | "user" | "viewer"[] | ja |
user_id | string | ja |
RoleBindingList
| Fält | Typ | Krävs |
|---|---|---|
items | RoleBindingOut[] | ja |
RoleBindingOut
| Fält | Typ | Krävs |
|---|---|---|
created_at | string | ja |
created_by_user_id | string | null | ja |
roles | string[] | ja |
user_id | string | ja |
ServiceClientList
| Fält | Typ | Krävs |
|---|---|---|
items | ServiceClientOut[] | ja |
ServiceClientOut
En service client som en tenant-admin ser den (`P19`). **Aldrig `client_secret_hash`, aldrig `allowed_audiences`, aldrig hela `allowed_scopes`.** Ytan administrerar EN rättighet, så den svarar med EN boolean. Att eka hela scope-listan hade gjort en delegeringsyta till ett fönster mot varje annan rättighet klienten bär — bland dem `tenant:export:read` (`D-60`), som hör till operatörsplanet och inte till tenantens.
| Fält | Typ | Krävs |
|---|---|---|
channel_allowed | boolean | ja |
client_id | string | ja |
created_at | string | ja |
delegation_allowed | boolean | ja |
last_used_at | string | null | ja |
name | string | ja |
status | string | ja |
TenantExport
En producents svar. `extra="forbid"` medvetet: bevarar de tre befintliga typade deklarationernas beteende, OCH gör att en producent som lägger ett fält utan att koordinatorn lär sig om det failar högt i stället för tyst.
| Fält | Typ | Krävs |
|---|---|---|
coverage | TenantExportCoverage | ja |
data | object | ja |
generated_at | string (date-time) | ja |
service | string | ja |
tenant_id | string (uuid) | ja |
TenantExportCoverage
| Fält | Typ | Krävs |
|---|---|---|
covered | string[] | ja |
not_covered | CoverageGap[] | ja |
TokenChannelRequest
Kanalkonto → person (`P3`, D-146). Anroparen är kanaladaptern (service- client med `token:channel`); den PÅSTÅR vem som skrev, och `auth.channel_identities` är det som gör påståendet bevisat.
| Fält | Typ | Krävs |
|---|---|---|
channel | string | ja |
external_user_id | string | ja |
team_id | string | ja |
tenant_id | string (uuid) | null | nej |
TokenClientRequest
| Fält | Typ | Krävs |
|---|---|---|
audience | string | null | nej |
tenant_id | string | null | nej |
TokenDelegateRequest
| Fält | Typ | Krävs |
|---|---|---|
audience | string | null | nej |
subject_token | string | ja |
TokenExchangeRequest
| Fält | Typ | Krävs |
|---|---|---|
idp_id_token | string | ja |
tenant_id | string | ja |
TokenResponse
| Fält | Typ | Krävs |
|---|---|---|
access_token | string | ja |
expires_in | integer | ja |
token_type | string | nej |
UserExport
| Fält | Typ | Krävs |
|---|---|---|
audit_events | object[] | ja |
authoring_documents | object | ja |
channel_identities | object[] | nej |
conversations | object | ja |
coverage | UserExportCoverage | ja |
feedback | object[] | ja |
generated_at | string (date-time) | ja |
oauth_codes | object[] | nej |
oauth_refresh_tokens | object[] | nej |
policy_decisions | object | ja |
profile | UserExportProfile | ja |
roles | string[] | ja |
tenant_id | string (uuid) | ja |
usage | object | ja |
user_id | string (uuid) | ja |
UserExportCoverage
| Fält | Typ | Krävs |
|---|---|---|
covered | string[] | ja |
not_covered | CoverageGap[] | ja |
UserExportProfile
| Fält | Typ | Krävs |
|---|---|---|
created_at | string (date-time) | ja |
display_name | string | null | ja |
email | string | null | ja |
first_login_at | string (date-time) | null | ja |
idp_groups | string[] | ja |
idp_sub | string | null | ja |
last_login_at | string (date-time) | null | ja |
status | string | ja |
user_id | string (uuid) | ja |
UserInviteRequest
| Fält | Typ | Krävs |
|---|---|---|
display_name | string | null | nej |
email | string | ja |
roles | "tenant_admin" | "assistant_editor" | "user" | "viewer"[] | nej |
UserList
| Fält | Typ | Krävs |
|---|---|---|
items | UserOut[] | ja |
UserOut
| Fält | Typ | Krävs |
|---|---|---|
created_at | string | ja |
display_name | string | null | ja |
email | string | null | ja |
first_login_at | string | null | ja |
id | string | ja |
idp_sub | string | null | ja |
last_login_at | string | null | ja |
roles | string[] | ja |
status | string | ja |
tenant_id | string | ja |
ValidationError
| Fält | Typ | Krävs |
|---|---|---|
ctx | object | nej |
input | any | nej |
loc | string | integer[] | ja |
msg | string | ja |
type | string | ja |