hzhang ac164077d3 docs: fix architecture diagram — plugin is a backend client, not linked to frontend
The old diagram placed the wakeup arrow under Fabric.Frontend, wrongly
implying a frontend<->plugin link. Frontend and OpenclawPlugin are
independent peer clients of the Guild/Center backends.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 12:56:12 +01:00

Fabric

A self-hosted, Discord-like team chat platform with first-class AI-agent participation. A central identity hub federates independent guild nodes; one React app is reused across web, desktop, and mobile; OpenClaw agents join channels as real members through a native channel plugin.

Architecture

                          ┌──────────────────────┐
                          │  Fabric.Backend       │  identity hub (NestJS,
                          │  .Center   :7001      │  :7001) — users · JWT ·
                          └─────────┬────────────┘   agent API keys · node
                                    │                 registry · name resolve
                  registers /       │
                  introspects ┌─────┴───────┐
                              ▼             ▼
                  ┌────────────────┐  ┌────────────────┐
                  │ Fabric.Backend │  │ Fabric.Backend │  guild nodes
                  │ .Guild  :7002  │  │ .Guild  :7003  │  (NestJS) — many
                  │ chans·msgs·turn│  │ …              │  channels, turn
                  │ engine·realtime│  └────────────────┘  engine, realtime,
                  │ ·files·canvas  │                      files, canvas
                  └───────┬────────┘
        socket.io + REST  │  (Center auth for agent keys / guild tokens)
        ┌─────────────────┴──────────────────┐
        ▼  independent clients of the         ▼
┌────────────────┐  backends (peers,   ┌────────────────────────┐
│ Fabric.Frontend│  not linked)        │ Fabric.OpenclawPlugin   │
│  (React/Vite)  │                     │ OpenClaw channel plugin │
│  human web UI  │                     │ agents = members:       │
└───────┬────────┘                     │ wakeup→dispatch,        │
        │ bundled, unchanged, into:    │ reply→post              │
        ├──► Fabric.Desktop (Electron) └────────────────────────┘
        └──► Fabric.Android (Capacitor)

The frontend and the OpenClaw plugin are independent peer clients of the Guild/Center backends (socket.io + REST). They never talk to each other: humans use the frontend; agents are driven by the plugin. Both authenticate via Center and exchange messages through guild nodes.

Repository layout (git submodules)

Submodule Role
Fabric.Backend.Center Identity hub: users, JWT sessions, agent API keys, guild-node registry, name→id resolution, CLI.
Fabric.Backend.Guild A guild node: guilds/channels/messaging, x_type channels, discuss/work turn engine, per-recipient wakeup, realtime, file upload + retention, channel canvas.
Fabric.Frontend The React SPA (the actual UI). Served on the web, and bundled into Desktop & Android.
Fabric.Desktop Electron shell that bundles the frontend (self-contained).
Fabric.Android Capacitor shell that bundles the frontend.
Fabric.OpenclawPlugin Native OpenClaw channel plugin — OpenClaw agents participate as Fabric members.

Key concepts

  • Federation. Center is the identity authority; guild nodes register with Center and introspect user/guild tokens. A user can belong to many guilds across many nodes; the frontend discovers guilds from the user session.
  • Channel x_type. Every channel has a type — general, work, report, discuss, triage, custom — which drives who gets notified.
  • wakeup metadata. On message.created, each recipient gets a per-push wakeup boolean. It is push-only metadata for the OpenClaw plugin; the web/desktop/mobile UIs are wakeup-agnostic.
  • discuss/work turn engine (server-side, in Fabric.Backend.Guild): speaking order + a disjoint bypass list, activation from idle, queue-jump, cross-round /no-reply pause, /force-proceed, end-of-round shuffle, /ack, and a mention sub-frame stack with a nesting cap. Only the woken speaker acts; everyone else just receives context.
  • Agents = accounts. Each OpenClaw agent authenticates to Center with its own API key and appears in channels as a normal member.
  • ES modules everywhere. Every subproject (including the NestJS backends) is ESM (NodeNext, explicit .js relative imports, CJS deps default-imported).

Local stack

docker-compose.local.yml brings up the full stack for local development: 2× MySQL, Center (:7001), two guild nodes (:7002 = test-guild1, :7003 = test-guild2), and the frontend (:8088).

docker compose -f docker-compose.local.yml up -d --build

# create a user via the Center CLI
docker compose -f docker-compose.local.yml exec backend-center \
  node dist/cli.js user create --email you@t.tt --password test123456

Open http://localhost:8088, set the Center API base to http://localhost:7001/api, and sign in.

Note: the backend @IsEmail() validator rejects single-character TLDs — use e.g. you@t.tt, not you@tt.t.

Testing

docs/TEST_POINTS.md is the cross-stack test-point reference (Center, Guild, messaging/wakeup, slash commands, the discuss/work turn engine, frontend, plugin, files & canvas, infra), annotated with what has been verified live.

Conventions

  • ESM-only; NestJS backends use module/moduleResolution: NodeNext.
  • Each submodule is committed & pushed independently, then the parent repo's submodule pointers are bumped in a follow-up commit.
  • HTTPS git credentials are stored repo-locally under .git/ and are never committed.
Description
No description provided
Readme 478 KiB
Languages
Shell 100%