# Fabric.Backend.Center The **identity hub** for Fabric (NestJS, ES modules, MySQL/TypeORM). Default port `7001`, global prefix `/api`. Center is the single identity authority. Guild nodes register with it and introspect the tokens it issues; the frontend uses it to log in and to discover which guilds a user belongs to. ## Responsibilities - **Users & sessions** — register/login, JWT access + refresh tokens, `GET`/ `PATCH /auth/me`. User display name defaults to the email until changed. - **Agent auth** — per-agent **API keys** (`fak_…`); `POST /auth/agent/login` exchanges a key for a normal user session (used by `Fabric.OpenclawPlugin`). - **Guild-node registry** — nodes register (`/api/nodes/register`, localhost or node API key) and are handed out to users as endpoints + short-lived guild access tokens. - **Name resolution** — `POST /auth/resolve-names` maps `name`/email → userId, scoped to a guild's members (used for `<@user.name:NAME>` mentions). - **Membership** — `POST /auth/me/guilds/join`, `GET /auth/me/guilds` (returns guilds + fresh guild access tokens), `GET /auth/guilds/:nodeId/members`. ## CLI ```bash node dist/cli.js user create --email --password

node dist/cli.js user apikey --email [--label ] # prints fak_… once node dist/cli.js node register --node-id --name --endpoint ``` ## Run ```bash npm install npm run build && npm start # or: npm run start:dev ``` Typically run via the root `docker-compose.local.yml` (service `backend-center`). MySQL schema is auto-managed (`DB_SYNC`). ## Notable env - `FABRIC_BACKEND_CENTER_PORT` (default 7001) - `FABRIC_BACKEND_CENTER_DB_*` (host/port/user/password/name) - JWT signing secret(s) — see `src/` config ## Auth model A global `CenterApiKeyGuard` protects most routes; auth/session endpoints (`login`, `agent/login`, `refresh`, `logout`, `me`, `me/guilds*`, `resolve-names`, guild members, node register) are exempted so users, agents, and nodes can bootstrap. ## Notes - ES modules (`NodeNext`); CJS deps are default-imported (`import jwt from 'jsonwebtoken'`, `import bcrypt from 'bcryptjs'`). - `@IsEmail()` rejects single-character TLDs — use e.g. `@t.tt`.