Jannis Braun 64d231d782 audit(federation): verify no parallel hmac-wipe-on-401 paths
Task 11 due-diligence audit for #19. Checked all signed-fetch sites in
packages/server/src for 4xx-branch mutations of federationPeers.hmacSecret
or federationPeers.status:

- sendCallRelay (federationOutbox.ts): on 4xx returns post_failed; on
  5xx/network returns peer_transient_failure. No peer-state mutation.
- sendTypingRelay (federationOutbox.ts): delegates to sendCallRelay with
  peeringTimeoutMs:0 (fire-and-forget). No peer-state mutation.
- cleanupExpiredApprovalRequests (storageJanitor.ts): sends denial,
  only deletes peerApprovalRequests row on success. No federationPeers
  mutation.
- DELETE /identity (users.ts): per-origin cleanup; only deletes local
  userFederationRegistry on success, never touches federationPeers.
- denyApprovalRequest (federation.ts): requires 2xx from remote before
  inserting/updating a rejected peer row. Admin-driven, not wipe.
- POST /peers/:id/rotate (federation.ts): mutates pendingHmacSecret only
  on 2xx; returns 502 on 4xx without state change.
- Auto-rotation in federationWorker.ts: same 2xx-gated pattern as manual
  rotate.
- Unreachable-recovery health check: only promotes to active on 2xx.
- ensurePeered/performHandshake (federationPeering.ts): on 403 with
  PEERING_REQUIRES_APPROVAL sets status='rejected' (explicit, not a
  HMAC-mismatch wipe); on other 4xx/5xx only deletes the row if it was
  a freshly created placeholder (existingPeerId falsy). Pre-existing
  peers are untouched.

Only federationWorker.ts:269 mutates HMAC-related state in response to
401/403, and that path was rewritten in Task 5 to use
evaluateAuthFailure and transition to needs_attention. No additional
handlers require the bounded-retry refactor.
2026-04-21 21:07:24 +02:00

Backspace

Open-source, self-hosted Discord alternative built with TypeScript.

Features

  • Real-time text messaging with WebSocket
  • Servers, channels, and role-based permission management
  • Voice and video chat via LiveKit
  • Screen sharing with configurable quality (VP9)
  • Direct messages (1-on-1 and group DMs up to 10)
  • DM voice/video calls with ringing
  • Friend system with requests
  • File uploads and image sharing
  • Markdown message formatting with syntax highlighting
  • Message reactions, replies, and editing
  • Typing indicators, presence status, and read states
  • Invite system with shareable codes
  • Instance-level admin panel (streaming limits)
  • Desktop app (Electron)
  • Mobile-responsive web UI
  • Docker deployment

Tech Stack

Layer Technology
Backend Fastify + TypeScript
Database SQLite (better-sqlite3) + Drizzle ORM
Auth JWT + bcrypt
Real-time WebSocket (ws)
Frontend React 18 + Tailwind CSS + Zustand
Voice/Video LiveKit
Desktop Electron
Build Vite + pnpm workspaces

Quick Start with Docker

# Clone the repository
git clone https://github.com/your-username/backspace.git
cd backspace

# Create environment file
cp .env.example .env

# Generate a JWT secret
echo "JWT_SECRET=$(openssl rand -hex 32)" >> .env

# Start Backspace
docker compose up -d

Open http://localhost:3000 in your browser. A default server "Backspace" is created automatically.

Default admin account: admin / admin123 (change this after first login).

Development Setup

Prerequisites

  • Node.js 20+
  • pnpm 8+

Install

pnpm install

Configure

cp .env.example .env
# Edit .env with your settings (generate a JWT_SECRET)

Run

# Start both server and web dev server
pnpm dev

# Or start individually
pnpm dev:server    # API server on :3005
pnpm dev:web       # Vite dev server on :5173

Build

pnpm build

This builds the shared types, server, and web frontend. The server serves the built frontend in production mode.

Project Structure

Backspace/
├── packages/
│   ├── shared/       # Shared TypeScript types & permissions
│   ├── server/       # Fastify API + WebSocket server
│   ├── web/          # React frontend (Vite + Tailwind)
│   └── desktop/      # Electron desktop app
├── data/             # SQLite DB + uploads (created at runtime)
├── Dockerfile
├── docker-compose.yml
└── .env.example

Voice & Video

Voice and video requires a LiveKit server. Set these in your .env:

LIVEKIT_URL=wss://your-livekit-server
LIVEKIT_API_KEY=your-api-key
LIVEKIT_API_SECRET=your-api-secret

Without LiveKit configured, text chat works fully but voice/video channels will not connect.

API

The server exposes a REST API and WebSocket endpoint:

  • REST API: http://localhost:3000/api/*
  • WebSocket: ws://localhost:3000/ws
  • Health check: GET /api/health

See CLAUDE.md for the full API reference.

Desktop App

The Electron desktop app wraps the web UI and adds system tray, notifications, and native window controls.

cd packages/desktop
pnpm build:ts    # Compile TypeScript
pnpm dev         # Run in development
pnpm build       # Package for distribution

License

MIT

S
Description
Fork proprio do Backspace — instancia chat.resenha.website
Readme AGPL-3.0
22 MiB
Languages
TypeScript 96.8%
HTML 1.3%
Shell 1.1%
JavaScript 0.4%
CSS 0.3%