Ignore:
Timestamp:
08/11/2026 04:24:25 PM (3 months ago)
Author:
Robin <roboburr@…>
Parents:
859b1707
Message:

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

Backport van 0261730 op main. 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 meldt zich niet. 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.

357 tests groen in een echte 1.6-omgeving (eigen npm ci, nodemailer 6.10.1
zoals stable vraagt, niet main's 9.x). 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.

Closes shaer-pmo.

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

File:
1 edited

Legend:

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

    r859b1707 rb60cf25  
    290290    notify(site.slug, { kind: 'offer_rejected', offer: offerId });
    291291    return { status: 202, id: offerId, url: offerId };
     292  }
     293
     294  // §1 is flat in BOTH directions. The Offer path above bars a ward from
     295  // offering to guard; this is the mirror: an actor that already guards wards
     296  // must not become a ward itself. Only the ward's own accept can create that
     297  // state, so the candidate and the existing guardians pass through untouched.
     298  //
     299  // Without it the inconsistency would also be invisible. actorProps() picks
     300  // one role with an if/else and would publish shaer:guardians while dropping
     301  // shaer:isGuardian, so this account keeps routing its wards' escalations
     302  // locally while every remote §4 check reads it as malformed and drops it —
     303  // a ward believing it is watched over when it is not, silent on both sides.
     304  if (me === offer.ward_uri && relations.listWards(site.slug).length) {
     305    return { status: 403, error: 'a_guardian_cannot_be_guarded' };
    292306  }
    293307
Note: See TracChangeset for help on using the changeset viewer.