What this is about
A revision has two parts:
- the state of the object: all fields as they were after the change,
- the revision data: number, time, and who made the change from where.
This page is about the second part.
A revision as an example
This is how a revision arrives in the history:
POST /api/rest/order/7e1…/history
{ "response": ["orderNr", "price"] }{ "data": [
{ "revision": { "id": "7e1…", "orderNr": "A-1000", "price": 120.5 },
"revisionMeta": {
"ref": 42,
"ts": 1790000200000,
"ip": "203.0.113.7",
"useragent": "Mozilla/5.0 (X11; Linux x86_64) …",
"username": "Anna Muster",
"actingUsername": null
},
"revisionType": "MOD" },
…
],
"meta": { … } }| Field in the response | Column in revinfo | Meaning |
|---|---|---|
revisionMeta.ref | id | Revision number. You need it for a rollback. |
revisionMeta.ts | timestamp | Time in milliseconds since 1 January 1970 (UTC) |
revisionMeta.username | username | Name of the person on whose behalf the change was made. Without a switch, the person from the token. |
revisionMeta.actingUsername | acting_username | Name of the logged-in person, up to 255 characters. Only filled after a user switch, otherwise null. |
revisionMeta.ip | ip_address | IP address of the request, up to 45 characters, so IPv6 fits too |
revisionMeta.useragent | user_agent | browser or program, up to 512 characters |
| – | user_id | ID of the person on whose behalf the change was made (claim sub). It is stored in the database, the history does not return it. |
| – | acting_user_id | ID of the logged-in person, up to 36 characters. Only filled after a user switch. The history does not return it. |
revisionType | – | ADD, MOD or DEL, see What is audited |
revision | row in <table>_AUD | the state of the object, only the requested fields |
Where the values come from
CDMS does not invent any of this. It comes from the request that caused the change:
-
1Client→CIASsends a writing request with a token
-
2CIASThe filter chain reads the IP address and the user agent from the request.IP: first entry in the header
X-Forwarded-For; if it is missing,X-Real-IP; if that is missing too, the remote address of the connection. User agent: the headerUser-Agent, otherwiseunknown. -
3CIASIt reads the user ID and the name from the token.ID: claim
sub. Name: by default claimname, otherwisepreferred_username. Which claims apply can be configured in CIAS. -
4CDMS→DatabaseWhen the request ends successfully, Envers writes the revision and takes over these four values.Result: The database assigns number and time when writing. After a user switch, the ID and name of the logged-in person are added as the acting person.
When: A person changes data through the API.
User ID, name, IP address and user agent of this request.
When: Lena acts on behalf of Ben with the header user.
user_id and username name Ben, acting_user_id and acting_username name Lena. In the history you see username: "Ben Beispiel" and actingUsername: "Lena Support". This holds with own roles just as with the roles of the target person.
Result: See User switch by header.
When: Code changes data outside an API request, for example a background job.
The revision is written anyway. If there is no request context at all, the four fields stay empty. If the job runs with a context of its own, they contain what the job sets, for example a technical user and internal.
One revision log per database
The table revinfo exists in every database in which CDMS stores data. The numbers count in each database on their own.
flowchart TB
subgraph S["System database"]
S1[("revinfo<br/>1, 2, 3 …")]
S2[("<systemmodel>_AUD")]
end
subgraph A["Tenant database A"]
A1[("revinfo<br/>1, 2, 3 …")]
A2[("order_table_AUD")]
end
subgraph B["Tenant database B"]
B1[("revinfo<br/>1, 2, 3 …")]
B2[("order_table_AUD")]
end
Which database that is depends on the level of the model: system models in the system database, tenant and user models in the database of the tenant. See Model levels: system, tenant, user and Which database? The persistence target.
In operating mode SINGLE everything lives in one database, and there is only one revinfo. See SINGLE and MULTI.
Pitfalls
What comes next
- Fetching revisions: Reading the history
- What the response format looks like in general: The response format
- Which personal data this creates: Data protection and retention