Worum es geht
CRMS bietet seine Funktionen über HTTP an, alle unter dem Pfad /crms. Das übernimmt die HTTP-Schnittstelle von CRMS. Sie ist ein Adapter: Sie liest eine Anfrage, ruft die passende Funktion eines CRMS-Moduls auf und schreibt die Antwort. Eigene Fachlogik hat sie nicht.
Wo die Routen laufen
Die Routen gibt es dort, wo CRMS eingebettet läuft, also im selben Prozess wie die Anwendung, und die HTTP-Schnittstelle von CRMS auf dem Klassenpfad liegt. Der eigene CRMS-Dienst bringt sie immer mit.
| Eingebettet mit HTTP-Schnittstelle | Eingebettet ohne HTTP-Schnittstelle | Entfernt | Der CRMS-Dienst selbst | |
|---|---|---|---|---|
| CRMS läuft | im Prozess der Anwendung | im Prozess der Anwendung | als eigener Dienst | als eigener Dienst |
| HTTP-Schnittstelle | im Build | nicht im Build | verboten, der Start schlägt fehl | immer dabei |
| Routen /crms/** | ja, hinter der Sicherheitskette der Anwendung | nein, die Anwendung ruft CRMS nur im Code auf | nein, die Anwendung nutzt crms-client | ja |
Bei der Betriebsart entfernt würde die Anwendung den CRMS-Dienst sonst unter eigenen Routen weiterreichen, hinter ihrer eigenen Sicherheit. Darum lehnt der Start die HTTP-Schnittstelle dort ab. Mehr zu den Betriebsarten unter Eingebettet oder getrennt.
Der Weg einer Anfrage
-
CIASSicherheitsketteIst das Token gültig? CIAS legt Person, Mandant und Rollen fest.↳ nein 401
-
CRMSAnfrage lesenGibt es eine angemeldete Person? Ist der Körper JSON, nicht zu groß, sind alle Felder bekannt und vom richtigen Typ?↳ nein 401
crms-authentication-required, 400malformed-json, 413, 415 oder 422validation-failed -
CRMSRolle und SichtbarkeitHat die Person die nötige Rolle, und sieht sie das Objekt?↳ nein 403 oder 404
- Das Modul führt die Funktion aus, die Antwort geht zurück
Die HTTP-Schnittstelle liest selbst kein Token. Die Person kommt über CIAS, siehe Die Rollen.
Rendern
| Route | Körper | Antwort | Wer |
|---|---|---|---|
POST /crms/render | die Render-Anfrage | die Bytes des Dokuments | jede angemeldete Person, für Vorlagen, die sie sieht |
POST /crms/render/validate | die Render-Anfrage | 200 {"violations": [...]}, leer heißt gültig | wie oben |
GET /crms/capabilities | – | was diese Installation anbietet | CRMS prüft keine Person, es gilt die Sicherheitskette der Anwendung |
Fürs Rendern braucht es keine eigene Rolle. Es reicht, angemeldet zu sein und die Vorlage sehen zu dürfen. Welche Vorlage eine Anfrage findet, steht unter Wie eine Vorlage gefunden wird, die Felder der Anfrage unter Die Render-Anfrage.
POST /crms/render
Content-Type: application/json
{ "template": "audit-report", "format": "PDF", "mode": "FINAL",
"reference": "audit-4711", "locale": "de-DE",
"data": { "customer": { "name": "ACME" } } }200
Content-Type: application/pdf
Content-Disposition: inline; filename="audit-report.pdf"
Crms-Template-Key: audit-report
Crms-Template-Scope: TENANT ← welche Ausgabe gewonnen hat
Crms-Template-Variant: de-DE ← welche Sprachvariante
Crms-Template-Revision: 3f1c… ← welche Revision der Vorlage
Crms-Template-Revision-Hash: sha-256:…
Crms-Document-Revision: 9a7e… ← nur bei FINAL
X-Content-Type-Options: nosniff
<die Bytes des PDF>/crms/render/validate prüft dieselbe Anfrage, ohne zu rendern. GET /crms/capabilities nennt die Formate, das Standard-PDF-Profil, die zugelassenen Scopes, die Sprachen, ob endgültige Dokumente gespeichert werden (documentRevisions), ob flüchtige Dokumente erlaubt sind (transientDocuments), und die Grenzen (timeout, maxOutputBytes, maxPayloadBytes, maxAttachmentCount, maxAttachmentBytes).
Vorlagen
Diese Routen nutzt ein Vorlagen-Editor. Jede Route ruft genau eine Funktion des Vorlagen-Moduls auf. Sehen heißt: die Vorlage gehört zum System, zu deinem Mandanten oder dir selbst. Schreiben heißt: zusätzlich die Schreibrolle des Scopes der Ausgabe. Prüfen heißt: die Rolle der aktuellen Freigabestufe.
| Route | Körper | Antwort | Wer |
|---|---|---|---|
GET /crms/templates | – | die Ausgaben, die du siehst | sehen |
POST /crms/templates | key, outputType, scope, defaultLocale | 201 die Ausgabe, mit Location | schreiben |
GET /crms/templates/{edition} | – | die Ausgabe | sehen |
GET /crms/templates/{edition}/variants | – | ihre Varianten, die Standardsprache zuerst | sehen |
POST /crms/templates/{edition}/variants | locale | 201 die Variante | schreiben |
GET /crms/variants/{variant}/draft | – | der Entwurf, oder 204 ohne Entwurf | schreiben |
PUT /crms/variants/{variant}/draft | expectedVersion, content | der gespeicherte Entwurf | schreiben |
GET /crms/variants/{variant}/draft/assets/{name} | – | ein Asset des Entwurfs, als Download | schreiben |
POST /crms/revisions/{revision}/draft | expectedVersion | der Entwurf mit dem Inhalt dieser Revision | schreiben |
POST /crms/variants/{variant}/submit | reason (optional) | die neue Revision | schreiben |
POST /crms/revisions/{revision}/approve | – | die Revision danach | prüfen |
POST /crms/revisions/{revision}/reject | reason | die Revision danach | prüfen |
POST /crms/variants/{variant}/rollback | target, reason (optional) | die neue, veröffentlichte Revision | schreiben |
POST /crms/variants/{variant}/retire | reason (optional) | 204 | schreiben |
GET /crms/variants/{variant}/revisions | – | alle Revisionen, die älteste zuerst | sehen |
GET /crms/variants/{variant}/trail | – | jeder Eintrag der Kette, mit allen Hashes | sehen |
POST /crms/variants/{variant}/verify | – | {"intact": true} oder {"intact": false, "brokenAt": 7} | sehen |
GET /crms/revisions/{revision}/content | – | der Inhalt der Revision, Assets beschrieben | sehen |
GET /crms/revisions/{revision}/assets/{name} | – | ein Asset der Revision, als Download | sehen |
Ein paar Regeln gelten für alle Vorlagenrouten:
- Ein Entwurf wird immer ganz gespeichert.
contentersetzt den alten Inhalt, mitsource,fieldsund allenassetsals Base64. Base64 ist eine Schreibweise, die Bytes als Text darstellt. expectedVersionist die Version des Entwurfs, auf der deine Änderung aufbaut,0für keinen. Hat jemand anderes inzwischen gespeichert, antwortet CRMS mit 409template-draft-changed.- Ob ein Grund Pflicht ist, entscheidet die Installation. Beim Zurückweisen ist er immer Pflicht.
- Der Körper ist begrenzt, Standard 16 MiB, einstellbar über
CODAMAI_CRMS_REST_TEMPLATE_MAX_BYTES. Darüber: 413request-too-large|<Grenze>. - Assets kommen als Download (
Content-Disposition: attachment) mitX-Content-Type-Options: nosniffundContent-Security-Policy: sandbox. So kann ein SVG im Browser keine Skripte auf der Seite der Anwendung ausführen.
Den ganzen Ablauf von Entwurf bis Veröffentlichung beschreiben Der Lebenszyklus einer Vorlage und Die Freigabe.
Dokumente
Diese Routen arbeiten mit endgültigen Dokumenten. Die Rolle prüft das Archiv, bevor es etwas nachschlägt, genauso wie bei einem eingebetteten Aufruf.
| Route | Rolle | Antwort |
|---|---|---|
GET /crms/documents?template=…&scope=…&reference=… | lesen | die Revisionen der Kette, die älteste zuerst |
GET /crms/documents/{revision} | lesen | die Bytes des Dokuments, inline |
POST /crms/documents/{revision}/verify | lesen | {"ok": true} oder {"ok": false, "problem": "<Schlüssel>"} |
POST /crms/documents/{revision}/legal-hold | Legal Hold | 204 |
POST /crms/documents/{revision}/legal-hold/release | Legal Hold | 204 |
POST /crms/documents/{revision}/erase | löschen | 204 |
- Beim Auflisten sind alle drei Parameter Pflicht. Fehlt einer, kommt 422
validation-failedmit der Regelrequired. - Die drei ändernden Routen brauchen einen Körper
{"reason": "litigation-hold"}. Der Grund ist ein Schlüssel in kebab-case, kein freier Text, denn er landet in einer Kette, die nie gelöscht wird. Freier Text ergibt 422validation-failed. - Das Lesen liefert die ganze Beschreibung der Revision in Kopfzeilen mit:
Crms-Document-Revision,Crms-Document-Number,Crms-Document-Format,Crms-Document-Stored-At,Crms-Document-Retain-Until,Crms-Document-Legal-Hold,Crms-Document-Content-Hashund dieCrms-Template-*-Kopfzeilen wie beim Rendern. - Das Archiv arbeitet immer im Mandanten der anfragenden Person und vermerkt sie als Handelnde.
Was Prüfen, Legal Hold und Löschen fachlich bedeuten, steht unter Prüfen und exportieren und Aufbewahrung, Legal Hold und Löschen.
Regeln für alle Routen
| Regel | Was sie bedeutet |
|---|---|
| Nur bekannte Felder | Ein unbekanntes Feld im Körper ergibt die Regel not-allowed. Doppelte Schlüssel und Text nach dem JSON-Objekt ergeben malformed-json. |
| Kein stilles Umwandeln | "5" ist keine Zahl. Ein Wert mit falschem JSON-Typ ist invalid. null zählt wie ein fehlendes Feld. |
| Eine Schreibweise je ID | IDs im Pfad sind UUIDs in der üblichen Langform, klein oder groß geschrieben. Kurzformen wie 1-1-1-1-1 ergeben invalid, mit dem Namen der Pfadvariablen als Feld. |
| Text statt Zahlen und Objekte | Zeiten sind ISO-8601-Text, Sprachen Sprach-Tags wie de-DE, Hashes <Algorithmus>:<hex>. |
| Komprimierter Körper | Jede Route nimmt Content-Encoding: gzip an. Die Grenze gilt für die entpackten Bytes. Eine andere Kodierung ergibt 415 content-encoding-unsupported. |
| Dokumente geschützt | Jede Dokumentantwort trägt X-Content-Type-Options: nosniff, HTML zusätzlich Content-Security-Policy: sandbox. Ein Skript in einer Vorlage läuft so nicht mit der Sitzung der lesenden Person. |
| Ganze Antworten | Ein Dokument kommt immer am Stück, nicht gestreamt. So kann auch ein später Fehler noch als Fehlerantwort kommen. |