Reuses Oasis's own private-message invite pattern (like the industry module:
pmModel.sendMessage([feed], 'KARVAN_INVITE', '... -> /karvan/<id>')), so the invite
lands in the contact's inbox with a link — no new SSB code, no touching the SSB
startup. Joining a room by link adopts a local mirror (karvanModel.adoptRoom, the
id is the capability). Real-time cross-device signaling (media/text sync between
the two mirrors) is the remaining Fase 2 piece (muxrpc ephemeral), deferred.
Verified single-node: invite publishes to the inbox, validation, adopt, form; 13/13
model tests (added adoptRoom).
Oasis ships no test runner, so this is a dependency-free node script (node
test/karvan_model.test.js). Covers rooms, ephemeral messages, the 250-msg ring
buffer, truncation/validation, self-destruct by idle+absolute TTL, idle reset on
activity, MAX_ROOMS eviction, and the WebRTC signaling mailbox. Lives in test/
(outside src/), so it is not bundled into the APK.