Ignore:
Timestamp:
08/08/2026 04:18:37 PM (4 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
abcf51a
Parents:
66d97b8
Message:

guardianship: §1 is flat in beide richtingen, ook bij accept

Het Offer-pad belet een ward om te offeren (a_ward_cannot_guard), maar het
Accept-pad kende geen spiegelbeeld: een actor die al wards heeft kon een
guardianship-Offer accepteren en werd zo ward én guardian tegelijk. §1 eist
flatheid in beide richtingen.

De fout zou zich bovendien niet melden. actorProps() kiest met een if/else
één rol en publiceert dan shaer:guardians terwijl shaer:isGuardian wegvalt:
lokaal blijven escalaties van de eigen wards binnenkomen, terwijl elke
remote §4-check de actor als malformed leest en laat vallen. Een ward die
denkt bewaakt te zijn en het niet is, stil aan beide kanten.

Alleen de accept van de ward kan die toestand maken, dus de kandidaat en de
bestaande guardians lopen er ongemoeid langs.

721 tests groen. Controleproef gedraaid: zonder de controle wordt de nieuwe
test rood en valt ook 'a guardian leaving sends an Undo (§3.2)' om, doordat
de actor dan werkelijk ward wordt.

Refs shaer-gk2; stable (1.6.0) heeft dezelfde omissie, zie shaer-pmo.

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

File:
1 edited

Legend:

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

    r66d97b8 r0261730  
    341341    notify(site.slug, { kind: 'offer_rejected', offer: offerId });
    342342    return { status: 202, id: offerId, url: offerId };
     343  }
     344
     345  // §1 is flat in BOTH directions. The Offer path above bars a ward from
     346  // offering to guard; this is the mirror: an actor that already guards wards
     347  // must not become a ward itself. Only the ward's own accept can create that
     348  // state, so the candidate and the existing guardians pass through untouched.
     349  //
     350  // Without it the inconsistency would also be invisible. actorProps() picks
     351  // one role with an if/else and would publish shaer:guardians while dropping
     352  // shaer:isGuardian, so this account keeps routing its wards' escalations
     353  // locally while every remote §4 check reads it as malformed and drops it —
     354  // a ward believing it is watched over when it is not, silent on both sides.
     355  if (me === offer.ward_uri && relations.listWards(site.slug).length) {
     356    return { status: 403, error: 'a_guardian_cannot_be_guarded' };
    343357  }
    344358
Note: See TracChangeset for help on using the changeset viewer.