Index: src/config/database.js
===================================================================
--- src/config/database.js	(revision ef1853cad6f220d1c174ec46d96a43d9e5596693)
+++ src/config/database.js	(revision fc404105536bc9fcadc1fdb7dceb0449fee77e98)
@@ -132,5 +132,10 @@
   ensureColumn('sites', 'show_search',     'INTEGER DEFAULT 1');
   ensureColumn('sites', 'show_archive_link', 'INTEGER DEFAULT 1');
-  ensureColumn('sites', 'og_theme', 'TEXT');               // OG share-card variant: NULL=auto (follow site theme) | 'light' | 'dark'
+  // Gated feature (FEP-633c): may external (non-fediverse) embeds be shown to
+  // this account? NULL = auto, which means OFF for a ward and ON for anyone
+  // else. The guardians flip it; the gate itself lives server-side, so a ward
+  // never even receives the thumbnail it is not allowed to see.
+  ensureColumn('sites', 'external_embeds', 'INTEGER');
+  ensureColumn('sites', 'og_theme', 'TEXT');             // OG share-card variant: NULL=auto (follow site theme) | 'light' | 'dark'
 
   // Per-post noindex + type
@@ -550,4 +555,5 @@
   ensureColumn('ap_timeline', 'link_json', 'TEXT');          // FEP-e232 object-link (quote/ref) tags from the inbound note, served back as `tag`
   ensureColumn('ap_timeline', 'quote_json', 'TEXT');         // FEP-044f resolved quoted-post snapshot (author + content), for the embedded quote card
+  ensureColumn('ap_timeline', 'embed_json', 'TEXT');         // resolved EXTERNAL embed (oEmbed/provider), thumbnail-only; gated per site (sites.external_embeds)
   ensureColumn('ap_timeline', 'author_emoji_json', 'TEXT');  // FEP-9098 custom emojis in the author's display name (shaer:author.emojis)
   ensureColumn('ap_timeline', 'reblog_emoji_json', 'TEXT');  // FEP-9098 custom emojis in the booster's display name (shaer:booster.emojis)
