UC-GEN-MSG-003 — Bericht openen
1. Kerngegevens
| Veld | Waarde |
|---|---|
| Usecase-ID | UC-GEN-MSG-003 |
| Naam | Bericht openen |
| Domein | Berichten |
| Primaire actor | Ingelogde gebruiker |
| Secundaire actor(en) | Systeem, andere deelnemers aan privéberichtthreads, broncomponenten die systeemberichten hebben aangemaakt |
| Rolcontext | Iedere ingelogde rolcontext; toegang wordt server-side beperkt tot eigen systeemberichten en eigen privéberichtthread-deelname |
| Betrokken schermen | SCH-GEN-02 — Berichtenoverzicht, SCH-GEN-04 — Open bericht, SCH-GEN-05 — Beantwoord bericht als vervolgcontext |
| Gerelateerde usecases | UC-GEN-MSG-001 — Berichtenoverzicht bekijken; UC-GEN-MSG-002 — Nieuw privébericht opstellen en verzenden; UC-GEN-MSG-004 — Bericht beantwoorden; UC-GEN-MSG-005 — Privéberichtthread verwijderen; UC-GEN-REL-005 — Relatie-uitnodiging accepteren of afwijzen |
| Primaire entiteiten | SystemMessages, PrivateMessageThreads, PrivateMessageThreadParticipants, PrivateMessages, PrivateMessageThreadEvents |
| Secundaire entiteiten / events | Users, RelationshipInvitations, Tickets, MessageUnreadCountChanged, SystemMessageReadStateChanged, PrivateThreadReadStateChanged, PrivateMessageThreadRemovedFromMailbox |
| Gerelateerde popups | POP-GEN-MSG-NOT-AVAILABLE, POP-GEN-MSG-DELETED |
| Popupregister | Ontwerpbronnen — Popup-register |
| MoSCoW | Must have |
2. Omschrijving
De gebruiker opent vanuit het berichtenoverzicht een systeembericht of privéberichtthread. Het systeem controleert server-side of de gebruiker toegang heeft tot het gekozen bericht, haalt de volledige detailcontext op en markeert het bericht of de thread voor deze gebruiker als gelezen.
Bij een systeembericht toont het systeem de volledige systeemberichtinhoud en eventuele domeinverwijzing via EntityType en EntityId. Het openen van het systeembericht verwerkt het onderliggende domeinobject niet automatisch. Een relatie-uitnodiging, ticket of privéthread waarnaar wordt verwezen, blijft een afzonderlijke vervolgactie met eigen autorisatie en regels.
Bij een privéberichtthread toont het systeem het laatst geopende bericht als hoofdbericht en daaronder de voor deze gebruiker zichtbare threadcontext. Eerdere privéberichten en threadgebeurtenissen worden als onderdeel van dezelfde conversatie getoond. Threadgebeurtenissen zijn geen losse systeemberichten en geen gewone privéberichten, maar maken wel onderdeel uit van de threadtijdlijn en kunnen bijdragen aan de ongelezenstatus.
De primaire detailroute voor privécommunicatie is de threadroute. Een individueel privébericht-messageId is geen primaire detailroute en geen autorisatiebewijs.
3. Scope
Deze usecase beschrijft:
- het openen van een systeembericht of privéberichtthread vanuit het berichtenoverzicht;
- het gebruiken van
/messages/system/{messageId}voor systeemberichten en/messages/thread/{threadId}voor privéthreads; - de server-side controle op eigen systeembericht of eigen threaddeelname;
- het markeren als gelezen bij openen;
- het tonen van het hoofdbericht, metadata en volledige berichtinhoud;
- het tonen van eerdere berichten en threadgebeurtenissen binnen een privéberichtthread;
- het tonen of blokkeren van vervolgacties op basis van het actuele capabilitycontract;
- het niet uitvoeren van reply/delete-mutaties zolang de bijbehorende Batch 6-usecases niet gebouwd zijn;
- de afhandeling wanneer het bericht, de thread of het onderliggende verwijzingsobject niet meer beschikbaar is;
- het veilig renderen van berichtinhoud, rich text en threadgebeurtenissen.
Deze usecase beschrijft niet:
- het samenstellen, zoeken, filteren en pagineren van het berichtenoverzicht;
- het opstellen of verzenden van een nieuw privébericht;
- het inhoudelijk beantwoorden van een privébericht;
- het accepteren of afwijzen van een relatie-uitnodiging;
- het behandelen van een ticket of melding waarnaar een systeembericht verwijst;
- het beheren van systeemberichtsjablonen, popupdefinities of systeeminstellingen;
- scheduler-gestuurde retentie of cleanup van privéberichten.
4. Pre-condities
| ID | Voorwaarde |
|---|---|
| PRE-001 | De gebruiker is ingelogd. |
| PRE-002 | Het gekozen mailboxitem komt uit het berichtenoverzicht of uit een functioneel gelijkwaardige berichtenroute. |
| PRE-003 | Het systeem kan bepalen of het mailboxitem een systeembericht of een privéberichtthread betreft. |
| PRE-004 | Bij een systeembericht kan het systeem SystemMessages.RecipientUserId, ReadAtUtc, EntityType en EntityId controleren. |
| PRE-005 | Bij een privéberichtthread kan het systeem de bijbehorende PrivateMessageThreadParticipants-regel van de ingelogde gebruiker controleren. |
| PRE-006 | Berichtinhoud en eventuele rich-textinhoud kunnen veilig worden gesanitized of veilig geëncodeerd voordat deze wordt weergegeven. |
5. Post-condities
| ID | Resultaat |
|---|---|
| POST-001 | De gebruiker ziet uitsluitend het systeembericht of de privéthread waarvoor server-side toegang is vastgesteld. |
| POST-002 | Bij een systeembericht is alleen de leesstatus van dat systeembericht voor de ontvanger gewijzigd. |
| POST-003 | Bij een privéberichtthread is alleen de participantgebonden leespositie van de ingelogde gebruiker gewijzigd. |
| POST-004 | Andere deelnemers aan een privéthread krijgen geen gewijzigde leesstatus door het openen door deze gebruiker. |
| POST-005 | Het openen van een systeembericht met EntityType en EntityId verwerkt het onderliggende domeinobject niet automatisch. |
| POST-006 | Threadcontext toont alleen berichten en threadgebeurtenissen die bij dezelfde thread horen en voor deze gebruiker zichtbaar zijn. |
| POST-007 | Wanneer de gebruiker vanuit de detailweergave een privéthread verwijdert, wordt alleen de eigen mailboxzichtbaarheid beëindigd. |
| POST-008 | Systeemberichten blijven niet-verwijderbaar. |
| POST-009 | Bij fout- of niet-beschikbaarstaten worden geen technische identifiers, stacktraces of interne databasenaamgeving getoond. |
6. Trigger
De gebruiker klikt in SCH-GEN-02 — Berichtenoverzicht op een systeembericht of privéberichtthread, of navigeert vanuit een geldige berichtenroute direct naar de detailweergave van een bericht.
7. Normale processtroom
| Stap | Actor | Scherm / component | Actie | Systeemrespons | Data / regel |
|---|---|---|---|---|---|
| 1 | Gebruiker | SCH-GEN-02 — Berichtenoverzicht | Klikt op een berichtregel. | Het systeem start de open-berichtflow. | Het route- of item-id is nooit voldoende voor autorisatie. |
| 2 | Systeem | Backend | Bepaalt het berichttype. | Het systeem splitst de flow in systeembericht of privéberichtthread. | Toegestane typen zijn systeembericht en privéthread-mailboxitem. |
| 3 | Systeem | Backend | Controleert authenticatie en objecttoegang. | Alleen bij geldige toegang wordt detaildata opgehaald. | Frontend-zichtbaarheid is geen beveiliging. |
| 4A | Systeem | Backend | Laadt een systeembericht. | Alleen het SystemMessages-record met RecipientUserId van de gebruiker wordt gebruikt. | Systeemberichten van andere gebruikers zijn uitgesloten. |
| 5A | Systeem | Backend | Markeert het systeembericht als gelezen. | ReadAtUtc wordt gevuld wanneer het bericht nog ongelezen was. | Mutatie is idempotent en gebruikergebonden. |
| 6A | Systeem | SCH-GEN-04 — Open bericht | Toont de systeemberichtvariant. | Titel, body, type, afzenderweergave en ontvangstmoment worden getoond. | Antwoorden en verwijderen zijn niet beschikbaar voor systeemberichten. |
| 7A | Systeem | SCH-GEN-04 — Open bericht | Bepaalt eventuele vervolgactie op basis van EntityType en EntityId. | De pagina toont alleen vervolgacties die voor het actuele domeinobject en de gebruiker toegestaan zijn. | Het openen zelf accepteert geen uitnodiging, wijzigt geen ticket en opent geen andere thread zonder vervolgactie. |
| 4B | Systeem | Backend | Laadt een privéberichtthread. | Alleen een thread met een participantregel voor de ingelogde gebruiker wordt gebruikt. | PrivateMessageThreadParticipants.UserId = huidige gebruiker en DeletedAtUtc is null. |
| 5B | Systeem | Backend | Laadt hoofdbericht, deelnemerscontext, eerdere berichten en threadgebeurtenissen. | Het systeem bouwt de detailweergave voor dezelfde thread. | Alleen PrivateMessages en PrivateMessageThreadEvents uit dezelfde thread. |
| 6B | Systeem | Backend | Markeert de thread voor deze gebruiker als gelezen. | LastReadMessageId en/of LastReadAtUtc wordt bijgewerkt voor de eigen participantregel. | Andere deelnemers worden niet geraakt. |
| 7B | Systeem | SCH-GEN-04 — Open bericht | Toont de privéberichtvariant. | Hoofdbericht, metadata, volledige body, eerdere berichten en thread-events worden getoond. | Alle dynamische waarden komen uit thread-, bericht-, participant- en gebruikerscontext. |
| 8 | Systeem | SCH-GEN-04 — Open bericht | Render veilig berichtinhoud en eventteksten. | Rich text en eventwaarden worden alleen veilig gesanitized of geëncodeerd weergegeven. | Vrije HTML, JavaScript en actieve inhoud zijn niet toegestaan. |
| 9 | Systeem | Header / tellercomponent | Actualiseert ongelezenindicatoren. | De ongelezenteller wordt opnieuw bepaald wanneer leesstatus is gewijzigd. | De teller gebruikt dezelfde logica als het berichtenoverzicht. |
| 10 | Gebruiker | SCH-GEN-04 — Open bericht | Kiest Terug naar berichten. | Het systeem navigeert terug naar SCH-GEN-02. | Terugnavigatie wijzigt geen berichtinhoud. |
| 11 | Gebruiker | SCH-GEN-04 — Open bericht | Kiest Beantwoorden bij een privéthread. | Het systeem opent SCH-GEN-05 — Beantwoord bericht wanneer de thread beantwoordbaar is. | Uitvoering valt onder UC-GEN-MSG-004. |
| 12 | Gebruiker | SCH-GEN-04 — Open bericht | Kiest Gesprek verlaten bij een privéthread. | Het systeem start de aparte verwijderflow voor privéberichtthreads. Na bevestiging en succesvolle verwerking verdwijnt de thread uit de eigen mailboxweergave en kan POP-GEN-MSG-DELETED worden getoond. | De feitelijke mutatie valt onder UC-GEN-MSG-005. |
8. Alternatieve en exceptionele processtromen
| ID | Vanaf stap | Situatie | Systeemgedrag | Popup / melding | Datamutatie |
|---|---|---|---|---|---|
| ALT-001 | 1 | De gebruiker is niet ingelogd. | Het systeem weigert toegang en leidt naar de login- of toegangsflow. | Generieke autorisatiemelding buiten deze usecase. | Geen. |
| ALT-002 | 3 | Het mailboxitem bestaat niet. | Het systeem toont een nette niet-beschikbaarmelding zonder technische details. | POP-GEN-MSG-NOT-AVAILABLE of gelijkwaardige inline foutstaat. | Geen. |
| ALT-003 | 3 | Het mailboxitem hoort niet bij de ingelogde gebruiker. | Het systeem weigert toegang zonder detaildata te tonen. | POP-GEN-MSG-NOT-AVAILABLE of gelijkwaardige inline niet-beschikbaarstaat. | Geen. |
| ALT-004 | 4B | De privéthread is voor deze gebruiker uit de mailbox verwijderd. | Het systeem behandelt de thread als niet meer beschikbaar binnen de normale mailboxroute. | POP-GEN-MSG-NOT-AVAILABLE of gelijkwaardige inline niet-beschikbaarstaat. | Geen. |
| ALT-005 | 5A of 6B | Het bericht of de thread was al gelezen. | Het systeem toont de detailweergave en verwerkt de leesactie idempotent. | Geen popup. | Geen functionele wijziging of dezelfde gelezenstatus blijft behouden. |
| ALT-006 | 7A | Het systeembericht verwijst naar een onderliggend object dat is afgehandeld, verlopen of niet meer toegankelijk is. | Het systeem toont de actuele status of blokkeert de vervolgactie. | Inline toelichting; popup hoort bij het onderliggende domein wanneer daar een actie wordt gestart. | Alleen ReadAtUtc kan zijn gewijzigd door openen. |
| ALT-007 | 7A | EntityType of EntityId is inconsistent of niet toegestaan. | Het systeem toont het systeembericht zonder uitvoerbare vervolgactie en registreert technische foutlogging. | POP-GEN-MSG-NOT-AVAILABLE of gelijkwaardige inline foutstaat. | Alleen ReadAtUtc kan zijn gewijzigd door openen. |
| ALT-008 | 5B | Er zijn geen eerdere privéberichten zichtbaar. | Het systeem verbergt de sectie eerdere berichten of toont een compacte lege staat. | Inline lege staat of geen sectie. | Leesstatusmutatie blijft toegestaan. |
| ALT-009 | 5B | Er zijn threadgebeurtenissen zonder gewone nieuwe berichten. | Het systeem toont de threadgebeurtenissen als neutrale systeemballonnen binnen de thread. | Geen popup. | Leespositie kan worden bijgewerkt. |
| ALT-010 | 8 | Berichtinhoud bevat onveilige of niet-toegestane opmaak. | Het systeem toont alleen veilig gesanitized of veilig geëncodeerde inhoud. | Geen popup. | Geen. |
| ALT-011 | 11 | Beantwoorden is niet toegestaan. | Het systeem verbergt of disabled de antwoordactie en voorkomt server-side starten van de antwoordflow. | Inline toelichting; verdere afhandeling valt onder UC-GEN-MSG-004. | Geen. |
| ALT-012 | 12 | De gebruiker probeert een systeembericht te verwijderen. | De frontend toont geen actieve verwijderactie of de backend weigert de gemanipuleerde actie. | Disabled state of generieke foutmelding. | Geen. |
| ALT-013 | 12 | De privéthread is inmiddels al verwijderd voor deze gebruiker. | Het systeem verwerkt de actie idempotent of toont dat het bericht niet meer beschikbaar is. | Inline melding of POP-GEN-MSG-DELETED wanneer de eindtoestand succesvol is bereikt. | Geen extra functionele wijziging. |
| ALT-014 | 12 | Het verwijderen van de privéthread mislukt technisch. | Het systeem behoudt de thread in de eigen mailboxweergave en toont geen succesmelding. | Inline foutmelding. | Geen gedeeltelijke verwijdering. |
| ALT-015 | 3-12 | Tijdens openen of lichte mutatie treedt een technische fout op. | Het systeem toont een nette foutstaat zonder technische details en voert geen onterechte vervolgactie uit. | Inline foutmelding. | Alleen volledig geslaagde mutaties worden bewaard. |
8.1 Privéthread openen als timeline
Voor privéthreads toont deze usecase één chronologische timeline van oud naar nieuw. De pagina gebruikt dus geen apart hoofdblok Ontvangen bericht met daaronder een los geschiedenisblok. In plaats daarvan toont de pagina een threadkop met threadicoon, onderwerp en threadmenu, gevolgd door de timeline.
De timeline bevat:
- berichtballonnen links/rechts op basis van actor;
- threadspecifieke deelnemeraccenten;
- compacte gecentreerde thread-events;
- een marker Nieuwe berichten als er activiteit is die voor de ingelogde gebruiker nieuw was op het moment van openen;
- een anker naar het laatste item als er geen nieuwe activiteit is.
Bij openen bepaalt het systeem eerst waar #new of #latest moet staan op basis van de bestaande readstate. Daarna mag de thread voor deze gebruiker als gelezen worden gemarkeerd. Alle op dat moment relevante zichtbare activiteit geldt dan als gelezen; de initiële scope houdt niet per individueel nieuw bericht bij of de gebruiker dat item daadwerkelijk op het scherm heeft gezien.
Lange threads worden windowed geladen. De eerste detailweergave bevat een configureerbaar aantal timeline-items rond het relevante startpunt. Oudere items worden via een beveiligde cursor geladen, zonder user-aanpasbare querystrings en zonder de objecttoegang te verruimen.
9. Business rules
| ID | Regel |
|---|---|
| BR-UC-GEN-MSG-003-001 | Een gebruiker mag alleen eigen systeemberichten of eigen privéberichtthreads openen. |
| BR-UC-GEN-MSG-003-002 | Server-side objectcontrole is verplicht bij openen, lezen, beantwoorden en verwijderen. |
| BR-UC-GEN-MSG-003-003 | Het openen van een systeembericht of privéthread geldt als leesactie voor de ingelogde gebruiker. |
| BR-UC-GEN-MSG-003-004 | Leesstatusmutaties raken nooit andere deelnemers aan een privéthread. |
| BR-UC-GEN-MSG-003-005 | Systeemberichten zijn niet beantwoordbaar en niet verwijderbaar door gebruikers. |
| BR-UC-GEN-MSG-003-006 | Een systeembericht met EntityType en EntityId verwerkt het onderliggende domeinobject niet automatisch bij openen. |
| BR-UC-GEN-MSG-003-007 | Een privéthread mag alleen worden getoond wanneer de gebruiker een participantregel heeft en de thread voor deze gebruiker niet uit de mailbox is verwijderd. |
| BR-UC-GEN-MSG-003-008 | Eerdere berichten en thread-events in de detailweergave moeten bij dezelfde thread horen als het hoofdbericht. |
| BR-UC-GEN-MSG-003-009 | Thread-events worden binnen de privéthread getoond als systeemachtige regels, maar worden niet opgeslagen of behandeld als SystemMessages. |
| BR-UC-GEN-MSG-003-010 | Thread-events kunnen bijdragen aan de ongelezenstatus wanneer zij na de laatst bekende leespositie van de participant liggen. |
| BR-UC-GEN-MSG-003-011 | Berichtinhoud, rich text en eventteksten worden veilig gesanitized of geëncodeerd voordat zij zichtbaar worden. |
| BR-UC-GEN-MSG-003-012 | Het verwijderen van een privéthread vanuit de detailweergave is participantgebonden en verwijdert geen thread, berichten of events voor andere deelnemers. |
| BR-UC-GEN-MSG-003-013 | Technische identifiers zoals GUID’s, thread-id’s, system-message-id’s en entity-id’s worden niet zichtbaar getoond in fout- of detailweergaven. |
Centrale business rules die hierbij horen:
| BusinessRule-ID | Toepassing |
|---|---|
BR-GEN-SEC-001 | Alle berichtacties vereisen server-side rol-, relatie- of objectcontrole. |
BR-GEN-MSG-001 | Alleen eigen systeemberichten en eigen privéthread-mailboxitems zijn zichtbaar. |
BR-GEN-MSG-002 | Systeemberichten zijn niet verwijderbaar door gebruikers. |
BR-GEN-MSG-003 | Verwijderen van een privéthread is participantgebonden. |
BR-GEN-MSG-004 | Gelezen- en ongelezenstatus wordt gebruiker- of participantgebonden bepaald. |
BR-GEN-MSG-005 | Headerbadge en samenvatting gebruiken dezelfde ongelezenlogica. |
BR-GEN-MSG-006 | Preview-, detail- en rich-textinhoud wordt veilig verwerkt voordat deze wordt weergegeven. |
BR-GEN-MSG-009 | Thread-events binnen privéberichtthreads kunnen bijdragen aan de ongelezenstatus. |
BR-GEN-MSG-010 | Het openen van een systeembericht of privéthread is een leesactie voor de ingelogde gebruiker. |
BR-GEN-MSG-011 | SystemMessages.EntityType + EntityId bepalen alleen de mogelijke vervolgcontext; openen van het systeembericht verwerkt het onderliggende domeinobject niet automatisch. |
BR-GEN-MSG-012 | De open-berichtweergave van een privéthread mag alleen berichten en thread-events uit dezelfde geautoriseerde thread tonen. |
BR-GEN-MSG-013 | Private thread detail is group-ready en mag niet uitgaan van één-op-één-gesprekken. |
BR-GEN-MSG-014 | Individuele private message-id's zijn geen primaire detailroute en geen autorisatiebewijs. |
10. Datavalidatie
Autorisatie en server-side controles
| Controle | Regel |
|---|---|
| Detailpagina openen | Alleen ingelogde gebruikers mogen een berichtdetailroute openen. Vanuit het overzicht mag een /open-route eerst eigen readstate wijzigen en daarna naar de canonieke detailroute redirecten. |
| Systeembericht openen | Server-side filter op SystemMessages.RecipientUserId = huidige gebruiker. |
| Privéthread openen | Server-side filter op PrivateMessageThreadParticipants.UserId = huidige gebruiker en DeletedAtUtc is null. |
| Hoofdbericht laden | Het hoofdbericht moet horen bij dezelfde thread als de participantregel. |
| Eerdere berichten laden | Alleen PrivateMessages uit dezelfde thread en binnen de zichtbare context van de participant. |
| Thread-events laden | Alleen PrivateMessageThreadEvents uit dezelfde thread. |
| Leesstatus systeembericht wijzigen | Alleen ReadAtUtc van het eigen systeembericht mag worden gevuld. |
| Leesstatus privéthread wijzigen | Alleen LastReadMessageId en/of LastReadAtUtc van de eigen participantregel mag worden bijgewerkt. |
| Systeembericht-vervolgactie tonen | EntityType en EntityId moeten toegestaan zijn en de gebruiker moet rechten hebben op de vervolgcontext. Afgehandelde, ingetrokken of verlopen relatie-uitnodigingen tonen geen accept/reject-knoppen maar een duidelijke statusmelding. |
| Beantwoorden tonen | Alleen voor beantwoordbare privéthreads waarin de gebruiker actief mag deelnemen. |
| Privéthread verwijderen | Vanuit de detailweergave mag alleen de verwijderflow voor de eigen participantregel bij een privéthread worden gestart; de bevestiging en mutatie vallen onder UC-GEN-MSG-005. |
| Systeembericht verwijderen | Niet toegestaan; backend weigert ook wanneer de frontendactie gemanipuleerd wordt. |
| Inhoud renderen | Alleen veilig gesanitized of veilig geëncodeerde inhoud mag worden weergegeven. |
Veld- en objectvalidatie
| Veld / object | Validatie |
|---|---|
| Route- of mailboxitemreferentie | Mag nooit als autorisatiebewijs worden gebruikt; server-side objectcontrole is verplicht. |
| Berichttype | Moet herleidbaar zijn tot systeembericht of privéthread-mailboxitem. |
SystemMessages.RecipientUserId | Moet overeenkomen met de ingelogde gebruiker voor openen en leesstatusmutatie. |
SystemMessages.ReadAtUtc | null betekent ongelezen; gevuld betekent gelezen. Bij openen wordt een actueel UTC-moment vastgelegd wanneer het bericht nog ongelezen was. |
SystemMessages.EntityType | Wanneer gevuld alleen een toegestane waarde, zoals RelationshipInvitation, Ticket of PrivateMessageThread. |
SystemMessages.EntityId | Wanneer gevuld verplicht in combinatie met EntityType; routing wordt in applicatielogica gevalideerd. |
PrivateMessageThreadParticipants.UserId | Moet overeenkomen met de ingelogde gebruiker voor openen, lezen, beantwoorden of verwijderen. |
PrivateMessageThreadParticipants.DeletedAtUtc | Moet leeg zijn om de thread via de normale mailboxroute te openen. |
PrivateMessageThreadParticipants.LastReadMessageId | Wanneer gevuld moet de waarde horen bij een PrivateMessages-record uit dezelfde thread. |
PrivateMessageThreadParticipants.LastReadAtUtc | Wordt in UTC bijgewerkt bij openen en gebruikt voor ongelezenbepaling, inclusief thread-events. |
PrivateMessages.ThreadId | Moet overeenkomen met de geopende thread. |
PrivateMessages.Body | Moet veilig gesanitized of veilig geëncodeerd zijn voordat deze wordt getoond. |
PrivateMessages.BodyFormat | Alleen ondersteunde formaten mogen worden gerenderd. |
PrivateMessages.SendAsUserId | Wanneer gevuld moet de afwijkende namens-weergave functioneel correct worden opgebouwd. |
PrivateMessageThreadEvents.ThreadId | Moet overeenkomen met de geopende thread. |
PrivateMessageThreadEvents.EventType | Alleen centraal ondersteunde eventtypes worden als threadgebeurtenis gerenderd. |
PrivateMessageThreadEvents.OldValue en NewValue | Alleen gebruiken bij eventtypes waarvoor voor/na-weergave functioneel betekenis heeft; veilig verwerken voor rendering. |
| Datumweergave | UTC-bronwaarden worden lokaal en consistent weergegeven. |
| Foutmeldingen | Mogen geen technische identifiers, stacktraces of interne databasenaamgeving bevatten. |
11. Datamutaties en events
| Stap | Type | Entiteit / event | Mutatie |
|---|---|---|---|
| 1-4A | Read | SystemMessages, Users | Ophalen van het eigen systeembericht en afgeleide displaywaarden. |
| 5A | Database | SystemMessages | ReadAtUtc wordt gevuld met actueel UTC-moment wanneer het systeembericht nog ongelezen was. Dit mag vóór detailrendering gebeuren wanneer de gebruiker vanuit het overzicht via de openroute navigeert. |
| 5A | Event | SystemMessageReadStateChanged | Leesstatus van het systeembericht is gewijzigd naar gelezen. |
| 5A | Event | MessageUnreadCountChanged | Ongelezenteller wordt opnieuw bepaald wanneer de gelezenstatus wijzigt. |
| 4B-5B | Read | PrivateMessageThreads, PrivateMessageThreadParticipants, PrivateMessages, PrivateMessageThreadEvents, Users | Ophalen van de geautoriseerde threaddetailcontext. |
| 6B | Database | PrivateMessageThreadParticipants | LastReadMessageId en/of LastReadAtUtc wordt bijgewerkt voor de eigen participantregel. |
| 6B | Event | PrivateThreadReadStateChanged | Leesstatus van de privéthread is gewijzigd naar gelezen voor de ingelogde gebruiker. |
| 6B | Event | MessageUnreadCountChanged | Ongelezenteller wordt opnieuw bepaald wanneer de gelezenstatus wijzigt. |
| 7A-8 | Read | RelationshipInvitations, Tickets of PrivateMessageThreads als vervolgcontext | Alleen actuele vervolgstatus of toegestane vervolgactie bepalen wanneer het systeembericht daarnaar verwijst. |
| 10 | Navigation | Geen domeinentiteit | Terugnavigatie naar het berichtenoverzicht. |
| 11 | Navigation | Geen domeinentiteit binnen deze usecase | Starten van de antwoordflow, mits toegestaan. |
| 12 | Vervolgflow | UC-GEN-MSG-005 | De detailweergave start de aparte verwijderflow. De bevestiging, participantgebonden mutatie en telleractualisatie worden daar uitgevoerd. |
12. Geen datamutaties
| Entiteit | Reden |
|---|---|
PrivateMessageThreads | Openen of participantgebonden verwijderen wijzigt de threadcontainer niet. |
PrivateMessages | Openen wijzigt de berichtinhoud niet en verwijdert geen berichten hard. |
PrivateMessageThreadEvents | Openen toont thread-events maar maakt of wijzigt deze niet. |
Users | Namen en deelnemersinformatie worden alleen gelezen voor display. |
SystemMessages.EntityType en EntityId | Openen wijzigt de domeinverwijzing niet. |
RelationshipInvitations | Een systeembericht openen accepteert of wijst een uitnodiging niet af. |
Tickets | Een systeembericht openen wijzigt geen melding of ticket. |
UserRelationships | Een bericht openen maakt, wijzigt of beëindigt geen relatie. |
SystemMessageTemplates | Detailweergave gebruikt bestaande berichtinhoud en wijzigt geen sjablonen. |
13. State diagram — leesstatus bij openen
14. Decision flow — bericht openen
15. Data lifecycle diagram — openen en lichte detailacties
16. Sequence diagrammen
Systeembericht openen
Privéberichtthread openen
Verwijderflow starten vanuit detail
17. Popupverwijzingen
| PopupKey | Moment | Variant | Doel |
|---|---|---|---|
POP-GEN-MSG-NOT-AVAILABLE | Wanneer een bericht, thread of mailboxitem niet bestaat, niet toegankelijk is, voor de gebruiker verwijderd is of niet langer via de normale mailboxroute geopend kan worden. | InfoOnly | Duidelijk maken dat het bericht of gesprek niet beschikbaar is zonder technische details prijs te geven. |
POP-GEN-MSG-DELETED | Na succesvolle verwijdering van een privéberichtthread uit de eigen mailboxweergave vanuit de detailpagina. | InfoOnly | Bevestigen dat de thread alleen uit de eigen mailboxweergave is verwijderd en niet voor andere deelnemers. |
18. Afleiding naar Functioneel Ontwerp / Technisch Ontwerp / Software Requirements Specification
| Doeldocument | Afleiding |
|---|---|
| Functioneel Ontwerp | Beschrijft de open-berichtflow voor systeemberichten en privéthreads, inclusief hoofdbericht, threadcontext, acties, disabled states, foutstaten en dynamische waarden. |
| Functioneel Ontwerp | Beschrijft dat het openen van een bericht als leesactie geldt en dat systeemberichten niet beantwoordbaar of verwijderbaar zijn. |
| Technisch Ontwerp | Technisch Ontwerp: berichten, systeemberichten, notificaties en privéthreads beschrijft de commands voor openen, readstate-update, detailreadmodel, veilige rendering en participantgebonden delete uit. |
| Technisch Ontwerp | Technisch Ontwerp: berichten, systeemberichten, notificaties en privéthreads beschrijft hoe EntityType + EntityId wordt gevalideerd en vertaald naar toegestane vervolgcontext zonder automatische domeinmutatie. |
| Software Requirements Specification | Bevat requirements voor server-side objecttoegang, readstate bij openen, threadcontext, thread-events, niet-beschikbaarstaten en participantgebonden delete. |
| Database-informatie | Controleer dat SystemMessages, PrivateMessageThreadParticipants, PrivateMessages en PrivateMessageThreadEvents voldoende velden en constraints bevatten voor deze flow. |
19. SRS-trace
Deze usecase bevat geen normatieve requirementtekst. De centrale eis en acceptatiecriteria staan in de SRS; onderstaande tabel koppelt de usecase-afleiding alleen aan centrale SRS-*- en AC-*-items.
| Usecase-afleiding | Dekt | Usecasecontext |
|---|---|---|
REQ-UC-GEN-MSG-003-001 | SRS-RDM-001 SRS-RDM-007 SRS-MSG-007 AC-RDM-001 AC-RDM-007 AC-MSG-007 | Een ingelogde gebruiker een eigen systeembericht of eigen privéberichtthread kunnen laten openen vanuit het berichtenoverzicht |
REQ-UC-GEN-MSG-003-002 | SRS-AUTH-001 SRS-MSG-007 AC-AUTH-001 AC-MSG-007 | Bij openen server-side controleren of het gekozen systeembericht of de gekozen privéthread bij de ingelogde gebruiker hoort |
REQ-UC-GEN-MSG-003-003 | SRS-MSG-001 AC-MSG-001 | Een systeembericht alleen tonen wanneer RecipientUserId overeenkomt met de ingelogde gebruiker |
REQ-UC-GEN-MSG-003-004 | SRS-MSG-003 AC-MSG-003 | Een privéthread alleen tonen wanneer de ingelogde gebruiker een geldige participantregel heeft en de thread niet voor deze gebruiker is verwijderd |
REQ-UC-GEN-MSG-003-005 | SRS-MSG-007 AC-MSG-007 | Het openen van een systeembericht als gelezenstatusmutatie voor dat systeembericht kunnen verwerken |
REQ-UC-GEN-MSG-003-006 | SRS-MSG-007 AC-MSG-007 | Het openen van een privéthread als participantgebonden readstate-mutatie kunnen verwerken |
REQ-UC-GEN-MSG-003-007 | SRS-MSG-007 AC-MSG-007 | Leesstatus van andere deelnemers niet wijzigen wanneer één gebruiker een privéthread opent |
REQ-UC-GEN-MSG-003-008 | SRS-RDM-001 SRS-RDM-002 SRS-MSG-006 AC-RDM-001 AC-RDM-002 AC-MSG-006 | Na readstatewijziging de ongelezenteller opnieuw kunnen bepalen |
REQ-UC-GEN-MSG-003-009 | SRS-MSG-001 AC-MSG-001 | Bij een systeembericht titel, inhoud, type, afzenderweergave, ontvangstmoment en toegestane vervolgcontext kunnen tonen |
REQ-UC-GEN-MSG-003-010 | SRS-MSG-007 AC-MSG-007 | Het onderliggende domeinobject waarnaar een systeembericht verwijst niet automatisch verwerken door alleen het systeembericht te openen |
REQ-UC-GEN-MSG-003-011 | SRS-MSG-001 AC-MSG-001 | EntityType en EntityId van een systeembericht valideren voordat een vervolgactie beschikbaar wordt gemaakt |
REQ-UC-GEN-MSG-003-012 | SRS-MSG-001 AC-MSG-001 | Bij een privéthread het hoofdbericht en de zichtbare threadcontext kunnen tonen |
REQ-UC-GEN-MSG-003-013 | SRS-RDM-001 SRS-RDM-007 SRS-RDM-008 SRS-MSG-001 AC-RDM-001 AC-RDM-007 AC-RDM-008 AC-MSG-001 | Eerdere berichten in een privéthread kunnen tonen volgens de functionele threadsortering |
REQ-UC-GEN-MSG-003-014 | SRS-MSG-001 AC-MSG-001 | Threadgebeurtenissen binnen een privéthread kunnen tonen als systeemachtige threadregels |
REQ-UC-GEN-MSG-003-015 | SRS-MSG-001 AC-MSG-001 | Threadgebeurtenissen niet behandelen als losse systeemberichten of gewone privéberichten |
REQ-UC-GEN-MSG-003-016 | SRS-MSG-006 AC-MSG-006 | Thread-events na de laatst bekende leespositie kunnen meenemen in de ongelezenstatus van de thread |
REQ-UC-GEN-MSG-003-017 | SRS-MSG-001 SRS-NFR-SEC-001 AC-MSG-001 AC-NFR-SEC-001 | Berichtinhoud, rich text en eventwaarden veilig sanitizen of encoden voordat deze worden weergegeven |
REQ-UC-GEN-MSG-003-018 | SRS-MSG-001 SRS-LRN-003 AC-MSG-001 AC-LRN-003 | De antwoordactie alleen beschikbaar maken voor beantwoordbare privéthreads waarin de gebruiker actief mag deelnemen |
REQ-UC-GEN-MSG-003-019 | SRS-MSG-001 SRS-LRN-003 AC-MSG-001 AC-LRN-003 | Systeemberichten niet beantwoordbaar maken |
REQ-UC-GEN-MSG-003-020 | SRS-MSG-003 AC-MSG-003 | Systeemberichten niet verwijderbaar maken voor gebruikers |
REQ-UC-GEN-MSG-003-021 | SRS-MSG-003 AC-MSG-003 | Een privéthread vanuit de detailweergave uit de eigen mailboxweergave kunnen verwijderen |
REQ-UC-GEN-MSG-003-022 | SRS-MSG-003 AC-MSG-003 | Het verwijderen van een privéthread uit de eigen mailboxweergave mag de thread, berichten en events voor andere deelnemers niet verwijderen |
REQ-UC-GEN-MSG-003-023 | SRS-MSG-003 AC-MSG-003 | Na succesvolle participantgebonden verwijdering POP-GEN-MSG-DELETED kunnen tonen |
REQ-UC-GEN-MSG-003-024 | SRS-ACC-003 SRS-ACC-005 SRS-MSG-003 SRS-NFR-ACC-001 AC-ACC-003 AC-ACC-005 AC-MSG-003 AC-NFR-ACC-001 | POP-GEN-MSG-NOT-AVAILABLE of een gelijkwaardige inline niet-beschikbaarstaat tonen wanneer een bericht of thread niet bestaat, niet toegankelijk is of voor de gebruiker verwij... |
REQ-UC-GEN-MSG-003-025 | SRS-MSG-001 AC-MSG-001 | In open-berichtweergaven en foutstaten geen technische identifiers, stacktraces of interne databasenaamgeving tonen |
REQ-UC-GEN-MSG-003-026 | SRS-MSG-001 AC-MSG-001 | UTC-bronwaarden lokaal en consistent tonen in de open-berichtweergave |
8.3 Opaque cursor voor oudere berichten
Wanneer een privé- of groepsthread meer historie bevat dan het initiële timelinevenster, toont de UI Eerdere berichten laden. Dit gebruikt geen querystringcursor en geen paginanummers. De client stuurt een hidden opaque cursor mee in een beveiligde POST.
De cursor is opgebouwd uit server-side context, conceptueel: thread-id, user-id, oudste geladen tijdstip, oudste timeline-item-id en een purpose/versie. Deze payload wordt beschermd met ASP.NET Data Protection. De gebruiker kan de inhoud niet zinvol lezen of aanpassen. Bij elk verzoek valideert de server opnieuw dat de cursor bij de route-thread en ingelogde gebruiker hoort, dat de gebruiker nog actieve participanttoegang heeft en dat de batchgrootte binnen de ingestelde limieten blijft.
Na een succesvolle response voegt de client de oudere items bovenaan de timeline toe en corrigeert de scrollpositie zodat de gebruiker visueel op dezelfde plek blijft. Bij een ongeldige cursor of toegangsverlies wordt geen threadinhoud teruggegeven en verschijnt een veilige foutmelding.