source: Klonkt/src/services/guardianship/notes.js@ e27b8db

main
Last change on this file since e27b8db was e27b8db, checked in by Robin Genis <roboburr@…>, 6 weeks ago

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@…>

  • Property mode set to 100644
File size: 3.6 KB
Line 
1/**
2 * Guardianship (FEP-633c) — note properties.
3 *
4 * The shaer:helpRequest flag (spec 5.2.1): a ward's call for help, only ever
5 * on direct notes. Everyone who does not speak shaer can ignore it.
6 */
7import { listGuardians } from './relations.js';
8
9/**
10 * shaer:hasGuardians (§2.2): an advisory OBJECT hint that the author is a ward,
11 * so a remote server can route interactions to the guardians WITHOUT fetching
12 * the actor. Stamped on every object a ward publishes; MUST be safely ignorable.
13 */
14export function hasGuardiansProps(slug) {
15 try { return (slug && listGuardians(slug).length) ? { 'shaer:hasGuardians': true } : {}; }
16 catch { return {}; }
17}
18
19/**
20 * May EXTERNAL (non-fediverse) embeds be shown to this account?
21 *
22 * A gated feature in the FEP-633c sense: a ward's world outside the fediverse
23 * is the guardians' call. `setting` is `sites.external_embeds`:
24 * null/undefined → auto: off for a ward, on for anyone else
25 * 0 → off, 1 → on (the guardians decided)
26 *
27 * Pure, so the rule is testable on its own. The gate is applied SERVER-side:
28 * a blocked embed is never serialised into the feed, because an embed that the
29 * client merely hides has still been delivered.
30 */
31export function externalEmbedsAllowed(setting, isWard) {
32 if (setting === 0 || setting === 1) return setting === 1;
33 return !isWard;
34}
35
36/**
37 * May a player run INSIDE the app/page for this account? The heavier sibling
38 * of the setting above, and deliberately separate: seeing that a video exists
39 * is not the same decision as handing the screen to a third party's player,
40 * with its engine, its end-screen and its next-video machine. Same shape, same
41 * default (off for a ward), and it only ever matters once embeds are allowed:
42 * you cannot play what you may not see.
43 */
44export function externalPlaybackAllowed(setting, isWard) {
45 if (setting === 0 || setting === 1) return setting === 1;
46 return !isWard;
47}
48
49/** True when an incoming object carries the ward hint (§2.2). Register-only for
50 * now; acted on later at reddings-boei / escalation routing. */
51export function objectHasGuardians(o) {
52 return !!o && (o['shaer:hasGuardians'] === true || o.hasGuardians === true);
53}
54
55/** Extra JSON-LD properties for an outgoing note built from an ap_outbox row. */
56export function helpRequestProps(post) {
57 return (post && post.visibility === 'direct' && post.help_request)
58 ? { 'shaer:helpRequest': true }
59 : {};
60}
61
62/** True when an incoming (C2S or S2S) note object carries the flag. */
63export function isHelpRequest(object) {
64 return !!object && (object['shaer:helpRequest'] === true || object.helpRequest === true);
65}
66
67/** shaer:wave: a gentle "thinking of you" from a guardian to its ward. A
68 * private nudge, never a feed post; non-shaer clients see a plain DM. */
69export function waveProps(post) {
70 return (post && post.visibility === 'direct' && post.wave)
71 ? { 'shaer:wave': true }
72 : {};
73}
74
75/** True when an incoming note is a wave. */
76export function isWave(object) {
77 return !!object && (object['shaer:wave'] === true || object.wave === true);
78}
79
80/** shaer:away (3.6.1): a guardian declaring itself away to its ward, with an
81 * end. Rides a direct note like the help request, so a ward on a plain
82 * server reads a human message; endTime is plain AS2. */
83export function awayProps(post) {
84 return (post && post.visibility === 'direct' && post.away_until)
85 ? { 'shaer:away': true, endTime: new Date(post.away_until).toISOString() }
86 : {};
87}
88
89export default { helpRequestProps, isHelpRequest, waveProps, isWave, awayProps, hasGuardiansProps, objectHasGuardians, externalEmbedsAllowed, externalPlaybackAllowed };
Note: See TracBrowser for help on using the repository browser.