CodamAIDocs
Topicdone

The parties in a request

User, browser, frontend with BFF, Keycloak, CIAS, CDMS, databases, file storage: who talks to whom, embedded and standalone.

Variants
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

What this is about

When you click “Show customers” in a CodamAI application, many programs are involved. Each has exactly one job. This page shows all of them in one picture and tells you who talks to whom.

The parties and their colors

Every party has the same color on every page. This is the legend for the pictures below:

  1. 1
    User
    the person in front of the screen
  2. 2
    Browser
    shows the pages and holds the encrypted session cookie. Never calls CDMS or CIAS itself
  3. 3
    Frontend
    the web application (Nuxt), e.g. the hub user interface, the CDMS portal or the CIAS portal
  4. 4
    BFF
    the server part of the frontend. It holds the tokens and calls CDMS and CIAS
  5. 5
    Keycloak
    the identity provider. Shows the login page, checks the password, issues tokens
  6. 6
    CIAS
    identity and access. Its filter chain checks every request, its modules manage users, tenants, roles
  7. 7
    CDMS
    the application with the data, e.g. the hub backend or your own CDMS application
  8. 8
    Database
    system database, tenant databases, in standalone mode also the CIAS database
  9. 9
    File storage
    directory or volume for file contents, only for applications with file models
  10. 10
    Email
    emails that CIAS sends, for example to confirm a registration

A few words on this:

  • BFF means Backend for Frontend. Every frontend has its own small server. Only it knows the tokens; the browser just has an encrypted cookie. Details in Session in the BFF and cookies.
  • A token is a signed ID card that Keycloak issues after sign-in. The BFF sends it with every call in the header Authorization: Bearer ….
  • The filter chain is CIAS code that runs before every endpoint. It checks the token and decides in which tenant the request runs. Details in What happens with the token on every request.
  • A tenant is a customer whose data is separated from everyone else’s. Each tenant can have its own database, see Which database? The persistence target.

The architecture picture

CDMS and CIAS run either embedded in one program or standalone as two services. The parties are the same, only the arrows between CDMS and CIAS change. Both pictures side by side:

Who talks to whom?

When: CDMS and CIAS run in the same process, as in the hub backend.

flowchart LR
    U(["User"]) --> B["Browser"]
    B -- "pages, session cookie" --> F["Frontend with BFF"]
    B -. "login page" .-> K["Keycloak"]
    F -- "fetch, refresh tokens" --> K
    subgraph P["Backend: one process"]
        FK["Filter chain (CIAS)"]
        C["CDMS"]
        CI["CIAS modules"]
        FK --> C
        FK --> CI
        C <-->|method call| CI
    end
    F -- "Bearer token<br/>/api/rest/… and /cias/…" --> FK
    FK -- "keys, token exchange" --> K
    CI -- "accounts, roles, groups<br/>(adapter)" --> K
    C --> SDB[("System DB<br/>with CIAS tables")]
    CI --> SDB
    C --> TDB[("Tenant DBs")]
    C --> FS[("File storage")]
    CI -.-> M["Email"]
    classDef user fill:#0f766e,stroke:#0f766e,color:#fff
    classDef client fill:#475569,stroke:#475569,color:#fff
    classDef cdms fill:#1976d2,stroke:#1976d2,color:#fff
    classDef cias fill:#8e24aa,stroke:#8e24aa,color:#fff
    classDef idp fill:#c2410c,stroke:#c2410c,color:#fff
    classDef db fill:#4d7c0f,stroke:#4d7c0f,color:#fff
    classDef mail fill:#be185d,stroke:#be185d,color:#fff
    class U,B user
    class F client
    class C cdms
    class FK,CI cias
    class K idp
    class SDB,TDB,FS db
    class M mail

Result: One backend process. CDMS and CIAS talk through method calls, the CIAS tables live in the system database.

When: CIAS runs as a separate service (cias-runtime).

flowchart LR
    U(["User"]) --> B["Browser"]
    B -- "pages, session cookie" --> F["Frontend with BFF"]
    B -. "login page" .-> K["Keycloak"]
    F -- "fetch, refresh tokens" --> K
    subgraph D1["Service 1"]
        FK["Filter chain (CIAS)"]
        C["CDMS"]
        FK --> C
    end
    subgraph D2["Service 2: cias-runtime"]
        CI["CIAS modules"]
    end
    F -- "Bearer token<br/>/api/rest/…" --> FK
    F -- "Bearer token<br/>/cias/…" --> CI
    FK -- "tenant served? attributes?<br/>(service account, HTTP)" --> CI
    CI -- "GET /cias/fetch<br/>(roles, attributes)" --> C
    FK -- "keys, token exchange" --> K
    CI -- "accounts, roles, groups<br/>(adapter)" --> K
    C --> SDB[("System DB")]
    C --> TDB[("Tenant DBs")]
    C --> FS[("File storage")]
    CI --> CDB[("CIAS DB")]
    CI -.-> M["Email"]
    classDef user fill:#0f766e,stroke:#0f766e,color:#fff
    classDef client fill:#475569,stroke:#475569,color:#fff
    classDef cdms fill:#1976d2,stroke:#1976d2,color:#fff
    classDef cias fill:#8e24aa,stroke:#8e24aa,color:#fff
    classDef idp fill:#c2410c,stroke:#c2410c,color:#fff
    classDef db fill:#4d7c0f,stroke:#4d7c0f,color:#fff
    classDef mail fill:#be185d,stroke:#be185d,color:#fff
    class U,B user
    class F client
    class C cdms
    class FK,CI cias
    class K idp
    class SDB,TDB,FS,CDB db
    class M mail

Result: Two services. CDMS asks CIAS over HTTP, CIAS has its own database. The filter chain still runs in the CDMS service.

The difference lies only between CDMS and CIAS. Browser, BFF, Keycloak and the CDMS databases look the same in both pictures. All differences in detail are in Embedded and standalone compared.

Who talks to whom?

FromToHowWhat for
BrowserFrontendHTTP with session cookieload pages, trigger actions
BrowserKeycloakredirectshow the login page, enter the password, sign out
BFFKeycloakHTTPfetch the tokens after sign-in, refresh the access token
BFFCDMSHTTP, Authorization: Bearer …read and write data under /api/rest/…
BFFCIASHTTP, Authorization: Bearer …administration under /cias/…: users, tenants, roles, registration
Filter chainKeycloakHTTPkeys to check the signature, token exchange
CIASKeycloakHTTP, through the adaptercreate accounts, write roles and groups
CDMSCIASembedded: method call. Standalone: HTTP with its own service accountMay the tenant be served? Which attributes apply?
CIASCDMSembedded: in the same process. Standalone: HTTP GET /cias/fetchWhich roles and attributes does the application declare?
CDMSDatabasesJDBCsystem database and one database per tenant
CDMSFile storagefile systemcontents of file models
CIASDatabaseJDBCembedded: tables in the system database. Standalone: its own CIAS database
CIASEmailmail serverconfirmation, invitation, link to set a password

Which frontends exist and which module they belong to is shown in The CodamAI modules. For this picture they are all built the same way: Nuxt with its own BFF, sign-in through Keycloak.

A request in steps

This is how “list of customers” travels through the parties. The user is already signed in.

GET of the customer list, from the click to the database
  1. 1
    User→Browser
    clicks "Customers"
  2. 2
    Browser→BFF
    calls a route of its own frontend, the session cookie goes along
  3. 3
    BFF
    decrypts the cookie and takes out the access token. If it has expired, it gets a new one from Keycloak
  4. 4
    BFF→CDMS
    sends POST /api/rest/crm/customer/query with Authorization: Bearer …
  5. 5
    Filter chain
    checks the token, determines the tenant and asks whether it may be served
  6. 6
    CDMS
    checks whether a role in the token may read the model
  7. 7
    CDMS→Tenant DB
    reads only the rows this person may see
  8. 8
    CDMS→BFF
    answers with data and meta
  9. 9
    BFF→Browser
    passes the data on to the page
    Result: The list appears. Neither the browser nor the page called CDMS directly

What can go wrong at each station and which answer comes back then is described in What happens with the token on every request and The path of a request through the layers.

Pitfalls

Next

Sources in the code and the knowledge base
  • hub-frontend – README.md, nuxt.config.ts (apiBaseUrl, ciasBaseUrl), server/utils/backendFetch.ts, ciasFetch.ts, sessionToken.ts, refreshToken.ts, server/api/auth/[...].ts
  • CDMS/frontend – README.md (Where it sits, Data flow), .env.example; CIAS/cias-frontend – README.md, server/utils/ciasFetch.ts, cmsFetch.ts
  • hub-backend – pom.xml, application.yaml (codamai.cias.tenancy.lookup local, codamai.cias.*), CiasEmbeddedConfiguration
  • CIAS/cias-authentication – filter chain (check and exchange the token, resolve and admit the tenant)
  • CIAS/cias-runtime – pom.xml, application.yml (datasource CIAS_DATABASE_URL); CIAS/cias-tenancy-client
  • CIAS/CLAUDE.md §6 operating models; CIAS/cias-iam-keycloak; CIAS/cias-notification
  • commons-persistence/CLAUDE.md (system DB + one DB per tenant)
  • CDMS/cdms-localfs-storage – FileProperties (basePath)
Search