Changeset df70d8e in Klonkt for tools


Ignore:
Timestamp:
08/08/2026 09:47:27 PM (4 weeks ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
1d76e0e
Parents:
f3c7a05
git-author:
Robin <roboburr@…> (08/08/2026 09:47:26 PM)
git-committer:
roboburr <roboburr@…> (08/08/2026 09:47:27 PM)
Message:

Het Offer IS de toestemming van de kandidaat (shaer-6wt)

Uitgezocht, en de fout was van mij. Ik gaf gisteren een "lead" af naar
handshake.js regel 600 -- de inkomende accept-tak die geen fanout doet. Die lead
was onjuist en ik trek hem terug.

Klonkt zegt het met zoveel woorden, en die regel had ik moeten lezen voordat ik
naar zijn code wees:

"The Offer carries the candidate's agreement -- a free ward then commits on

its own accept."

De afsluitende Accept van de kandidaat waar mijn daemon op wachtte, komt bij een
VRIJE ward nooit, en dat hoort ook niet. Dev deed precies wat het moest doen; de
daemon bleef wachten op iets dat het protocol niet stuurt. Dat verklaart ook @mee
meteen: haar Klonkt implementeert dit goed en committeerde op haar eigen ja.

De daemon telt nu echt. Partijen zijn de kandidaat, de ward zelf en de bestaande
guardians uit to; de kandidaat staat er meteen als ja in. Committen als
IEDEREEN ja heeft gezegd -- niet "commit bij mijn eigen ja", want dat werkt voor
de eerste guardian en is stilletjes fout voor de tweede. Wat nog ontbreekt wordt
gelogd, zodat een half afgemaakte handshake zichtbaar is in plaats van stil.

En de telling in offer-many: 202 is hier de NORMALE uitkomst, geen mislukking.
Het scherm zei "verstuurd 0" terwijl alles goed ging, en een verzonnen
mislukking is net zo verwarrend als een verzwegen fout.

RESULTAAT: 100 wards, beide kanten eens, over http met HTTP-signatures en zonder
TLS. Eerste meting van de caseload: 1414 poortrijen in 26 ms, maar de wards-queue
die de apps elke verversing ophalen is 222 KB.

Location:
tools/ward-farm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • tools/ward-farm/farm.mjs

    rf3c7a05 rdf70d8e  
    123123// juist dit het moment waarop iemand moet nadenken; dat staat er hier expliciet
    124124// bij zodat deze code nooit ergens anders terechtkomt.
     125//
     126// HET OFFER IS AL DE TOESTEMMING VAN DE KANDIDAAT, en daar zat mijn fout. Ik
     127// wachtte op een afsluitende Accept van de kandidaat, en die komt bij een VRIJE
     128// ward nooit -- terecht. Klonkt zegt het met zoveel woorden in handshake.js:
     129// "The Offer carries the candidate's agreement -- a free ward then commits on
     130// its own accept." Dev deed dus precies wat het hoorde te doen; mijn daemon
     131// bleef wachten op iets dat het protocol niet stuurt.
     132//
     133// De afsluitende Accept van de kandidaat bestaat WEL, maar in het meerpartijen-
     134// geval: heeft het kind al guardians, dan moeten die eerst ja zeggen en sluit de
     135// kandidaat af. Vandaar de telling hieronder in plaats van "commit bij mijn
     136// eigen ja" -- dat laatste zou werken voor de eerste guardian en stilletjes fout
     137// zijn voor de tweede.
    125138
    126139/**
     
    139152}
    140153
     154/**
     155 * Een ja bijschrijven, en committen zodra iedereen ja heeft gezegd.
     156 *
     157 * Dezelfde regel als readyToCommit in Klonkt: de ward, de kandidaat, en -- als
     158 * het kind er al had -- minstens een van de bestaande guardians.
     159 */
     160function telAccept(w, offerId, wie) {
     161  const off = w.offers[offerId];
     162  if (!off || off.commit) return 'onbekend offer';
     163  if (wie && !off.accepts.includes(wie)) off.accepts.push(wie);
     164  const iedereen = off.partijen.every((p) => off.accepts.includes(p));
     165  if (!iedereen) { noteer(w, { wacht_op: off.partijen.filter((p) => !off.accepts.includes(p)) }); return 'nog niet compleet'; }
     166  off.commit = new Date().toISOString();
     167  if (!w.guardians.includes(off.kandidaat)) w.guardians.push(off.kandidaat);
     168  noteer(w, { commit: off.kandidaat });
     169  return 'guardian erbij';
     170}
     171
    141172async function verwerkInbox(w, activity) {
    142173  const type = Array.isArray(activity.type) ? activity.type[0] : activity.type;
     
    151182    if (subject !== uriVan(w.naam)) return 'niet voor mij';
    152183    const kandidaat = typeof o.object === 'string' ? o.object : (o.object && o.object.id);
    153     w.offers[activity.id] = { kandidaat, at: Date.now() };
     184    // De partijen: de kandidaat, ikzelf, en mijn bestaande guardians (die staan
     185    // in `to`). De kandidaat telt meteen als ja -- zijn Offer IS zijn instemming.
     186    const partijen = [...new Set([
     187      kandidaat,
     188      uriVan(w.naam),
     189      ...(Array.isArray(activity.to) ? activity.to : []),
     190    ])].filter(Boolean);
     191    w.offers[activity.id] = { kandidaat, at: Date.now(), partijen, accepts: [kandidaat] };
    154192    bewaarStaat(staat);
    155193    // Accepteren, gericht aan iedereen die in `to` stond plus de kandidaat, zodat
     
    174212      } catch (e) { noteer(w, { fout: String(e.message), naar: doel }); }
    175213    }
    176     bewaarStaat(staat);
     214    telAccept(w, activity.id, uriVan(w.naam));
    177215    return 'geaccepteerd';
    178216  }
    179217
    180218  if (type === 'Accept') {
    181     // De laatste Accept van de kandidaat is de commit (3.1.3). Wij houden hem
    182     // gewoon bij: wie ons bewaakt is het enige dat wij hoeven te weten.
    183     const binnenste = o && o.object;
    184     const rel = binnenste && (Array.isArray(binnenste.type) ? binnenste.type[0] : binnenste.type) === 'Relationship'
    185       ? binnenste : (relType === 'Relationship' ? o : null);
    186     const kandidaat = rel && (typeof rel.object === 'string' ? rel.object : (rel.object && rel.object.id));
    187     const wie = kandidaat || actor;
    188     if (wie && !w.guardians.includes(wie)) {
    189       w.guardians.push(wie);
    190       bewaarStaat(staat);
    191       return 'guardian erbij';
    192     }
    193     return 'al bekend';
     219    // Een ja van een mede-partij (een bestaande guardian, of de kandidaat die in
     220    // het meerpartijengeval afsluit). `object` is de offer-id.
     221    const offerId = typeof o === 'string' ? o : (o && o.id);
     222    if (!offerId || !w.offers[offerId]) return 'onbekend offer';
     223    return telAccept(w, offerId, actor);
    194224  }
    195225
  • tools/ward-farm/offer-many.mjs

    rf3c7a05 rdf70d8e  
    6969  try {
    7070    const uit = await AP.ingestOutboxActivity(site, { id: site.owner_id, username: slug }, activity);
    71     if (uit && (uit.status === 201 || uit.status === 200)) gestuurd++;
     71    // 202 is hier de NORMALE uitkomst: de handshake is aangenomen en loopt, de
     72    // commit valt pas als de ward antwoordt. Ik telde hem als mislukt, en de
     73    // eindregel zei daardoor "verstuurd 0" terwijl alles goed ging -- een
     74    // verzonnen mislukking is net zo verwarrend als een verzwegen fout.
     75    if (uit && uit.status >= 200 && uit.status < 300) gestuurd++;
    7276    else { mislukt++; console.warn(`  ${naam}: ${uit && uit.status} ${uit && uit.error}`); }
    7377  } catch (e) {
Note: See TracChangeset for help on using the changeset viewer.