Changeset d56d471 in Klonkt for src/services/guardianship/handshake.js
- Timestamp:
- 07/29/2026 12:36:50 PM (6 weeks ago)
- Branches:
- main
- Children:
- 7a93fcf
- Parents:
- 6100ce9
- File:
-
- 1 edited
-
src/services/guardianship/handshake.js (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/guardianship/handshake.js
r6100ce9 rd56d471 81 81 } 82 82 return anyDelivered; 83 } 84 85 /** 86 * §5.6, the closing of the loop: a settled gated decision answers the Offer 87 * that opened it. Accept when it settled on the proposed value, Reject when on 88 * the opposite. Without this the proposer's screen can only ever say 89 * "waiting", forever, whatever actually happened: the tally lives on the 90 * ward's server and nobody else may read it, so the ward's server must speak. 91 */ 92 function answerGatedProposer(site, offerId, r) { 93 const o = gated.recallGatedOffer(offerId); 94 if (!o || !o.proposer) return; 95 const me = deps.selfId(site.slug); 96 if (o.proposer === me) return; // the ward proposed to itself: nothing to write home 97 const agreed = r.value === !!o.value; 98 deps.deliverTo(site, o.proposer, { 99 id: `${me}#gatedanswer-${Date.now().toString(36)}${Math.floor(Math.random() * 1e4).toString(36)}`, 100 type: agreed ? 'Accept' : 'Reject', 101 actor: me, to: [o.proposer], object: offerId, 102 }).catch(() => { /* the delivery queue retries */ }); 83 103 } 84 104 … … 301 321 // ── I am the WARD: record, tally, and forward to the other guardians. 302 322 if (gs.ward === me) { 303 gated.rememberGatedOffer(offerId, site.slug, gs.feature, gs.value );323 gated.rememberGatedOffer(offerId, site.slug, gs.feature, gs.value, actor); 304 324 // The proposer's Offer carries its own agreement (§3.1's one-step clause). 305 325 const r = gated.recordGatedVote(site.slug, gs.feature, actor, gs.value); … … 326 346 } else { 327 347 gated.clearGatedReviews(offerId); // settled at once: nothing left to ask 348 answerGatedProposer(site, offerId, r); 328 349 } 329 350 notify(site.slug, { kind: 'gated_setting', feature: gs.feature, value: gs.value, state: r.state }); … … 385 406 // Accept / Reject of an offer we (also) track. 386 407 const offerId = idOf(activity.object); 408 // §5.6, the answer coming HOME: the ward's server settled a decision we 409 // proposed and answers our Offer. Accept = it settled on what we proposed, 410 // Reject = on the opposite. Only the ward may say so: the answer must come 411 // from the ward the proposal was about, or anyone could close our books. 412 const sent = gated.recallSent(offerId); 413 if (sent && sent.guardian_slug === site.slug) { 414 if (actor !== sent.ward_uri) return false; // not the ward's voice: not an outcome 415 const outcome = type === 'Accept' ? 'accepted' : 'rejected'; 416 gated.settleSent(offerId, outcome); 417 notify(site.slug, { kind: 'gated_outcome', feature: sent.feature, value: !!sent.value, outcome, ward: sent.ward_uri }); 418 return true; 419 } 387 420 // §5.6: a fellow guardian answering a gated-setting proposal. The Accept only 388 421 // references the offer, so the value comes from the proposal we stored. A … … 392 425 const value = type === 'Accept' ? !!gsOffer.value : !gsOffer.value; 393 426 const r = gated.recordGatedVote(site.slug, gsOffer.feature, actor, value); 427 if (r.state === 'settled') answerGatedProposer(site, offerId, r); 394 428 notify(site.slug, { kind: 'gated_setting', feature: gsOffer.feature, value, state: r.state }); 395 429 return true;
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)