Local-first scientific paper platform with multi-user auth and profile-based curation.
- Users register/login with
username + password. - Each user can create multiple research profiles (
publicorprivate). - Profiles hold manual paper relevance selections with optional notes/tags.
- Public profiles are discoverable and browsable by other users.
- Liking a paper enqueues a PDF download job into local cache.
- Cached PDFs are publicly accessible only when paper is present in at least one public profile.
- Failed jobs are visible with error reason and manually retryable.
Legacy global relevance endpoints (/api/digests, /api/pending, label/resolve/retry) now return 410 Gone.
docker compose up --buildOpen UI at http://localhost:8080.
postgresdedup,keyword,pipeline,arxiv-watcher,rss-watcher(ingestion path)api(auth/profile/public API + UI hosting)worker(PDF download jobs + cache cleanup)ollama(local model service for pipeline/deep verify paths)
POST /api/auth/registerPOST /api/auth/loginPOST /api/auth/logoutGET /api/auth/meGET /api/profiles/mePOST /api/profilesPATCH /api/profiles/{id}DELETE /api/profiles/{id}POST /api/profiles/{id}/accessPOST /api/profiles/{id}/analysis/backfillGET /api/profiles/{id}/analysis/candidatesGET /api/public/profilesGET /api/public/u/{username}/{slug}POST /api/profiles/{id}/likesPATCH /api/profiles/{id}/likes/{paperId}DELETE /api/profiles/{id}/likes/{paperId}GET /api/public/papers/{id}/pdfGET /api/jobs/failuresPOST /api/jobs/{id}/retryPOST /api/admin/ingest/arxiv-rescan(admin, requiresDEDUP_ADDR; body: optionalsince/untilRFC3339,innerQueryarXiv search fragment, optionalmaxPages)
- CSRF token is required on mutating authenticated endpoints (
X-CSRF-Tokenheader). - First registered account is automatically marked admin.
- PDF cache cleanup removes files not referenced by any profile like for 3+ days.
- Profile configuration is profile-local; there is no global inherited config hierarchy.
- arXiv API: export.arxiv.org allows about one request per 3 seconds. This codebase rate-limits each process (
internal/arxiv) and retries 429 usingRetry-After. Admin rescan requests 2000 rows per page (API maximum slice). SetARXIV_API_MIN_INTERVAL(Gotime.ParseDuration, ≥3s) onapiandarxiv-watcherif both hit arXiv—each container has its own limiter, so run them conservative (e.g.4s) during overlapping workloads.