Index: src/routes/activitypub.js
===================================================================
--- src/routes/activitypub.js	(revision fa24f7b3d10d789b3f1b8b9e1a06aff5d64d5817)
+++ src/routes/activitypub.js	(revision 8a474ab1b2ce34c493e6e674100b989019d38cfe)
@@ -365,5 +365,5 @@
   const authorInfo = (r, prefix) => authorInfoFrom(r, prefix, p);
   const {
-    embedsAllowed, playbackAllowed, imagesAllowed, musicAllowed, quotesAllowed, emojiAllowed,
+    embedsAllowed, playbackAllowed, imagesAllowed, musicAllowed, videoAllowed, quotesAllowed, emojiAllowed,
   } = p;
   const reacties = reactions || new Map();
@@ -392,5 +392,5 @@
       // Friends' media travels along (media_json → AS2 attachment), so the
       // client renders their images/audio like own outbox posts.
-      attachment: AP.gateAttachments(AP.timelineAttachments(t.media_json), { images: imagesAllowed, audio: musicAllowed }),
+      attachment: AP.gateAttachments(AP.timelineAttachments(t.media_json), { images: imagesAllowed, audio: musicAllowed, video: videoAllowed }),
       // The note's preserved tags, so the client can render them: FEP-9098
       // Emoji tags (:shortcode: → image) and FEP-e232 Link tags (quotes /
@@ -467,4 +467,5 @@
       'shaer:images': p.imagesAllowed,
       'shaer:music': p.musicAllowed,
+      'shaer:video': p.videoAllowed,
       'shaer:quoteCards': p.quotesAllowed,
       'shaer:customEmoji': p.emojiAllowed,
@@ -495,4 +496,5 @@
     imagesAllowed: gate('gate_images'),
     musicAllowed: gate('gate_music'),
+    videoAllowed: gate('gate_video'),
     quotesAllowed: gate('gate_quote_cards'),
     emojiAllowed: emoji,
@@ -557,5 +559,5 @@
       // mention row keeps the resolved quote, not the raw tags.
       tag: [{ type: 'Mention', href: me, name: myHandle }, ...(p.emojiAllowed ? (AP.timelineEmojis(m.emoji_json) || []) : [])],
-      attachment: AP.gateAttachments(AP.timelineAttachments(m.media_json), { images: p.imagesAllowed, audio: p.musicAllowed }),
+      attachment: AP.gateAttachments(AP.timelineAttachments(m.media_json), { images: p.imagesAllowed, audio: p.musicAllowed, video: p.videoAllowed }),
       // FEP-633c: what kind of message this is. The wave is a gentle nudge from
       // a guardian; the help request is the buoy. Both render differently.
@@ -829,5 +831,5 @@
   const P = gatesFor(auth.site);
   const {
-    embedsAllowed, playbackAllowed, imagesAllowed, musicAllowed, quotesAllowed,
+    embedsAllowed, playbackAllowed, imagesAllowed, musicAllowed, videoAllowed, quotesAllowed,
     emojiAllowed, messagesAllowed, composeAllowed, repliesAllowed, threadsAllowed,
     followingAllowed, gateAuthor,
@@ -1423,7 +1425,8 @@
   const kring = threadsOpen ? { notes: uit.notes, hidden: 0 } : AP.filterThreadToCircle(auth.site.slug, uit.notes);
   const imagesOk = gate2('gate_images'), musicOk = gate2('gate_music'), emojiOk = gate2('gate_custom_emoji');
+  const videoOk = gate2('gate_video');
   uit.notes = kring.notes.map((n) => ({
     ...n,
-    attachment: AP.gateAttachments(n.attachment, { images: imagesOk, audio: musicOk }),
+    attachment: AP.gateAttachments(n.attachment, { images: imagesOk, audio: musicOk, video: videoOk }),
     tag: emojiOk ? n.tag : AP.stripEmojiTags(n.tag),
     // De emoji-poort knipt in de byline zelf: FEP-9098 zit in de tag van de
