ORISO Dokumentation
Flows & Internals

Data Model (Conceptual)

The product-level data model: User, Tenant, Counseling Center, Topic, Session, Chat, Transcript, Role, Live-Chat Link, Magic Link — their attributes and relationships.

This is the conceptual data model — the product entities and their relationships. The precise relational schema lives in ORISO-Database; this page maps each entity to its owning service so you can navigate the code without effort.

7.1 Entity-Relationship Map

erDiagram
  TENANT ||--o{ AGENCY : owns
  TENANT ||--|| LEGAL_TEMPLATE : has
  AGENCY ||--o{ AGENCY_LIVE_CHAT_LINK : "publishes via"
  AGENCY ||--o{ AGENCY_POSTCODE_RANGE : covers
  AGENCY ||--o{ CONSULTANT_AGENCY : binds
  AGENCY ||--o{ AGENCY_TOPIC : offers
  AGENCY ||--|| LEGAL_TEMPLATE : "may override"
  TOPIC ||--o{ AGENCY_TOPIC : "is offered as"
  TOPIC ||--o{ AGENCY_LIVE_CHAT_LINK : "scopes"
  USER ||--o{ CONSULTANT_AGENCY : "is consultant in"
  USER ||--o{ SESSION : "as consultant"
  USER ||--o{ MAGIC_LINK : "issued"
  USER ||--o{ ROLE_ASSIGNMENT : has
  ROLE ||--o{ ROLE_ASSIGNMENT : grants
  TICKET ||--|| SESSION : "promoted to"
  CLIENT_PSEUDONYM ||--|| TICKET : "owns"
  CLIENT_PSEUDONYM ||--o| SESSION : "joins"
  SESSION ||--|| MATRIX_ROOM : "anchored by"
  SESSION ||--o{ CASE_NOTE : "has (counselor-owned)"
  SESSION ||--o{ AUDIT_LOG : produces

7.2 Entities

7.2.1 Tenant

Owned by TenantService.

AttributeTypeNotes
idUUIDPK
namestringDisplay name (e.g. "Caritas Berlin")
regionstringRegional identifier
data_policy_signed_attimestampRequired before agency creation
live_chat_enabledbooleanTenant-wide live-chat kill-switch
created_attimestamp
disabled_attimestampSoft-disable for account suspension

Relationships: 1 → N Agency, 1 → 1 tenant-level LegalTemplate.

7.2.2 Agency (Counseling Center)

Owned by AgencyService.

AttributeTypeNotes
idUUIDPK
tenant_idUUIDFK to Tenant; immutable
slugstringURL-friendly; unique within tenant
namestringDisplay name
descriptiontextPublic-facing description
live_chat_enabledbooleanPer-center toggle (AND'd with tenant flag)
imprint_overridesjsonb | nullIf null, inherits
data_policy_overridesjsonb | nullIf null, inherits
gdpr_overridesjsonb | nullIf null, inherits
created_attimestamp

Relationships: N → 1 Tenant, 1 → N AgencyLiveChatLink, 1 → N AgencyPostcodeRange, M ↔ N User via ConsultantAgency, M ↔ N Topic via AgencyTopic.

7.2.3 Topic (Consulting Type)

Owned by ConsultingTypeService (relational + MongoDB).

AttributeTypeNotes
idUUIDPK
slugstringURL slug (e.g. debt)
title_i18njsonbLocalised titles
description_i18njsonbLocalised descriptions
default_gdpr_snippet_i18njsonbOptional fallback
ui_metadatajsonb (Mongo)Rich UI hints (icons, colors, ordering)

7.2.4 User

Owned by UserService + Keycloak.

AttributeTypeNotes
idUUIDPK; same as Keycloak user id
emailstring | nullRequired for staff, null for anonymous clients
display_namestringPseudonym for anonymous; real for staff
languagestringISO 639-1
created_attimestamp
disabled_attimestamp
mfa_enrolled_attimestampMandatory for tenant/platform admins

Subtype: Consultant attributes (when role includes consultant):

AttributeTypeNotes
supervisor_functionbooleanMaps to supervisor-consultant role
live_chat_enabledbooleanPer-counselor live-chat toggle
group_chat_enabledbooleanMaps to group-chat-consultant role

Subtype: Anonymous Client (when role = anonymous):

AttributeTypeNotes
pseudonymstringAuto-generated, never reused
cookie_session_idstringBound to browser cookie
topicstring | nullIf joined via topic-attached link
zip_codestring | nullIf client typed one
last_seen_attimestampHeartbeat marker
expected_lifespanseconds–minutesWiped on disconnect

7.2.5 Role & RoleAssignment

Source of truth: Keycloak realm. Mirrored read-only in UserService for fast checks.

RoleWhat it grants
user-adminPlatform Admin
tenant-adminTenant Admin
single-tenant-adminRestricted Tenant Admin
agency-admin / restricted-agency-adminCounselor Admin
restricted-consultant-adminA subset of consultant-admin powers
consultantCounselor
supervisor-consultantSupervisor function (flag)
group-chat-consultantGroup-chat-capable counselor (flag)
topic-adminManages global topics
anonymousClient in waiting room
userReserved for future registered client
technical / notifications-technicalService accounts

RoleAssignment has (user_id, role, scope) where scope is optional (e.g. agency_id for agency-admin).

7.2.6 Ticket (Live-Chat Ticket)

Owned by UserService.

AttributeTypeNotes
idUUIDPK
agency_idUUIDThe agency the link / zip routed them to
topic_idUUID | nullFrom the link or client choice
client_user_idUUIDThe anonymous user
stateenumWaiting, Accepted, Consented, Active, Paused, Ended, Abandoned, Purged
accepted_byUUID | nullCounselor who picked it
created_attimestamp
updated_attimestamp

When state reaches Consented, the ticket spawns a Session.

7.2.7 Session

Owned by UserService.

AttributeTypeNotes
idUUIDPK; the opaque session id
ticket_idUUIDFK
agency_idUUIDDenormalized for fast queries
consultant_idUUIDThe counselor
client_pseudonymstringWiped on Purged
topic_idUUID | null
matrix_room_idstring!abc:matrix.oriso-dev.site
started_attimestamp
ended_attimestamp | null
purged_attimestamp | null
stateenumMirrors ticket state machine

7.2.8 MatrixRoom

Owned by Matrix Synapse (PostgreSQL). Not a row we manage from backend services; we hold only the room id in our Session.

7.2.9 CaseNote (planned)

Owned by UserService.

AttributeTypeNotes
idUUIDPK
consultant_idUUIDFK; owner of the note
session_idUUIDOpaque link; does not identify a person
body_encryptedbytesEncrypted at rest
ai_assistedbooleanTrue if AI-summarized
created_attimestamp
updated_attimestamp

Owned by AgencyService.

AttributeTypeNotes
idUUIDPK
agency_idUUIDFK
topic_idUUID | nullNull = any topic
slugstringUsed in URL
enabledbooleanSoft-disable
created_byUUIDFK to user
created_attimestamp

7.2.11 AgencyPostcodeRange

Owned by AgencyService.

AttributeTypeNotes
idUUID
agency_idUUID
postcode_fromstringGerman PLZ string-comparison-safe
postcode_tostring
topic_idUUID | null

7.2.12 ConsultantAgency

Many-to-many binding of counselors to agencies.

AttributeTypeNotes
consultant_idUUID
agency_idUUID
roleenumconsultant, agency-admin, restricted-agency-admin
topicsUUID[]The topics this counselor handles at this agency
supervisor_functionboolean
created_attimestamp

7.2.13 LegalTemplate

Owned by whatever entity provides it (platform / tenant / agency).

AttributeTypeNotes
idUUID
owner_typeenumplatform, tenant, agency
owner_idUUID | nullNull for platform (singleton)
imprint_text_i18njsonb
data_policy_text_i18njsonb
gdpr_text_i18njsonb
versionintBumped on every save
stamped_attimestampWhen it became "active"

Inheritance is a read-side concern: the resolver walks agency → tenant → platform and returns the most specific non-null version.

Owned by UserService.

AttributeTypeNotes
jtiUUIDPK
issued_to_emailstring
rolestringRealm role to assign
agency_idUUID | nullIf applicable
issued_attimestamp
expires_attimestamp24 h
consumed_attimestamp | nullSingle-use guard

7.2.15 AuditLog

Owned by UserService.

AttributeTypeNotes
idUUID
timestamptimestamp
actor_idUUID | nullThe user who acted (or null for system)
actionstringe.g. session.accept, session.purge, magic_link.consumed, legal_template.update
target_typestring
target_idUUID
metadatajsonbOpaque data — never PII

7.3 Cardinalities and Lifetime Comparison

EntityCardinalityLifetime
Platform Admin1–2Persistent
Tenant1–NPersistent
Tenant Admin1+ per tenantPersistent
Agency1+ per tenantPersistent
Counselor Admin1+ per agencyPersistent
Counselor1+ per agencyPersistent
Topicglobal, finite listPersistent
Live-chat link1+ per agencyPersistent (until disabled)
Magic linkmany24 h
Anonymous Clientmany, ephemeralSeconds-to-hours, then wiped
Ticketmany, ephemeralUntil session ends
Sessionmany, ephemeralUntil purged (≤ 48 h post-end)
Matrix roomone per sessionUntil purged (≤ 48 h post-end)
Case noteone or more per sessionPersistent (counselor-owned)
Audit rowmany1 year

7.4 Privacy-Sensitive Fields (Quick Reference)

FieldWhereTreatment
pseudonymUserServiceWiped on disconnect
cookie_session_idUserServiceWiped with pseudonym
client.emailn/aNever stored
client.ipn/aNever stored, only used in-memory at ingress
consultant.emailUserService + KeycloakEncrypted column
matrix message bodySynapseMegolm ciphertext only
case_note.body_encryptedUserServiceAt-rest encrypted
magic_link.tokennot storedOnly its jti and metadata

7.5 May-2026 Additions (from Figma)

The Figma extraction surfaces several entities that were not in the original model. Each is owned by an existing service to keep the topology stable.

7.5.1 ChatType

Owned by AgencyService + frontend constants.

AttributeTypeNotes
keyenumanonymous, one_to_one, group, supervision
label_i18njsonbUI labels
feature_permissionsjsonblinks to FeaturePermission rows

7.5.2 GroupChat (subtype of Session)

Owned by UserService.

AttributeTypeNotes
idUUIDPK; same as Session.id when applicable
chat_typeenumone of team, peer_support, family, internal_round, supervision
label_subtypestring"Lokal 1:1", "Live 1:1", "Kreis", "Intern", "Fachblick", "Trauerhilfe", … (UI label)
supervision_enabledbooleanmirrors the room flag
schedule_attimestamp | nullfor live-scheduled rounds
created_byUUIDFK to User

7.5.3 MessageAddressing

Owned by UserService (logged) + Matrix (delivered).

AttributeTypeNotes
event_idstringMatrix event id of the original
recipient_setUUID[]The N recipients (subset of room members)
visibility_labelstringThe pill text shown ("3 Moderators", etc.)
restricted_send_strategyenumrelay_bot, per_recipient_megolm

This is the data layer behind Multi-Recipient Send.

7.5.4 MarkAnnotation / BlurAnnotation

Stored as encrypted Matrix events of type de.oriso.annotation.mark or de.oriso.annotation.blur. Logical structure:

AttributeTypeNotes
event_idstringAnnotation event id
target_event_idstringThe message being annotated
range{ start, end }Character offsets
colorstringHighlight color
labelstring | null"Great Aspects", "Dangerous Behaviors", …
blurbooleanIf true, applies the 80%-white overlay
visibilityenumprivate_to_author, shared_in_thread

7.5.5 HandoverEvent

Owned by UserService.

AttributeTypeNotes
idUUIDPK
session_idUUIDThe opaque session affected
from_counselor_idUUID
to_counselor_idUUID
reasonenumholiday, sickness, emergency, law_violation, colleague_fired, custom
custom_reason_texttext | nullOnly when reason = custom
consentsjsonb{ client: bool, counselor_b: bool, supervisor: bool }
started_attimestamp
completed_attimestamp | null

7.5.6 EscalationRequest

Owned by UserService.

AttributeTypeNotes
idUUIDPK
session_idUUID
requester_idUUIDThe counselor who triggered
recipient_idUUID | nullThe internal escalation target (counselor / supervisor)
modeenuminternal, external
notetextCounselor's note for context (encrypted at rest)
statusenumrequested, accepted, resolved, cancelled, expired
created_attimestamp
resolved_attimestamp | null

7.5.7 Notification

Owned by UserService.

AttributeTypeNotes
idUUIDPK
recipient_idUUIDTarget user
typestringinquiry.accepted, handover.completed, appointment.reminder, …
title_i18njsonb
body_i18njsonb
linked_session_idUUID | nullFor deep-link
read_attimestamp | null
email_sentbooleantrue if mirrored to email
created_attimestamp

7.5.8 ClientEmail

Owned by UserService (privileged column).

AttributeTypeNotes
user_idUUIDPK
email_encryptedbytescolumn-encrypted
verified_attimestamp | nullAfter click-through
visible_to_rolesenum[]platform_admin only — never to counselors

7.5.9 MFAFactor

Owned by Keycloak (mirror in UserService for query speed).

AttributeTypeNotes
user_idUUID
typeenumapp_totp, email_magic, webauthn
enrolled_attimestamp

7.5.10 FeaturePermission

Owned by TenantService (platform-default + tenant-override) + AgencyService (agency-override).

AttributeTypeNotes
idUUIDPK
owner_typeenumplatform, tenant, agency
owner_idUUID | nullNull for platform
chat_typeenumanonymous, one_to_one, group, supervision
feature_keystringe.g. audio_calls, voice_messages, multi_recipient_send
enabledboolean
updated_attimestamp

The resolver returns the AND of all levels: effective = platform.enabled AND tenant.enabled AND agency.enabled.

7.5.11 ChatTag

Owned by AgencyService.

AttributeTypeNotes
idUUID
agency_idUUID
name_i18njsonb
colorstring
created_attimestamp

7.5.12 SystemMessage

Computed at render-time; persisted as a synthetic Matrix event with type=de.oriso.system_message. Logical:

AttributeTypeNotes
keystringinquiry.accepted, e2ee.enabled, supervision.added, handover.completed, live_call.active, chat.archived, holiday, sickness, emergency, …
body_i18njsonbTemplated copy
levelenuminfo, important, warning, legal

7.7 Why This Schema Looks the Way It Does

  • Separation of Tenant / Agency / Topic — historical and intentional. Tenants own legal liability; agencies own day-to-day work; topics are global so a "debt" client landing on a different agency still finds the right counselors.
  • Anonymous user ≠ persistent user — they share a table out of pragmatism, but the lifecycle is completely different and is enforced via state and scheduled cleanup.
  • CaseNote owned by counselor, not session — so when a session is purged the note stays useful and untraceable to a person.
  • LegalTemplate as polymorphic owner — single resolver, simple inheritance, single source of truth for "what does this client see".

Auf dieser Seite