Rabble is a small Lace-backed multiplayer word game. Games, players, guesses, registration requests, grants, and revocations are immutable records. The Node CLI and browser share one JavaScript action/projection core, and records move only through explicit bounded sync.
The base frontend entry is //u//rabble//index.html; the
packaged HTTP compatibility host serves
//u//rabble/http//index.html.
A game steward marks a rabble/game descriptor. Players
mark their own rabble/player and exact-linked
rabble/guess records. A waypoint steward marks registration
grants and revocations. Registration controls endpoint admission only;
it does not grant game or player authority.
For each (Waypoint-Steward, Subject), greatest TAI is
current and greatest hash wins at equal TAI. The result is active or
revoked. Without a statement, a request gives requested;
otherwise status is missing. There is no registration
conflict state.
A Game value is a portable domain key, not record
identity. Exactly one valid descriptor hash defines it. Multiple
descriptors are an explicit conflict and no TAI winner is chosen; the
game, players, and guesses are excluded from the game view.
Current player state uses greatest TAI then greatest hash. Each guess
remains authorized by its exact historical active
Player+Link; a later leave or rejoin does not rewrite that
link, and an inactive linked record never authorizes a guess. The
endpoint independently enforces author equality for game, player, and
guess records even after registration.
Guesses sort by TAI then hash. Their hashes choose temporary targets from the current option set and feedback filters that set. TAI is presentation data, not trusted chronology. This is a public low-stakes game, not an anti-cheat design: game words, names, guesses, notes, and registration metadata may be exposed as whole records. Revocation changes future selection, not bytes already copied.
Create an identity and game:
npm --prefix incubator/rabble run rabble -- \
--identity incubator/rabble/.lace-data/alice-identity.json identity create
npm --prefix incubator/rabble run rabble -- \
--store incubator/rabble/.lace-data/alice \
--identity incubator/rabble/.lace-data/alice-identity.json \
game create --title "Friday Rabble" --words crane,slate,bring,jolly
Mutations remain local until explicit exchange:
npm --prefix incubator/rabble run rabble -- \
--store incubator/rabble/.lace-data/alice \
--identity incubator/rabble/.lace-data/alice-identity.json \
sync once ws:127.0.0.1:8867/interlace \
--waypoint-steward V.8qgOfsaEJkK1tzX51sTT9NKdM8J2SrzQq6k8cRPzvP0.H3
Inspect local registration state:
npm --prefix incubator/rabble run rabble -- \
--store incubator/rabble/.lace-data/alice \
--identity incubator/rabble/.lace-data/alice-identity.json \
registration status \
--waypoint-steward V.8qgOfsaEJkK1tzX51sTT9NKdM8J2SrzQq6k8cRPzvP0.H3
--game GAME narrows game, player, and guess exchange but
never bypasses active registration. Run with --help for
create, join, guess, registration review, and sync commands.
Build and run the complete Rabble host with Deno:
npm --prefix incubator/rabble run host
The command builds dist/, then serves the browser
interface and its Interlace endpoint together on
http://127.0.0.1:8867/. Host records persist under
.lace-data/rabble/host. Pass host options after
--, for example
--listen ws:127.0.0.1:0/interlace or
--store-path PATH.
The browser provides the same local game, join, guess, registration, and sync actions. It does not add implicit startup or post-write synchronization.
npm --prefix incubator/rabble test
git diff --check
The package tests cover the integrated build shape, projection/action behavior, filesystem reopen, CLI subprocesses, paired WebSocket exchange, and endpoint admission policy.