Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision e62eee4b3ba1595f02ee56042ffbb72b7e0fb115)
+++ src/services/ActivityPubService.js	(revision 89d3c06476e361dffafed7c6889ced7f38eebf52)
@@ -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
