Changeset 8179fdb in Klonkt


Ignore:
Timestamp:
08/08/2026 10:35:28 PM (4 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
060d4a5
Parents:
bfd9c73
git-author:
Robin <roboburr@…> (08/08/2026 10:34:09 PM)
git-committer:
Robin <roboburr@…> (08/08/2026 10:35:28 PM)
Message:

De gedeelde kern eruit: ap-core.js (shaer-drc, stap 1)

Voorbereiding op music/, en de reden dat die volgorde nodig is: een submap kan
pas zelfstandig bestaan als de primitieven ergens staan waar BEIDE uit kunnen
putten. Zou music/ ze uit ActivityPubService halen, dan importeert die weer
terug -- een kring. Guardianship doet het al goed: die map kent alleen db en
zijn eigen buren, en niemand importeert terug.

Verhuisd, ongewijzigd: PUBLIC, AP_CONTEXT, safeUrl, actorId, noteId,
guessMediaType. ActivityPubService importeert ze en geeft de vier door die hij
altijd al exporteerde, zodat elke bestaande aanroep blijft werken.

De grens van ap-core is PUUR: geen database, geen netwerk, geen toestand. Komt
daar iets bij dat wel iets weet, dan hoort het er niet.

FOUT ONDERWEG, en het is de fout waar ik gisteren nog een aantekening over
maakte: mijn eerste poging knipte op REGELNUMMERS. Daarmee begon het blok van
guessMediaType midden in zijn commentaar en eindigde het voor de sluitende
accolade -- syntaxfout, en de suite viel in zijn geheel om. Opnieuw gedaan op
tekstankers, met een assertie dat elk blok compleet is. Regelnummers zijn geen
structuur.

Geen gedragsverandering -- alleen verplaatst.

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

Location:
src/services
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    rbfd9c73 r8179fdb  
    2929import Blocklist from './BlocklistService.js';
    3030import * as Guardianship from './guardianship/index.js';
    31 
    32 const PUBLIC = 'https://www.w3.org/ns/activitystreams#Public';
    33 // Full JSON-LD context for every AP object we emit: AS2 core + security (publicKey) + the
    34 // extension terms we actually use (Mastodon/toot + schema.org), each with a term definition
    35 // so a strict JSON-LD processor resolves them instead of dropping them → valid AS2/JSON-LD.
    36 // This is the same context shape Mastodon publishes, so Mastodon sees no change.
    37 const AP_CONTEXT = [
    38   'https://www.w3.org/ns/activitystreams',
    39   'https://w3id.org/security/v1',
    40   {
    41     toot: 'http://joinmastodon.org/ns#',
    42     schema: 'http://schema.org#',
    43     sensitive: 'as:sensitive',
    44     Hashtag: 'as:Hashtag',
    45     manuallyApprovesFollowers: 'as:manuallyApprovesFollowers',
    46     discoverable: 'toot:discoverable',
    47     // FEP-7628 (account moves): same term declaration Mastodon ships.
    48     alsoKnownAs: { '@id': 'as:alsoKnownAs', '@type': '@id' },
    49     movedTo: { '@id': 'as:movedTo', '@type': '@id' },
    50     featured: { '@id': 'toot:featured', '@type': '@id' },
    51     PropertyValue: 'schema:PropertyValue',
    52     value: 'schema:value',
    53     embedUrl: { '@id': 'schema:embedUrl', '@type': '@id' },
    54     // Wat een track beschrijft en AS2 niet kent (shaer-0nh). Funkwhale zet deze
    55     // vier op zijn Audio; het bleken geen eigen verzinsels maar termen die
    56     // schema.org gewoon heeft -- en schema.org stond hier al. De SLEUTELS zijn
    57     // die van Funkwhale, want daar leest hij op; de BETEKENIS komt van
    58     // schema.org, dus we hoeven geen vreemd vocabulaire binnen te halen.
    59     license: { '@id': 'schema:license', '@type': '@id' },
    60     position: 'schema:position',
    61     bitrate: 'schema:bitrate',
    62     size: 'schema:contentSize',
    63     // Poll (Question) extension: Question/oneOf/anyOf/endTime/closed are AS2 core, but the
    64     // per-poll unique-voter count is a Mastodon (toot) term — declare it so the emitted
    65     // Question stays valid JSON-LD (a strict processor would otherwise drop votersCount).
    66     votersCount: 'toot:votersCount',
    67     // Kanaal-vocabulaire (shaer-0nh). Funkwhale declareert `category` niet
    68     // inline maar via zijn eigen remote context https://funkwhale.audio/ns, en
    69     // die host is vanaf hier onbereikbaar -- de IRI hieronder is dus AFGELEID
    70     // en niet geverifieerd. Wat vandaag telt voor interop is de JSON-sleutel,
    71     // want daar matchen lezers op; de declaratie zorgt alleen dat een strikte
    72     // JSON-LD-processor hem niet laat vallen. Nakijken zodra die host weer
    73     // antwoordt.
    74     category: { '@id': 'https://funkwhale.audio/ns#category' },
    75     // FEP-633c (Guardians): the shaer namespace, owned by the guardianship
    76     // module (src/services/guardianship/).
    77     ...Guardianship.SHAER_CONTEXT,
    78   },
    79 ];
     31import { PUBLIC, AP_CONTEXT, safeUrl, actorId, noteId, guessMediaType } from './ap-core.js';
     32// Doorgeven wat hier altijd vandaan kwam, zodat elke bestaande aanroep blijft werken.
     33export { AP_CONTEXT, actorId, noteId, guessMediaType };
     34
    8035
    8136// Short random suffix so two activity ids minted in the same millisecond (e.g.
     
    8540// Keep only http(s) URLs — drops javascript:/data:/etc so a remote actor can't
    8641// smuggle a dangerous scheme into a stored href/src (rendered in owner-only views).
    87 const safeUrl = (u) => { const s = String(u == null ? '' : u).trim(); return /^https?:\/\//i.test(s) ? s : ''; };
    8842
    8943// ── SSRF guard for outbound fetches ───────────────────────────────
     
    259213
    260214// ── document builders ─────────────────────────────────────────────
    261 export function actorId(base, slug) { return `${base}/ap/users/${encodeURIComponent(slug)}`; }
    262 
    263 /**
    264  * mediaType raden uit een bestandsnaam. Stond twee keer functie-lokaal in dit
    265  * bestand, met een commentaar dat ze "dezelfde afleiding" waren -- en dat was
    266  * niet zo: de ene kende video, de andere alleen beeld. Nu een kaart, hier.
    267  * De terugval is image/jpeg omdat dit alleen op omslagen en bijlagen wordt
    268  * losgelaten, nooit op geluid: dat draagt zijn eigen mime_type uit de database.
    269  */
    270 export function guessMediaType(u) {
    271   const e = ((u || '').split('?')[0].match(/\.(\w+)$/) || [])[1];
    272   return ({
    273     jpg: 'image/jpeg', jpeg: 'image/jpeg', png: 'image/png', gif: 'image/gif',
    274     webp: 'image/webp', avif: 'image/avif',
    275     mp4: 'video/mp4', webm: 'video/webm', mov: 'video/quicktime',
    276   })[(e || '').toLowerCase()] || 'image/jpeg';
    277 }
    278 export function noteId(base, postId) { return `${base}/ap/notes/${encodeURIComponent(postId)}`; }
     215
    279216
    280217/** Eén Link uit een AS2 `url` kiezen op mediaType. Een `url` mag een string,
Note: See TracChangeset for help on using the changeset viewer.