Index: src/routes/activitypub.js
===================================================================
--- src/routes/activitypub.js	(revision fbfd7a199340cd773cd153df2388d88f2084eea2)
+++ src/routes/activitypub.js	(revision 6c4ff7e385f99367e75efde44e5b671992c43e88)
@@ -1043,4 +1043,19 @@
 });
 
+/**
+ * Mag deze aanvrager alles van `slug` zien? Waar bij de eigenaar zelf, en waar
+ * voor de actor waar `slug` naartoe verhuisd is (FEP-1580, Source Instance).
+ *
+ * Eén plek voor die vraag, want hij komt op meerdere collecties terug en twee
+ * antwoorden op dezelfde vraag lopen vroeg of laat uiteen.
+ */
+async function magAlles(req, slug) {
+  const auth = OAuth.verifyBearer(req.headers.authorization);
+  if (auth && auth.site.slug === slug) return true;
+  if (!req.headers['signature']) return false;
+  const v = await AP.verifyRequest(req).catch(() => null);
+  return !!(v && v.id && AP.isMoveTarget(slug, v.id));
+}
+
 // ── FEP-1580: de vertaaltabel van een verhuizing ──────────────────
 //
@@ -1115,8 +1130,8 @@
 // stap 3). Een playlist is een keuze hieruit; deze collectie is alles wat de
 // artiest heeft opengezet, ook wat in geen enkele playlist staat.
-router.get('/ap/users/:slug/tracks', (req, res) => {
+router.get('/ap/users/:slug/tracks', async (req, res) => {
   const site = publicSite(req.params.slug);
   if (!site) return res.status(404).end();
-  AP.sendAP(res, AP.buildTrackCollection(baseUrl(req), site, AP.siteOpenTracks(site.id)));
+  AP.sendAP(res, AP.buildTrackCollection(baseUrl(req), site, AP.siteOpenTracks(site.id, { alles: await magAlles(req, site.slug) })));
 });
 
