Index: test/ward-pwa.test.js
===================================================================
--- test/ward-pwa.test.js	(revision 084b046d930ee79f779d73d05b08e90d00fd684f)
+++ test/ward-pwa.test.js	(revision 52188632909b3b1b9120748844eed2779f7fc030)
@@ -172,2 +172,42 @@
   } finally { server.close(); }
 });
+
+
+test('het gesprek draagt beide kanten en een zwaai heet een zwaai', async () => {
+  // Eén binnengekomen bericht (ap_mentions) en één eigen antwoord (ap_outbox,
+  // direct). Het gesprek moet ze allebei dragen, elk met zijn richting.
+  const VRIEND = 'https://elders.example/ap/users/vriend';
+  db.prepare(`INSERT INTO ap_mentions (slug, object_uri, actor_uri, actor_name, actor_handle, content, wave, published, created_at)
+              VALUES ('mee', 'https://elders.example/n/w1', ?, 'Vriend', '@vriend@elders.example', '<p>👋</p>', 1, datetime('now'), datetime('now'))`)
+    .run(VRIEND);
+  // post_id is NOT NULL (een reply hangt normaal onder een post); een direct
+  // bericht draagt daar een leeg anker, precies zoals deliverDirectNote doet.
+  db.prepare(`INSERT INTO ap_outbox (id, site_slug, post_id, in_reply_to, content, visibility, to_actors, created_at)
+              VALUES ('out-1', 'mee', '', NULL, '<p>hoi terug</p>', 'direct', ?, datetime('now', '+1 minute'))`)
+    .run(JSON.stringify([VRIEND]));
+
+  const { server, port } = await listen(appWith({ user: { id: 'u1' } }));
+  try {
+    const r = await fetch(`http://127.0.0.1:${port}/ward/api/thread?with=${encodeURIComponent(VRIEND)}`);
+    assert.equal(r.status, 200);
+    const { items } = await r.json();
+    const dirs = items.map((i) => i.dir).sort();
+    assert.deepEqual(dirs, ['in', 'out'], 'een kant van het gesprek ontbreekt');
+    // De zwaai-vlag overleeft de reis: de client toont hem groter, en dat kan
+    // alleen als de server hem niet als kale tekst plat slaat.
+    assert.equal(items.find((i) => i.dir === 'in').wave, true);
+  } finally { server.close(); }
+});
+
+test('een bericht sturen eist een echte ontvanger en echte tekst', async () => {
+  const { server, port } = await listen(appWith({ user: { id: 'u1' } }));
+  try {
+    const post = (body) => fetch(`http://127.0.0.1:${port}/ward/api/message`, {
+      method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),
+    });
+    // Geen uri: weigeren, want "aan niemand" bestaat niet.
+    assert.equal((await post({ to: 'vriend', text: 'hoi' })).status, 400);
+    // Lege tekst: weigeren, een leeg bericht versturen kan niet.
+    assert.equal((await post({ to: 'https://elders.example/ap/users/vriend', text: '  ' })).status, 400);
+  } finally { server.close(); }
+});
