CodamAIDocs
Topicdone

Suspend and close tenants, validity

What suspending, resuming, activating, closing and a validity window do, and why there is no deleting.

Variants
suspendresumeactivatecloseset validity windowno DELETE

What this is about

A customer does not pay, a security incident is being investigated, a contract ends: Then a tenant should stop working. CIAS offers five actions for this:

  • suspend: temporarily out of operation, everything is kept
  • resume: back in operation after a suspension
  • activate: put a tenant into operation that never was
  • close: ended for good, nothing is deleted
  • validity window: from when and until when the tenant is served

All five only change the record in CIAS. Keycloak and the tenant’s database stay untouched. The change takes effect at the tenant gate, which asks on every request whether the tenant is served.

The endpoints

All of them are under /cias/admin/tenants/{id}, all require a platform administrator, and all respond with the changed tenant.

ActionCallAllowed fromEvent
suspendPOST …/{id}/suspendany standing except CLOSEDSuspended
resumePOST …/{id}/resumeonly SUSPENDEDResumed
activatePOST …/{id}/activatePENDING or ACTIVE, and only if the rollout is PROVISIONEDActivated
closePOST …/{id}/closeany standingClosed
set validityPOST …/{id}/validityany standing–

The {id} is the technical ID of the tenant, not its key. You get the ID for a key with GET /cias/admin/tenants/by-key?key=nordbau.

The actions in detail

What each action does

When: unpaid invoice, security incident, customer request

  1. 1
    Admin→CIAS
    POST /cias/admin/tenants/0f6c…/suspend
  2. 2
    CIAS
    standing → SUSPENDED, event Suspended
  3. 3
    CIAS
    from now on the gate answers “not served”, everywhere after 30 seconds at the latest

Result: Every request for nordbau ends with 403 cias.authentication.tenant-not-served. The data stays, nothing has to be set up again.

When: The reason for the suspension is resolved.

  1. 1
    Admin→CIAS
    POST /cias/admin/tenants/0f6c…/resume
  2. 2
    CIAS
    rollout PROVISIONED? yes → standing ACTIVE. no → standing PENDING. Event Resumed

Result: If the tenant is not suspended at all, CIAS refuses: 409 cias.tenancy.illegal-transition.resume. A tenant that was suspended before its setup finished comes back as PENDING and becomes active as soon as the setup succeeds.

When: A tenant in PENDING should go into operation, for example after a manual setup.

  1. 1
    Admin→CIAS
    POST /cias/admin/tenants/0f6c…/activate
  2. 2
    CIAS
    rollout PROVISIONED? yes → standing ACTIVE, event Activated

Result: If the rollout is not finished, CIAS refuses: 409 cias.tenancy.illegal-transition.activate. Putting a tenant without a database into operation would only show up on the customer's first request. CIAS does not activate a suspended tenant either, also with 409: only resuming lifts a suspension.

When: The customer has left.

  1. 1
    Admin→CIAS
    POST /cias/admin/tenants/0f6c…/close
  2. 2
    CIAS
    standing → CLOSED, event Closed

Result: Final. After that, activate, resume and suspend are refused: 409 cias.tenancy.illegal-transition.activate, …resume or …suspend. Closing a tenant that is already closed changes nothing.

When: Someone wants to “get rid of” a tenant.

There is no DELETE endpoint. A database is the one thing whose loss cannot be undone, and an HTTP call that deletes it would be a bigger risk than an orphaned database. The record also stays, so that the audit knows which customer old entries belong to.

Result: A closed tenant keeps its key. The same key cannot be given to a new customer.

The validity window

A tenant can have a window: valid from (validFrom) and valid until (validUntil). Both are days, both are inclusive, both may be empty. Empty means: open on that side.

This lets you model a contract without anyone having to remember it on the key date:

gantt
    dateFormat YYYY-MM-DD
    axisFormat %d.%m.
    section nordbau
    created and ACTIVE, but not valid yet :crit, 2026-09-22, 2026-10-01
    served                                :active, 2026-10-01, 2026-12-31
    expired, no longer served             :crit, 2026-12-31, 2027-01-15

In this example, validFrom = 2026-10-01 and validUntil = 2026-12-31. The tenant is ACTIVE the whole time, but it is only served from Oct 1 up to and including Dec 31.

Request
POST /cias/admin/tenants/0f6c…/validity
{ "validFrom": "2026-10-01", "validUntil": "2026-12-31" }
Response
HTTP 200
{ "key": "nordbau", "status": "ACTIVE",
  "validFrom": "2026-10-01", "validUntil": "2026-12-31", … }
What the call /validity does
validFrom in the callvalidUntil in the callNew window
2026-10-012026-12-31Oct 1 to Dec 31
empty2026-12-31open until Dec 31
emptyemptyno window any more, valid every day
2026-12-312026-10-01400 cias.tenancy.invalid-request: end before start

The call always replaces the whole window. An empty value means “open”, not “as before”. So if you only want to extend the end, send the start again as well. And {} removes both limits. This is exactly how you enable an expired tenant again.

Suspend or window?

Which action fits?
OccasionEnd known?Action
contract with a fixed start or endyesvalidity window, it takes effect on the key date by itself
unpaid invoice, incident, clarificationnosuspend, resume later
customer is gone for good–close

Pitfalls

Next

Sources in the code and the knowledge base
  • CIAS/cias-tenancy – TenantAdminController (/{id}/activate, /{id}/suspend, /{id}/resume, /{id}/close, /{id}/validity, GET, /by-key), TenantRestDtos.ChangeValidityRequest, TenantExceptionHandler
  • CIAS/cias-tenancy – TenantService (activate, suspend, resume, close, changeValidity), Tenant (activate, suspend, resume, close, changeValidity, requireOrderedWindow, isServedOn), TenantEvent (Activated, Suspended, Resumed, Closed)
  • CIAS/cias-tenancy – TenantAdministrationService (platform administrator for every operation)
  • CIAS/cias-authentication – TenantGate (TTL), TenantGateProperties (codamai.cias.tenant-gate.ttl 30s)
  • CIAS/cias-tenancy/docs/adr – ADR-016 (section 3a), ADR-020
Search