Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
eeed5f0
feat(server): replace HTTP Basic Auth with token auth, add registrati…
YaoYinYing Jul 12, 2026
1227119
refactor(server): seed user DB from users file only on first startup
YaoYinYing Jul 12, 2026
3afcaa7
refactor(server): drop users.txt seeding, bootstrap admin only
YaoYinYing Jul 12, 2026
f45512e
feat(server): token auth, API keys, registration workflow, module split
YaoYinYing Jul 12, 2026
3426f4d
refactor(server): consolidate _env_bool, shrink error branch
YaoYinYing Jul 12, 2026
dfef7f4
fix(server): add server/ to sys.path for test module loading
YaoYinYing Jul 12, 2026
24b6db6
feat(server): add ALLOWED_EMAIL_DOMAINS and +suffix normalisation
YaoYinYing Jul 12, 2026
95d726a
docs: update CHANGELOG for email domain and test fix
YaoYinYing Jul 12, 2026
1d86b88
test(server): switch integration tests from Basic Auth to Bearer token
YaoYinYing Jul 12, 2026
b7e994f
fix(server): restore root group in Docker socket access
YaoYinYing Jul 12, 2026
55b2b2a
fix(server): harden auth, fix gunicorn worker crash, redesign auth pages
YaoYinYing Jul 13, 2026
fee2e98
fix(server): replace bare file input with labeled upload trigger
YaoYinYing Jul 13, 2026
d972305
fix(server): use JS click delegation for file upload trigger
YaoYinYing Jul 13, 2026
c2cc1e8
fix(server): replace hidden attr with visually-hidden for file input
YaoYinYing Jul 13, 2026
1f842cd
fix(server): download/logout buttons, error page CSS extraction, file…
YaoYinYing Jul 13, 2026
a25a21f
fix(server): add drag-and-drop file upload, fix create-task UI classes
YaoYinYing Jul 13, 2026
9c856dc
chore(server): remove test-click diagnostic endpoint, update changelog
YaoYinYing Jul 13, 2026
f4ecf6c
docs(server): document drag-and-drop upload, new module structure
YaoYinYing Jul 13, 2026
e2e5aee
feat(server): add admin user control panel with registration audit an…
YaoYinYing Jul 13, 2026
9672047
fix(server): accept email in login, not just username
YaoYinYing Jul 13, 2026
2773f62
refactor(server): add explicit username field to admin add-user form
YaoYinYing Jul 13, 2026
42c7c13
feat(server): add forgot/reset password flow
YaoYinYing Jul 13, 2026
9adbc03
feat(server): add inline Modify button to user management table
YaoYinYing Jul 13, 2026
e8ab0e3
refactor(server): harden API data models with Pydantic
YaoYinYing Jul 13, 2026
d43bb5f
refactor(server): rename to pssm_gremlin_server pip package, move tests
YaoYinYing Jul 13, 2026
48c72d3
docs: update server docs, dev guide, and CHANGELOG; prune REvoDesign …
YaoYinYing Jul 14, 2026
94f8b67
fix(server): harden auth gate, redact secrets from logs, unify admin …
YaoYinYing Jul 14, 2026
31ed5c7
fix(server): require email verification in auth gate; drop root group…
YaoYinYing Jul 14, 2026
ecb5fe3
fix(server): add CSRF bearer-auth gate, close email-verification bypass
YaoYinYing Jul 14, 2026
d7f4882
fix(server): extend CSRF bearer gate to task mutation routes
YaoYinYing Jul 14, 2026
9d8cca6
Harden server auth admin controls
YaoYinYing Jul 14, 2026
576148f
Auto-detect Docker socket group at runtime
YaoYinYing Jul 14, 2026
7f6c4f1
feat(server): add optional Resend SDK email backend, consolidate to p…
YaoYinYing Jul 14, 2026
0291f34
feat(server): add role system (admin/user/guest), CAPTCHA, email rede…
YaoYinYing Jul 14, 2026
2ce0879
feat(server): add Terms of Service page
YaoYinYing Jul 14, 2026
e3e98f3
feat(dev): add CHANGELOG.md duplicate-section checker with pre-commit…
YaoYinYing Jul 14, 2026
14adbe1
fix(server): unblock guest Bearer-token auth, add guest delete guard
YaoYinYing Jul 14, 2026
401c450
fix(server): use request Host header for email links, fix CAPTCHA tests
YaoYinYing Jul 14, 2026
c1dd6e2
feat(server): browser hardening, upload quotas, runner de-escalation,…
YaoYinYing Jul 15, 2026
5c251f7
chore(server): tidy env files, add comments, remove obsolete requirem…
YaoYinYing Jul 15, 2026
dccd1e1
chore(server): auto-derive RUNNER_UID/GID, remove DEFAULT_ADMIN_PASSW…
YaoYinYing Jul 15, 2026
88a7198
chore(server): remove DEFAULT_ADMIN_PASSWORD, always auto-generate
YaoYinYing Jul 15, 2026
5286784
fix(test): inject admin password via sqlite3 after server bootstrap
YaoYinYing Jul 15, 2026
2c93ec5
fix(server): restore DEFAULT_ADMIN_PASSWORD env plumbing, fix GID res…
YaoYinYing Jul 15, 2026
b764dd4
fix(server): replace noreply@ with hello@ in all from-address defaults
YaoYinYing Jul 15, 2026
1a044ed
fix(server): prevent duplicate admin digest emails
YaoYinYing Jul 15, 2026
2802b71
fix(server): add ±5s jitter to digest sleep so workers drift apart
YaoYinYing Jul 15, 2026
8f57955
feat(server): add HTML email templates with warm design
YaoYinYing Jul 15, 2026
c86c8cd
fix(server): backfill admin_notified on upgrade, exclude admins from …
YaoYinYing Jul 15, 2026
abef676
docs(server): clarify that flock auto-releases on process death
YaoYinYing Jul 15, 2026
72c35ba
feat(server): capture registration IP and display in user management
YaoYinYing Jul 15, 2026
375e625
feat(server): configurable client IP/country headers, track country o…
YaoYinYing Jul 15, 2026
be21724
docs(server): document CDN IP header reference in env.example and README
YaoYinYing Jul 15, 2026
d650419
fix(server): strip quotes from CLIENT_IP_HEADERS values, quote exampl…
YaoYinYing Jul 15, 2026
fb6a026
Update .env.example
YaoYinYing Jul 15, 2026
c32adac
fix(server): run DB backup inside web container to avoid host permiss…
YaoYinYing Jul 15, 2026
9552719
fix(server): avoid FASTA filename collision in shared upload folder
YaoYinYing Jul 15, 2026
d2070cb
feat(server): allow download of partial results from failed tasks
YaoYinYing Jul 15, 2026
4a8f845
feat(server): show error tooltip on failed task cards in dashboard
YaoYinYing Jul 15, 2026
c94c9a8
docs: add changelog entries for filename collision, backup, failed-ta…
YaoYinYing Jul 15, 2026
2122a5d
fix(server): three bugs — escapeAttr corrupting user data, approved_b…
YaoYinYing Jul 15, 2026
fece3f8
Improve failed task runner log downloads
YaoYinYing Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/server-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Server Tests

on:
workflow_dispatch:
push:
branches: [main]
paths:
- "server/**"
pull_request:
branches: [main]
paths:
- "server/**"

jobs:
ServerTests:
runs-on: ubuntu-latest
timeout-minutes: 20

env:
OS: ubuntu-latest
PYTHON: "3.12"

defaults:
run:
shell: bash -el {0}

steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # 0.12.1

- name: Checkout Repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Setup Python
uses: actions/setup-python@2f17f13ef37957a9bc7461aa1a61b211e3c1c3ae # v7.0.0
with:
python-version: "3.12"

- name: Install Server and Test Dependencies
run: |
python -m pip install --upgrade pip
pip install -e "server/[test]"

- name: Run Server Tests (non-Docker)
run: |
python -m pytest server/tests/ -v \
-k "not Docker and not docker and not runner_image and not server_image and not test_server_image and not test_runner_image and not test_server_rejects and not test_server_reports and not running_gremlin"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,6 @@ src/REvoDesign/UI/Ui_REvoDesign.py
.claude/worktrees/
.claude/scheduled_tasks.lock
.claude/settings.local.json
users.sqlite3
testerror.txt
/server/server_state
7 changes: 7 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ repos:
language: script
pass_filenames: false

- id: check-changelog-duplicates
name: Reject duplicate section headers in CHANGELOG.md
entry: python dev/tools/check_changelog_duplicates.py CHANGELOG.md
language: system
pass_filenames: false
files: ^CHANGELOG\.md$

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
Expand Down
181 changes: 181 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ All Qt imports MUST go through `REvoDesign.Qt` — never import PyQt5 or PyQt6 d
| `validate-ui-i18n` | Smoke-test runtime UI loading + i18n pipeline |
| `reject-generated-main-ui` | Ensure `Ui_REvoDesign.py` is never re-introduced |
| `check-qt-binding-imports` | Reject direct PyQt5/PyQt6 imports |
| `check-changelog-duplicates` | Reject duplicate `### Section` headers within a version block in CHANGELOG.md |

### Key conventions

Expand Down
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ help:
@echo " reinstall Reinstall after code changes"
@echo " compile-ui Compile UI to Python code"
@echo " translate Translate UI translation into binaries"
@echo " prepare-test Run pip to install pytest-related packages and server-test deps"
@echo " prepare-test Run pip to install pytest-related packages"
@echo " test Run the UnitTest suite"
@echo " all-test Run all tests (firstly the parallel(also the fastest), secondly the serial(also the slower), finally the slowest) "
@echo " fast-test Run all fast tests (first order)"
Expand Down Expand Up @@ -121,7 +121,6 @@ translate:

prepare-test:
python -m pip install pytest pytest-cov pytest-order pytest-dependency coverage -q --no-cache-dir
python -m pip install "celery[redis]==5.3.4" docker==7.1.0 Flask==3.1.3 Flask-HTTPAuth==4.8.1 SQLAlchemy==2.0.46 -q --no-cache-dir

# unit test
test:
Expand Down
79 changes: 79 additions & 0 deletions dev/tools/check_changelog_duplicates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""Check CHANGELOG.md for duplicate section headers within a version block.

Usage:
python dev/tools/check_changelog_duplicates.py [CHANGELOG.md]

Exit code: non-zero if duplicates found.
"""

from __future__ import annotations

import re
import sys
from collections import Counter
from pathlib import Path

VERSION_RE = re.compile(r"^##\s+\[")
SECTION_RE = re.compile(r"^###\s+(.+)")


def check_changelog(path: Path) -> list[str]:
"""Return a list of duplicate-section errors. Empty list = clean."""
errors: list[str] = []
lines = path.read_text().splitlines()

current_version: str | None = None
sections: list[tuple[int, str]] = [] # (line_number, section_name) for current version

def flush() -> None:
"""Check the accumulated sections for the current version block."""
nonlocal sections
if not sections:
return
counts = Counter(name for _, name in sections)
for name, count in counts.items():
if count > 1:
dupes = [ln for ln, sn in sections if sn == name]
errors.append(
f"{path}:{dupes[0]}: section '### {name}' appears {count} times "
f"under '{current_version}' (lines {', '.join(map(str, dupes))})"
)
sections = []

for i, line in enumerate(lines, start=1):
# Version header starts a new block
m = VERSION_RE.match(line)
if m:
flush()
current_version = line.strip()
continue

# Section header within a version block
m = SECTION_RE.match(line)
if m and current_version is not None:
sections.append((i, m.group(1).strip()))

flush() # check the last version block
return errors


def main() -> int:
path = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("CHANGELOG.md")
if not path.exists():
print(f"File not found: {path}", file=sys.stderr)
return 1

errors = check_changelog(path)
if errors:
print(f"{len(errors)} duplicate section(s) found:\n", file=sys.stderr)
for e in errors:
print(f" {e}", file=sys.stderr)
return 1

print("CHANGELOG.md: no duplicate sections.")
return 0


if __name__ == "__main__":
sys.exit(main())
Loading
Loading