Changeset 7e53594 in Klonkt
- Timestamp:
- 08/10/2026 03:53:26 AM (4 weeks ago)
- Branches:
- main
- Children:
- 0db3c72
- Parents:
- f06ed56
- Files:
-
- 6 edited
-
src/routes/activitypub.js (modified) (1 diff)
-
src/services/guardianship/index.js (modified) (1 diff)
-
src/services/guardianship/queues.js (modified) (1 diff)
-
src/services/guardianship/relations.js (modified) (1 diff)
-
test/activitypub-as2.test.js (modified) (1 diff)
-
test/guardian-event-log.test.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/activitypub.js
rf06ed56 r7e53594 344 344 // guardians' real states here and nowhere else. 345 345 queueRoute('guardians', (id, slug) => Guardianship.guardiansCollection(id, slug)); 346 347 // ── Het logboek (FEP-633c §4.2, shaer:log) ──────────────────────────── 348 // NAAST de wachtrijen en niet erin: alles onder shaer:queues wacht op een 349 // antwoord, dit is wat er al besloten is. Eigen pad, dezelfde eigenaar-only 350 // bearer. Het bestaat omdat een weigering anders alleen te merken viel doordat 351 // er iets uit een lijst verdween, en "het is weg" is geen reden. 352 router.get('/ap/users/:slug/log', (req, res) => { 353 const auth = OAuth.verifyBearer(req.headers.authorization); 354 if (!auth || auth.site.slug !== req.params.slug) return res.status(403).end(); 355 const me = `${baseUrl(req)}/ap/users/${auth.site.slug}`; 356 AP.sendAP(res, { 357 '@context': AP.AP_CONTEXT, 358 ...Guardianship.logCollection(`${me}/log`, auth.site.slug, (s) => AP.listGuardianEvents(s, 50)), 359 }, 'private, no-store'); 360 }); 346 361 // De hulpvragen MET hun staat (5.2.1, shaer-lgo). De apps lazen ze uit de feed 347 362 // en wisten dus niet of er al iemand op af was -- daarom bleef een afgehandeld -
src/services/guardianship/index.js
rf06ed56 r7e53594 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, helpCollection } from './queues.js';21 export { offersCollection, followsCollection, outgoingFollowsCollection, logCollection, 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
rf06ed56 r7e53594 118 118 } 119 119 120 export default { offersCollection, followsCollection, outgoingFollowsCollection, wardsCollection, guardiansCollection, helpCollection, helpItemsFor, wardGates, wardGuardianStatuses }; 120 /** 121 * Het logboek (§4.2): wat er is besloten, en waarom. 122 * 123 * Geen wachtrij, en daarom een eigen sleutel op de actor. Elk item draagt zijn 124 * soort en, als die er was, de REDEN -- want zonder die reden merkte een ward 125 * een weigering alleen doordat er iets uit een lijst verdween. 126 * 127 * `type` is geen AS2-werkwoord: de meeste soorten zijn er geen. Een lapse-stem 128 * of een opgepakte hulpvraag is geen Accept, en het zo noemen zou netter lezen 129 * dan het is. 130 * 131 * De lezer levert `listEvents` aan; deze module kent ActivityPubService niet en 132 * houdt dat zo (zie de kop van delivery.js). 133 */ 134 export function logCollection(id, slug, listEvents) { 135 const items = (typeof listEvents === 'function' ? listEvents(slug) : []).map((e) => { 136 const { id: n, kind, created, ...rest } = e; 137 const item = { id: `${id}/${n}`, type: 'shaer:Event', 'shaer:kind': kind, published: created }; 138 for (const [k, v] of Object.entries(rest)) { 139 if (v === undefined || v === null) continue; 140 item[k.startsWith('shaer:') ? k : `shaer:${k}`] = v; 141 } 142 return item; 143 }); 144 return collection(id, items); 145 } 146 147 export default { offersCollection, followsCollection, outgoingFollowsCollection, wardsCollection, guardiansCollection, helpCollection, helpItemsFor, wardGates, wardGuardianStatuses, logCollection }; 121 148 122 149 // ── Wat er voor een ward gated is (shaer-ahy.1) ───────────────────────── -
src/services/guardianship/relations.js
rf06ed56 r7e53594 82 82 help: `${id}/queues/help`, 83 83 }, 84 // NAAST de wachtrijen, niet erin. Alles onder shaer:queues wacht op een 85 // antwoord; dit is wat er al besloten is, met de reden erbij (§4.2). 86 // Geschiedenis onderbrengen bij een woord dat "wachtend" betekent maakt van 87 // twee dingen één, en dat is precies de fout die de rest van deze module 88 // net heeft opgeruimd. 89 'shaer:log': `${id}/log`, 84 90 }; 85 91 const guardians = listGuardians(slug).map((r) => r.other_uri); -
test/activitypub-as2.test.js
rf06ed56 r7e53594 45 45 // `help` is de vragenlijst met haar STAAT (5.2.1): de apps lazen hulpvragen uit 46 46 // de feed en wisten niet of er al iemand op af was. 47 'shaer:queues', 'offers', 'follows', 'outgoingFollows', 'wards', 'guardians', 'help', 47 'shaer:queues', 'offers', 'follows', 'outgoingFollows', 'wards', 'guardians', 48 // §4.2: het logboek staat NAAST de wachtrijen, want het wacht nergens op. 49 'shaer:log', 'help', 48 50 // Elke OPEN hulpvraag zit in de collectie; daarom mag een app uit afwezigheid 49 51 // concluderen dat iets niet open is (shaer-6wt). -
test/guardian-event-log.test.js
rf06ed56 r7e53594 76 76 assert.doesNotThrow(() => AP.onGuardianshipEvent(null, { kind: 'setting' })); 77 77 }); 78 79 // ── De collectie die de apps lezen (shaer:log) ──────────────────────────── 80 // Het logboek staat NAAST shaer:queues. Alles daarin wacht op een antwoord; dit 81 // is wat er al besloten is. Een aparte sleutel dus, en een aparte vorm. 82 83 test('de actor wijst het logboek aan, los van de wachtrijen', async () => { 84 const G = await import('../src/services/guardianship/index.js'); 85 const props = G.guardianshipActorProps('https://test.example/ap/users/kid', 'kid'); 86 assert.equal(props['shaer:log'], 'https://test.example/ap/users/kid/log'); 87 assert.equal(props['shaer:queues'].log, undefined, 88 'geen geschiedenis onder een woord dat "wachtend" betekent'); 89 }); 90 91 test('elk item draagt zijn soort en zijn reden mee', async () => { 92 const G = await import('../src/services/guardianship/index.js'); 93 const c = G.logCollection('https://test.example/ap/users/kid/log', 'kid', 94 (s) => AP.listGuardianEvents(s, 50)); 95 assert.equal(c.type, 'OrderedCollection'); 96 const weigering = c.orderedItems.find((i) => i['shaer:kind'] === 'offer_rejected'); 97 assert.ok(weigering, 'de weigering staat erin'); 98 assert.equal(weigering['shaer:reason'], 'not_a_teapot', 99 'MET de reden: daarvoor bestaat dit ding'); 100 assert.equal(weigering['shaer:candidate'], 'https://elders.example/users/tess'); 101 assert.ok(weigering.published, 'en wanneer'); 102 // Geen AS2-werkwoord: een lapse-stem of een opgepakte hulpvraag is geen 103 // Accept, en het zo noemen zou netter lezen dan het is. 104 assert.equal(weigering.type, 'shaer:Event'); 105 }); 106 107 test('een leeg logboek is een lege collectie, geen fout', async () => { 108 const G = await import('../src/services/guardianship/index.js'); 109 const c = G.logCollection('https://test.example/ap/users/niemand/log', 'niemand', 110 (s) => AP.listGuardianEvents(s, 50)); 111 assert.equal(c.totalItems, 0); 112 assert.deepEqual(c.orderedItems, []); 113 });
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)