Private
Public Access
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1c9a85ab3 | ||
|
|
62a25c6278 | ||
|
|
7a84d2f09f | ||
|
|
d74527a29c | ||
|
|
f0e4c76ffd |
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "frontend",
|
||||
"runtimeExecutable": "npm",
|
||||
"runtimeArgs": ["--prefix", "frontend", "run", "dev"],
|
||||
"port": 5173
|
||||
},
|
||||
{
|
||||
"name": "frontend-preview",
|
||||
"runtimeExecutable": "npm",
|
||||
"runtimeArgs": ["--prefix", "frontend", "run", "preview"],
|
||||
"port": 4173
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -17,6 +17,7 @@ dist-ssr/
|
||||
## Editors / OS
|
||||
.vscode/
|
||||
.idea/
|
||||
.claude/
|
||||
.DS_Store
|
||||
|
||||
## Test / coverage
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# Contributing to DS Chat
|
||||
|
||||
Thanks for considering a contribution.
|
||||
|
||||
## Reporting bugs and requesting features
|
||||
|
||||
Open an issue on this project's issue tracker. Include steps to reproduce
|
||||
for a bug, or the problem you're trying to solve for a feature request —
|
||||
that's usually more useful than a proposed solution.
|
||||
|
||||
## Development setup
|
||||
|
||||
See the root [README.md](README.md)'s Quickstart, plus
|
||||
[backend/README.md](backend/README.md) and
|
||||
[frontend/README.md](frontend/README.md) for the full local dev setup
|
||||
(Postgres, Redis, Python venv, migrations, the Vite dev server).
|
||||
[ARCHITECTURE.md](ARCHITECTURE.md) covers the overall system design if
|
||||
you're orienting yourself before a larger change.
|
||||
|
||||
## Before opening a pull request
|
||||
|
||||
- **Tests**: run `pytest` in `backend/` for any backend change, and add
|
||||
tests for new behavior rather than just the happy path — see
|
||||
`backend/README.md`'s "Run tests" section. For frontend changes, run
|
||||
`npx tsc -b` in `frontend/` and confirm `npm run build` succeeds.
|
||||
- **Style**: match the conventions already in the file you're editing
|
||||
rather than introducing a new pattern — this codebase doesn't have a
|
||||
separate style guide beyond "look at what's already there."
|
||||
- **Scope**: smaller, focused PRs are easier to review than large ones
|
||||
that mix unrelated changes.
|
||||
|
||||
## Contributor terms
|
||||
|
||||
By submitting a contribution (a pull request, patch, or similar), you
|
||||
agree that:
|
||||
|
||||
1. Your contribution is licensed under the project's own license,
|
||||
AGPL-3.0-or-later ([LICENSE](LICENSE)), and
|
||||
2. You grant the project's maintainer(s) a perpetual, worldwide,
|
||||
non-exclusive right to also relicense your contribution under different
|
||||
terms — for example, as part of a separately-licensed commercial
|
||||
offering built on this project.
|
||||
|
||||
This keeps the option of a future dual-licensed (open-source +
|
||||
commercial) version of the project available, without requiring a
|
||||
separate signed agreement for every contribution.
|
||||
|
||||
*This is a lightweight starting point, not a substitute for legal advice —
|
||||
if you're contributing something substantial, or maintaining a fork with
|
||||
your own commercial plans, it's worth having this reviewed by a lawyer
|
||||
rather than relying on the paragraph above alone.*
|
||||
+37
-15
@@ -132,35 +132,45 @@ sudo -u ds-chat ssh-keygen -t ed25519 -f /srv/ds-chat/.ssh/id_ed25519 -N ""
|
||||
sudo cat /srv/ds-chat/.ssh/id_ed25519.pub
|
||||
```
|
||||
|
||||
Add that public key as a **read-only deploy key** on the Gitea repo
|
||||
(Settings → Deploy Keys), then:
|
||||
This project is hosted at
|
||||
**[github.com/ds-ksmith/DS-Chat](https://github.com/ds-ksmith/DS-Chat)**.
|
||||
Add that public key there as a **read-only deploy key** (Settings → Deploy
|
||||
Keys on the repo), then:
|
||||
|
||||
```bash
|
||||
sudo -u ds-chat ssh-keyscan git.darksingularity.org >> /srv/ds-chat/.ssh/known_hosts
|
||||
sudo -u ds-chat git clone git@git.darksingularity.org:DarkSingularity/ds-chat.git /srv/ds-chat
|
||||
sudo -u ds-chat ssh-keyscan github.com >> /srv/ds-chat/.ssh/known_hosts
|
||||
sudo -u ds-chat git clone git@github.com:ds-ksmith/DS-Chat.git /srv/ds-chat
|
||||
```
|
||||
|
||||
(If your Gitea's SSH is on a non-default port, adjust the clone URL and
|
||||
`ssh-keyscan -p <port>` accordingly.)
|
||||
(Deploying from your own fork instead? Substitute its clone URL — the same
|
||||
deploy-key/access-token steps work the same way on GitHub, GitLab, Gitea,
|
||||
and most other git hosts.)
|
||||
|
||||
**Alternative: a personal/deployment-user access token instead of a deploy
|
||||
key** — skip the `.ssh`/`ssh-keygen`/`ssh-keyscan` commands above entirely
|
||||
and clone over HTTPS with the token embedded in the URL:
|
||||
|
||||
```bash
|
||||
sudo -u ds-chat git clone https://<TOKEN>@git.darksingularity.org/DarkSingularity/ds-chat.git /srv/ds-chat
|
||||
sudo -u ds-chat git clone https://<TOKEN>@github.com/ds-ksmith/DS-Chat.git /srv/ds-chat
|
||||
```
|
||||
|
||||
The token then lives in plaintext in `/srv/ds-chat/.git/config` (`git
|
||||
remote -v` shows it) — readable by root and the `ds-chat` user, not by
|
||||
anyone else under normal file permissions. `deploy/upgrade.sh`'s later
|
||||
`git pull`s reuse this same authenticated URL automatically, no extra
|
||||
`git fetch`es reuse this same authenticated URL automatically, no extra
|
||||
setup needed. Fine as long as the token is scoped to read-only access on
|
||||
just this repo.
|
||||
|
||||
Either way, now that the repo is cloned:
|
||||
Either way, now that the repo is cloned, check out the latest release tag
|
||||
rather than deploying whatever the default branch's tip happens to be —
|
||||
`deploy/upgrade.sh` follows the same rule on every later upgrade (see §6),
|
||||
so this keeps the very first deploy consistent with all the ones after it:
|
||||
|
||||
```bash
|
||||
cd /srv/ds-chat
|
||||
sudo -u ds-chat git fetch --tags
|
||||
LATEST_TAG="$(sudo -u ds-chat git tag --sort=-creatordate | head -n1)"
|
||||
sudo -u ds-chat git checkout --detach "$LATEST_TAG"
|
||||
sudo -u ds-chat mkdir -p /srv/ds-chat/uploads
|
||||
```
|
||||
|
||||
@@ -232,7 +242,16 @@ admin sets it up.
|
||||
`/ws`) whenever that directory exists — that's what lets Nginx Proxy
|
||||
Manager forward the whole domain to one port with no custom path routing.
|
||||
|
||||
Before building, copy `frontend/.env.example` to `frontend/.env.production`
|
||||
and set `VITE_SOURCE_URL` to wherever *your* copy of the repo lives — see
|
||||
that file's own comment for why this matters (AGPL-3.0 source-availability
|
||||
compliance). Vite bakes this in at build time, so it needs to be in place
|
||||
before `npm run build` runs, and needs re-running after any future change
|
||||
to it.
|
||||
|
||||
```bash
|
||||
sudo -u ds-chat cp /srv/ds-chat/frontend/.env.example /srv/ds-chat/frontend/.env.production
|
||||
sudo -u ds-chat nano /srv/ds-chat/frontend/.env.production # set VITE_SOURCE_URL
|
||||
sudo -u ds-chat bash -c 'cd /srv/ds-chat/frontend && npm ci && npm run build'
|
||||
```
|
||||
|
||||
@@ -320,12 +339,15 @@ This is config in NPM's own UI/database, not a file this repo ships:
|
||||
sudo -u ds-chat /srv/ds-chat/deploy/upgrade.sh
|
||||
```
|
||||
|
||||
Pulls latest `main`, reinstalls backend deps, runs `alembic upgrade head`,
|
||||
rebuilds the frontend, restarts `ds-chat`, and curls `/api/health` to
|
||||
confirm it came back up. Fails loudly (`set -euo pipefail`) and stops
|
||||
before restarting anything if an earlier step — most importantly a failed
|
||||
migration — errors out, so a bad deploy doesn't take down the previously
|
||||
working one.
|
||||
Fetches tags and checks out whichever one sorts newest (`git tag
|
||||
--sort=-creatordate`) — deliberately not the default branch's tip, so
|
||||
running this between releases is a safe no-op rather than pulling in
|
||||
whatever's mid-flight on `main`. Then reinstalls backend deps, runs
|
||||
`alembic upgrade head`, rebuilds the frontend, restarts `ds-chat`, and
|
||||
curls `/api/health` to confirm it came back up. Fails loudly
|
||||
(`set -euo pipefail`) and stops before restarting anything if an earlier
|
||||
step — most importantly a failed migration — errors out, so a bad deploy
|
||||
doesn't take down the previously working one.
|
||||
|
||||
Active users get disconnected for a few seconds during the restart and
|
||||
reconnect automatically (same reconnect logic as §4's NPM-timeout note) —
|
||||
|
||||
@@ -629,8 +629,8 @@ to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
DS Chat, a self-hosted, real-time team chat service.
|
||||
Copyright (C) 2026 Keith Smith
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "ds-chat"
|
||||
version = "2026.9.3"
|
||||
version = "2026.9.4"
|
||||
description = "DS Chat backend service"
|
||||
license = { text = "AGPL-3.0-or-later" }
|
||||
requires-python = ">=3.11"
|
||||
|
||||
+11
-2
@@ -16,9 +16,18 @@ BACKEND_DIR="${REPO_DIR}/backend"
|
||||
FRONTEND_DIR="${REPO_DIR}/frontend"
|
||||
ENV_FILE="/etc/ds-chat/env"
|
||||
|
||||
echo "==> Pulling latest code"
|
||||
echo "==> Fetching latest release"
|
||||
cd "$REPO_DIR"
|
||||
git pull --ff-only
|
||||
git fetch --tags --force
|
||||
LATEST_TAG="$(git tag --sort=-creatordate | head -n1)"
|
||||
if [[ -z "$LATEST_TAG" ]]; then
|
||||
echo "No tags found -- nothing to deploy" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Deploying $LATEST_TAG"
|
||||
# Detached HEAD, not a branch checkout -- this directory only ever runs a
|
||||
# tagged release, never whatever the default branch's tip happens to be.
|
||||
git checkout --quiet --detach "$LATEST_TAG"
|
||||
|
||||
echo "==> Installing backend dependencies"
|
||||
cd "$BACKEND_DIR"
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Shown as the "Source code" link in the app's About screen -- required
|
||||
# for AGPL-3.0 section 13 compliance once you deploy this (a link so users
|
||||
# interacting with the app over the network can get the actual source,
|
||||
# including any modifications you've made). The default below points at
|
||||
# the upstream project -- fine if you're running it unmodified, but if
|
||||
# you've forked or patched the code, point this at *your* copy instead.
|
||||
VITE_SOURCE_URL=https://github.com/ds-ksmith/DS-Chat
|
||||
+1
-1
@@ -112,7 +112,7 @@ src/
|
||||
LoginPage.tsx, SignupPage.tsx, ForgotPasswordPage.tsx, ResetPasswordPage.tsx
|
||||
ChatShellPage.tsx, AdminPage.tsx, HelpPage.tsx
|
||||
|
||||
styles/tokens.css design tokens (DarkSingularity theme: colors, spacing, etc.)
|
||||
styles/tokens.css design tokens (default theme: colors, spacing, etc.)
|
||||
sw.ts custom service worker (injectManifest): app-shell
|
||||
precache + NetworkFirst runtime caching, push/notificationclick
|
||||
handlers, SKIP_WAITING messaging for the update-prompt flow
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"private": true,
|
||||
"version": "2026.9.3",
|
||||
"version": "2026.9.4",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -10,8 +10,10 @@ interface AboutModalProps {
|
||||
// users remotely through a computer network, you should also make sure
|
||||
// that it provides a way for users to get its source... its interface
|
||||
// could display a 'Source' link" -- this modal is that link, not just a
|
||||
// courtesy credits screen.
|
||||
const SOURCE_URL = 'https://git.darksingularity.org/DarkSingularity/ds-chat'
|
||||
// courtesy credits screen. Deliberately not a hardcoded URL: whoever
|
||||
// deploys this needs to point it at *their* copy of the repo (including
|
||||
// any modifications), not the upstream project -- see frontend/.env.example.
|
||||
const SOURCE_URL = import.meta.env.VITE_SOURCE_URL as string | undefined
|
||||
|
||||
export function AboutModal({ onClose }: AboutModalProps) {
|
||||
return (
|
||||
@@ -39,11 +41,13 @@ export function AboutModal({ onClose }: AboutModalProps) {
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
{SOURCE_URL && (
|
||||
<p className="about-modal-line">
|
||||
<a href={SOURCE_URL} target="_blank" rel="noopener noreferrer">
|
||||
Source code
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className="modal-actions" style={{ marginTop: '1rem' }}>
|
||||
<button type="button" className="btn-secondary" onClick={onClose}>
|
||||
|
||||
Reference in New Issue
Block a user