CodamAIDocs
Topicdone

The path of a request through the layers

Filter 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.

Variants
readcreateupdate and delete (with visibility check)searchsuccess: commit before the responsefailure: rollbackstop at any station

What this is about

Every request to CDMS passes through the same stations, always in the same order. Each station has exactly one job and may stop the request. If you know the stations, you know where an error came from as soon as you see it.

The stations

A request from the outside in
  1. CIAS
    Filter chain
    Is the token valid? Which person, which tenant? Is the tenant served? Is a context switch allowed?
    ↳ no 401 (no valid token on a protected path) · 403 (tenant not served or not determinable)
  2. CDMS
    REST layer
    Can the request be read? Which fields does response ask for? Take over files from multipart or Base64.
    ↳ no 400 (malformed request, response missing)
  3. CDMS
    System layer
    Does the person have the role? Is the row visible to them? Are all fields valid? Run hooks, write relations along.
    ↳ no 403 (role missing) · 404 (not visible) · 422 (invalid)
  4. CDMS
    Persistence
    Which database? Only the visible rows, only the requested columns. When reading, the READ hook runs afterwards.
    ↳ no 400 / 403 (tenant missing or not allowed) · 409 (value already taken, object still referenced) · 400 (value does not fit the column) · 503 (database unreachable)
  5. CDMS
    Commit
    Did everything work? Then make the transaction permanent, before the response is written.
    ↳ no Rollback, 409 on a conflict, 503 if the database cannot be reached, otherwise 500
  6. Response with data and meta; the change is stored permanently

Who knows what

Each layer only knows its own part. That makes them replaceable and testable.

StationModuleknowsdoes not know
Filter chaincias-authenticationtoken, person, tenant, rolesmodels, data
REST layercdms-rest-apipaths, payloads, field selectiondatabase
System layercdms-system-layer, cdms-authorizationbusiness rules, permissions, relations, hooksSQL, database choice
Persistencecdms-persistence-databasedatabases, tables, SQLHTTP, payloads
Files (optional)cdms-localfs-storagestorage paths, byteseverything else

The result of the filter chain is the RequestContext: an object that lives for exactly this request and holds person, tenant, allowed tenants, roles and attributes. Every later station reads from it; none of them reads the token itself.

The paths one by one

Four kinds of requests

When: POST /read/{id} or GET /read/{id}

sequenceDiagram
    participant C as Client
    participant F as Filter chain (CIAS)
    participant R as REST layer
    participant S as System layer
    participant P as Persistence
    participant DB as Database
    participant H as Hooks
    C->>F: POST /read/{id} + token
    F->>F: check token, fill RequestContext
    F->>R: pass on
    R->>R: resolve response (fields, references)
    R->>S: readObject(id, field selection)
    S->>S: check read role
    S->>S: add security filters (owner, attributes)
    S->>P: query
    P->>DB: SELECT only the requested columns
    DB-->>P: row
    P-->>S: entity
    S->>H: after hook (READ), e.g. decrypt a field
    S->>S: convert the entity into a DTO
    S->>S: load references one by one, each with its own permission check and READ hook
    S-->>R: DTO
    R-->>C: data + meta

Result: No match, or the match is not visible: 404. The READ hook sees every loaded object before it becomes the response.

When: POST /create

sequenceDiagram
    participant C as Client
    participant F as Filter chain (CIAS)
    participant R as REST layer
    participant S as System layer
    participant H as Hooks
    participant P as Persistence
    C->>F: POST /create + token
    F->>R: RequestContext filled
    R->>R: take over files, resolve response
    R->>S: createObject(DTO)
    S->>S: check role, copy fields,<br/>set defaults, collect violations,<br/>create children recursively
    S->>H: before hooks
    S->>S: report all violations at once (422)
    S->>P: store
    S->>H: after hooks
    S->>P: flush, then read back (with READ hook)
    S-->>R: DTO
    R-->>C: data + meta

Result: The hooks run before validation. So a hook may fill a required field that the client does not even know about.

When: PUT, PATCH, DELETE, rollback

  1. 1
    Client→CDMS
    sends the change with the id of the object
  2. 2
    CDMS
    checks first whether the row is visible to this person, with the same filters as for reading
    Not visible → 404. So knowing someone else's id is not enough to change their data.
  3. 3
    CDMS→Database
    loads the complete object
  4. 4
    CDMS
    checks the role, applies the change, runs hooks, validates
  5. 5
    CDMS→Database
    stores, reads back (DELETE does not read back)
  6. 6
    CDMS→Client
    commits and responds

Result: You can only change or delete what you can also read.

When: POST /query

  1. 1
    Client→CDMS
    sends response and parameter (filter, sorting, page)
  2. 2
    CDMS
    resolves the field selection, checks the read role
  3. 3
    CDMS
    puts the client's filter together with the security filters into one common AND bracket
    That way no client filter can bypass the security filters, not even an OR.
  4. 4
    CDMS→Database
    counts the matches (for totalCount) and reads the requested page
  5. 5
    Hook
    after hook (READ) for every loaded object, before it goes into the list
  6. 6
    CDMS→Client
    responds with data (list) and meta (numbers)

Result: No matches is not an error: 200 with an empty list.

When is a change stored?

The transaction covers the whole request, not individual methods. CDMS makes it permanent at a fixed point: right before the response is written.

End of a request
All stations successful?Commit successful?Result
yesyesResponse 2xx, the change is permanent. A request that follows immediately already sees it.
yesnoRollback. 409 if a concurrent change or the stored data prevented the commit, 503 if the database could not be reached, otherwise 500
no–Rollback of all databases the request touched. The error response says what went wrong

More in One request, one transaction.

Where each decision is made

QuestionStation
Who is asking, for which tenant?Filter chain (CIAS)
May the tenant be served at all?Filter chain (CIAS)
Which fields come back?REST layer (resolution) and persistence (column selection)
May the person do this operation on this model?System layer, through the model roles
May the person see or change this row?System layer, through the owner filter and attribute filters
Is the content valid?System layer, through validation
Which database?Persistence, through the model level
When is it stored?Commit at the end of the request

Pitfalls

Sources in the code and the knowledge base
  • CIAS/cias-authentication – JwtSessionFilter
  • CDMS/cdms-rest-api – AbstractRestApi, Expander, CdmsExceptionMapper, RequestTransactionCommitter
  • CDMS/cdms-system-layer – AbstractSystemLayer (createObject, readObject, updateObject, patchObject), AbstractLayer (recursivePrepare, assertVisibleForWrite)
  • CDMS/cdms-authorization – AbstractAuthorizationLayer
  • commons-persistence – DatabaseRequestContext
  • documentation/10-cdms-grundlagen/01-schichten-und-request-flow.md, 30-daten-und-persistenz/02-transaktionen.md
Search