Ignore:
Timestamp:
07/29/2026 10:29:55 AM (6 weeks ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
6d5ce0c
Parents:
329873e
Message:

Het doorgestuurde voorstel werd geweigerd: verkeerde afzender

Robin meldde dat stap 2 niet gebeurt, en beta's log zegt waarom:

[AP] guardianship Offer got 401 from https://boiert.eu/ap/users/opie/inbox
[AP] guardianship Offer got 401 from https://boiert.eu/ap/users/boiert/inbox

Het doorsturen werkt dus wel, maar de ontvangers weigeren het, en terecht. Ik
stuurde door met de voorsteller in actor terwijl de sleutel van het kind
ondertekent. Het lichaam beweerde de ene afzender, de handtekening bewees de
andere: signer mismatch, 401, precies wat die controle hoort te doen.

5.3 doet het al goed en had het voorbeeld moeten zijn: een gated follow wordt
doorgestuurd ALS HET KIND. Nu deze ook, met de voorsteller in shaer:proposer
zodat het scherm van de guardian nog steeds de juiste naam toont.

En de test die dit had moeten vangen: die controleerde DAT er doorgestuurd
werd, niet namens wie. Hij stond groen terwijl er niets aankwam. Nu controleert
hij de afzender en de proposer, en hij faalt op de oude code.

Changed files:
src/services/guardianship/handshake.js

  • doorsturen met actor = het kind, plus shaer:proposer
  • de ontvanger leest de voorsteller uit shaer:proposer

src/routes/guardian.js

  • hetzelfde op het lokale pad: ondertekenen en beweren moeten kloppen

test/gated-settings.test.js

  • de afzender van het doorgestuurde voorstel is het kind; de proposer reist apart mee en komt op het scherm terecht

remarks: 322 tests groen. De 401's die in de bezorgwachtrij staan dragen nog de
oude vorm en blijven falen tot ze opgeven; een nieuw voorstel is de weg vooruit.

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

File:
1 edited

Legend:

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

    r329873e rc8e03c6  
    317317          for (const g of relations.listGuardians(site.slug).map((x) => x.other_uri)) {
    318318            if (g === actor) continue;   // the proposer already answered
     319            // The forward goes out AS THE WARD, because the ward's key signs
     320            // it. Keeping the proposer in `actor` made every receiver answer
     321            // 401 signer mismatch, and rightly so: the body claimed one author
     322            // and the signature proved another. §5.3 forwards a gated follow
     323            // the same way. Who proposed it rides along separately, for the
     324            // guardian's screen.
    319325            deps.deliverTo(site, g, {
    320               id: offerId, type: 'Offer', actor, to: [g], object: activity.object,
     326              id: offerId, type: 'Offer', actor: me, to: [g], object: activity.object,
     327              'shaer:proposer': actor,
    321328            }).catch(() => { /* the delivery queue retries */ });
    322329          }
     
    333340        gated.recordGatedReview(site.slug, {
    334341          id: offerId, wardUri: gs.ward, wardInbox: wardDoc && wardDoc.inbox,
    335           proposer: actor, feature: gs.feature, value: gs.value,
     342          // A forward is signed by the ward, so `actor` is the ward; the
     343          // guardian who opened it travels in shaer:proposer.
     344          proposer: (typeof activity['shaer:proposer'] === 'string' ? activity['shaer:proposer'] : actor),
     345          feature: gs.feature, value: gs.value,
    336346        });
    337347        notify(site.slug, { kind: 'gated_review', feature: gs.feature, value: gs.value, ward: gs.ward });
Note: See TracChangeset for help on using the changeset viewer.