ksmithandClaude Sonnet 5 ad745c734e Fix WNS push 400s and improve push failure logging (#56)
WNS (Windows/Edge push) has required an X-WNS-Cache-Policy header
since April 2024; the production venv was likely still on the old
pywebpush 2.0.x installed when the app was first deployed, which
predates the library's fix. Floored the dependency at 2.4.0 (current
latest) so the next deploy picks it up.

Also logs response body and headers on any non-410/404 push failure,
not just body text -- WNS's own 400s carry their actual reason in a
header, which the old body-only logging would still have missed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 21:04:04 -06:00
2026-08-28 20:47:49 -06:00

DS Chat

A self-hosted, real-time team chat service in the spirit of Slack/Discord/ Mattermost (channel-based, no threaded conversations) — built from scratch as a full-stack solo project, running in production on my own infrastructure rather than as a demo. Invite-only: there's no public sign-up, every account comes from an admin invite or a room invite. See ARCHITECTURE.md for the full system design and phased build plan.

DS Chat main view: a room with Markdown formatting, an @mention, and emoji reactions

Custom theme builder Same room, custom theme applied
The custom theme builder: a live, hoverable mockup mapped to 12 color fields The same room under a custom theme built with the theme editor

Also responsive on mobile — screenshot

Features

  • Auth & accounts — session-based auth, invite-only signup (admin-issued site invites or room invites, both delivered by email), password reset, per-user light/dark/midnight/sunset presets plus a live theme builder for fully custom, named, savable color themes.
  • Rooms — open and private rooms, owner/admin/member roles, invites, room browsing/search, file/image galleries per room.
  • Real-time chat — WebSocket-based messaging with automatic reconnect and backoff, Markdown rendering, @mentions with autocomplete and inline highlighting, emoji reactions, message editing, image and file attachments (drag-and-drop, paste, or picker) with inline previews for images/PDFs/text/Markdown, unread indicators, and presence (online/away/ offline, with a manual "appear offline" override).
  • Notifications — Web Push for offline/backgrounded members, with per-type opt-in/out (mentions vs. all messages), plus in-app unread badges.
  • PWA — installable, offline-capable (cached room/message data, a dedicated offline banner), with automatic update detection that prompts a reload as soon as a new deploy goes live.
  • Admin portal — user management, site invites, SMTP configuration, audit log, and management of the bot/webhook system below.
  • Bots & integrations — scoped API tokens for bot accounts, incoming webhooks (post into a room from an external system) and outgoing webhooks (signed HMAC event delivery on message create/update), all with SSRF protection on any admin-supplied external URL.
  • Scale-out — Redis-backed pub/sub for WebSocket fan-out and presence, so the app runs across multiple horizontally-scaled instances rather than a single process.

Tech stack

  • Backend: Python, FastAPI, SQLAlchemy 2.0 (fully async), PostgreSQL, Redis, Alembic migrations, argon2 password hashing, Web Push (VAPID).
  • Frontend: React 19, TypeScript, Vite, a hand-rolled WebSocket client with reconnect/backoff and visibility-aware presence, a PWA service worker (Workbox) for offline caching and push.
  • Deployment: two bare Debian 13 servers (app + DB/cache), no containers — see DEPLOYMENT.md.

Structure

  • backend/ — FastAPI + SQLAlchemy 2.0 (async) + PostgreSQL + Redis. See backend/README.md for local setup, migrations, how to create a user (site registration is invite-only — no public sign-up endpoint), and the full API surface.
  • frontend/ — React + Vite PWA covering the full feature set: auth, room roles/invites, chat, offline caching, push notifications, and the admin portal. See frontend/README.md.

Quickstart

# 1. Postgres (see backend/README.md for details)
docker run -d --name ds-chat-postgres \
  -e POSTGRES_USER=ds_chat -e POSTGRES_PASSWORD=ds_chat -e POSTGRES_DB=ds_chat \
  -p 5432:5432 postgres:16-alpine

# 2. Redis (required — used for cross-instance WebSocket fan-out and presence)
docker run -d --name ds-chat-redis -p 6379:6379 redis:7-alpine

# 3. Backend
cd backend
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
cp .env.example .env   # then set SESSION_SECRET
.venv/bin/alembic upgrade head
.venv/bin/python -m app.cli create-user alice alice@example.com "some-password"
.venv/bin/uvicorn app.main:app --reload &

# 4. Frontend (in another shell)
cd frontend
npm install
npm run dev

Then open http://localhost:5173 and log in with the account created above. The Vite dev server proxies /api and /ws to the backend on :8000, so no CORS configuration is needed in development.

Deployment

See DEPLOYMENT.md for the full production runbook — two Debian 13 servers, no containers, matching ARCHITECTURE.md §9.

License

AGPL-3.0-or-later — see LICENSE. If you run a modified version of this software as a network service, you must make the corresponding source available to its users (AGPL §13).

S
Description
No description provided
Readme AGPL-3.0
4.1 MiB
v2026.9.4
Latest
2026-09-04 21:38:08 -06:00
Languages
Python 54%
TypeScript 39.6%
CSS 5.9%
Shell 0.4%