Ga naar inhoud

IRMA voor ontwikkelaars: begrippen

Deze pagina legt de begrippen uit die je nodig hebt om goed met de IRMA-API te werken, zelf of via een agent. Wat nu al werkt en wat nog komt, staat er per onderdeel bij.

Alles in IRMA hoort bij één organisatie. Een service-token hoort bij precies één organisatie en ziet nooit iets van een andere. Met een gebruikerstoken werk je in de organisatie(s) waar die gebruiker lid van is; ziet het account er meer dan één, dan kies je er een met de header X-Irma-Active-Org: <uuid> (in de CLI: --active-org).

Binnen een organisatie bepaalt de leesscope wat je mag zien. Een beheerder kan de leestoegang per afdeling beperken (zie IRMA: beheer). Elk antwoord van /v1 zegt welke leesscope gold:

readScopeBetekenis
allJe ziet alles van de organisatie.
beperktJe ziet alleen wat bij je afdelingen hoort.
geenJe leesscope is leeg.
mijnJe vroeg zelf om alleen je eigen deel (scope=mijn), binnen een volledige leesscope.

Staat er beperkt of geen, dan betekent een lege of korte lijst niet dat er niets bestaat. Een agent hoort dat in zijn antwoord te zeggen.

Sommige routes rekenen over de hele organisatie en kunnen niet eerlijk tot een deel krimpen, zoals de simulaties en de audit-checks. Die weigeren een beperkte leesscope met 403 en { "error": "scope_te_smal" }. Dat is geen storing: voor die vragen is volledige leestoegang nodig.

Elk antwoord van de taaklaag /v1 heeft dezelfde vorm, de envelop:

{
"data": { "risks": [ { "id": "…", "title": "Phishing", "net": { "score": 8, "level": "medium" } } ] },
"context": {
"organization": { "id": "…", "name": "Gemeente Zuiderveld" },
"project": null,
"readScope": "all",
"asOf": "2026-10-24T10:00:00.000Z",
"filters": { "sort": "-netScore" }
},
"completeness": { "returned": 10, "total": 37, "truncated": true, "nextOffset": 10 },
"notIncluded": [ { "what": "Wijzigingshistorie met van/naar-waarden", "use": "GET /v1/risks/{id}/history" } ],
"provenance": { "kind": "stored", "note": "…" },
"next": [ { "action": "GET /v1/risks/{id}", "when": "voor één risico met maatregelen" } ]
}

(Voorbeeld met de demo-organisatie Gemeente Zuiderveld.) Sleutels zijn Engels; de teksten in notIncluded, next en provenance.note zijn Nederlands, de taal van de app.

VeldWat het zegtWaarom
dataHet eigenlijke antwoord.
contextVoor welke organisatie, welk project, welke leesscope, op welk moment en met welke filters het antwoord geldt.Een getal zonder context is niet te controleren.
completenessHoeveel rijen er terugkwamen (returned) en hoeveel er in totaal zijn (total), of dit een deel is (truncated), waar de volgende pagina begint (nextOffset), en wat bewust is weggelaten met de reden (excluded).Een pagina mag nooit voor het geheel worden aangezien.
notIncludedWat dit antwoord niet bevat, en welke aanroep het wel heeft.Zo vraagt een agent het juiste op in plaats van te raden.
provenanceWaar de cijfers vandaan komen: stored (opgeslagen gegevens), engine (een uitkomst van de rekenkern, met run, seed en iteraties) of derived (een afgeleide vergelijking).Een percentiel of verlies moet naar een echte run te herleiden zijn.
nextDe logische vervolgstappen.Zodat een agent geen endpoints verzint.

Waarom zo streng? Een assistent die alleen een ruwe lijst van tienduizenden tekens kreeg, ging rekenen en schatten in plaats van op te zoeken. De envelop maakt eerlijk antwoorden de makkelijkste weg: wat ontbreekt staat erbij, net als waar het wel te vinden is.

Lijsten geven standaard 50 rijen en maximaal 200 (limit). Met offset sla je rijen over; completeness.nextOffset zegt waar de volgende pagina begint, en is null op de laatste. total klopt ook bij een limit. Bij zoeken kan de bron zelf afkappen; dan staat er totalIsLowerBound: true en is total een ondergrens. Een volledige lijst ophalen: Paginering (alleen voor Prudai-medewerkers, inloggen vereist).

Een agent wijzigt je registers niet rechtstreeks. Wat een agent voorstelt, komt als concept klaar te staan en een mens neemt het over of niet. Schrijfroutes voor concepten via de API komen later.

Er is één uitzondering: incidenten aanleveren. Een melding uit monitoring of een SIEM mag niet wachten op een review, dus die komt direct in het register Incidenten. De fingerprint voorkomt dat herhalingen dubbele incidenten worden.

Een simulatie starten (POST /v1/simulations) slaat een rekenuitkomst op en verandert geen register.

In de CLI is elke schrijfactie een droogloop tot je --no-dry-run --yes meegeeft. Daarnaast komt er per tool een menselijke goedkeuringsstap (x-prudai-approval in de API-beschrijving). Hoe die gaat werken: Goedkeuring van agentacties (alleen voor Prudai-medewerkers, inloggen vereist); daar staat ook het niveau per endpoint zodra IRMA het publiceert.

Vandaag

  • /agent/v1 (incidenten aanleveren): een service-token met scopes die een beheerder kiest: incidents:write (aanleveren) en incidents:read (lezen). Mist een scope, dan krijg je 403.
  • /v1 (taaklaag): het toegangstoken van een ingelogde gebruiker. Je krijgt precies wat die gebruiker in de app mag: dezelfde rol en dezelfde leesscope. Service-tokens werken op /v1 nog niet.

Komt eraan

  • Scopes voor service-tokens op /v1, in de vorm object:werkwoord (zoals incidents:read), met bundels voor veelvoorkomende taken.
  • Een scope geeft nooit meer dan een IRMA-rol toelaat: wat een token mag, is de doorsnede van zijn scopes en de rol.

Een 403 is het ontwerp, geen fout. Vraag geen bredere sleutel om één actie te laten lukken.

  • Een incident dat een service-token aanlevert, legt vast welk token het aanleverde.
  • De wijzigingshistorie van een risico (GET /v1/risks/{id}/history, irma risks history) toont per veld wie het veranderde: een gebruiker, de assistent, een agent, een import of het systeem.
  • Het starten van een simulatie via /v1 komt in de audittrail van IRMA. Die trail is onveranderlijk: regels kunnen niet worden gewijzigd of verwijderd, en elke regel is aan de vorige gekoppeld. Zie Audittrail.

Een fout van /v1 is geen envelop maar { "error": "<code>", "message": "…" }. 400 en 422 betekenen dat de invoer niet klopt, 404 een onbekend id (of een van een andere organisatie), 409 dat iets nog niet kan (bijvoorbeeld een run die nog loopt), 401 en 403 ontbrekende of onvoldoende rechten. De CLI vertaalt dat naar exitcode 2; netwerkfouten en serverfouten naar 1. Zie CLI-referentie. Alle foutcodes per endpoint: Fouten (alleen voor Prudai-medewerkers, inloggen vereist).

/v1 verandert alleen door toevoegingen: nieuwe velden, nieuwe endpoints, nieuwe waarden waar dat is aangekondigd. Een veld verdwijnt niet en verandert niet van betekenis. Elke wijziging komt in een changelog. Schrijf je client zo dat hij onbekende velden negeert.