Changeset e27b8db in Klonkt for src/routes/posts.js


Ignore:
Timestamp:
07/29/2026 10:04:36 AM (6 weeks ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
329873e
Parents:
88d7c8f
Message:

Afspelen in de app als tweede gated feature, en het gat in de gate

Bij het uitzoeken van de YouTube-vraag bleek de gate lek. De web-Krant bouwt de
speler uit de inhoud van de post via timelineEmbedHtml, en dat pad raakte
gateEmbeds nooit. Een ward wiens guardians niets hadden toegestaan kreeg dus de
volledige YouTube-speler op het web, terwijl de app niets liet zien: het zware
ding open, het lichte dicht. Precies omgekeerd.

Nu zijn het twee besluiten, want het zijn twee dingen. Zien dat er een filmpje
is, is niet hetzelfde als het scherm afstaan aan de motor van een derde partij,
compleet met eindscherm en volgende-video. shaer:externalEmbeds houdt de kaart,
shaer:externalPlayback de speler, allebei standaard uit voor een ward, en
afspelen vereist de kaart: je kunt niet spelen wat je niet mag zien.

En het antwoord op Robins vraag over de links: die vallen er ook onder. De gate
verborg tot nu toe alleen het plaatje terwijl de kale link eronder gewoon
aantikbaar bleef, dus de deur stond open met een doek eroverheen. Staat de gate
dicht, dan toont de kaart zich nog wel maar is hij geen deur meer.

De server bepaalt wat gespeeld mag worden, niet de client: hij levert
shaer:playerUrl mee, alleen bij een open gate en alleen in de privacy-variant
(youtube-nocookie met rel=0, of de eigen speler van de PeerTube-instance). De
app houdt zo geen lijst van hosts bij; hij speelt wat hij krijgt aangereikt.

Changed files:
src/config/database.js

  • kolom sites.external_playback

src/services/guardianship/notes.js

  • externalPlaybackAllowed naast externalEmbedsAllowed

src/services/guardianship/gated.js

  • shaer:externalPlayback in de feature-tabel

src/services/ActivityPubService.js

  • timelineEmbed voegt shaer:playerUrl toe als afspelen mag; playerUrlFor kent alleen privacy-varianten en weigert de rest

src/routes/activitypub.js

  • shaer:capabilities op de owner-only inbox-read: wat mag dit account
  • de embed draagt de speler-URL alleen bij een open playback-gate

src/routes/posts.js

  • het gat gedicht: de speler-iframe op de web-Krant valt nu onder de gate

src/routes/guardian.js

  • de voorstel-route is feature-bewust; het lokale pad stuurt nu ook door

src/assets/js/guardian.js

  • tweede knop in het paneel, alleen zichtbaar als de kaart al aan staat

src/services/i18n.js

  • de labels in nl, en, de

test/gated-settings.test.js

  • drie tests: de speler-URL rijdt alleen mee bij een open gate, een pagina die we niet framen blijft een thumbnail, en afspelen vereist de kaart

remarks: 280 tests groen. Niets geforceerd: beide gates staan standaard uit
voor een ward en twee van de drie guardians moeten nog steeds akkoord gaan.

-robo
Co-Authored-By: Claude Opus 5 <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/posts.js

    r88d7c8f re27b8db  
    10841084function gateEmbeds(site, rows) {
    10851085  if (!site || !rows.length) return rows;
    1086   let isWard = false;
    1087   try { isWard = Guardianship.listGuardians(site.slug).length > 0; } catch { /* no relations yet */ }
    1088   if (Guardianship.externalEmbedsAllowed(site.external_embeds, isWard)) return rows;
     1086  if (embedsAllowedFor(site)) return rows;
    10891087  return rows.map((r) => (r && r.embed_json ? { ...r, embed_json: null } : r));
     1088}
     1089
     1090function isWardSite(site) {
     1091  try { return !!site && Guardianship.listGuardians(site.slug).length > 0; } catch { return false; }
     1092}
     1093function embedsAllowedFor(site) {
     1094  return !site || Guardianship.externalEmbedsAllowed(site.external_embeds, isWardSite(site));
     1095}
     1096/**
     1097 * May a third-party PLAYER run inside this page? (FEP-633c 5.6, the heavier
     1098 * sibling of the preview gate.) This was the hole: the player iframe is built
     1099 * from the note's content by timelineEmbedHtml, on a path that never touched
     1100 * gateEmbeds. A ward whose guardians had allowed nothing still got the full
     1101 * YouTube player on the web, while the app showed nothing at all: the heavy
     1102 * thing open, the light thing shut. Playback also requires the preview gate,
     1103 * because you cannot play what you may not see.
     1104 */
     1105function playbackAllowedFor(site) {
     1106  if (!site) return true;
     1107  if (!embedsAllowedFor(site)) return false;
     1108  return Guardianship.externalPlaybackAllowed(site.external_playback, isWardSite(site));
    10901109}
    10911110
     
    10981117  const rows = gateEmbeds(site, site ? ActivityPubService.getTimeline(site.slug, FEED_PAGE + 1, offset) : []);
    10991118  const hasMore = rows.length > FEED_PAGE;
     1119  // Players (a third party's engine inside our page) ride the playback gate;
     1120  // a Klonkt site's own audio embed is ours and stays.
     1121  const mayPlay = playbackAllowedFor(site);
    11001122  const timeline = rows.slice(0, FEED_PAGE).map((p) => {
    1101     let embedHtml = timelineEmbedHtml(p.content);
     1123    let embedHtml = mayPlay ? timelineEmbedHtml(p.content) : null;
    11021124    let content = p.content;
    11031125    let embedUrl = null;
Note: See TracChangeset for help on using the changeset viewer.