# Service accounts en automatisering Deze gids beschrijft scoped service accounts en tokens voor geautomatiseerde toegang tot de API. Beheerders kunnen een tijdelijk, minimaal gemachtigd importtoken via **Beheer** in de webapplicatie aanmaken en intrekken. De volledige levenscyclus blijft ook via de API beschikbaar voor gecontroleerde automatisering. ## Wat is een service account? Een service account is een niet-persoonlijke identiteit voor een geautomatiseerd systeem (bijvoorbeeld een CI/CD-pipeline of, in de toekomst, een MCP-server) dat via de API met het platform moet praten zonder een gewone gebruikersaanmelding te gebruiken. - Een service account heeft één of meer **tokens**. Elk token heeft zijn eigen **scopes** (rechten), een optionele vervaldatum en kan onafhankelijk van andere tokens worden ingetrokken. - Een token bewijst zichzelf met een `Authorization: Bearer `-header, in plaats van een sessiecookie. - Scopes verruimen nooit de gewone workspace-rechten — ze beperken alleen wat een reeds geauthenticeerde aanroep mag proberen. Een token met alleen `knowledge:search` kan nooit een pagina aanmaken, ongeacht welke rol de aanmakende beheerder zelf heeft. Service accounts aanmaken, tonen, tokens uitgeven en intrekken kan **alleen** door een ingelogde beheerder (rol Eigenaar/Beheerder), via een gewone, cookie-geauthenticeerde aanroep met CSRF-bescherming — nooit door een service account zelf. Een service account kan dus nooit zijn eigen rechten verruimen of een nieuw token voor zichzelf aanmaken. ## Beschikbare scopes | Scope | Betekenis | | --- | --- | | `knowledge:read` | Pagina's lezen | | `knowledge:search` | Zoeken in de kennisbank | | `pages:read` | Individuele pagina's ophalen | | `pages:write` | Pagina's aanmaken/bewerken | | `projects:read` | Projectdossiers en projectcontext lezen | | `projects:write` | Projecten bewerken | | `project-updates:append` | Een update aan een project toevoegen | | `decisions:read` | Architectuurbeslissingen lezen | | `decisions:write` | Architectuurbeslissingen aanmaken | | `runbooks:read` | Runbooks lezen | | `runbooks:write` | Runbooks aanmaken | | `attachments:read` / `attachments:write` | Bijlagen lezen / uploaden | | `imports:read` / `imports:execute` | Importstatus lezen / een import uitvoeren | | `audit:read` | Audittrail lezen | | `system:read` | Systeeminformatie lezen | Een aanvraag met een onbekende scope wordt geweigerd (HTTP 422) — er is geen manier om per ongeluk een niet-bestaande of verkeerd gespelde scope aan een token te koppelen. ## Een service account aanmaken ### Via de webapplicatie 1. Meld aan als beheerder en open **Beheer**. 2. Kies onder **Serviceaccounts** een van de drie vaste profielen, afhankelijk van de taak: - **Importserviceaccount aanmaken (pagina's en bijlagen)** — uitsluitend `pages:read`, `pages:write`, `attachments:read` en `attachments:write`. Voor het generieke Markdown-/bijlage-publicatietraject (`tools/knowledge-ingestion/`). - **Automatiseringsserviceaccount aanmaken (infrastructuur, projecten, runbooks)** — uitsluitend `infrastructure:read`, `infrastructure:write`, `projects:read`, `projects:write`, `project-updates:append`, `runbooks:read` en `runbooks:write`. Voor het synchroniseren van gecureerde infrastructuurfeiten (`POST /inventory/curated-package`), het beheren van redactionele serviceprofielen, en het publiceren van projectdossiers en runbooks. - **Migratieserviceaccount aanmaken (LeafWiki-import)** — uitsluitend `imports:read` en `imports:execute`. Voor een eenmalige, gecontroleerde LeafWiki-migratie (`POST /admin/imports/preflight`/`/execute`/`/rollback`). Deliberately gescheiden van het automatiseringsprofiel: een token voor dagelijkse infrastructuur-/projectpublicatie mag nooit ook een migratie kunnen starten. 3. Kopieer het eenmalig getoonde token onmiddellijk naar de automatisering of een geheimenbeheerder. 4. Trek het token na gebruik in via dezelfde beheerpagina. Geen van beide vaste profielen dekt elke mogelijke automatisering — voor een taak die een andere scopecombinatie nodig heeft (bijvoorbeeld alleen zoeken, of alleen architectuurbeslissingen), gebruikt een beheerder de API hieronder met exact de benodigde scopes, nooit ruimer dan nodig. ### Via de API ```bash curl -X POST https://hub.example/api/v1/service-accounts \ -H "Content-Type: application/json" \ -H "X-CSRF-Token: " \ -b cookies.txt \ -d '{"name":"CI-bot","description":"Leest en doorzoekt de kennisbank vanuit de CI-pipeline.","scopes":["knowledge:search","pages:read"]}' ``` Het antwoord bevat het **ruwe token exact één keer**: ```json { "serviceAccountId": "…", "tokenId": "…", "rawToken": "ikh__" } ``` Bewaar dit token onmiddellijk in een geheimenbeheerder. Het platform slaat nooit de ruwe waarde op — alleen een cryptografische hash — en kan het dus nadien nooit meer tonen. Is het token kwijt, dan moet een nieuw token worden uitgegeven en het oude worden ingetrokken. ## Een service account gebruiken ```bash curl https://hub.example/api/v1/search?q=backup \ -H "Authorization: Bearer ikh__" ``` Een aanroep zonder de vereiste scope wordt geweigerd — de mutatie of leesactie vindt nooit plaats, ook al is het token op zich geldig. ## Tokens roteren Geef eerst een nieuw token uit, werk de client bij, en trek pas daarna het oude token in. Een service account is op deze manier nooit tijdelijk onbruikbaar tijdens rotatie: ```bash curl -X POST https://hub.example/api/v1/service-accounts//tokens \ -H "Content-Type: application/json" -H "X-CSRF-Token: …" -b cookies.txt \ -d '{"scopes":["knowledge:search","pages:read"]}' ``` ## Een token intrekken ```bash curl -X POST https://hub.example/api/v1/service-accounts/tokens//revoke \ -H "X-CSRF-Token: …" -b cookies.txt ``` Intrekking is onmiddellijk van kracht: de eerstvolgende aanroep met dat token wordt geweigerd, zonder wachttijd. ## Herhaalde aanroepen veilig maken (Idempotency-Key) Een aanmaak- of toevoegaanroep (bijvoorbeeld een nieuwe pagina, beslissing, runbook of projectupdate) accepteert een optionele `Idempotency-Key`-header. Een netwerkfout tijdens een eerdere poging kan zo veilig opnieuw worden geprobeerd zonder het risico op een dubbele pagina of dubbele update: - Dezelfde sleutel met exact dezelfde aanvraaginhoud: het eerder gegeven antwoord wordt gewoon opnieuw teruggegeven, zonder de actie nogmaals uit te voeren. - Dezelfde sleutel met een andere aanvraaginhoud: dit wordt geweigerd (HTTP 409) — er wordt nooit stilzwijgend iets anders uitgevoerd onder een hergebruikte sleutel. ## Projectcontext voor automatisering `GET /api/v1/projects/{projectId}/context` geeft een compacte, begrensde momentopname van een project (huidige stand, recente updates, actieve mijlpalen, beslissingen, runbooks, documenten) met stabiele citaten (`kind`, `id`, `revisie`, `titel`, pad, laatst bijgewerkt) in één aanroep — bedoeld voor een toekomstige MCP-server die snel projectcontext nodig heeft zonder tientallen losse aanroepen. Wanneer er meer items zijn dan het maximum, toont het antwoord expliciet `truncation.truncated: true` met per onderdeel het weggelaten aantal — er wordt nooit stilzwijgend informatie weggelaten zonder dat te melden.