CodamAIDocs

Contents

Each row names the path, the content and the variants covered in full. Status: 213 topics, 213 done, 0 in draft, 0 planned.

CDMS – Data

The data layer of CodamAI. A model becomes a REST API that reads, searches, writes and deletes data. It checks every request for permissions and tenant, and it logs every change.

1. Basics: model, layers, endpoints

What a CDMS model is, on which level its data lives, which layers a request passes through, and which endpoints a model gets.

1.1 Model levels: system, tenant, usercdms/grundlagen/modell-ebenenEvery model belongs to one of three levels. The level decides which database holds the data and whether a person only sees their own rows.
SYSTEM (always the system DB)TENANT (tenant DB)USER (tenant DB + owner _userId)operating mode MULTIoperating mode SINGLEnot specified → TENANTsubtypes inherit the levelrelations across levelstechnical client and USER models
1.2 One model, four shapescdms/grundlagen/modell-gestaltenAt runtime a model exists as an entity (database), a DTO (response), a payload (input) and metadata (description). This page explains when each shape is in play and how data is mapped between them.
EntityDTOCreatePayloadUpdatePayloadPATCH with a free mapreference as IdWrapper {id, @type}reference as nested payloadMeta (MetaClassInfo, MetaFieldInfo, MetaFieldRules)create, replace, update, read
1.3 System fields that the server setscdms/grundlagen/systemfelderCDMS sets fields such as id, _createdOn, _userId, _MODELTYPE and _version itself. This page explains when each field is set and which of them the client may send.
id_createdOn_updatedOn_userId (USER models only)_MODELTYPE / @type_version (file models only)internal helper fieldssent by the client → ignored
1.4 The path of a request through the layerscdms/grundlagen/request-wegFilter chain, REST layer, system layer, persistence, commit: what each station checks, what it decides and which error it stops with. Separately for reads and writes.
readcreateupdate and delete (with visibility check)searchsuccess: commit before the responsefailure: rollbackstop at any station
1.5 Which endpoints a model hascdms/grundlagen/endpunkteThe fixed set of operations per model (create, read, update, delete, query, history, rollback, file) and how the endpoint list on the model switches individual operations on and off.
standard setempty endpoint list = everything except historyUPDATE enables PUT and PATCHREAD without QUERYHISTORY / HISTORY_ROLLBACKUPLOAD / DOWNLOADsingleton modelabstract model (hub API)file modelnot present → 404
1.6 Singletons: exactly one objectcdms/grundlagen/singletonSome models exist only once per scope, for example the settings of a user. This page explains how the paths without an ID work and what happens on a second create or when the object is missing.
singleton per systemper tenantper usercreate, read, replace, update, deletesecond create → 400read/update without object → 404delete without object → no effectfile, history and rollback
1.7 Abstract models and @typecdms/grundlagen/abstrakte-modelleA general concept with several concrete types, such as “customer” with private and business customers. This page explains how the hub API forwards requests to the right subtype and when the client has to send @type.
create with @typereplace and update with @typeread and delete: type from the idsearch in two phasesparallel read stepssubtype endpoints directlypermissions and filters of the subtypesunknown type
1.8 The response format: data and metacdms/grundlagen/antwortformatEvery response has the same envelope. This page explains what is in data and meta for a single object, a list, the history and errors.
single object (SingleResponse)list (QueryResponse)history (AuditQueryResponse)errorvalidation error with violationscreated but not read backDELETE without bodyfile download

2. From model to application

How a model in the hub becomes runnable code: modeling, fetching metadata, generating, project scaffold, and how schema changes run in a controlled way through the MCP server.

2.1 Modeling in the hubcdms/modellieren/hub-modellierenWhat you define in the hub: system, folder, model, field, relation, rules, endpoints, roles. And which modeling rules apply.
System (module)Folder and enumerationData model, abstract model, file modelPrimitive field, enum field, relation fieldRules on the fieldEndpointsRolesAccess filters and hooks
2.2 Code generation in the buildcdms/modellieren/generierungThe build fetches the metadata from the hub, stores it as a YAML cache, and generates 15 classes per model from it. This page explains the flow and what is created when.
online (metadata via REST)offline (CODEGEN_OFFLINE, existing cache)skip fetching entirely (cdms.generator.fetch.skip)export from the hub as a ZIPper modelonce per buildonly the first time
2.3 The project scaffoldcdms/modellieren/projektrahmenWhat a new project gets the first time (POM, main class, configuration) and which branches exist, for example CIAS embedded or removed.
Authentication OIDC or NONECIAS EMBEDDED / REMOTE / NONEDatabase MYSQL / MARIADBStorage FILESYSTEM or NONEMonitoring ACTUATOR or NONEAuditing (derived)first download, later build
2.4 Generated code and custom codecdms/modellieren/generiert-und-eigenWhy generated code is never changed by hand, and where your custom code belongs: hooks, custom filters, custom controllers and services, configuration.
generated, do not touchHookcustom filterattribute filtercustom controller or serviceconfiguration
2.5 Schema change through the MCP servercdms/modellieren/mcp-aenderungHow an AI client changes a model through the hub's MCP server: read, validate the blueprint, plan the change set, approve, apply exactly once.
read onlyvalidate blueprintplan change setapproveapprove a destructive changeapplysecond apply at the same timeundo (roll back)Operation Context: one target CDMSsomeone else's operationIdblueprint with an environmentbase has changedconnecting Claude Codeanother MCP client

3. Reading data

Reading an object and deciding exactly which fields and references come back: field selection, wildcards, nested references, abstract types, and what happens in the database.

3.1 Reading an objectcdms/lesen/einzelobjektHow POST /read/{id} and GET /read/{id} work, what comes back for a missing or invisible object, and how singleton and abstract model differ.
POST /read/{id} with responseGET /read/{id} (= *)Singleton POST/GET /readabstract modelnot present → 404invisible → 404without read role → 403reference without read role → 403response missing → 400
3.2 Field selection with responsecdms/lesen/feldauswahlThe response list decides what comes back, and it is mandatory. This page lists the possible entries and what happens when the list is missing or a field is unknown.
Field nameWildcardObject {field, response}excluderesponse missing → 400empty list → system fields onlyunknown field → silently ignoredobject on a simple field → ignoredpermissions apply per model, not per field
3.3 Wildcards + and *cdms/lesen/wildcardsHow you request many fields at once with + and *, what the partial wildcards name+, +name, name* and *name match, and why * needs more permissions than you might think.
+ alone* alonePrefix: name+ / name*Suffix: +name / *nameCombining several entriesexcludeWildcard without matchesMarker in the middle of a wordGET /read = ** without read permission on a reference
3.4 Expanding references and listscdms/lesen/referenzen-ausbauenHow a reference is fully loaded with { field, response }, how lists get their own filter, sorting and page size, and how deep this may go.
Single referencesingle reference not set or invisible → nullListList with parameterseveral levelsback reference is added automaticallyno match count for nested listsreference without read role → 403
3.5 Reading through abstract typescdms/lesen/abstrakte-referenzenIf a reference points to an abstract model, CDMS returns the fields of all possible subtypes. This page explains how that is resolved and how the client tells the types apart.
abstract single referenceabstract list@type in the response+ means: fields of all subtypesfield of only one subtypepermissions of the subtype
3.6 What happens in the database when readingcdms/lesen/datenbankwirkungThe field selection drives the SQL query: only the requested columns, references via LEFT JOIN, no loading in the background. This page explains why this is fast and when it gets expensive.
Tuple projectionLEFT JOINcount, determine IDs, fetch fieldsexpanded single reference as a read of its ownnested lists as separate queriesdeep nestingsubtypes of abstract models

4. Searching, filtering, paging

Querying lists with POST /query: filter tree of AND/OR groups, all operators, search patterns with LIKE, paths across relations, sorting, pages, and the filters the server always adds.

4.1 Structure of a searchcdms/suchen/query-aufbauWhat a search request looks like: response, parameter with query, order, page, limit, meta, and which default values apply.
minimal searchwith filterwith sortingwith pageswithout parameterwithout read role → 403
4.2 All filter operatorscdms/suchen/operatorenEQ, NEQ, LIKE, IN, ISNULL, ISNOTNULL, BEFORE, AFTER, SAMEORBEFORE, SAMEORAFTER, MEMBEROF: what each one means, which field types it applies to and how the value is written.
EQNEQLIKEIN (comma-separated string)ISNULLISNOTNULLBEFOREAFTERSAMEORBEFORESAMEORAFTERMEMBEROFoperator does not fit the field type
4.3 Search patterns with LIKE: % and _cdms/suchen/like-suchmusterHow the placeholders % and _ work in a LIKE search, why CDMS does not add % automatically, that there is no escaping, and what upper and lower case depend on.
exact value without %starts with (abc%)ends with (%abc)contains (%abc%)exactly one character (_)% or _ as a real characterupper/lower case depends on the databaseLIKE is the default operatorLIKE on a non-text field
4.4 AND/OR groupscdms/suchen/und-oder-gruppenHow type, filter and group form a filter tree, why the default is OR and how the tree becomes a condition.
one group ANDone group OR (default)nested groupsOR group with filter and groupforgotten typeempty group
4.5 Filtering and sorting across relationscdms/suchen/pfadeDot notation like customer.address.city: how CDMS joins the tables for it and why objects without the relation do not drop out.
one stepseveral stepsobject without relation (LEFT JOIN)across a listID of the referenceunknown pathsorting across a path
4.6 Searching collections with MEMBEROFcdms/suchen/memberofHow you find the objects whose list contains a certain element, and why MEMBEROF on a non-list field is rejected.
by IDin an OR groupnot a list field → 400invalid UUID → 400
4.7 Sortingcdms/suchen/sortierungSeveral sort criteria, direction ASC/DESC/NONE, sorting across relations, and what happens with a wrong sort path.
ASCDESCNONEseveral criteriavia pathwithout ordercriterion without directionwrong path → 400
4.8 Paging and match countcdms/suchen/blaetternHow page, limit and meta work together, why limit: -1 returns everything, and where totalCount comes from.
limit setlimit -1 (everything)limit 0page past the endnegative pagemetaabstract model
4.9 Filters in nested listscdms/suchen/unterlistenWhen a parameter goes at the top level and when inside a response entry, and what this means for the amount of data.
filter on the matchesfilter on a sublistboth togethersublist without limit
4.10 Date and time valuescdms/suchen/datumswerteIn which format dates, times and timestamps are written, and how time ranges are filtered.
DateTimeTimestampTime rangeSystem fields _createdOn, _updatedOnwrong format
4.11 Filters that always run alongcdms/suchen/unsichtbare-filterWhat the server invisibly adds to every search: owner, attribute filters, custom mandatory filters, and that the tenant takes effect through the choice of database. Explains why two persons see different matches.
owner filterattribute filtercustom mandatory filtertenant via databaseattribute missing → 422mandatory filter not applicable → 500
4.12 When a filter does not fitcdms/suchen/kaputte-filterWhat happens with a missing key, a wrong operator, a value that does not fit, an invalid UUID, an unknown field or an unresolvable mandatory filter.
key/param missing → 400invalid UUID → 400unknown field → 400operator does not fit the field → 400field of a subtype → allowedvalue does not fit the type → 400operator unknown → 400wrong sort field → 400parameter null → 400mandatory filter unresolvable → 500

5. Writing data

Creating and changing objects: create, PUT (replace) and PATCH (change), the null trap, default values, validation, and what happens with concurrent changes.

5.1 Creating an objectcdms/schreiben/anlegenWhat happens step by step with POST /create: system fields, default values, hooks, validation, saving, reading back.
JSONwith files (multipart or Base64)Singletonabstract model with @typewith child objectsno role → 403rule violated → 422response missing → 400
5.2 Replacing with PUTcdms/schreiben/put-ersetzenPUT describes the complete target state. This page explains what happens to missing fields, references and lists, and where the ID comes from.
simple field missing → emptyreference missing → detacheddependent child missing → deletedlist missing → clearedchild with id → linked or replaced along with itchild without id → createdID from data, not from the pathnot visible → 404
5.3 Changing with PATCHcdms/schreiben/patch-aendernPATCH only changes what you name. This page explains the three states of every field (missing, null, value) for simple fields, references and lists.
field missing → unchangedfield null → clearedvalue → setlist [] → clearedpartial list → target statechild with id → change only what was sentchild without id → createdwithout id → 400
5.4 PUT or PATCH? The null trapcdms/schreiben/put-oder-patchWhich verb for what, and why a form object with empty fields clears everything with PATCH.
saving a formchanging one fieldclearing a field on purposetyped object sent to PATCHsending back an object you readcreate or change?
5.5 Default valuescdms/schreiben/defaultwerteWhen a field automatically gets a value on create, which kinds of defaults exist, and what happens to an unusable default.
literalNOW()LocalDate.NOW(), LocalDateTime.NOW(), LocalTime.NOW()enum preset valueonly on create, also for childrenexplicit null → defaultnot on PUT/PATCHunusable → dropped
5.6 Validationcdms/schreiben/validierungWhich rules are attached to fields, when they are checked, that all violations come collected in one 422, and what the path of a nested error looks like.
required field on create/updatenot emptylengthpatternmin/maxfuture/pastscope ALWAYS/CREATE/UPDATEpatch only checks what was sentchild objectsunique (database) → 409wrong type in JSON → 400 invalid-value
5.7 Concurrent changescdms/schreiben/gleichzeitig-aendernThere is no save, and normal models have no optimistic locking: the last change wins. Only file models detect a conflict.
normal model: last write winsPATCH instead of PUT makes conflicts smallerfile model: 409 on overlapping requestsclient decides create/update based on the id

6. Relations and nested writing

How objects are connected to each other, and how you create, link, change or remove connected objects in the same request.

6.1 Relation types and recursive flagscdms/beziehungen/beziehungstypenThe four relation types and the permissions CREATE, UPDATE and DELETE, which define what CDMS may do across a relation.
ONETOONEONETOMANYMANYTOONEMANYTOMANYFlag CREATEFlag UPDATEFlag DELETEReading: role instead of flagRoles for children
6.2 The four cases in nested writingcdms/beziehungen/vier-faelleTwo questions decide whether a child object is created, changed, only linked or rejected: Does it have an id? Is the matching flag set?
without id + CREATE → createwithout id, without CREATE → 400with id + UPDATE → update alongwith id, without UPDATE → only linkunknown id → 404Lists with PATCHRoles of the childrenStrict mode off
6.3 Lists as target statecdms/beziehungen/listen-zielzustandA list in the payload describes what the list should look like afterwards. This page explains what happens to members that no longer appear.
removed with DELETE flag → deletedremoved without DELETE flag → detachedn:m: connection removed, even with the DELETE flagnew membersempty listlist missing: PUT vs. PATCHorderduplicate entries
6.4 Both sides of a relationcdms/beziehungen/beide-seitenCDMS maintains the other side of a relation automatically. Why the client should not send the back reference.
1:11:n from the 1 side1:n from the n siden:mBack reference sent alongPUT without the list of the other side
6.5 Many-to-many through a join tablecdms/beziehungen/n-zu-mHow n:m relations are mapped through a separate join model, and what this means when writing.
MANYTOMANY with a generated join tableseparate join model with two n:1create a linkremove a linkdelete one end
6.6 Cycle protectioncdms/beziehungen/zyklusschutzHow CDMS prevents nested reading or writing from going around in circles.
Reading: as deep as the responseReading: A → B → AWildcards stop at the idWriting: the back reference is skippedWriting: each object onceinternal field _reference

7. Deleting data

How an object is deleted, what happens to dependent objects and files, and what is left afterwards.

7.1 How a DELETE runscdms/loeschen/loeschablaufCheck visibility, load, check roles, cascade, hooks, remove: the steps of a delete and the errors at each point. There is only hard deletion.
regular modelsingletonabstract modelinvisible → 404without delete role → 403deleting twice
7.2 Dependent objects (cascades)cdms/loeschen/kaskadenWhen children are deleted along with the parent and when they are only unlinked, that every child needs its own delete role, and that a missing role rolls back everything.
with DELETE flag → deleted alongwithout DELETE flag → unlinkedper relation type: 1:1, 1:n, n:1, n:m, join modelacross several levelsrole missing anywhere → everything rolled backfield role instead of class role
7.3 Deleting by changingcdms/loeschen/indirekt-loeschenA PUT or PATCH that removes a dependent child from a list or a reference deletes it. This page explains when that happens.
PUT: list missing → all dependent children deletedPUT/PATCH: child missing from the list → deletedPATCH: list missing → unchangedsingle reference null → deletedwithout DELETE flag → only unlinkedroles and hooks
7.4 Deleting file modelscdms/loeschen/dateien-loeschenWhen a file model is deleted, the record, the file content and all retained versions disappear. The history of the record remains, the content does not.
deleted directlydeleted along through the DELETE flag (1:1, 1:n)removed from the parent through PUT/PATCHshared file (n:1, n:m) → staysall versions gone
7.5 What remains after a deletecdms/loeschen/was-bleibtThe history stays readable, there is no recycle bin (soft delete), and a rollback does not bring deleted objects back.
history readableno soft deleteno revival through rollbacknon-audited model → nothing remainscreate again from the history

8. Transactions and consistency

When changes are final: one request is one transaction, commit before the response, and where atomicity ends.

8.1 One request, one transactioncdms/transaktionen/ein-requestEverything in a request succeeds or nothing does. This page explains when a commit and when a rollback happens, and that there is no bracket spanning two requests.
success → commit before the responseerror anywhere → rollbackconflict at commit → 409two requests → two transactionshooks inside the transaction, side effects not
8.2 Create and read back: STRICT or LENIENTcdms/transaktionen/anlegen-und-zuruecklesenAfter a create, CDMS reads the object back for the response. What happens when reading back fails is decided by the CreateReadMode.
STRICT (default): everything rolled backLENIENT: created, 200 with notice and idcan be overridden per requestsetting of the installationsingletons: always STRICT
8.3 No atomicity across two databasescdms/transaktionen/datenbankgrenzenA change that touches the system DB and a tenant DB is not atomic. This page explains when that happens and what it means.
normal request: one databasehook or custom code writes both levelserror before the commit → both rolled backerror during the commit → partial state possibleoperating mode SINGLE
8.4 Files and transactioncdms/transaktionen/dateien-und-transaktionFile contents are only prepared while the request runs and take effect after the commit. If the request fails, the file storage stays as it was.
successerror while preparing the fileerror after preparingerror after the commitdeleting
8.5 May the client retry?cdms/transaktionen/wiederholenWhich operations can be repeated safely, and for which a repetition creates a second object.
GET/POST read, queryPUTPATCHDELETEPOST createrollbackafter 401after 4xxafter 5xxno response

9. Files

Uploading, downloading, replacing and versioning files: where the bytes live, where the metadata lives, and how both stay together.

9.1 What a file model iscdms/dateien/datei-modellMetadata in the database, content in the file storage. This page explains who manages which part.
standalone file modelfile as a child of another modelfields the server setsendpoints
9.2 Uploadingcdms/dateien/hochladenThe two ways multipart and Base64, the matching endpoints, and how file part and file object find each other by name.
POST /create/uploadPUT /update/{id}/uploadPATCH /update/{id}/uploadBase64 in the JSONseveral files in one requestname does not match → 400duplicate names → rejected
9.3 Downloadingcdms/dateien/herunterladenHow GET /{id}/file works, why the token is in the URL here, and which permissions and limits apply.
regular file model: GET /{id}/filesingleton: GET /fileaccess_token in the URLchecks: token, read, download roleresponse headers
9.4 Replacing and renamingcdms/dateien/ersetzen-umbenennenWhat an update with and without a new file does: replace the content, only rename, or both.
with new file → content replacedwithout file → content staysrename onlyrename and replacePUT and PATCHconcurrently → 409
9.5 File versionscdms/dateien/versionenFor audited file models every old state is kept. How the versions are stored, how revision and content belong together, and when content is simply overwritten.
audited → versionsnot audited → overwrittenrevision and version belong togetheraccess only through rollbackswitching on auditing laterno automatic cleanup
9.6 Storage layout and tenant isolation in storagecdms/dateien/ablageHow the storage path is built, how tenants are separated in the file system, and how a file is stored atomically.
MULTI: path with tenantSINGLEsystem model without tenanttenant missing → rejectedatomic storingdirectory permissions
9.7 Size limitscdms/dateien/grenzenWhich size limits apply to uploads and downloads, what happens when one is exceeded, and where to configure them.
upload: 25 MB per file, 500 MB per request, 500 partssame limits for multipart and Base64413 with the limit in the messageKeysetting via standard propertiesproxy and ingress in frontdownload: whole file in memoryhard limit 2 GiBno quota per tenant
9.8 Storage backendscdms/dateien/speicher-backendsWhere the file contents live: local file system or volume, and applications without any file storage.
FILESYSTEM: local file system / volumeNONE: no file storagestartup check of the base directoryhealth checkrunning in a container

10. Data security

Who may see and change what: permissions on model, relation and row, own data, attribute filters, why invisible objects return 404, and how strict mode handles errors.

10.1 The three levels at a glancecdms/sicherheit/drei-ebenenModel (may I run this operation?), relation (may I go through this field?) and row (may I access this object?). How the levels apply one after another.
Reading and searchingChanging and deletingCreatingnested request
10.2 Model rolescdms/sicherheit/modellrollenWhich role an operation requires: base role, role per action, endpoint role, public access. PATCH uses the update role.
base role allows everythingaction role replaces the base roleendpoint rolepublicAccesshistory, rollback, downloadabstract model
10.3 How role names are builtcdms/sicherheit/rollennamenThe API path /audit/question becomes audit-question, and that becomes audit-question-read. The rule shown with examples.
base roleaction rolefield rolemodel without a foldernested folders, spaces, CamelCasecustom name from the model file
10.4 Permissions on relations (field roles)cdms/sicherheit/feldrollenA field role on a relation allows reading or writing a child model through exactly one field, without direct access to the child model. On simple fields a role works differently: as an additional condition.
field role instead of class roleonly through this fieldno direct endpointone level only, this operation onlyon simple fields: additional condition
10.5 Protected values (roles on simple fields)cdms/sicherheit/geschuetzte-werteA role on a simple field protects a single value. Whoever does not hold it does not see the field, cannot change it and cannot search by it. The model itself stays readable.
in addition to the model rolewildcard leaves it out, name is refusedthe change is what gets checkedclearing needs the delete rolePUT without a value keeps itfilter and order need the read role
10.6 Encrypted fieldscdms/sicherheit/verschluesselte-felderA text field with the rule "encrypted" is stored encrypted in the database and comes back decrypted. What you configure for it, how a key change works and what the field cannot do.
create and change: store encryptedread, search, history: answer decryptedkey and previous keysvalues still stored as plain textfilter and sorting refusednot together with "unique"
10.7 Only your own data (owner filter)cdms/sicherheit/eigene-datenIn user models every person sees only their own rows. How _userId is set and checked.
CreateReadSearchChange and deletechildren created alongTechnical client without a personon behalf of another person
10.8 Attribute filtercdms/sicherheit/attributfilterAn attribute of the person (e.g. projects) restricts a data field. How EQ/IN is formed, what * means, what happens when the attribute is missing and what applies to people with several tenants.
one value → EQseveral values → IN* → unrestrictedmissing/empty → 422field through a relationseveral attribute filters on one modelPerson with several tenants
10.9 Custom data filterscdms/sicherheit/eigene-filterHow a project adds its own visibility rules and why a mandatory filter that cannot be resolved aborts the request instead of silently disappearing.
filter returns a conditionfilter returns null → no restrictionfilter throws an error → request failsseveral filters on one modelunresolvable → 500
10.10 Why invisible objects return 404cdms/sicherheit/unsichtbar-ist-404An object you may not see does not exist from the caller's point of view. This also applies to changing and deleting: you can only write what you can read.
ReadSearchreferences and lists in the responseChangeDeleteRollbackDownload
10.11 Strict mode: error or silently ignorecdms/sicherheit/strict-modeWhether a request that is not allowed returns an error or is silently trimmed. Where this applies and why strict is the default.
strict: missing role → 403lenient: read → 404, query → 403lenient: writing → 403 with its own keylenient: reference in the response → nullnested create strict/lenientonly configurable globally
10.12 Access without a tokencdms/sicherheit/ohne-tokenWhat a request without a token can reach: open paths, endpoints without a role, and how an invalid token is handled.
no token → 403invalid, expired or foreign token → 401open paths without a tokenendpoint without a role (publicAccess)token in the URL for downloads

11. Tenant isolation in CDMS

How CDMS keeps customers apart: one database per tenant, where the tenant of a request comes from, how it is switched, and which rules are never broken.

11.1 SINGLE and MULTIcdms/mandanten/single-multiThe two operating modes of data storage: one database for everyone or one per tenant. What changes as a result.
SINGLEMULTIoperating mode missing → start failsold and new key contradict each other → start failschanging the operating mode later
11.2 Where the tenant of a request comes fromcdms/mandanten/woher-mandantThe tenant is in the token. This page explains how it is read and what happens without a tenant.
from the organization in the tokenfrom the tenant attributeselection among several organizationsseveral organizations without selection → 403organization and attribute contradict each other → 403no tenant in MULTI → 403, behind it 400SINGLE ignores it
11.3 Which database? The persistence targetcdms/mandanten/welche-datenbankThe decision whether an access lands in the system DB or in the tenant DB, as a complete decision table. Without a fallback to the system DB.
system modeltenant model with tenantwithout context → 500without tenant → 400tenant not allowed → 403operating mode SINGLEdatabase missing or unreachable
11.4 Tenant switch by headercdms/mandanten/mandantenwechselHow an authorized person works for another tenant with the tenant header, and why a switch without the role is silently ignored.
selection among own organizationsprivileged switchwithout role → silently ignoredtarget not allowed → 403target suspended → 403operating mode SINGLE
11.5 User switch by headercdms/mandanten/benutzerwechselHow an authorized person works on behalf of another person, with their own roles or with those of the target person, and which checks come first.
with role, own roleswith role, roles of the target personwithout role → refusedtarget person unknown or not in the tenant → refusedlookup not possible → refusedinvalid value in user-roles → refusedwithout the target person's consent → refusedconsent for own roles, target requested → refusedconsent in another tenant → refusedconsent revoked → refused from the next requestservice account of an exempt clientconsent switched off (consent=off)request, approve, grant directly, revoke a consentwhat switches and what stayscreatehistorytogether with a tenant switchoperating mode SINGLE
11.6 Is the tenant served?cdms/mandanten/mandant-bedientBefore every access the filter chain asks CIAS whether the tenant is active. This page gives the CDMS view; the details are in the CIAS section.
activesuspended, closed or outside the validity periodunknownCIAS not reachableafter a tenant switchrequest without a tenantoperating mode SINGLE
11.7 Databases, pools, migrationcdms/mandanten/datenbanken-poolsEvery tenant has its own database with its own connection pool. When it is created and how its schema is migrated.
creation at provisioningcreation on first accessdatabase missing without approval → 500server not reachable → 503migration per tenantpool per targetevicting unused tenants
11.8 Rules that are never brokencdms/mandanten/invariantenThe security invariants of tenant isolation: no fallback to the system DB, separate type sets, only three places may set a tenant.

12. Audit, history, rollback

How every change stays traceable: revisions, reading the history, rolling back to an old state, and what happens to files and relations along the way.

12.1 What is auditedcdms/audit/was-auditiertWhich models have a history, which operations create a revision, and which revision types exist.
auditing: trueADDMODDELnot audited model
12.2 What a revision recordscdms/audit/revisionsdatenNumber, time, person, IP address, browser, and that each database has its own revision log.
revision numbertimeperson (ID and name)acting person after a user switchIP addressuser agentchange without a userone revision log per database
12.3 Reading the historycdms/audit/historie-lesenHow POST /{id}/history returns revisions page by page, which permissions you need, and why deleted objects have a history too.
normal modelSingletondeleted objectwithout history role → 403invisible object → 404unknown id → empty list (model without a filter)paging with page and limit
12.4 Rolling back to an old statecdms/audit/rollbackA rollback creates a new revision with the old content. What comes back (own fields, single references) and what does not (lists, deleted objects).
simple fieldssingle referenceslists (not)deleted object (not)revision of another object → rejectedSingleton
12.5 Rollback for filescdms/audit/rollback-dateienHow the file content is copied back during a rollback, and why the current state is saved first.
content comes back with the recordcurrent content is saved as a version firstrollback of a rollbackrevision without fileVersion → content stayssame content as nowname, size and type
12.6 Audit is not the same as system fieldscdms/audit/audit-und-systemfelderThe difference between _createdOn on the object and the revision history.
_createdOn_updatedOn_userIdhistorynot audited model
12.7 Data protection and retentioncdms/audit/datenschutzWhich personal data the audit contains and how long revisions are kept.
data about the acting persondata in the object contentafter the object is deletedretention without expirywho may read the history

13. Plugging in your own subject-area logic

How project logic gets into the standard flows without changing generated code: hooks, their order, and how they behave on errors and with nested objects.

13.1 Hooks: types and timingcdms/erweitern/hooksWhich hook points exist (before and after the database change, per operation) and how a hook is registered.
CREATEUPDATEPATCHDELETEROLLBACKREAD (after loading, before the response)beforeafterorder via @Ordermodel hook and field hook
13.2 Field hookscdms/erweitern/feld-hooksReusable logic for a single value: store it encrypted, derive it, normalise it. What a field hook looks like, how you assign it to a field and when it runs.
before writing (beforeDatabaseChange)after reading (afterDatabaseRead)transforming hookderiving hook (runsOnEveryWrite)several hooks on one fieldPATCH, PUT with a field role, ROLLBACKnot searchable (keepsValueSearchable)
13.3 The order within a write operationcdms/erweitern/hook-reihenfolgeRecursion, before hooks, validation, saving, after hooks. Why a before hook may still fill a required field.
Create, PUT, PATCHDELETEROLLBACKbefore hook fills a required fieldbefore hook sets an invalid valuebefore hook changes a valid field
13.4 Hooks for nested objects and cascadescdms/erweitern/hooks-verschachteltHooks also fire for children and for objects deleted by a cascade. How they are collected, in which order they run, and when no hooks fire.
child createdchild changedchild deleted by cascadechild only unlinked (no hook)child only linked (no hook)order: operations, parents and childrenREAD hooks for expanded references
13.5 A hook writes itselfcdms/erweitern/hook-schreibt-selbstWhen a hook creates something through a system layer itself, that is a write inside a write. Each gets its own level: its own checks, its own hooks, one shared commit. The depth is bounded and measurable.
hook creates a valid recordouter record is invalidinner record is invalidafter hooks of both levelsinner create with LENIENThook writes on every write (too deep)setting the maximum depthdepth in monitoring
13.6 When a hook failscdms/erweitern/hook-fehlerAn error in a hook rolls back the whole request. How the error reaches the client.
before hook throwsafter hook throwsREAD hook throwsHookValidationException → 422HookExecutionException → 500other exception → 500

14. Understanding errors

What errors look like, what each status code means and how to tell 401, 403 and 404 apart.

14.1 The error formatcdms/fehler/fehlerformatWhich fields an error response has, and what a client should branch on.
Error response from CDMSValidation error with violationsRefusal by the filter chainResponse without a bodyStatus 200 in error shape (LENIENT)
14.2 Map of status codescdms/fehler/statuscodesEvery status code with the situations in which CDMS returns it: 200, 400, 401, 403, 404, 409, 413, 422, 500, 503.
200 (including the LENIENT special case)400401403404409413422500503
14.3 401, 403 or 404?cdms/fehler/401-403-404The three codes that are mixed up most often, as a decision path: when to renew, when to give up, when the object is invisible.
401: token invalid or expired403 without a token403 from the tenant check403: role missing404: object missing or invisible404: path unknownOrder of role and visibility
14.4 Getting validation errors into the formcdms/fehler/validierung-ins-formularHow a client maps the collected violations of a 422 to the form fields, including nested paths.
simple fieldfield in a single referencefield in a listfield the form does not showunknown rule400 invalid-value with patherrors without a fieldthrough a BFF

CIAS – Identity and access

The bridge between a CodamAI application and the identity provider (Keycloak). CIAS knows who a person is, which tenant they belong to, which roles exist, and who may grant them. Keycloak handles the sign-in itself.

1. Basics: what CIAS is and what it is not

The terms and the split you need to understand any CIAS flow: the objects and their owners, tenant and group, the two permission matrices, the write direction, and the ceiling.

1.1 CIAS as a bridge to the identity providercias/grundlagen/brueckeWhat CIAS does and what it explicitly does not do: no login, no passwords, no checking of permissions on data. With the table “CIAS does / CIAS does not”.
What Keycloak doesWhat CIAS doesWhat the application doesWrite direction application → CIAS → KeycloakRead direction: Keycloak leads for accountsembedded / standalone
1.2 The objects and who owns themcias/grundlagen/objekteUser, tenant, role, role grant, group, attribute, module: what each object is, who owns it, and what Keycloak keeps of it as a copy.
UserTenantRoleRole grantGroupUser attributeProfile attributeModule
1.3 Tenant, organization, groupcias/grundlagen/mandant-organisation-gruppeTwo structural terms, not three. The tenant separates data, the group bundles roles, “organization” is only Keycloak's name for a dynamic tenant. With the one question that decides, and a scenario played through.
TenantOrganization (Keycloak only)GroupParent/child structure (deliberately not)
1.4 The two permission matricescias/grundlagen/zwei-matrizenHow a permission is carried (realm role, client role, organization role, group, attribute) is CIAS. What a permission allows (model, operation, field) is CDMS. Why CIAS does not keep a model-operation matrix.
Matrix A: carrier of a permissionMatrix B: content of a permission
1.5 The ceiling: nobody grants more than they havecias/grundlagen/obergrenzeThe rule above every write path: a grant never exceeds the granter. What it means for roles, groups and attributes, and how it differs from delegation.
RolesGroups (through their roles)Attributes (range of values)platform-admin

2. Login and token

How a person or a service gets a token, how it is renewed and ended, and what happens with the token on every request.

2.1 Sign in in the browsercias/login/browser-loginThe path from “open page” to “signed in” via Keycloak with authorization code, with all variants of the login page.
not signed in → redirectautomatic loginafter sign-out (no auto login)return only to internal pathsKeycloak pages: password, OTP, forgot password
2.2 Sign in as a service (client credentials)cias/login/dienst-loginHow a server gets a token without a person, what this is meant for, and why user-owned models usually return nothing with it.
Client credentialsCIAS at the Keycloak admin APIService asks CIAS (lookup)
2.3 Session in the BFF and cookiescias/login/bff-sitzungWhy the token lives in the frontend's server and not in the browser, what the session cookie looks like, and why every portal has its own cookie prefix.
Cookie httpOnly, sameSite=laxown prefix per portallifetime 1 h
2.4 Renew the tokencias/login/token-erneuernWhen and how the token is renewed before it expires, and what happens when a refresh is rejected or fails.
Refresh successfulRefresh rejected (4xx) → sign in againKeycloak not reachable (5xx) → retry later
2.5 Sign outcias/login/abmeldenHow signing out deletes cookies, how Keycloak ends the session, and why the login page does not sign you in again right away.
with ID tokenwithout ID token (confirmation page)without configured Keycloak (local only)
2.6 What happens with the token on every requestcias/login/token-pruefungThe filter chain step by step: read the header, validate, exchange, read the identity, resolve the tenant, admit the tenant, build the roles, perform the switch, clean up.
valid tokenno token → 403invalid, expired or foreign token → 401token exchange refused → 401Keycloak unreachable → 503MULTI without tenant → 403tenant not unique or not served → 403user switch refused → 403SINGLE: the tenant in the token does not count
2.7 Token exchangecias/login/token-exchangeWhy CIAS exchanges every user token for one for its own client, how long the result is cached, and what happens with a misconfigured realm.
Exchange with cache hitExchange without cacheToken without jti (no cache)Realm misconfigured → 401Keycloak unreachable → 503
2.8 What is read from the tokencias/login/claimsWhich claim goes where in the RequestContext: user, name, realm roles, business roles, organization, tenant, allowed tenants, attributes.
user and namerealm roles and business rolesgroupsorganization and tenantallowed tenantsattributesprotocol claims (not read)
2.9 Effective roles: global or in the tenantcias/login/effektive-rollenHow CIAS builds the valid roles from global roles and roles of the organization, and why globally granted roles can drop away under a dynamic tenant.
global roles onlyOrganization without its own rolesOrganization with its own roles (replaces)Realm roles (always)user switch with the target person's roles
2.10 Why revoking permissions takes effect with a delaycias/login/rechteentzug-verzoegertRevoked permissions stay in the token until it expires or the exchange cache runs out. How long this takes and how to block someone immediately.
role revokedattribute value per tenant changedtenant suspendedaccount suspended

3. Registration

How a person becomes a user: one flow with four variants, email verification, password at Keycloak, approval, tenant assignment, initial roles, hooks and emails.

3.1 One flow, four variantscias/registrierung/ueberblickSelf-registration, creation by the platform administrator, invitation by the tenant administrator, and redeeming the invitation: what stays the same and what differs.
SELF_SERVICEPLATFORM_ADMINTENANT_ADMINRedeem an invitationnew address / known addresswith / without approval
3.2 The states of a registrationcias/registrierung/zustaendeFrom INITIATED to COMPLETED: every state, every transition, and where EXPIRED and FAILED come from.
INITIATEDPENDING_VERIFICATIONVERIFIEDPENDING_APPROVALAPPROVEDREJECTEDPROVISIONINGCOMPLETEDFAILEDEXPIRED
3.3 Self-registrationcias/registrierung/selbstregistrierungA person registers without signing in, through the public form. The full flow with approval and a new tenant.
new addressaddress already knownwith approvalwithout approvalnew tenant (CREATE_NEW)without tenant (NONE)
3.4 Creation by the platform administratorcias/registrierung/admin-anlageThe platform administrator creates a person and is the only one allowed to name the tenant in the payload.
with tenant from the payload (FROM_PAYLOAD)without tenant (NONE)flow not configured → rejected
3.5 Invitation by the tenant administratorcias/registrierung/einladungA tenant administrator invites a person into their own tenant. The tenant always comes from their token, never from the payload.
new personperson already has an account (joining)tenant in the payload (is ignored)caller without tenant → 403
3.6 Redeem an invitationcias/registrierung/einladung-einloesenWhat the invited person sees and does: fetch the open fields, redeem the link, membership.
fetch the open fieldsacceptalready accepted (same response)link unknown or expired → 404
3.7 The email is the accountcias/registrierung/bestehendes-kontoOne account per address, any number of tenants. What happens when a known address registers, and why nobody is added to a tenant without consent.
NEW_ACCOUNTADDITIONAL_MEMBERSHIPknown without tenant → “already registered”abandoned account is taken overlocked account stays lockedolder open attempt is replaced
3.8 Verify the emailcias/registrierung/email-bestaetigenCIAS creates the account disabled, sends its own email with a one-time link, and enables the account only after the click. How the link is protected.
clicksecond click (same result)link unknown or expired → 404admin verifies manually
3.9 Set the passwordcias/registrierung/passwort-setzenCIAS never sees a password. How the person sets their password at Keycloak after verification, and what happens without a password setup link.
with password setup link in the welcome emailwithout link (“Forgot password”)link later via admin
3.10 Approval by an administratorcias/registrierung/freigabeWhen a registration needs approval: approve, reject, retry, discard.
approvereject (email REJECTED)retry provisioningdiscard (unused account is deleted)list of registrations
3.11 Where the tenant comes fromcias/registrierung/mandant-zuordnenThe six kinds of tenant assignment and the order in which policy and hook decide.
NONECREATE_NEWJOIN_EXISTINGFROM_CALLERFROM_PAYLOADFROM_INVITATIONHook overrides
3.12 What happens on completioncias/registrierung/bereitstellungProvisioning in a fixed order: determine initial roles, enable the account, create or assign the tenant, grant roles, welcome email.
new tenantexisting tenant (static)existing tenant (dynamic)without tenanterror → FAILED
3.13 Initial roles as a rule setcias/registrierung/startrollenWhich roles a new person gets is decided by a rule set per situation (founder, member, without tenant). Who may write rules and why the tenant rule replaces instead of adds.
TENANT_FOUNDERTENANT_MEMBERTENANTLESSDefault of the installation (bean)Installation ruleTenant rule (replaces)Delegation checked again when applied
3.14 Your own logic: hooks and eventscias/registrierung/hooks-eventsHooks run inside the registration and may reject it, events follow afterwards. All hook points and what a hook must not do.
Hook rejects → 422Hook changes tenantHook changes initial rolesHook with FROM_CALLER (not called)Events
3.15 Protecting the public endpointscias/registrierung/oeffentliche-antwortenWhy self-registration always returns the same answer, why invalid links look the same, and how throttling works.
always 202link error 404, second click 202throttling per addressthrottling per client429 without Retry-After
3.16 Clean up abandoned registrationscias/registrierung/aufraeumenHow waiting registrations are set to EXPIRED after their deadline, unused accounts are deleted, and old registrations are removed.
waiting, expiredreplaced by a newer attemptdiscarded by handdelete old registrations

4. User management

The user record in CIAS from the subject area view: status, suspend, close, move, maintain attributes, and why the order of the write operations decides security.

4.1 The user recordcias/benutzer/datensatzWhy CIAS keeps its own record next to the Keycloak account, what it contains, and what it never contains.
Fields of the recordwhat it never containshow a record is createdQueries for administrators
4.2 The lifecycle of a usercias/benutzer/statusPENDING, ACTIVE, SUSPENDED, CLOSED: every transition and why CLOSED is final.
PENDINGACTIVESUSPENDEDCLOSED
4.3 The write ordercias/benutzer/schreibreihenfolgeWhen revoking, Keycloak first; when granting, CIAS first. Why exactly this way round, and what happens if something fails in between.
Revoke accessGrant accessFailure between the stepsonly in CIAS
4.4 Suspend, reactivate, closecias/benutzer/sperren-schliessenThe three status operations step by step, and the fact that closing disables the account but does not delete it.
suspendunsuspend (reactivate)closeno deletion
4.5 Import existing accountscias/benutzer/importierenHow CIAS imports Keycloak accounts it does not know yet as users.
unknown active accountunknown, inactive accountalready knownskipped (several organizations, address taken)
4.6 Rename and change the home tenantcias/benutzer/umziehenWhat happens when you rename a person or change their home tenant, and the fact that the membership in Keycloak does not move along.
renamechange home tenantremove home tenantclosed person
4.7 Maintain a person's attributescias/benutzer/attribute-pflegenThe three storage locations for attributes (CIAS-internal, Keycloak profile, per tenant) and who may write what.
CIAS attributesProfile attributes (end up in the token)Per-tenant attributesDelegation per attributeCeiling for values
4.8 Resend the password setup linkcias/benutzer/passwort-linkHow an administrator sends a person a new link to set their password.
send linkaccount not activedelivery not configuredKeycloak extension missing
4.9 Self-service: own tenant and languagecias/benutzer/selbstauskunftWhat a signed-in person can look up and change about themselves.
own tenantread languagechange languagenot offered

5. Tenants

The tenant as the isolation boundary: static or dynamic, its business status, its technical rollout, how it is resolved and admitted on every request, and how you switch between tenants.

5.1 Static and dynamic tenantscias/mandanten/statisch-dynamischA static tenant hangs on a user attribute, a dynamic one on a Keycloak organization. When each one fits.
STATICDYNAMIC
5.2 The lifecycle of a tenantcias/mandanten/lebenszyklusTwo separate states: the business standing (PENDING to CLOSED) and the technical rollout (NOT_PROVISIONED to PROVISIONED). When a tenant is served.
PENDINGACTIVESUSPENDEDCLOSEDNOT_PROVISIONEDIN_PROGRESSPROVISIONEDFAILEDValidity window
5.3 Create and provision a tenantcias/mandanten/anlegenStore the intent, create and migrate the database, store the result. What happens in SINGLE, in MULTI and with a standalone CIAS.
MULTI: create the databaseSINGLE: nothingstandalone CIAS: nothingfailure → FAILED, can be retriedstuck rollout → FAILED after 30 min
5.4 The tenant keycias/mandanten/schluesselWhy the key cannot change, which characters are allowed, and that it is also the database name. How it is built during a self-registration.
from the company namefrom the email domaincustom building rule
5.5 Suspend and close tenants, validitycias/mandanten/sperren-schliessenWhat suspending, resuming, activating, closing and a validity window do, and why there is no deleting.
suspendresumeactivatecloseset validity windowno DELETE
5.6 Determine the tenant of a requestcias/mandanten/aufloesenThe six rules CIAS uses to determine the tenant from the token and header, with the results RESOLVED, NONE, AMBIGUOUS and CONFLICT.
no organization, attribute tenantno organization, no attribute → NONEattribute contradicts membership → CONFLICTheader selects own organizationexactly one organizationseveral without selection → AMBIGUOUS
5.7 Admit the tenant (tenant gate)cias/mandanten/zulassenResolving and admitting are two steps. How the gate asks, remembers for 30 seconds, answers from memory during an outage, and why unknown and suspended look the same.
CIAS reachableCIAS down, tenant knownCIAS down, tenant unknownsuspended tenantsuspension takes effect up to one TTL later
5.8 Switch between tenantscias/mandanten/wechselnSelecting among your own organizations without a special role, privileged switch with a role, user switch, and the fact that the tenant is admitted again after every switch.
select own organizationprivileged switchwithout role → silently ignoredtarget suspended → 403user switch
5.9 In SINGLE the tenant in the token does not countcias/mandanten/single-ignoriertIn the operating mode SINGLE the tenant in the token is ignored: no gate, no switch. Why this is so and why one switch carries two meanings here.
SINGLEMULTI
5.10 Working for a tenant without a requestcias/mandanten/arbeit-ohne-anfrageHow background work (timers, jobs) runs for a tenant, through the same gate, and which three places may set a tenant.
tenant is servedtenant not servednestedwithout roles

6. Grant roles and permissions

The role catalog, the levels of a role, how modules register their roles, who may grant roles, time-limited grants, and how a role gets into the token.

6.1 The role catalogcias/rollen/katalogWhat CIAS keeps for every role: key and client, owner module, scope, delegation, display group, retirement.
PLATFORMTENANTretired
6.2 Realm role, client role, organization rolecias/rollen/ebenenThe three levels at which a role is granted, where it ends up in the token, and who reads it.
Realm roleClient role, globalClient role in the organization
6.3 Modules register their rolescias/rollen/deklarationEvery module declares its roles and attributes itself. How CIAS takes in the declaration, embedded as a bean or standalone via /cias/fetch, and what happens with a rejected declaration.
embedded (bean)standalone (GET /cias/fetch)REJECTED: only this module drops outREFUSED: key collisionattribute conflict stops everythingmodule declares platform role → rejected
6.4 Reconciliation with Keycloakcias/rollen/abgleichAt startup and at the push of a button, CIAS brings roles, profile attributes and claim mappers in Keycloak up to date. Why Keycloak first and then the catalog, and why nothing is ever deleted but retired instead.
at startupon requestnew rolewithdrawn role → retiredrequired attribute without default → rejected
6.5 How a role gets from the code into the tokencias/rollen/rolle-ins-tokenThe whole path: declaration in the module, catalog, creation in Keycloak, grant, claim in the token.
Tenant role in a dynamic tenantRole through a groupInitial role of a registration
6.6 Grant a rolecias/rollen/vergebenWho may grant? The platform administrator always, everyone else only with delegation, within the ceiling and in the same tenant. The flow with all rejections.
Platform administratorTenant administrator with delegationwithout delegation → 403above the ceiling → 403other tenant → 403tenant without organization → rejected
6.7 Time-limited rolescias/rollen/befristetGrants with a start and an end: SCHEDULED, ACTIVE, EXPIRED, REVOKED, and how a timer adds and removes them in Keycloak.
SCHEDULEDACTIVEEXPIREDREVOKED
6.8 Revoke a rolecias/rollen/entziehenWhat happens when you revoke a role, in which order, and when it reaches the token.
active grantscheduled grantalready revokedexpired → 409role in the organization
6.9 The platform's realm rolescias/rollen/plattformrollenplatform-admin, user, mail-template-admin, allowed-tenant-context-switch, allowed-user-context-switch, declaration-reader: what each one is for and who may grant it.
platform-adminusermail-template-adminallowed-tenant-context-switchallowed-user-context-switchdeclaration-reader

7. Groups

Groups as role bundles with members: create them, maintain members, the default group, reconciliation with Keycloak and how groups interact with dynamic tenants.

7.1 What a group iscias/gruppen/was-ist-eine-gruppeA bundle of realm roles and client roles with members, managed by CIAS, kept in Keycloak as a marked copy.
realm roles in the groupclient roles of several modules in the groupgroup without rolesdefault group
7.2 Manage groups and memberscias/gruppen/verwaltenCreate, change, delete, add and remove members, take over existing Keycloak groups.
createchangedeleteadd memberremove memberimport
7.3 The default groupcias/gruppen/standardgruppeWhich group every new person gets automatically, and why this only applies to new accounts.
registration completedexisting account registersaccount is created directly in Keycloakgroup becomes a default groupgroup is no longer a default groupKeycloak unreachable
7.4 Reconciliation with Keycloakcias/gruppen/abgleichHow the sync state PENDING/SYNCHRONIZED comes about and when reconciliation runs.
at startupon request
7.5 Group roles under dynamic tenantscias/gruppen/grenzenWhy client roles granted globally, including those from groups, do not apply under a dynamic tenant that has roles of its own, and how to plan groups accordingly.
tenant without roles of its owntenant with roles of its ownrealm roles from groups

8. User attributes

Details on the account that become claims in the token and filter rows in CDMS: where they come from, how modules declare them, who may write them and which tenants a value applies to.

8.1 Two origins of attributescias/attribute/herkunftPlatform attributes (e.g. tenant) and project attributes from the model. The difference and why it matters.
platform attributeproject attribute
8.2 Registering attributescias/attribute/deklarationHow a module declares an attribute, why a required attribute needs a default value, and how the attribute catalog comes about.
optionalrequired with default valuerequired without default value → rejectedpreference of the personper tenant
8.3 The path into the tokencias/attribute/weg-ins-tokenProfile in Keycloak, claim mapper, claim in the token, attribute in the RequestContext.
one valueseveral valuesno valuevalue per tenant
8.4 Who may write an attributecias/attribute/wer-schreibtDelegation per attribute and ceiling for values: an administrator can only grant values they hold themselves. * means unrestricted.
platform administratordelegatedvalue contained → okvalue wider → refused*not registered or withdrawn → refusedbound to the person → refused
8.5 One value per person or per tenantcias/attribute/pro-mandantAn attribute applies either to the person in all tenants (USER) or separately per tenant (USER_IN_TENANT). How the right value gets into the token and the attribute filter when a person belongs to several tenants.
USER: one value for all tenantsUSER_IN_TENANT: one value per tenantperson with one tenantperson with several tenantsCIAS unreachable
8.6 How an attribute goes away againcias/attribute/verschwindenAn attribute that no module declares any more is retired, not deleted.
module withdraws the attributeanother module keeps registering itmodule unreachableregistered again, by the same moduleregistered again, by another module

9. Notifications

Which emails CIAS sends, how the right template is found, and who may change templates.

9.1 Which emails existcias/benachrichtigungen/mailartenEach email with its occasion: verification, membership invitation, invitation, already registered, awaiting approval, rejected, welcome, set password, consent to a user switch.
VERIFY_EMAILMEMBERSHIP_INVITATIONINVITATIONALREADY_REGISTEREDAPPROVAL_PENDINGREJECTEDWELCOMEPASSWORD_SETUPSWITCH_CONSENT_REQUESTEDSWITCH_CONSENT_USED
9.2 How the right template is foundcias/benachrichtigungen/vorlage-findenOne default per email and language, plus a tenant's own wording: the search from the tenant to the default, database before what ships, and what happens with a broken template.
tenant + languagetenant + language codedefault + languagedefault + language codedefault in the fallback languageapplication and flow as placeholdersbroken template → skipped
9.3 Edit templatescias/benachrichtigungen/vorlagen-bearbeitenWho may change which template: editors (platform administrator, mail-template-admin) all of them, tenant administrators only their own and only approved kinds. Reset a default instead of deleting it.
editortenant administratorkind not approved → refusedsomeone else's template → refusedtemplate cannot be generated → refusedreset a defaultdelete a tenant's wording
9.4 Sending and brandingcias/benachrichtigungen/versandSMTP or log, logo and colors as data, languages.
SMTPLognotification switched offbranding through the contextbranding through an own templatelanguages

10. Audit in CIAS

One audit trail for the whole platform: which events go into it, what is missing, and who may read them.

10.1 One trail for everythingcias/audit/eine-spurA single listener writes every business event into a table that only grows. What an entry looks like.
event with a logged-in callerevent without a callerlong text is cutwriting failschange is rolled back
10.2 Which events are loggedcias/audit/ereignisseWhich events go into the audit trail: registration, user, consent to a user switch, tenant, role grant.
RegistrationEventUserEventSwitchConsentEventTenantEventAuthorizationEvent
10.3 Read the auditcias/audit/lesenWho may read the audit and in which form the entries are available.
platform administratoreveryone else → refusedpage too large → refused
10.4 CIAS audit and CDMS historycias/audit/cias-und-cdms-auditTwo different records: CIAS records events around people and permissions, CDMS records data states. When to look where.
question about permissions and people → CIAS auditquestion about data → CDMS historyquestion about both

11. Connection to the identity provider

How CIAS talks to Keycloak without the business modules knowing Keycloak: ports and adapters, the Keycloak adapter, the in-memory adapter for tests, and the Keycloak extension.

11.1 Ports and adapterscias/identity-provider/ports-adapterThe business logic talks to interfaces (“ports”), an adapter translates for Keycloak. Which ports exist and why a second provider is a second artifact.
Keycloak adapter selectedin-memory adapter selectedno provider selectedprovider unreachableprovider reports a conflictprovider does not know the objectprovider refusesa second provider
11.2 The Keycloak adaptercias/identity-provider/keycloak-adapterWhat the adapter creates in Keycloak and how: organizations, organization roles as groups, profile attributes with permissions, health check.
login as a service accountlogin as an administratorcreate an account and change its stateorganization and membershipglobal rolerole in an organizationrevoke a role in an organizationprofile attribute: factprofile attribute: preferencecreate or correct a claim mappinghealth check: reachablehealth check: unreachable
11.3 The in-memory adapter for tests and developmentcias/identity-provider/memory-adapterAn identity provider in memory, checked against the same contract tests, for tests and local development without Keycloak.
contract testtest of a whole applicationlocal development (profile local)role not createdpassword link from memoryforeign group for a testrestart
11.4 The Keycloak extension for the password linkcias/identity-provider/keycloak-erweiterungA jar that runs in Keycloak and returns the signed link instead of emailing it itself. What happens without the extension.
extension installed: linkextension missing: no linkaccount unknownrequest refusedclient not permittedin-memory adapter instead of KeycloakKeycloak started with --optimized

12. Security principles

The principles behind every CIAS process, in one place: refuse when in doubt, indistinguishable refusals, no defaults for permissions, and behavior during outages.

12.1 Reject when in doubtcias/sicherheit/fail-closedNo default tenant, no default administrator role, required configuration without a default. Why an application would rather not start than start generously.
no default tenantno default rolesexplicitly empty means nobodyrequired beansstartup refusedrequired field in the request
12.2 Rejections that reveal nothingcias/sicherheit/ununterscheidbarUnknown and suspended look the same, public endpoints always answer the same way, admin rejections are identical. Why this way nobody can probe for information.
form: new and known addresslink: unknown or expiredtenant: unknown, suspended or unreachableadministration: no permissionlookups for services
12.3 When CIAS or Keycloak failscias/sicherheit/ausfaelleWhat happens during an outage: the tenant gate answers from memory, registration and administration answer with 503, a failed provisioning stays repeatable.
CIAS downKeycloak down during a requestKeycloak down during registrationKeycloak down during administrationProvisioning failedRestart during an outage

13. User interfaces

Which user interfaces exist for sign-in, registration and administration, and which flows start there.

13.1 The login pages (Keycloak theme)cias/oberflaechen/login-seitenWhich pages the login theme provides and which flow leads to which page.
Sign inSign in in two stepsForgot passwordSet or change passwordOTPVerify email (Keycloak)Page expiredError and infoConfirm sign-outRegister (Keycloak)
13.2 The admin interfacecias/oberflaechen/verwaltungThe pages for users, tenants, roles, groups, registrations and email templates, and which CIAS flows they trigger.
UsersTenantsRolesGroupsRegistrationsEmail templateswithout the platform administrator roleaccount without a tenant
13.3 Register and verifycias/oberflaechen/registrierungsseitenThe public pages “Register” and “Verify”, and how they build their form from the server's field description.
Load the formSubmit: acceptedSubmit: too fast or too oldSubmit: refused, throttled, switched offTrap filled inalready signed inVerify: without approvalVerify: with approvalVerify: setting unknownLink incomplete or invalid
13.4 The CIAS portalcias/oberflaechen/cias-portalCIAS's own portal: sign-in, overview of the services with their CIAS connection, status display.
opened on its ownopened from the hub (moduleId)Connection: readyConnection: refusedConnection: not servedConnection: unreachableService will not start like thisList empty or not loadable

CDMS and CIAS together

How CDMS and CIAS work together, as a single unit in one process or as separate services. With flows walked through from login to the database. A good starting point for newcomers.

1. The platform at a glance

The modules, the parties in a request and the key terms in pictures, before we get into the flows.

1.1 The CodamAI moduleszusammenspiel/ueberblick/moduleCDMS, CIAS, CRMS, the hub and the shared building blocks: what each module is for, which repositories it consists of and how everything fits together.
CDMS: data layer and generatorCIAS: identity and accessCRMS: reportsHub: user interface and central backendshared building blockslibrary, service, user interface, tool
1.2 The parties in a requestzusammenspiel/ueberblick/beteiligteUser, browser, frontend with BFF, Keycloak, CIAS, CDMS, databases, file storage: who talks to whom, embedded and standalone.
embedded: CDMS and CIAS in one processstandalone: CIAS as a separate servicefrontend: hub user interface, CDMS portal, CIAS portal, CRMS user interfaceapplication with and without file storage
1.3 The key terms in pictureszusammenspiel/ueberblick/begriffeToken, tenant, user, role, group, attribute, model, hook, revision: each term with one sentence and one picture.
TokenTenantUserRole (in the token and effective)GroupAttribute (per person and per tenant)ModelHookRevision
1.4 Who decides what?zusammenspiel/ueberblick/wer-entscheidetKeycloak logs you in, CIAS gives meaning and writes permissions, the token carries them, CDMS enforces them. Which question each part answers.
Keycloak: login and tokenCIAS: meaning, grants, filter chain, tenant gateToken: carries the permissionsCDMS: enforcement on the dataHook: the project's own business logic

2. A single unit or separate services

The two topologies of CIAS next to CDMS: embedded in one process or as a separate service. What runs in each, who calls whom, why both must behave the same in the subject area — and how that relates to the operating mode of the data storage, SINGLE or MULTI.

2.1 CIAS embedded (a single unit)zusammenspiel/betriebsarten/eingebettetCIAS runs in the same process as CDMS or the hub backend. Which modules are included, how CDMS calls CIAS, and which database CIAS uses.
with starterwithout starter (hub-backend, generated project)tenant check through a method callattribute lookup through a method calldeclaration as a beansystem database of the host
2.2 CIAS as a separate servicezusammenspiel/betriebsarten/getrenntCIAS runs as its own service. What the CDMS service then brings along itself, which calls go over HTTP, and with which token.
tenant check through HTTPattribute lookup through HTTPdeclaration through GET /cias/fetchservice token instead of user tokenown CIAS databaseCIAS does not answer
2.3 Embedded and standalone comparedzusammenspiel/betriebsarten/vergleichAll differences between “CIAS in the same process” and “CIAS as a separate service” in one overview: artifacts, calls, database, failure behavior and the delay of a suspension.
embedded (a single unit)standalone (two services)CIAS reachable / not reachable
2.4 Configuration decides what runszusammenspiel/betriebsarten/konfigurationEvery CIAS module sits behind a switch with no default value. Why no CIAS class activates itself, and what is decided at build time (which provider adapter).
module onmodule offswitch missing → startup failsgenerator: EMBEDDED / REMOTE / NONE
2.5 SINGLE and MULTI across both moduleszusammenspiel/betriebsarten/single-multiWhat the data storage operating mode does in CDMS and in CIAS, and that the same switch also decides whether the tenant in the token is checked.
SINGLEMULTIswitch missingone switch for data storage and tenant check
2.6 Why both modes must behave the same in the subject areazusammenspiel/betriebsarten/fachlich-gleichSame code, same rules, same refusals. What “functionally identical” means in practice, where the difference does show, and where it does not.
one question, two pathssame: rules, answers, refusalsdifferent: latency, outage, start-up checks

3. The path of a request, end to end

Flows walked through across all parties: from login to the row in the database, the path of the token, the tenant check in both operating modes, and what happens when something fails.

3.1 From login to the datazusammenspiel/anfrageweg/login-bis-datenA person logs in and opens a list. Every step through browser, BFF, Keycloak, CIAS and CDMS to the database and back, in both operating modes.
embedded (one process)standalone (two services)first request after signing inlater request from a running sessionaccess token expiredrefusal at every station
3.2 The path of the tokenzusammenspiel/anfrageweg/token-wegWhere the token is created, where it is stored, who exchanges it and who reads it, until it arrives at CDMS as a RequestContext.
user through a portaldownload with the token in the URLservice token for the lookupsreader token for the declaration
3.3 The tenant check in both operating modeszusammenspiel/anfrageweg/mandantenpruefungHow the tenant gate asks: embedded through a method call, standalone through HTTP, with cache, timeout and error handling.
embeddedstandalonecache hittimeout403 from the lookup
3.4 When CIAS is not reachablezusammenspiel/anfrageweg/ausfallWhat CDMS does in standalone mode when CIAS goes down: keep serving known tenants, reject unknown ones, tenant-bound attributes cannot be read.
tenant in cachetenant unknowntenant-bound attributesrequest without a tenantrestart during the outage
3.5 A write across all layerszusammenspiel/anfrageweg/schreibvorgangA form is saved: from the click through BFF, token check, permissions, validation, hooks, saving, audit and commit to the response.
creating (POST /create)changing (PUT and PATCH)deleting (DELETE)refusal at every stagesuccess: commit before the responsefailure: rollback of the whole request

4. Startup, provisioning, reconciliation

What happens before the first request arrives: cold start, registering the modules' roles and attributes with CIAS, a new tenant from start to finish, and the database schemas.

4.1 Cold start of an installationzusammenspiel/bereitstellung/kaltstartMigrations, bootstrap (platform roles, first tenant, first administrator), intake of the declarations, reconciliation of roles and groups, in this order.
bootstrap onbootstrap offfirst administrator must exist in Keycloakembeddedstandalone
4.2 Modules register roles and attributeszusammenspiel/bereitstellung/deklarationHow CDMS reports its roles and attributes to CIAS: embedded as a bean, standalone through /cias/fetch with its own role, and what happens on a rejection.
embeddedstandalonerejected
4.3 A new tenant, end to endzusammenspiel/bereitstellung/neuer-mandantFrom creation in CIAS through the organization in Keycloak and the database to the first request in CDMS that passes the gate for this tenant.
through administrationthrough self-registrationembeddedstandalone
4.4 Databases and schemaszusammenspiel/bereitstellung/schemataWhich databases exist (system, one per tenant, CIAS), who migrates which schema, and in which order.
System DBTenant DBCIAS embedded (own migration history)CIAS standalone (own DB)

5. Scenarios walked through

Typical business cases from start to finish, across CIAS and CDMS. Every scenario links to the individual pages.

5.1 A new customer is set upzusammenspiel/szenarien/neuer-kundeA company registers itself, gets approved, receives its tenant and its first administrator, who immediately creates data.
with approvalwithout approvalMULTI: own databaseSINGLE: no own databaseaddress already knownkey already takenprovisioning fails
5.2 A colleague is invitedzusammenspiel/szenarien/mitarbeiter-einladenThe administrator invites a colleague. The colleague confirms, sets her password and sees the data of her tenant, but only the data her roles allow.
colleague is newcolleague already has an account with another customerlink expiredclicked twicecaller without the role or without a tenant
5.3 One person in two tenantszusammenspiel/szenarien/zwei-mandantenA consultant works for two customers. How she chooses between the tenants, which roles apply in each and which attribute values apply to her.
two organizations (selection)static tenant with allowedTenants (privileged switch)roles per tenantattribute values per tenantno selection sent
5.4 Support looks into a tenantzusammenspiel/szenarien/support-wechselA platform employee switches into a customer tenant with a role and a header to reproduce a problem. What he sees and what he does not.
tenant switch onlytenant switch and user switch, own rolestenant switch and user switch, Ben's rolestenant role missing → silently ignoreduser role missing or Ben not in nordbau → 403Ben has not consented → 403requesting and approving a consenttarget not allowedtarget suspendedsupport is a member itself (selection)
5.5 A person leaves the companyzusammenspiel/szenarien/mitarbeiter-gehtSuspend, revoke roles, close the account: what takes effect immediately, what only when the token expires, and what happens to her data and the audit.
revoke rolessuspend the accountclose the accountit has to stop nowthe person comes back
5.6 A customer cancelszusammenspiel/szenarien/kunde-kuendigtThe tenant is suspended and later closed. What happens to logins, running requests and the database.
validity window for the end of the contractsuspend nowclosethe customer's peoplethe customer comes back
Search