Archivist archive les conversations Slack (messages, threads, reactions, fichiers), calcule des classements hebdo/mensuels, et expose une UI moderne avec authentification.
Ce README documente le monorepo racine.
La documentation backend détaillée reste dans apps/backend/README.md.
- Vue d'ensemble
- Architecture
- Structure du repo
- Prérequis
- Installation locale
- Variables d'environnement
- Commandes utiles
- API et sécurité
- CI/CD et release
- Maintenance et debug
- Licence
- Ingestion en temps réel des événements Slack (
/api/slack/events) - Backfill asynchrone en 3 phases (messages, fichiers, agrégations)
- Stockage SQL (Neon/Postgres) + archivage fichiers Cloudflare R2
- Dashboard threads (
recent,week,month,top) - Auth complète (register/login/logout/me, reset password, préférences anonymat)
- UI Next.js avec proxy BFF vers le backend Rust
- Monorepo:
bunworkspaces +turbo - Backend: Rust (
axum,sqlx,vercel_runtime) - Frontend: Next.js 16 + React 19 + Tailwind v4 + composants shadcn/ui
- Infra cible: Vercel (frontend + backend), Slack Events API, Neon, Cloudflare R2, Upstash QStash
Slack Events API
-> Backend Rust (Vercel Functions)
-> Postgres (messages, rollups, auth, jobs)
-> R2 (fichiers archivés)
-> QStash (orchestration workers sync)
Utilisateur navigateur
-> Frontend Next.js (port 3001 en local)
-> /api/auth/* proxy (cookie session + secret interne)
-> /api/record/* proxy (cookie session + secret interne)
-> Backend Rust
Points importants:
- Les routes backend
api/auth/*etapi/record/*sont protégées par un header internex-archivist-internal-secret. - Le frontend joue le rôle de BFF: il ajoute ce header, relaie la session, et gère les cookies HTTP-only.
- Les pages applicatives sont protégées par middleware (
apps/frontend/proxy.ts) et redirigent vers/loginsans session.
.
|- apps/
| |- backend/ # API Rust, workers sync, migrations SQL, assets SSR legacy
| `- frontend/ # App Next.js + routes proxy /api/auth et /api/record
|- packages/
| `- contracts/ # Réservé aux contrats partagés
|- scripts/
| |- db/ # Probes SQL read-model
| |- dev/ # Checks de régression locale backend
| |- perf/ # Probes perf endpoints
| `- release/ # Preflight env + smoke test déploiement
`- docs/
|- phase5-deploy-cutover.md
`- performance/*
- Node.js 22.x (aligné CI)
bun(version stable récente)- Rust stable (+
cargo) sqlx-clipour migrations locales- Optionnel mais recommandé:
vercelCLI
Installation sqlx-cli:
cargo install sqlx-cli --no-default-features --features postgres,rustlsbun installcp .env.example .env
cp apps/frontend/.env.example apps/frontend/.env.localPuis renseigner les valeurs nécessaires (voir section Variables d'environnement).
Depuis apps/backend:
source ../../.env
DATABASE_URL="$DATABASE_URL_UNPOOLED" sqlx migrate runMode Rust direct (script racine):
bun run dev:backendMode Vercel local (utile pour simuler le runtime Vercel):
cd apps/backend
bun run dev:vercelbun run dev:frontendURLs locales habituelles:
- Frontend:
http://localhost:3001 - Backend direct (cargo):
http://localhost:3000 - Backend via vercel dev:
http://localhost:3100
Source de vérité: .env.example.
DATABASE_URLDATABASE_URL_UNPOOLEDSLACK_SIGNING_SECRETSLACK_BOT_TOKEN(ouSLACK_USER_TOKENselon le mode de backfill)ADMIN_TOKENFRONTEND_BACKEND_SHARED_SECRETBACKEND_API_BASE_URLNEXT_PUBLIC_API_BASE_URL(optionnelle en preflight, mais utile en split frontend/backend)EMAIL_ENCRYPTION_KEYEMAIL_LOOKUP_KEY
CLOUDFLARED_R2_ACCOUNT_IDCLOUDFLARED_R2_ACCESS_KEYCLOUDFLARED_R2_SECRET_KEYCLOUDFLARED_R2_BUCKETCLOUDFLARED_R2_PUBLIC_URL
UPSTASH_QSTASH_TOKENUPSTASH_QSTASH_URLUPSTASH_QSTASH_CURRENT_SIGNING_KEYUPSTASH_QSTASH_NEXT_SIGNING_KEYBACKFILL_WORKER_TOKEN- Optionnelles:
BACKFILL_WORKER_URL,BACKFILL_FILES_WORKER_URL,BACKFILL_AGGREGATE_WORKER_URL
AUTH_DEV_EXPOSE_RESET_TOKEN=truepeut exposer le token de reset en dev uniquement.- Les comptes sont liés aux utilisateurs Slack existants en DB (email eligible).
bun run build
bun run lint
bun run typecheck
bun run test
bun run checkbun run dev:backend
bun run dev:frontendbun run check:backend:dev
bun run check:backend:dev -- http://localhost:3100
bun run check:backend:dev -- http://localhost:3100 ./logs/app.logbun run release:preflight
bun run release:smoke -- https://<backend-domain> https://<frontend-domain>scripts/perf/probe_backend_endpoints.sh https://archivist-backend.vercel.app 5
scripts/db/probe_read_model_queries.sh --tab all --limit 50
scripts/db/probe_read_model_queries.sh --tab all --limit 50 --api-url http://localhost:3100POST /api/slack/eventsGET /api/healthPOST /api/admin/sync(BearerADMIN_TOKEN)POST /api/admin/sync/run(worker token et/ou signature QStash)POST /api/admin/sync/files(worker token et/ou signature QStash)POST /api/admin/sync/aggregate(worker token et/ou signature QStash)
POST /api/auth/registerPOST /api/auth/loginPOST /api/auth/logoutGET /api/auth/mePOST /api/auth/change-passwordPATCH|POST /api/auth/preferencesPOST /api/auth/password/forgotPOST /api/auth/password/resetGET /api/record/threads?...GET /api/record/thread?channel_id=...&ts=...
Les routes frontend correspondantes (apps/frontend/app/api/auth/[...path]/route.ts et apps/frontend/app/api/record/[...path]/route.ts) injectent:
x-archivist-internal-secretx-archivist-session(si cookie session présent)
Workflows GitHub:
.github/workflows/ci-backend.yml: fmt + check + test + clippy Rust.github/workflows/ci-frontend.yml: install + typecheck + build frontend.github/workflows/release-smoke.yml: smoke test manuel backend/frontend.github/workflows/sync.yml: sync cron toutes les 10 min (POST /api/admin/sync)
Runbook de cutover:
docs/phase5-deploy-cutover.md
# Backfill local + sync users + archivage fichiers batch
cargo run --manifest-path apps/backend/Cargo.toml --bin backfill_local
# Archivage one-shot de fichiers existants
cargo run --manifest-path apps/backend/Cargo.toml --bin archive_files_local -- --purge
# Recalcul historique des scores hebdo
cargo run --manifest-path apps/backend/Cargo.toml --bin compute_weekly_scores
# Read-model rollups
cargo run --manifest-path apps/backend/Cargo.toml --bin rebuild_rollups -- --enqueue-only
cargo run --manifest-path apps/backend/Cargo.toml --bin repair_rollup -- --channel C123 --ts 1700000000.000000
cargo run --manifest-path apps/backend/Cargo.toml --bin validate_rollups -- --strict --sample 300missing internal secret configuration: variableFRONTEND_BACKEND_SHARED_SECRETabsente côté backend et/ou frontend.401 unauthorizedsur/api/record/*: requête directe backend sans session/proxy frontend.- Port déjà pris: garder
3000libre si backend en runtime direct. release:preflighten échec: clé manquante ou vide dans.env.
Si vous cherchez les détails d'implémentation backend (architecture interne, endpoints SSR historiques, SQLX, tests), voir apps/backend/README.md.
Ce projet est en double licence:
- Open source:
AGPL-3.0-or-later(voirLICENSE) - Commercial: autorisation commerciale écrite requise hors conformité AGPL
(voir
LICENSE-COMMERCIAL.md)