Ignore:
Timestamp:
08/07/2026 12:00:22 PM (5 weeks ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
4c1e327
Parents:
ea138c0
git-author:
Robin <roboburr@…> (08/07/2026 12:00:20 PM)
git-committer:
roboburr <roboburr@…> (08/07/2026 12:00:22 PM)
Message:

Modules laden vanuit de shell in plaats van inline script (shaer-bqr, stap 1)

Het mechanisme uit optie C, met de bottom-tab als eerste geval zodat het ook
te bewijzen is.

WAAROM. De CSP-nonce rouleert per verzoek (shaer-0i6). Een script dat via htmx
binnenkomt draagt dus een nonce die het document niet kent en wordt geweigerd.
De chrome komt bij ELKE navigatie out-of-band opnieuw binnen, dus daar valt de
JS bij de eerste klik binnen de site al weg.

HOE. Een bootstrap in shell.ejs -- die komt alleen bij een volledige laadbeurt
binnen en heeft dus wel de goede nonce. Hij leest body[data-js], een lijst
modulenamen, en importeert ze uit /assets/js/mod/. Een dynamische import vanuit
een vertrouwd script is precies waar strict-dynamic voor bedoeld is, dus de
module zelf heeft geen nonce nodig.

Bij een htmx-navigatie zet de pcmsNav-trigger data-js opnieuw en haalt de
bootstrap op wat er nieuw bij staat. 'chrome' staat er altijd bij.

De naam wordt een PAD, dus hij moet door /[a-z0-9-]+$/ -- geen punt, geen
schuine streep.

EERSTE GEVAL: de zoekknop van de bottom-tab. Geen servergegevens erin, al
gedelegeerd, al voorzien van een slot -- dus de verhuizing verandert niets aan de
logica en het mechanisme is er echt mee te toetsen.

WAT DIT BLOOTLEGT VOOR DE VOLGENDE STAP: het topnav-script interpoleert
vertalingen (<%= t('search.section_posts') %>) en kan dus niet zomaar een
statisch bestand worden. Servergegevens horen via een data-attribuut naar een
module, niet via interpolatie in de code. Dat is een eigen stap en staat als
zodanig in mod/chrome.js opgeschreven.

Templates compileren, suite 551/551. Het echte bewijs is een klik BINNEN de site:
na een herlading werkt alles toch al.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    rea138c0 r1e172f3  
    49024902      const wardDoc = await fetchActor(wardUri).catch(() => null);
    49034903      const fai = actorInfo(await fetchActor(follower).catch(() => null), follower);
    4904       Guardianship.follows.recordReview(gslug, { id: followId, wardUri, wardInbox: wardDoc && wardDoc.inbox, follower, followerHandle: fai.handle, followerIcon: fai.icon, followJson: JSON.stringify(fo) });
     4904      // De RICHTING bewaren (shaer-jdb). shaer:direction wordt sinds de uitgaande
     4905      // gate meegestuurd maar werd nergens gelezen, dus een uitgaande belandde
     4906      // hier als "deze ward wil deze ward volgen" met het doel weggegooid.
     4907      // Terugval voor oudere afzenders: is de volger de ward zelf, dan is het
     4908      // uitgaand -- dat volgt uit de vorm en hoeft niet geloofd te worden.
     4909      const uitgaand = act['shaer:direction'] === 'outgoing' || follower === wardUri;
     4910      const doel = uitgaand ? (typeof fo.object === 'string' ? fo.object : (fo.object && fo.object.id)) : null;
     4911      const dai = uitgaand ? actorInfo(await fetchActor(doel).catch(() => null), doel) : null;
     4912      Guardianship.follows.recordReview(gslug, {
     4913        id: followId, wardUri, wardInbox: wardDoc && wardDoc.inbox,
     4914        follower, followerHandle: fai.handle, followerIcon: fai.icon, followJson: JSON.stringify(fo),
     4915        direction: uitgaand ? 'outgoing' : 'incoming',
     4916        target: doel || null, targetHandle: dai ? dai.handle : null,
     4917      });
    49054918      const L = pushLang(gslug);
    49064919      pushEvent(gslug, { type: 'guardian', title: i18nT(L, 'push.n_guard_cog_t'), body: i18nT(L, 'push.n_guard_cog_b', { who: fai.name || fai.handle || i18nT(L, 'notif.someone') }), url: `${pushPrefix(gslug)}/guardian` });
Note: See TracChangeset for help on using the changeset viewer.