Changeset 86e6a45 in Klonkt
- Timestamp:
- 08/08/2026 07:24:44 AM (5 weeks ago)
- Branches:
- main
- Children:
- a9ede28
- Parents:
- 0b0cd54
- git-author:
- Robin <roboburr@…> (08/08/2026 07:24:42 AM)
- git-committer:
- roboburr <roboburr@…> (08/08/2026 07:24:44 AM)
- Files:
-
- 1 added
- 6 edited
-
src/routes/activitypub.js (modified) (1 diff)
-
src/services/ActivityPubService.js (modified) (1 diff)
-
src/services/guardianship/index.js (modified) (1 diff)
-
src/services/guardianship/queues.js (modified) (3 diffs)
-
src/services/guardianship/relations.js (modified) (1 diff)
-
test/activitypub-as2.test.js (modified) (1 diff)
-
test/help-c2s.test.js (added)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/activitypub.js
r0b0cd54 r86e6a45 314 314 // guardians' real states here and nowhere else. 315 315 queueRoute('guardians', (id, slug) => Guardianship.guardiansCollection(id, slug)); 316 // De hulpvragen MET hun staat (5.2.1, shaer-lgo). De apps lazen ze uit de feed 317 // en wisten dus niet of er al iemand op af was -- daarom bleef een afgehandeld 318 // verzoek daar staan (Barts melding, 8-8). 319 queueRoute('help', (id, slug) => Guardianship.helpCollection(id, slug)); 316 320 317 321 // ── Inbox read (owner only, AP C2S) ─────────────────────────────── -
src/services/ActivityPubService.js
r0b0cd54 r86e6a45 3344 3344 } 3345 3345 const gateReq = Guardianship.gatereq.parseRequest(object); 3346 const r = await deliverDirectNote(site, { recipients, text: plain, language: object.language || null, inReplyTo: typeof object.inReplyTo === 'string' ? object.inReplyTo : null, attachments: atts, helpRequest: help, awayUntil, gateRequest: gateReq && gateReq.feature }); 3346 // Een hulpvraag oppikken of afsluiten vanuit de app (5.2.1, shaer-lgo). 3347 // De markering IS al een gewone directe note met een shaer:-eigenschap, 3348 // dus hier hoeft niets nieuws bij: de app stuurt precies wat de PWA 3349 // stuurt, en het gaat over dezelfde bezorging naar de mede-guardians. 3350 // 3351 // We boeken hem ook LOKAAL. Zonder dat zou de guardian die de knop 3352 // indrukt zijn eigen markering pas zien als hij bij zichzelf 3353 // terugkomt -- en die weg bestaat niet. 3354 const mark = Guardianship.help.parseMarker(object); 3355 if (mark) { 3356 const base2 = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, ''); 3357 Guardianship.help.record(mark.noteUri, actorId(base2, site.slug), mark.kind, `@${site.slug}`); 3358 } 3359 const r = await deliverDirectNote(site, { recipients, text: plain, language: object.language || null, inReplyTo: typeof object.inReplyTo === 'string' ? object.inReplyTo : null, attachments: atts, helpRequest: help, awayUntil, gateRequest: gateReq && gateReq.feature, helpMark: mark }); 3347 3360 if (!r || !r.id) return { status: 502, error: 'direct_failed' }; 3348 3361 return { status: 201, id: r.id, url: `${base}/ap/notes/${r.id}` }; -
src/services/guardianship/index.js
r0b0cd54 r86e6a45 19 19 export { wireDelivery, c2sVisibility, deliverDirectNote } from './delivery.js'; 20 20 export { wireHandshake, handleOutbox as handleGuardianshipOutbox, handleInbox as handleGuardianshipInbox, parseRelationship, parseUndoRelationship, endGuardianship } from './handshake.js'; 21 export { offersCollection, followsCollection, outgoingFollowsCollection, wardsCollection, guardiansCollection } from './queues.js';21 export { offersCollection, followsCollection, outgoingFollowsCollection, wardsCollection, guardiansCollection, helpCollection } from './queues.js'; 22 22 export * as availability from './availability.js'; 23 23 export { wireAvailability } from './availability.js'; -
src/services/guardianship/queues.js
r0b0cd54 r86e6a45 16 16 import * as gated from './gated.js'; 17 17 import * as gatereq from './gatereq.js'; 18 import * as help from './help.js'; 19 import db from '../../config/database.js'; 18 20 import * as handshake from './handshake.js'; 19 21 … … 116 118 } 117 119 118 export default { offersCollection, followsCollection, outgoingFollowsCollection, wardsCollection, guardiansCollection, wardGates, wardGuardianStatuses };120 export default { offersCollection, followsCollection, outgoingFollowsCollection, wardsCollection, guardiansCollection, helpCollection, helpItemsFor, wardGates, wardGuardianStatuses }; 119 121 120 122 // ── Wat er voor een ward gated is (shaer-ahy.1) ───────────────────────── … … 179 181 }); 180 182 } 183 184 185 // ── Hulpvragen met hun staat (shaer-lgo, shaer-ahy.1) ─────────────────── 186 // 187 // De PWA had dit al; de apps kregen alleen de losse notes uit de feed en wisten 188 // dus NIET of er al iemand op af was. Daarom bleef een afgehandeld verzoek daar 189 // gewoon staan -- Barts melding. De staat wordt hier een keer berekend, zoals bij 190 // wardGates: twee berekeningen zouden twee guardians een ander beeld geven van 191 // hetzelfde kind. 192 193 /** De hulpvragen van deze guardian, met wie erop af is en of het dicht is. */ 194 export function helpItemsFor(slug, limit = 50) { 195 let rijen = []; 196 try { 197 rijen = db.prepare( 198 `SELECT object_uri, actor_uri, actor_name, actor_handle, actor_icon, content, published, created_at 199 FROM ap_mentions WHERE slug = ? AND help_request = 1 ORDER BY created_at DESC LIMIT ?`, 200 ).all(slug, limit); 201 } catch { return []; } 202 const staat = help.statusFor(rijen.map((r) => r.object_uri)); 203 const mijn = new Set(relations.listWards(slug).map((w) => w.other_uri)); 204 return rijen.map((r) => ({ 205 ...r, 206 // Bij twijfel OPEN. Een hulpvraag die er afgehandeld uitziet terwijl hij dat 207 // niet is, is de gevaarlijke fout -- niet andersom. 208 state: help.withWardship( 209 staat.get(r.object_uri) || { open: true, pickedUpBy: [], handled: null, ageMs: null }, 210 mijn.has(r.actor_uri), 211 ), 212 })); 213 } 214 215 /** Dezelfde vragen als collectie voor de apps (5.2.1). */ 216 export function helpCollection(id, slug) { 217 const items = helpItemsFor(slug).map((h) => ({ 218 id: h.object_uri, 219 type: 'Note', 220 attributedTo: h.actor_uri, 221 'shaer:handle': h.actor_handle || undefined, 222 content: h.content || '', 223 published: h.published || h.created_at, 224 'shaer:helpRequest': true, 225 // De staat als platte velden: een app hoeft hem niet af te leiden, en kan 226 // hem dus ook niet anders afleiden dan het paneel. 227 'shaer:open': h.state.open, 228 'shaer:handledBy': h.state.handled ? (h.state.handled.handle || h.state.handled.uri) : undefined, 229 'shaer:handledAt': h.state.handled ? h.state.handled.at : undefined, 230 'shaer:pickedUpBy': h.state.pickedUpBy.map((p) => p.handle || p.uri), 231 'shaer:formerWard': h.state.formerWard || undefined, 232 })); 233 return collection(id, items); 234 } -
src/services/guardianship/relations.js
r0b0cd54 r86e6a45 80 80 wards: `${id}/queues/wards`, 81 81 guardians: `${id}/queues/guardians`, 82 help: `${id}/queues/help`, 82 83 }, 83 84 }; -
test/activitypub-as2.test.js
r0b0cd54 r86e6a45 40 40 // `outgoingFollows` is §5.3 turned around: the ward's own follow requests, 41 41 // waiting for the guardians (shaer-p729). 42 'shaer:queues', 'offers', 'follows', 'outgoingFollows', 'wards', 'guardians', 42 // `help` is de vragenlijst met haar STAAT (5.2.1): de apps lazen hulpvragen uit 43 // de feed en wisten niet of er al iemand op af was. 44 'shaer:queues', 'offers', 'follows', 'outgoingFollows', 'wards', 'guardians', 'help', 43 45 // ActivityPub §4.1 `endpoints` vocabulary (same category as sharedInbox), used for C2S. 44 46 'oauthAuthorizationEndpoint', 'oauthTokenEndpoint', 'uploadMedia',
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)