ddat interop with dat js cable interop with cabal js ddat's frontend = dat-thang cable fe = cable-thang dillo support based on cel's dillo-dat bootstrap node xplatform support Signed-off-by: divo <418@cryspace.space>
8.0 KiB
Cable and Cabal interoperability notes
This document describes the test-only Cabal/Hypercore interoperability
harness under tests/interop/cabal/. It is kept to compare historical
behavior and is excluded from production builds and runtime paths.
The production cable and cable-thang clients are C/S7 applications:
Cesspool handles discovery and transport, Sleep handles persistent local
feeds, and S7 represents room events as S-expressions. Cabal CLI and
Hypercore are test targets, not production dependencies.
Which client to run
The working historical Cabal terminal client is cabal-cli. To join a room,
run:
cabal-cli cabal://<room-key>
The cable executable also supports local Sleep feed and Cesspool bootstrap
commands. The native Cable chat client is cable-thang, using a terminal-style
SDL2 layout inspired by Cabal's TUI. Build with make ENABLE_SDL2=1; create an
address in the terminal with build/linux/cable --new, then launch the GUI with
build/linux/cable-thang <cable://address>. Use /join NAME, /nick NAME,
Ctrl+N, and Ctrl+P in the client.
Cabal behaviors being ported
The Cabal CLI's /whoami (also /key) displays the local user key, while
/nick changes that user's display name. Those are different things: the
user's public key is the stable identity within that room; the nickname is a
readable label published as an about record in that user's room feed.
The CLI's usage and commands are listed in the
cabal-cli README. The
cabal-core API
documents getLocalKey() as the local user's key and documents messages as
records published to user feeds. Cabal creates its local writer feed inside
each room's storage, so a user's key is room-scoped, stable for that room, and
can differ in another room. A room key and its optional ?admin=<key>
moderation key are separate from each user's feed key. Cabal text records use
chat/text with channel and text fields.
Dat-era Cabal reference
Cabal Core 5.0.1 is a concrete older reference candidate: it was published about seven years ago, and a 2019 Cabal walkthrough describes the chat as running over Dat (the walkthrough was later updated for Cabal Core 5.0). The bundled Dillo Dat tree supplies a nearby protocol reference with Hypercore 7.7.1, hypercore-protocol 6.12.0, Hyperdrive 9.16.0, and hyperdiscovery 7.1.1. Use those versions to guide backwards-adaptation; do not treat current Cabal Core 16 or its Hyper:// networking as the target.
The repeatable JS behavior tests remain useful for room identity, nicknames, channels, and record shapes. To run them against the historical package, point CABAL_JS_MODULE and CABAL_CLIENT_MODULE at a Cabal Core 5.0.x install, then run make test-cabal-interop.
Current C groundwork
cable addressaccepts room keys withcabal://,cable://, orhyper://, including a?admin=<64 hex>parameter, and prints canonicalcable://room addresses while retaining the admin key separately.cable whoami <room-address>and dat-thang expose a persistent local user key as acable://<64 hex>user address. Each room gets its own 64-byte Ed25519 secret at~/.cable/rooms/<room-key>/user-feed.key, with owner-only permissions. The key is stable in that room across restarts and distinct from the room and admin keys.hyper://parsing only aliases the key representation; production Cable does not implement the newer Hypercore stack.- The library defines a bounded Cable text-message envelope and libsodium sealed-box encrypt/decrypt helpers.
- dat-thang's left panel is a peer list again. Double-clicking a discovered peer opens a direct-message pane; messages use the C-only sealed Cesspool record and can be exchanged between Cable-enabled dat-thang clients.
cable-thangis a native C/S7 room client. Cesspool handles discovery and authenticated transport, Sleep persists local feeds, and S7 builds signed room-event S-expressions. The room UI supports room creation, named channels, nickname changes, and channel cycling. This path is Cable's own protocol and does not claim Cabal wire interoperability.
Hypercore feed storage check
The test-only Cable compatibility writer occupies the room/0 slot used by Cabal Core 5's
multifeed, exposes the expected localname, and shares the Hypercore tree,
signature, bitfield, key, and data files. Run
tests/interop/dat/cable_hypercore_compat.ps1 on Windows with WSL and Node installed. It
writes Cabal-shaped nick and chat JSON blocks from C, opens and verifies them
with the bundled Hypercore 7.7.1, appends a JavaScript block, then confirms C
reads that appended block. This verifies the standalone C feed format against
the legacy Hypercore fixture. It is separate from the native Sleep feeds used
by cable-thang.
Side-by-side regression harness
tests/interop/cabal/cabal_cable_side_by_side.js creates a Cabal JS room, publishes a nick
and chat/text entry, and verifies that a second Cabal JS instance receives
both through Cabal's live replication stream. It then gives Cable that exact
room address, including ?admin=, checks address normalization, and checks
that Cable's local user address persists in the room and changes for a second
room. This covers address normalization and the CLI's local identity utility;
it does not exercise cable-thang's network session.
tests/interop/cabal/cabal_cli_features.js uses cabal-cli's own cabal-client API to create
a room, execute /nick and /join, traverse joined channels using the same
channel ordering as the CLI's Ctrl+N handler, and exchange chat/text entries
between two independently opened Cabal clients over live Hypercore replication.
The C SDL live harness is tests/interop/cabal/cable_js_c_live.js; it launches one Cabal
Core JavaScript peer and one headless SDL/C client, then checks peer discovery
and chat in both directions through the Cabal Hypercore feeds. Run it with
make test-cable-live ENABLE_SDL2=1 after building SDL2 support and installing
Node.js and Cabal Core. The test uses a local Hyperswarm DHT bootstrap node and
separate client UDP ports.
Run it once the historical JS cabal-core package and Node are available. The
test invokes Cabal JS directly; the UI command for people is cabal-cli:
make test-cabal-interop CABAL_JS_MODULE=/path/to/cabal-cli/node_modules/cabal-core
make test-cabal-interop CABAL_CLIENT_MODULE=/path/to/cabal-cli/node_modules/cabal-client
On Windows with Cable built in WSL, run the same harness with Windows Node and the installed Cabal package, routing each Cable CLI call through WSL:
$env:CABAL_JS_MODULE = "$env:APPDATA\npm\node_modules\cabal-cli\node_modules\cabal-core"
$env:CABLE_BIN = "$PWD\build\cable"
$env:CABLE_RUNNER = 'wsl'
node tests/interop/cabal/cabal_cable_side_by_side.js
The harness maps its temporary Cable home directory into WSL for this mode. This is useful when the WSL distribution has no Node installation; no second Node runtime is needed.
The normal make test runs this harness when it can resolve cabal-core; it
prints SKIP when the configured Node runtime cannot resolve the optional JS
package. A standalone make test-cabal-interop reports the resolution error
directly.
Compatibility boundary
The upstream Cabal components documented here use Hypercore feed replication
and their own Cabal database/index conventions. Cable's current GUI messages
use a Cesspool transport record and do not enter Cabal feeds, so they are not
yet readable by Cabal JS clients. /nick in Cabal appends a { type: "about", content: { name: nick } } record to the user's room feed; the public user-feed
key remains its unique identity. Cable has not yet implemented that nickname
record in the Cabal message schema.
The next compatibility layer needs the Hypercore transport/session selected
for the deployed Cabal version, feed discovery, Cabal's multiwriter user-feed
model, and its JSON message/index schema. Dat archive wire identifiers and
dat:// handling remain independent.