mirror of
https://github.com/btouchard/ackify.git
synced 2026-02-11 16:28:52 -06:00
- Implement PKCE (Proof Key for Code Exchange) with S256 method - Add crypto/pkce module with code verifier and challenge generation - Modify OAuth flow to include code_challenge in authorization requests - Update HandleCallback to validate code_verifier during token exchange - Extend session lifetime from 7 to 30 days - Add comprehensive unit tests for PKCE functions - Maintain backward compatibility with fallback for non-PKCE sessions - Add detailed logging for OAuth flow with PKCE tracking PKCE enhances security by preventing authorization code interception attacks, as recommended by OAuth 2.1 and OIDC standards. feat: add encrypted refresh token storage with automatic cleanup - Add oauth_sessions table for storing encrypted refresh tokens - Implement AES-256-GCM encryption for refresh tokens using cookie secret - Create OAuth session repository with full CRUD operations - Add SessionWorker for automatic cleanup of expired sessions - Configure cleanup to run every 24h for sessions older than 37 days - Modify OAuth flow to store refresh tokens after successful authentication - Track client IP and user agent for session security validation - Link OAuth sessions to user sessions via session ID - Add comprehensive encryption tests with security validations - Integrate SessionWorker into server lifecycle with graceful shutdown This enables persistent OAuth sessions with secure token storage, reducing the need for frequent re-authentication from 7 to 30 days.
9.6 KiB
9.6 KiB
Architecture
Stack technique et principes de conception d'Ackify.
Vue d'Ensemble
Ackify est une application monolithique moderne avec séparation claire backend/frontend.
┌─────────────────────────────────────────┐
│ Client Browser │
│ (Vue.js 3 SPA + TypeScript) │
└──────────────┬──────────────────────────┘
│ HTTPS / JSON
┌──────────────▼──────────────────────────┐
│ Go Backend (API-first) │
│ ├─ RESTful API v1 (chi router) │
│ ├─ OAuth2 Service │
│ ├─ Ed25519 Crypto │
│ └─ SMTP Email (optionnel) │
└──────────────┬──────────────────────────┘
│ PostgreSQL protocol
┌──────────────▼──────────────────────────┐
│ PostgreSQL 16 Database │
│ (Signatures + Metadata + Sessions) │
└─────────────────────────────────────────┘
Backend (Go)
Clean Architecture Simplifiée
backend/
├── cmd/
│ ├── community/ # Point d'entrée + injection dépendances
│ └── migrate/ # Outil migrations SQL
├── internal/
│ ├── domain/
│ │ └── models/ # Entités métier (User, Signature, Document)
│ ├── application/
│ │ └── services/ # Logique métier (SignatureService, etc.)
│ ├── infrastructure/
│ │ ├── auth/ # OAuth2 service
│ │ ├── database/ # Repositories PostgreSQL
│ │ ├── email/ # SMTP service
│ │ ├── config/ # Variables d'environnement
│ │ └── i18n/ # Backend i18n
│ └── presentation/
│ ├── api/ # HTTP handlers API v1
│ └── handlers/ # Legacy OAuth handlers
├── pkg/
│ ├── crypto/ # Ed25519 signatures
│ ├── logger/ # Structured logging
│ ├── services/ # OAuth provider detection
│ └── web/ # HTTP server setup
├── migrations/ # SQL migrations
├── templates/ # Email templates (HTML/text)
└── locales/ # Backend translations
Principes Go Appliqués
Interfaces :
- ✅ Définies dans le package qui les utilise
- ✅ Principe "accept interfaces, return structs"
- ✅ Repositories implémentés dans
infrastructure/database/
Injection de Dépendances :
- ✅ Constructeurs explicites dans
main.go - ✅ Pas de container DI complexe
- ✅ Dépendances claires et visibles
Code Quality :
- ✅
go fmtetgo vetclean - ✅ Pas de code mort
- ✅ Interfaces simples et focalisées
Frontend (Vue.js 3)
Structure SPA
webapp/
├── src/
│ ├── components/ # Composants réutilisables
│ │ ├── ui/ # shadcn/vue components
│ │ └── ...
│ ├── pages/ # Pages (router views)
│ │ ├── Home.vue
│ │ ├── Admin.vue
│ │ └── ...
│ ├── services/ # API client (axios)
│ ├── stores/ # Pinia state management
│ ├── router/ # Vue Router config
│ ├── locales/ # Traductions (fr, en, es, de, it)
│ └── composables/ # Vue composables
├── public/ # Assets statiques
└── scripts/ # Build scripts
Stack Frontend
- Vue 3 - Composition API
- TypeScript - Type safety
- Vite - Build tool (HMR rapide)
- Pinia - State management
- Vue Router - Client routing
- Tailwind CSS - Utility-first styling
- shadcn/vue - UI components
- vue-i18n - Internationalisation
Routing
const routes = [
{ path: '/', component: Home }, // Public
{ path: '/signatures', component: MySignatures }, // Auth required
{ path: '/admin', component: Admin } // Admin only
]
Le frontend gère :
- Route
/avec query param?doc=xxx→ Page de signature - Route
/admin→ Dashboard admin - Route
/signatures→ Mes signatures
Base de Données
Schéma PostgreSQL
Tables principales :
signatures- Signatures Ed25519documents- Métadonnées documentsexpected_signers- Tracking signatairesreminder_logs- Historique emailschecksum_verifications- Vérifications intégritéoauth_sessions- Sessions OAuth2 + refresh tokens
Voir Database pour le schéma complet.
Migrations
- Format :
XXXX_description.up.sql/XXXX_description.down.sql - Appliquées automatiquement au démarrage (service
ackify-migrate) - Outil :
/backend/cmd/migrate
Sécurité
Cryptographie
Ed25519 :
- Signatures digitales (courbe elliptique)
- Clé privée 256 bits
- Non-répudiation garantie
SHA-256 :
- Hachage payload avant signature
- Détection de tampering
- Chaînage blockchain-like (
prev_hash)
AES-256-GCM :
- Chiffrement refresh tokens OAuth2
- Clé dérivée de
ACKIFY_OAUTH_COOKIE_SECRET
OAuth2 + PKCE
Flow :
- Client génère
code_verifier(random) - Calcule
code_challenge = SHA256(code_verifier) - Auth request avec
code_challenge - Provider retourne
code - Token exchange avec
code + code_verifier
Sécurité :
- Protection contre interception du code
- Méthode S256 (SHA-256)
- Activé automatiquement
Sessions
- Cookies sécurisés (HttpOnly, Secure, SameSite=Lax)
- Chiffrement HMAC-SHA256
- Stockage PostgreSQL avec refresh tokens chiffrés
- Durée : 30 jours
- Cleanup automatique : 37 jours
Build & Déploiement
Multi-Stage Docker
# Stage 1 - Frontend build
FROM node:22-alpine AS frontend
COPY webapp/ /build/webapp/
RUN npm ci && npm run build
# Output: webapp/dist/
# Stage 2 - Backend build + embed frontend
FROM golang:alpine AS backend
ENV GOTOOLCHAIN=auto
COPY backend/ /build/backend/
COPY --from=frontend /build/webapp/dist/ /build/backend/cmd/community/web/dist/
RUN go build -o community ./cmd/community
# Frontend embedded via embed.FS
# Stage 3 - Runtime (distroless)
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=backend /build/backend/community /app/community
CMD ["/app/community"]
Résultat :
- Image finale < 30 MB
- Binaire unique (backend + frontend)
- Aucune dépendance runtime
Injection Runtime
Le ACKIFY_BASE_URL est injecté dans index.html au démarrage :
// Remplace __ACKIFY_BASE_URL__ par la valeur réelle
html = strings.ReplaceAll(html, "__ACKIFY_BASE_URL__", baseURL)
Permet de changer le domaine sans rebuild.
Performance
Backend
- Connection pooling PostgreSQL (25 max)
- Prepared statements - Anti-injection SQL
- Rate limiting - 5 auth/min, 10 doc/min, 100 req/min
- Structured logging - JSON avec request IDs
Frontend
- Code splitting - Lazy loading routes
- Tree shaking - Dead code elimination
- Minification - Production builds optimisés
- HMR - Hot Module Replacement (dev)
Database
- Index sur (doc_id, user_sub, session_id)
- Constraints UNIQUE pour garanties
- Triggers pour immutabilité
- Autovacuum activé
Scalabilité
Limites Actuelles
- ✅ Monolithe : ~10k req/s
- ✅ PostgreSQL : Single instance
- ✅ Sessions : In-database (pas de Redis)
Scaling Horizontal (futur)
Pour > 100k req/s :
- Load Balancer - Multiple instances backend
- PostgreSQL read replicas - Séparation read/write
- Redis - Cache sessions + rate limiting
- CDN - Assets statiques
Monitoring
Logs Structurés
Format JSON :
{
"level": "info",
"timestamp": "2025-01-15T14:30:00Z",
"request_id": "abc123",
"method": "POST",
"path": "/api/v1/signatures",
"duration_ms": 42,
"status": 201
}
Health Check
GET /api/v1/health
Response :
{
"status": "healthy",
"database": "connected"
}
Métriques (futur)
- Prometheus metrics endpoint
- Grafana dashboards
- Alerting (PagerDuty, Slack)
Tests
Coverage
72.6% code coverage (unit + integration)
- Unit tests : 180+ tests
- Integration tests : 33 tests PostgreSQL
- CI/CD : GitHub Actions + Codecov
Voir Development pour lancer les tests.
Choix Techniques
Pourquoi Go ?
- ✅ Performance native (compiled)
- ✅ Concurrency simple (goroutines)
- ✅ Typage fort
- ✅ Binaire unique
- ✅ Déploiement simple
Pourquoi Vue 3 ?
- ✅ Composition API moderne
- ✅ TypeScript natif
- ✅ Reactive par défaut
- ✅ Ecosystème riche
- ✅ Performances excellentes
Pourquoi PostgreSQL ?
- ✅ ACID compliance
- ✅ Contraintes d'intégrité
- ✅ Triggers
- ✅ JSON support
- ✅ Mature et stable
Pourquoi Ed25519 ?
- ✅ Sécurité moderne (courbe elliptique)
- ✅ Performance > RSA
- ✅ Signatures courtes (64 bytes)
- ✅ Standard crypto/ed25519 Go