Index: src/config/database.js
===================================================================
--- src/config/database.js	(revision e62eee4b3ba1595f02ee56042ffbb72b7e0fb115)
+++ src/config/database.js	(revision 709dc6fc92eb30af5384833e3f355b2d62423768)
@@ -177,4 +177,10 @@
   ensureColumn('sites', 'gate_custom_emoji', 'INTEGER');  // FEP-9098 emoji-plaatjes (shaer-ytw)
   ensureColumn('sites', 'gate_account_move', 'INTEGER');  // FEP-7628 Move (shaer-tge)
+  // Wie de ward ZELF mag volgen (shaer-p729): de tegenhanger van shaer:follows,
+  // dat over de andere richting gaat. §5.3 schrijft alleen het doorsturen voor
+  // van een Follow NAAR een ward; wat je verder gated is een keuze van de
+  // implementatie, en dit is die keuze. Verstelbaar, anders dan de inkomende
+  // kant: een kind dat ouder wordt hoort niet eeuwig te blijven vragen.
+  ensureColumn('sites', 'gate_following', 'INTEGER');     // zelf iemand volgen (shaer-p729)
   // The heavier sibling (FEP-633c 5.6): may a player from outside this app run
   // INSIDE it? A preview is a picture; playback hands the screen to a third
Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision e62eee4b3ba1595f02ee56042ffbb72b7e0fb115)
+++ src/services/ActivityPubService.js	(revision 709dc6fc92eb30af5384833e3f355b2d62423768)
@@ -5476,4 +5476,12 @@
   const guardians = Guardianship.listGuardians(slug).map((g) => g.other_uri);
   if (!guardians.length) return null;                                   // not a ward: nothing to gate
+  // shaer:following (shaer-p729) — its own gate, apart from shaer:follows,
+  // which governs the OTHER direction. §5.3 fixes the inbound one on: a Follow
+  // aimed at a ward MUST pass the guardians. About this direction the FEP says
+  // nothing, so it is ours to set and ours to let go of, and the guardians can
+  // relax it for a child who has grown into it. Undecided means gated for a
+  // ward, the same automatiek as the rest of the family.
+  const gateRow = db.prepare('SELECT gate_following FROM sites WHERE slug = ?').get(slug);
+  if (Guardianship.wardGateAllowed(gateRow && gateRow.gate_following, true)) return null;
   if (guardians.includes(targetUri)) return null;                       // your own guardian
   if (Guardianship.outgoing.isMutual(slug, targetUri)) return null;     // already vetted by name
Index: src/services/guardianship/gated.js
===================================================================
--- src/services/guardianship/gated.js	(revision e62eee4b3ba1595f02ee56042ffbb72b7e0fb115)
+++ src/services/guardianship/gated.js	(revision 709dc6fc92eb30af5384833e3f355b2d62423768)
@@ -68,4 +68,5 @@
   'shaer:customEmoji': 'gate_custom_emoji',
   'shaer:accountMove': 'gate_account_move',
+  'shaer:following': 'gate_following',
 };
 /**
@@ -112,7 +113,20 @@
   { feature: 'shaer:customEmoji', kind: 'setting', reversible: true, bead: 'shaer-ytw' },
   { feature: 'shaer:accountMove', kind: 'setting', reversible: true, bead: 'shaer-tge' },
-  // Altijd aan voor een ward (5.3): niet te verzetten, wel te tonen. Een paneel
-  // dat alleen verstelbare dingen laat zien verzwijgt de helft van wat er geldt.
+  // Wie de ward mag VOLGEN, en wie de ward mag volgen: twee poorten, want twee
+  // vragen. Ze stonden hier als één rij, en dan telt het paneel de ene richting
+  // en zwijgt over de andere -- een guardian ziet "follows: 3 wachtend" en weet
+  // niet of er drie vreemden bij zijn kind willen of dat zijn kind drie keer
+  // heeft gevraagd of het iemand mag volgen. Dat zijn niet dezelfde zorg.
+  //
+  // Inkomend is vast: §5.3 EIST dat een Follow naar een ward langs de guardians
+  // gaat, dus die staat aan en blijft aanstaan. Tonen mag, verzetten niet.
   { feature: 'shaer:follows', kind: 'perRequest', reversible: true, fixed: true },
+  // Uitgaand is verstelbaar, en dat verschil is opzet. De FEP zegt over deze
+  // richting niets: §5.3 gaat alleen over een Follow die op een ward AF komt.
+  // Wat je verder gated is expliciet aan de implementatie gelaten, dus dit is
+  // onze keuze en niet die van de spec -- en dan hoort hij ook echt te kunnen
+  // worden losgelaten, want een kind dat ouder wordt hoort niet eeuwig te
+  // blijven vragen wie het mag volgen (shaer-p729, shaer-yeo5).
+  { feature: 'shaer:following', kind: 'perRequest', reversible: true, bead: 'shaer-p729' },
 
   // GEPLAND, en dat is bij deze twee geen achterstand maar een besluit.
Index: src/services/guardianship/queues.js
===================================================================
--- src/services/guardianship/queues.js	(revision e62eee4b3ba1595f02ee56042ffbb72b7e0fb115)
+++ src/services/guardianship/queues.js	(revision 709dc6fc92eb30af5384833e3f355b2d62423768)
@@ -158,5 +158,10 @@
 export function wardGates(mySlug, wardUri) {
   const statuses = wardGuardianStatuses(wardUri);
-  const wachtend = follows.listReviewsByDirection(mySlug, 'incoming')
+  // Per richting geteld, want het zijn twee zorgen. "follows: 3 wachtend" liet
+  // een guardian niet zien of er drie vreemden bij zijn kind willen of dat zijn
+  // kind drie keer heeft gevraagd of het iemand mag volgen (shaer-p729).
+  const wachtendIn = follows.listReviewsByDirection(mySlug, 'incoming')
+    .filter((r) => r.ward_uri === wardUri).length;
+  const wachtendUit = follows.listReviewsByDirection(mySlug, 'outgoing')
     .filter((r) => r.ward_uri === wardUri).length;
   return gated.gateRows({
@@ -172,5 +177,8 @@
       feature: p.feature, value: !!p.value, status: gated.sentStatus(p, Date.now()),
     })),
-    waiting: { 'shaer:follows': wachtend || undefined },
+    waiting: {
+      'shaer:follows': wachtendIn || undefined,
+      'shaer:following': wachtendUit || undefined,
+    },
     // De vraag van het kind zelf staat APART van wat er in een wachtrij staat
     // (shaer-8ru). Allebei "n waiting" noemen maakt van twee verschillende
