Ignore:
Timestamp:
07/29/2026 07:15:16 AM (6 weeks ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
e27b8db
Parents:
439f095
Message:

Een gated voorstel bereikte de andere guardians nooit

Op de vloot nagekeken waarom YouTube-voorbeelden bij beta uit blijven: het
voorstel van sound-fabrics staat er, met een ja van een van de drie guardians,
en het is stil verlopen. Niet omdat iemand bezwaar had, maar omdat niemand
anders het ooit gezien heeft.

Het voorstel wordt geadresseerd aan de server van het kind, want die telt en
handhaaft (5.6). Maar daarmee bereikt het alleen de voorsteller en het kind. De
twee guardians op andere servers weten van niets, kunnen dus niet antwoorden, en
een drempel van twee is onhaalbaar. Elk voorstel verloopt na een dag.

De ontbrekende schakel is het doorsturen, precies wat 5.3 al doet voor een
gated follow: de server van het kind kent de gezaghebbende guardian-lijst, dus
die stuurt het voorstel door. Elke guardian bewaart een kopie die hij kan
beantwoorden, en het antwoord reist terug naar het kind, dat telt.

Changed files:
src/config/database.js

  • tabel ap_gated_reviews, de guardian-kopie (zelfde vorm als ap_follow_reviews)

src/services/guardianship/gated.js

  • de kopie-opslag: bewaren, lezen, beantwoorden, opruimen

src/services/guardianship/handshake.js

  • ward-kant: doorsturen naar de andere guardians zodra het voorstel openstaat
  • guardian-kant: de doorgestuurde kopie bewaren om te kunnen antwoorden

src/routes/guardian.js

  • gatedReviews in de dashboardstaat; POST /guardian/api/gated/:id stuurt het antwoord naar de inbox van het kind

src/assets/js/guardian.js, src/assets/css/guardian.css

src/services/i18n.js

  • de teksten in nl, en, de

test/gated-settings.test.js

  • de hele keten: voorstellen, doorsturen naar allebei de anderen, de kopie opslaan, antwoorden, en pas bij twee van drie gaat de gate open

remarks: dit forceert niets; het maakt alleen mogelijk wat de spec al bedoelde.
Twee van de drie guardians moeten nog steeds akkoord gaan, en het venster is
24 uur.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/guardianship/gated.js

    r439f095 r88d7c8f  
    145145}
    146146
     147// ── The guardian-side copy (the missing leg of §5.6) ──────────────
     148// A proposal addressed to the ward's server reaches only the proposer and the
     149// ward. The other guardians never learn it exists, so a threshold of two can
     150// never be met and every proposal expires unanswered. The ward's server
     151// therefore FORWARDS it, exactly as it forwards a gated follow (§5.3): each
     152// guardian stores a copy it can answer, and the answer travels back to the
     153// ward, which tallies.
     154
     155let _rs = null;
     156function rstmts() {
     157  if (!_rs) {
     158    _rs = {
     159      ins: db.prepare(`INSERT INTO ap_gated_reviews (id, guardian_slug, ward_uri, ward_inbox, proposer, feature, value)
     160                       VALUES (?,?,?,?,?,?,?)
     161                       ON CONFLICT(guardian_slug, id) DO UPDATE SET value = excluded.value, ward_inbox = excluded.ward_inbox`),
     162      get: db.prepare('SELECT * FROM ap_gated_reviews WHERE guardian_slug = ? AND id = ?'),
     163      bySlug: db.prepare('SELECT * FROM ap_gated_reviews WHERE guardian_slug = ? ORDER BY created_at DESC'),
     164      del: db.prepare('DELETE FROM ap_gated_reviews WHERE guardian_slug = ? AND id = ?'),
     165      delAll: db.prepare('DELETE FROM ap_gated_reviews WHERE id = ?'),
     166    };
     167  }
     168  return _rs;
     169}
     170
     171export function recordGatedReview(guardianSlug, r) {
     172  rstmts().ins.run(r.id, guardianSlug, r.wardUri, r.wardInbox || null, r.proposer || null, r.feature, r.value ? 1 : 0);
     173  return rstmts().get.get(guardianSlug, r.id);
     174}
     175export function getGatedReview(guardianSlug, id) { return rstmts().get.get(guardianSlug, id); }
     176export function listGatedReviews(guardianSlug) { return rstmts().bySlug.all(guardianSlug); }
     177export function removeGatedReview(guardianSlug, id) { rstmts().del.run(guardianSlug, id); }
     178/** Drop every guardian's copy once the decision has settled or lapsed. */
     179export function clearGatedReviews(id) { rstmts().delAll.run(id); }
     180
    147181export function rememberGatedOffer(offerId, slug, feature, value) {
    148182  try {
     
    160194  tallyGatedSetting, thresholdFor, featureColumn, recordGatedVote, gatedProgress, GATED_WINDOW_MS,
    161195  parseGatedSetting, buildGatedOffer, rememberGatedOffer, recallGatedOffer,
     196  recordGatedReview, getGatedReview, listGatedReviews, removeGatedReview, clearGatedReviews,
    162197};
Note: See TracChangeset for help on using the changeset viewer.