Worum es geht
Eine Vorlage ist ein gelenktes Dokument: Sie ändert sich nur über einen neuen, geprüften Stand, und jeder Bericht lässt sich auf genau diesen Stand zurückführen. Dafür hat jede Sprachvariante eine Kette. Das ist eine Liste von Einträgen, die nur wächst. Jeder Eintrag hält einen Schritt fest: eingereicht, freigegeben, abgelehnt, veröffentlicht, ersetzt, zurückgezogen.
Die Zustände
flowchart LR
D["Entwurf"] -->|einreichen| R["IN_REVIEW<br/>in Prüfung"]
D -->|"einreichen,<br/>ohne Freigabestufen"| P
R -->|"letzte Stufe<br/>freigegeben"| P["PUBLISHED<br/>veröffentlicht"]
R -->|ablehnen| X["REJECTED<br/>abgelehnt"]
P -->|"nächste Revision<br/>veröffentlicht"| S["SUPERSEDED<br/>ersetzt"]
P -->|zurückziehen| T["RETIRED<br/>zurückgezogen"]
S -.->|"zurücksetzen:<br/>neue Revision"| P
T -.->|"zurücksetzen:<br/>neue Revision"| P
| Zustand | Bedeutung |
|---|---|
IN_REVIEW | eingereicht, läuft durch die Freigabestufen |
PUBLISHED | die Revision der Variante, die rendert. Es gibt höchstens eine |
SUPERSEDED | war veröffentlicht, wurde von einer späteren ersetzt |
REJECTED | in der Prüfung abgelehnt. Ein neuer Versuch ist eine neue Revision |
RETIRED | war veröffentlicht, wurde ohne Nachfolger zurückgezogen |
Der Entwurf ist kein Zustand einer Revision. Er liegt neben der Kette und wird erst beim Einreichen zur Revision.
Die Aktionen
Wann: der Entwurf ist fertig
-
1Client→CRMS
POST /crms/variants/{variant}/submitmit{"reason": "…"} -
2CRMSprüft die Schreibrolle des Scopes und den Grund
-
3CRMSgibt es keinen Entwurf? → 409
template-draft-missing -
4CRMSlässt den Quelltext vom Renderer parsen. Syntaxfehler → 422
template-source-rejectedmitviolations -
5CRMSläuft schon eine Revision in Prüfung? → 409
template-review-pending -
6CRMS→Datenbankhängt einen Eintrag
REVISIONan. Hat der Scope keine Freigabestufen, gleich danachPUBLISHEDErgebnis: neue Revision,IN_REVIEWoderPUBLISHED
Wann: eine Revision ist in Prüfung
POST /crms/revisions/{revision}/approve. Wer die Rolle der aktuellen Stufe hat, gibt frei. Nach der letzten Stufe ist die Revision veröffentlicht. Alle Regeln stehen unter Freigabeketten.
Ergebnis: Eintrag APPROVED, nach der letzten Stufe zusätzlich PUBLISHED
Wann: eine Revision in Prüfung ist nicht in Ordnung
POST /crms/revisions/{revision}/reject mit Grund. Der Grund ist hier immer Pflicht. Wer ablehnt, braucht die Rolle der aktuellen Stufe. Der Entwurf bleibt erhalten, du arbeitest darin weiter und reichst neu ein.
Ergebnis: Eintrag REJECTED, die Revision bleibt abgelehnt
Wann: eine frühere Fassung soll wieder gelten
POST /crms/variants/{variant}/rollback mit {"target": "<revision>", "reason": "…"}. Das Ziel muss SUPERSEDED oder RETIRED sein. CRMS legt eine neue Revision mit dem alten Inhalt an und veröffentlicht sie sofort, ohne Freigabestufen: Der Inhalt war schon einmal freigegeben.
Ergebnis: neue Revision mit rollbackOf, PUBLISHED. Gibt es eine bisher veröffentlichte, wird sie SUPERSEDED
Wann: die Variante soll gar nicht mehr rendern
POST /crms/variants/{variant}/retire mit Grund. Die veröffentlichte Revision wird RETIRED, und die Variante hat keine veröffentlichte Revision mehr. Ohne veröffentlichte Revision antwortet CRMS mit 409 template-not-published.
Ergebnis: Eintrag RETIRED, Antwort 204
Einreichen, Zurücksetzen und Zurückziehen brauchen die Schreibrolle des Scopes, siehe Wie eine Vorlage aufgebaut ist. Wer freigeben und ablehnen darf, regelt die Freigabekette, siehe Freigabeketten.
Weiterarbeiten an einem alten Stand
POST /crms/revisions/{revision}/draft mit {"expectedVersion": 3} kopiert den Inhalt einer beliebigen Revision in den Entwurf ihrer Variante. So setzt du nach einer Ablehnung oder an einem älteren Stand an, ohne alles neu zu tippen.
Der Grund
Ein Grund ist ein kurzer Text, warum etwas geschieht. Er landet in der Kette.
| Aktion | Grund Pflicht? | Was ohne Grund passiert |
|---|---|---|
| Ablehnen | immer | 422 template-reason-required |
| Einreichen, Zurücksetzen, Zurückziehen | ja (Standard) | 422 template-reason-required |
| Einreichen, Zurücksetzen, Zurückziehen | abgeschaltet | Aktion läuft, der Eintrag hat keinen Grund |
| Freigeben | – | Eine Freigabe hat keinen Grund, sie hat eine Bedeutung (siehe Freigabeketten) |
Abschalten lässt sich die Pflicht mit CODAMAI_CRMS_TEMPLATE_REASON_REQUIRED=false, im Hub mit dem Feld templateReasonRequired. Ein Grund hat höchstens 2000 Zeichen, sonst template-reason-too-long|2000.
Die Kette und ihre Hashes
Ein Hash ist ein Fingerabdruck: eine kurze Zeichenfolge, die sich komplett ändert, sobald sich am Inhalt ein Zeichen ändert. CRMS nutzt SHA-256 und schreibt einen Hash als sha-256:<hex>.
- Der Inhalts-Hash einer Revision ist der Hash ihres Quelltexts. Felder und Assets stehen mit ihren eigenen Hashes im Eintrag
REVISION. - Der Hash eines Eintrags deckt alles ab, was der Eintrag sagt, dazu den Inhalts-Hash der Revision und den Hash des Eintrags davor.
Weil jeder Eintrag den vorigen einschließt, fällt eine geänderte, gelöschte oder umsortierte Zeile auf. Und weil auch eine Freigabe den Inhalts-Hash trägt, bindet sie genau den Inhalt, der freigegeben wurde.
GET /crms/variants/{variant}/trail[
{
"sequence": 1, ← Position, ohne Lücken
"type": "REVISION",
"revision": "0b7e…",
"actor": "anna", ← aus dem Token
"at": "2026-10-17T08:30:00.123456Z",
"reason": "Neues Logo",
"attributes": { "number": 1, "scope": "TENANT",
"locale": "de", "fields": [ … ],
"assets": [ … ], "approval": { … }, … },
"contentHash": "sha-256:9f86…",
"hash": "sha-256:41c2…"
},
{
"sequence": 2,
"type": "APPROVED",
…
"previousHash": "sha-256:41c2…", ← Hash von Eintrag 1
"hash": "sha-256:a07d…"
}
]| Aufruf | Wirkung |
|---|---|
GET /crms/variants/{variant}/revisions | alle Revisionen mit Zustand, Nummer, Autor, Grund, Hash, Stufen und Freigebenden, älteste zuerst |
GET /crms/variants/{variant}/trail | alle Einträge der Kette, mit jedem Hash, zum Nachrechnen |
POST /crms/variants/{variant}/verify | CRMS rechnet die Kette nach. Antwort {"intact": true} oder {"intact": false, "brokenAt": 4} mit dem ersten Eintrag, der nicht passt |
GET /crms/revisions/{revision}/content | Quelltext, Felder und beschriebene Assets einer Revision |
Jeder Eintrag geht zusätzlich in das Journal des Mandanten, bei System-Vorlagen in das der Plattform. Damit liegt der Nachweis auch außerhalb der Vorlagentabellen. Mehr unter Die Hash-Ketten.