CodamAIDocs
Topicdone

CIAS embedded (a single unit)

CIAS runs in the same process as CDMS or the hub backend. Which modules are included, how CDMS calls CIAS, and which database CIAS uses.

Variants
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

What this is about

Embedded means: CIAS is not a program of its own but a set of jar files inside the same process as the application. A process is one running program; CDMS and CIAS then share memory, database connection and configuration.

The application that takes CIAS in is called the host here. That is, for example, the hub backend or a project generated with the CDMS generator.

What the same setup looks like with two services is under CIAS as a separate service. The differences side by side are under Embedded and standalone compared.

The process picture

flowchart LR
    F["Frontend with BFF"] -- "bearer token" --> P
    subgraph P["One process"]
        direction TB
        FK["Filter chain<br/>(cias-authentication)"]
        C["CDMS"]
        CI["CIAS modules<br/>tenancy, user, authorization, …"]
        FK --> C
        FK --> CI
        C <-->|method call| CI
    end
    P --> SDB[("System database<br/>CDMS tables + CIAS tables")]
    C --> TDB[("Tenant databases")]
    CI -- "adapter" --> K[(Keycloak)]
    FK -- "keys, token exchange" --> K
    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
    class F client
    class C cdms
    class FK,CI cias
    class K idp
    class SDB,TDB db

Everything inside the box is one program. Only three lines leave it: to the database, to Keycloak, and to the frontend.

Which modules a host includes

CIAS consists of many small modules, each of them its own jar. A host does not automatically take all of them. There are two ways to include them.

Two ways to include CIAS
With starter
cias-spring-boot-starter
  • one dependency that brings along all the business modules: cias-tenancy, cias-user, cias-authorization, cias-registration, cias-notification, cias-audit
  • wires them itself (auto-configuration), the host writes no configuration classes
  • also builds the ports to the identity provider, the first start (bootstrap) and the timers
  • brings its own migration run for the CIAS tables
  • this is how the standalone CIAS service cias-runtime runs
Without starter
single jars, own configuration
  • the host names every module one by one in its pom.xml
  • it writes the wiring itself, in its own configuration classes
  • it takes only what it needs – often cias-tenancy, cias-user, cias-authorization, cias-iam-keycloak
  • this is how the hub backend works, and how the CDMS generator produces a project with cias: EMBEDDED

Why without the starter at all? Because the starter brings more than a CDMS host wants: its own caller context, its own migration run, and a bean for the identity provider that fails the start when no provider is configured. A host that only wants to carry CIAS dormant therefore takes the single jars.

No CIAS module switches itself on

Every module sits behind a switch codamai.cias.<modul>.enabled, and none of these switches has a default value. That is deliberate: at startup CDMS scans all classes under com.codamai. Without these switches CIAS would spring to life in every application that happens to have the jar on its classpath.

The starter avoids the scan a second way: it registers as an auto-configuration, and auto-configurations are excluded from component scanning. So it arrives because the jar is there and the conditions match, not because somebody scanned a package name.

How CDMS calls CIAS

Embedded, all three questions between CDMS and CIAS are ordinary method calls. No HTTP, no token, no timeout.

QuestionWho asksWho answersHow
May tenant kunde-a be served?the tenant gate in cias-authenticationLocalTenantLookupAdapter in cias-tenancymethod call
Which tenant-bound attribute values does this person hold here?the attribute lookup in cias-authenticationLocalTenantBoundAttributeAdapter in cias-usermethod call
Which roles and attributes does CDMS declare?the reconciliation in cias-authorizationLocalModuleDeclarationAdapter reads the host’s beanmethod call

A few words on that:

  • The tenant gate is the place that checks, before every request, whether the customer is served at all. Details under Admit the tenant (tenant gate).
  • An attribute is a value on a person that CDMS filters rows by, for example regionen. Some of them apply per tenant, see One value per person or per tenant.
  • The declaration is the list of all roles and attributes a module knows. See Modules register their roles.
  • A bean is an object that Spring creates and manages at startup. “Declaring it as a bean” here means: the object is already in the process, you only have to name it.

The declaration as a bean

Embedded, CIAS does not call the endpoint GET /cias/fetch. Instead the configuration names, per module, the bean that holds the declaration:

codamai:
  cias:
    authorization:
      declarations:
        modules:
          - name: cias
            client: ${cias_client}
            bean: ciasIdentityRegistry
          - name: cdms
            client: ${cias_client}
            bean: roleRegistryService

Both modules live in the same process and therefore share one Keycloak client. name says whose roles are whose; without the name the reconciliation could not tell them apart. roleRegistryService is the class the CDMS generator writes from the models.

Every entry names either a bean or a URL, never both and never neither. A typo fails the start instead of surfacing weeks later during a reconciliation.

One request from front to back

sequenceDiagram
    participant B as BFF
    participant F as Filter chain (CIAS)
    participant T as Tenant gate (CIAS)
    participant U as cias-user
    participant C as CDMS
    participant DB as Tenant DB
    B->>F: POST /api/rest/crm/customer/query + token
    F->>F: check token, exchange it, resolve tenant
    F->>T: may "kunde-a" be served?
    Note over F,T: method call, no network
    T-->>F: yes (remembered for 30 s)
    F->>U: which attribute values does the person hold in "kunde-a"?
    U-->>F: regionen = [nord]
    F->>C: RequestContext filled
    C->>DB: SELECT … (only allowed rows)
    DB-->>C: rows
    C-->>B: data + meta

The 30 seconds are the tenant gate’s memory (codamai.cias.tenant-gate.ttl). Embedded it only saves a database query — CIAS cannot go down on its own here, because it stands and falls with the process.

Which database CIAS uses

Embedded, CIAS has no database of its own. Its tables live in the host’s system database, next to the host’s own tables. That has to be so: cias_tenant lists every tenant of the installation and therefore cannot exist once per tenant.

Which databases there are otherwise is under Which database? The persistence target.

How the tables come to be

Migrations of the CIAS tables

When: The host takes cias-spring-boot-starter and sets codamai.cias.migration.enabled: true.

The starter runs one Flyway pass per module, each with its own history table (flyway_schema_history_cias_tenancy, …_cias_user, …). That is necessary because every CIAS module is its own repository and starts its numbering at V1__ – six modules with six scripts called “version one” do not fit into one shared history.

  1. 1
    Build
    The host names the locations it migrates – one per module. A named location without scripts fails the start
  2. 2
    Database
    When a module's history table is missing, the pass starts at version 0 and applies every script
    The usual baseline “version one” would be wrong here: after the first module the schema is never empty again, and the second module would skip its own V1__ as “already applied”.
  3. 3
    CIAS
    Only then does the persistence layer start
    Result: Every module has its own history and can move on by itself

When: The host includes the modules one by one, like the hub backend or a generated project.

Then there is no CIAS migration run. Instead the host registers the CIAS entities with its own persistence – a ManagedTypesContribution with scope SYSTEM – and the tables come to be the same way the host's own tables do.

Result: One schema, one path, no second migration machinery in the process.

How a CDMS project manages its schema is under Databases, pools, migration.

What the host has to supply itself

CIAS refuses to guess a few things. Without the starter the host states them in a configuration class of its own; with the starter, the starter fills in the technical parts and the security statements stay with the host.

The statements the host makes
  1. 1
    Developer
    Which roles administer the platform (codamai.cias.platform-administrator-roles)
    No default. An empty value means “nobody” and is a valid statement; a guessed default role would hand platform administration to whoever happens to hold that role.
  2. 2
    Developer
    Who is calling – a CallerContextProvider that reads user and roles from the request context
    CDMS maintains that context anyway. A request without a user is anonymous rather than an error, because system passes have no caller.
  3. 3
    Developer
    Registering the entities, so the CIAS tables belong to the system database
  4. 4
    Developer
    A transaction bracket for the writing CIAS services
    CDMS works without a central transaction manager – its boundary is the request, not the method. The host therefore builds the bracket locally and hands it to CIAS only.
  5. 5
    Developer
    Which roles may read GET /cias/fetch (codamai.cdms.cias.reader-roles)
    Result: The endpoint exists and is guarded embedded as well. The preset is the realm role declaration-reader.

Watch out

Next

Sources in the code and the knowledge base
  • CIAS/cias-spring-boot-starter – pom.xml, AutoConfiguration.imports, CiasAutoConfiguration, CiasIamAutoConfiguration (iamPorts), CiasSchemaAutoConfiguration, CiasSchemaMigration, CiasMigrationProperties, CiasDeclarationAutoConfiguration, CiasReconciliationAutoConfiguration, CiasSchedulingAutoConfiguration, CiasBootstrapAutoConfiguration
  • hub-backend – pom.xml, CiasEmbeddedConfiguration, CiasIdentityConfiguration, CiasRepositoryTransactionsPostProcessor, CiasRegistrationSupportConfiguration, application.yaml (codamai.cias.*)
  • CIAS/cias-tenancy – CiasTenancyConfiguration (lookup local), LocalTenantLookupAdapter
  • CIAS/cias-user – CiasUserConfiguration, LocalTenantBoundAttributeAdapter
  • CIAS/cias-authentication – TenantGate, TenantGateProperties, AttributeLookup
  • CIAS/cias-authorization – LocalModuleDeclarationAdapter, ModuleDeclarationPort, ModuleDeclarationSources
  • CDMS/cdms-scaffold – cdms-version-registry.yaml (ciasDependencies EMBEDDED), CdmsScaffoldService (EMBEDDED_CIAS_YAML), CdmsReadmeWriter
  • commons-persistence – ManagedTypesContribution, SchemaMigrationConfiguration
  • CIAS/cias-kernel/docs/adr/adr-022-tenant-lookup-port.md; CIAS/CLAUDE.md §6, §38
Search