# Gedrag en hoofdscenario's Deze pagina beschrijft gedrag als ketens van waarneembare stappen. De backend blijft in iedere keten verantwoordelijk voor autorisatie en duurzame invarianten; browserstatus is slechts tijdelijke presentatietoestand. ## Start en eerste setup 1. `main.rkt` maakt de datamap aan en leest `database.rktd` wanneer die bestaat. 2. Bij bekende database-instellingen voert `initialize-database!` alle nog ontbrekende migraties in volgorde uit en verwijdert het verlopen sessies. 3. `server.rkt` controleert of schema, een ingeschakelde administrator en alle vendor-assets aanwezig zijn. 4. Zolang een voorwaarde ontbreekt, gaan normale requests naar `/setup`. 5. Setup test PostgreSQL, installeert het schema, maakt de eerste administrator en downloadt de vastgepinde frontendbestanden. 6. Na een volledige setup gaat de browser naar `/login`. Setup is daarmee ook een reparatiepad voor ontbrekende browserassets. Het is geen anonieme route naar wiki-inhoud. ## Aanmelden en een request uitvoeren Bij succesvolle authenticatie genereert de backend een willekeurig sessietoken en CSRF-token. Alleen de SHA-256-hash van het sessietoken staat in PostgreSQL; het ruwe token gaat in de cookie naar de browser. Iedere API-handler die inhoud schrijft vereist een geldige sessie, voldoende rol en het CSRF-token uit die sessie. `reader` leest. `editor` erft lezen en mag pagina's en CMaps creëren, wijzigen, archiveren en bestanden uploaden. `admin` erft editorrechten en beheert gebruikers en systeeminstellingen. ## Pagina lezen 1. De browser haalt eerst de paginacatalogus op zonder alle Markdown. 2. Navigatie naar een pagina vraagt de actuele pagina met Markdown op. 3. Namespaced links en WikiWords worden naar interne routes vertaald. 4. EasyMDE/Marked rendert dezelfde Markdown voor leesweergave, preview en historische versies. 5. DOMPurify saneert de HTML voordat zij in het document komt. 6. Fenced code wordt met highlight.js gemarkeerd en `{{cmap:slug}}` wordt daarna met een read-only CMap gehydrateerd. Een dubbelklik op een ingebedde CMap opent de volledige editor. De ingesloten kaart is niet een tweede opslagvorm. ## Pagina maken of wijzigen Een nieuwe pagina krijgt een namespace en stabiele slug. Bij opslaan stuurt de browser titel, Markdown, tags en bij een bestaande pagina het bekende `currentVersion` mee. De opslagmodule vergrendelt de actuele rij binnen een PostgreSQL-transactie. Alleen als de meegestuurde basisversie gelijk is aan de databaseversie worden actuele toestand, nieuwe onveranderlijke versie, todo-index en bijlageverwijzingen samen vastgelegd. Is iemand anders eerder geweest, dan volgt `version-conflict`; de oudere editor mag de nieuwere versie niet stilzwijgend overschrijven. Hernoemen of verplaatsen behoudt dezelfde pagina-id en maakt een alias voor het oude adres. Archiveren verwijdert de pagina niet fysiek en behoudt historie en bijlagen. ## Conceptmap bewerken De CMap-editor houdt conceptidentiteit, plaatsingen, verbindingszinnen, connectors, groepen en sub-CMaps in één document met `schemaVersion: 2`. Positie en vormgeving horen bij de plaatsing en CMap-context. Kop en subtekst hebben daarbinnen elk hun eigen typografie. Het bewerkbare kleurenpalet is alleen browserinstelling; een toegepaste kleur wordt als concrete hexwaarde bij de plaatsing opgeslagen en verandert dus niet wanneer het palette later wijzigt. Bewerkingen gaan eerst door een lokale Undo/Redo-historie. Na een afgeronde handeling plant de browser een autosave; een nieuwe handeling verschuift die timer. Een lopende save kan een volgende save noodzakelijk maken, zodat tussentijdse wijzigingen niet verdwijnen. Iedere serveropslag controleert opnieuw het basisversienummer en schrijft de actuele CMap-toestand. Autosave beschermt de werkstand zonder een historieregel te maken. Ctrl/Cmd-S en **Nu opslaan** maken een handmatige historieversie, waarvan per CMap de vijf nieuwste blijven staan. **Snapshot maken** schrijft ook zonder inhoudsverschil een herkenbaar, onbeperkt bewaard moment met een omschrijving. Een historische versie laden verandert alleen de editor; pas een volgende opslag maakt daarvan een nieuwe actuele versie. Een editor kan een afzonderlijk geschiedenisitem verwijderen zonder de actuele CMap te veranderen. Wanneer een actueel CMap-concept een `pageSlug` heeft, toont de gelezen wikipagina onder de inhoud een verwijzing naar dat concept. Plaatsingen worden op `conceptId` gegroepeerd en iedere betrokken CMap is rechtstreeks aanklikbaar. Alleen actuele, niet-gearchiveerde CMap-documenten tellen mee; historische CMap-versies leveren geen navigatielinks op. ## Zoeken, Recent en navigatiegraaf Paginazoeken gebruikt een opgeslagen gewogen `tsvector` en GIN-index. CMap-zoeken verzamelt titel, slug, labels en synopses uit JSONB. Recent voegt de nieuwste pagina- en CMapwijzigingen samen. De gecombineerde navigatiegraaf leest verwijzingen uit alle huidige pagina's en CMaps. Hij wordt in de browser gecachet totdat een catalogus opnieuw wordt geladen. Dit levert rijke navigatie op, maar is het belangrijkste schaalrisico; zie [Verwachte performance](racket-wiki:performance). ## Wachtwoordherstel en mail De publieke herstelactie geeft altijd dezelfde reactie, ook als een account niet bestaat. Een echte aanvraag maakt een gehashte, eenmalige code die één uur geldig is en past rate limiting per gebruiker toe. Na succesvol herstel worden bestaande sessies ingetrokken. SMTP kan STARTTLS gebruiken. Standaard gebruikt mail `ssl-secure-client-context` en controleert certificaatketen en hostnaam. Alleen voor een bewust vertrouwde lokale server kan de administrator onvertrouwde certificaten accepteren; dan gebruikt de verbinding moderne TLS zonder serverauthenticatie. De testmail gebruikt eerst de nog niet opgeslagen formulierwaarden. ## Foutgedrag Verwachte domeinfouten worden zo dicht mogelijk bij hun grens herkend: ongeldige input als 400, ontbrekende authenticatie als 401, onvoldoende rechten als 403, ontbrekende inhoud als 404 en versieconflict als 409. Technische uitzonderingen moeten voldoende context in de serverconsole behouden zonder wachtwoorden, tokens of databasegeheimen te loggen.