15 KiB
🔐 Ackify
Proof of Read. Compliance made simple.
Service sécurisé de validation de lecture avec traçabilité cryptographique et preuves incontestables.
Visitez notre site : https://www.ackify.eu/fr
🎯 Pourquoi Ackify ?
Problème : Comment prouver qu'un collaborateur a bien lu et compris un document important ?
Solution : Signatures cryptographiques Ed25519 avec horodatage immutable et traçabilité complète.
Cas d'usage concrets
- ✅ Validation de politiques de sécurité
- ✅ Attestations de formation obligatoire
- ✅ Prise de connaissance RGPD
- ✅ Accusés de réception contractuels
- ✅ Procédures qualité et compliance
📸 Vidéos
Cliquez sur les GIFs pour ouvrir les vidéos WebM dans votre navigateur.
1) Création d’une signature
|
2) Parcours de signature utilisateur
|
📸 Captures d'écran
Page d'accueil
|
Demande de signature
|
Signature confirmée
|
Liste des signatures
|
Intégration Outline
|
Intégration Google Docs
|
⚡ Démarrage Rapide
Avec Docker (recommandé)
# Installation automatique
curl -fsSL https://raw.githubusercontent.com/btouchard/ackify/main/install/install.sh | bash
# Ou téléchargement manuel
curl -O https://raw.githubusercontent.com/btouchard/ackify/main/install/compose.yml
curl -O https://raw.githubusercontent.com/btouchard/ackify/main/install/.env.example
# Configuration
cp .env.example .env
# Éditez .env avec vos paramètres OAuth2
# Génération des secrets
export ACKIFY_OAUTH_COOKIE_SECRET=$(openssl rand -base64 32)
export ACKIFY_ED25519_PRIVATE_KEY=$(openssl rand 64 | base64 -w 0)
# Démarrage
docker compose up -d
# Test
curl http://localhost:8080/health
Variables obligatoires
ACKIFY_BASE_URL="https://votre-domaine.com"
ACKIFY_OAUTH_CLIENT_ID="your-oauth-client-id" # Google/GitHub/GitLab
ACKIFY_OAUTH_CLIENT_SECRET="your-oauth-client-secret"
ACKIFY_DB_DSN="postgres://user:password@localhost/ackify?sslmode=disable"
ACKIFY_OAUTH_COOKIE_SECRET="$(openssl rand -base64 32)"
Optionnel : Notifications email (SMTP)
ACKIFY_MAIL_HOST="smtp.gmail.com" # Serveur SMTP
ACKIFY_MAIL_PORT="587" # Port SMTP (défaut: 587)
ACKIFY_MAIL_USERNAME="votre-email@gmail.com" # Identifiant SMTP
ACKIFY_MAIL_PASSWORD="votre-app-password" # Mot de passe SMTP
ACKIFY_MAIL_FROM="noreply@entreprise.com" # Adresse expéditeur
ACKIFY_MAIL_FROM_NAME="Ackify" # Nom expéditeur
# Si ACKIFY_MAIL_HOST n'est pas défini, le service email est désactivé (pas d'erreur)
🚀 Utilisation Simple
1. Demander une signature
https://votre-domaine.com/sign?doc=procedure_securite_2025
→ L'utilisateur s'authentifie via OAuth2 et valide sa lecture
2. Vérifier les signatures
# API JSON - Liste complète
curl "https://votre-domaine.com/status?doc=procedure_securite_2025"
# Badge PNG - Statut individuel
curl "https://votre-domaine.com/status.png?doc=procedure_securite_2025&user=jean.dupont@entreprise.com"
3. Intégrer dans vos pages
<!-- Widget intégrable -->
<iframe src="https://votre-domaine.com/embed?doc=procedure_securite_2025"
width="500" height="300"></iframe>
<!-- Via oEmbed -->
<script>
fetch('/oembed?url=https://votre-domaine.com/embed?doc=procedure_securite_2025')
.then(r => r.json())
.then(data => document.getElementById('signatures').innerHTML = data.html);
</script>
🔧 Configuration OAuth2
Providers supportés
| Provider | Configuration |
|---|---|
ACKIFY_OAUTH_PROVIDER=google |
|
| GitHub | ACKIFY_OAUTH_PROVIDER=github |
| GitLab | ACKIFY_OAUTH_PROVIDER=gitlab + ACKIFY_OAUTH_GITLAB_URL |
| Custom | Endpoints personnalisés |
Provider personnalisé
# Laissez ACKIFY_OAUTH_PROVIDER vide
ACKIFY_OAUTH_AUTH_URL="https://auth.company.com/oauth/authorize"
ACKIFY_OAUTH_TOKEN_URL="https://auth.company.com/oauth/token"
ACKIFY_OAUTH_USERINFO_URL="https://auth.company.com/api/user"
ACKIFY_OAUTH_SCOPES="read:user,user:email"
Restriction par domaine
ACKIFY_OAUTH_ALLOWED_DOMAIN="@entreprise.com" # Seuls les emails @entreprise.com
Log level setup
ACKIFY_LOG_LEVEL="info" # can be debug, info, warn(ing), error. default: info
🛡️ Sécurité & Architecture
Sécurité cryptographique
- Ed25519 : Signatures numériques de pointe
- SHA-256 : Hachage des payloads contre le tampering
- Horodatage immutable : Triggers PostgreSQL
- Sessions chiffrées : Cookies sécurisés
- CSP headers : Protection XSS
Architecture Go
cmd/ackapp/ # Point d'entrée
internal/
domain/ # Logique métier
models/ # Entités
repositories/ # Interfaces persistance
application/ # Use cases
services/ # Implémentations métier
infrastructure/ # Adaptateurs
auth/ # OAuth2
database/ # PostgreSQL
email/ # Service SMTP
config/ # Configuration
presentation/ # HTTP
handlers/ # Contrôleurs + interfaces
templates/ # Vues HTML
pkg/ # Utilitaires partagés
Stack technique
- Go 1.24.5 : Performance et simplicité
- PostgreSQL : Contraintes d'intégrité
- OAuth2 : Multi-providers
- SMTP : Rappels de signature par email (optionnel)
- Docker : Déploiement simplifié
- Traefik : Reverse proxy HTTPS
📊 Base de Données
-- Table principale des signatures
CREATE TABLE signatures (
id BIGSERIAL PRIMARY KEY,
doc_id TEXT NOT NULL, -- ID document
user_sub TEXT NOT NULL, -- ID OAuth utilisateur
user_email TEXT NOT NULL, -- Email utilisateur
signed_at TIMESTAMPTZ NOT NULL, -- Timestamp signature
payload_hash TEXT NOT NULL, -- Hash cryptographique
signature TEXT NOT NULL, -- Signature Ed25519
nonce TEXT NOT NULL, -- Anti-replay
created_at TIMESTAMPTZ DEFAULT now(), -- Immutable
referer TEXT, -- Source (optionnel)
prev_hash TEXT, -- Prev Hash
UNIQUE (doc_id, user_sub) -- Une signature par user/doc
);
-- Table des signataires attendus (pour le suivi)
CREATE TABLE expected_signers (
id BIGSERIAL PRIMARY KEY,
doc_id TEXT NOT NULL,
email TEXT NOT NULL,
name TEXT NOT NULL DEFAULT '', -- Nom d'affichage (optionnel)
added_at TIMESTAMPTZ NOT NULL DEFAULT now(),
added_by TEXT NOT NULL, -- Admin qui a ajouté
notes TEXT,
UNIQUE (doc_id, email) -- Une attente par email/doc
);
-- Table des métadonnées de documents
CREATE TABLE documents (
doc_id TEXT PRIMARY KEY,
title TEXT NOT NULL DEFAULT '',
url TEXT NOT NULL DEFAULT '', -- Emplacement du document
checksum TEXT NOT NULL DEFAULT '', -- SHA-256/SHA-512/MD5
checksum_algorithm TEXT NOT NULL DEFAULT 'SHA-256',
description TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
created_by TEXT NOT NULL DEFAULT ''
);
Garanties :
- ✅ Unicité : Un utilisateur = une signature par document
- ✅ Immutabilité :
created_atprotégé par trigger - ✅ Intégrité : Hachage SHA-256 pour détecter modifications
- ✅ Non-répudiation : Signature Ed25519 cryptographiquement prouvable
- ✅ Suivi : Signataires attendus pour monitoring de complétion
- ✅ Métadonnées : Informations de documents avec URL, checksum et description
🚀 Déploiement Production
compose.yml
version: '3.8'
services:
ackapp:
image: btouchard/ackify-ce:latest
environment:
ACKIFY_BASE_URL: https://ackify.company.com
ACKIFY_DB_DSN: postgres://user:pass@postgres:5432/ackdb?sslmode=require
ACKIFY_OAUTH_CLIENT_ID: ${ACKIFY_OAUTH_CLIENT_ID}
ACKIFY_OAUTH_CLIENT_SECRET: ${ACKIFY_OAUTH_CLIENT_SECRET}
ACKIFY_OAUTH_COOKIE_SECRET: ${ACKIFY_OAUTH_COOKIE_SECRET}
labels:
- "traefik.enable=true"
- "traefik.http.routers.ackify.rule=Host(`ackify.company.com`)"
- "traefik.http.routers.ackify.tls.certresolver=letsencrypt"
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: ackdb
POSTGRES_USER: ackuser
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
Variables production
# Sécurité renforcée
ACKIFY_OAUTH_COOKIE_SECRET="$(openssl rand 64 | base64 -w 0)"
ACKIFY_ED25519_PRIVATE_KEY="$(openssl rand 64 | base64 -w 0)"
# HTTPS obligatoire
ACKIFY_BASE_URL="https://ackify.company.com"
# PostgreSQL sécurisé
ACKIFY_DB_DSN="postgres://user:pass@postgres:5432/ackdb?sslmode=require"
# Optionnel : SMTP pour rappels de signature
ACKIFY_MAIL_HOST="smtp.entreprise.com"
ACKIFY_MAIL_FROM="noreply@entreprise.com"
ACKIFY_MAIL_USERNAME="${SMTP_USERNAME}"
ACKIFY_MAIL_PASSWORD="${SMTP_PASSWORD}"
📋 API Complète
Authentification
GET /login?next=<url>- Connexion OAuth2GET /logout- DéconnexionGET /oauth2/callback- Callback OAuth2
Signatures
GET /sign?doc=<id>- Interface de signaturePOST /sign- Créer signatureGET /signatures- Mes signatures (auth requis)
Consultation
GET /status?doc=<id>- JSON toutes signaturesGET /status.png?doc=<id>&user=<email>- Badge PNG
Intégration
GET /oembed?url=<embed_url>- Métadonnées oEmbedGET /embed?doc=<id>- Widget HTML
Supervision
GET /health- Health check
Administration
GET /admin- Tableau de bord (restreint)GET /admin/docs/{docID}- Détails du document avec gestion des signataires attendusPOST /admin/docs/{docID}/expected- Ajouter des signataires attendusPOST /admin/docs/{docID}/expected/remove- Retirer un signataire attenduPOST /admin/docs/{docID}/reminders/send- Envoyer des rappels par email aux lecteurs en attenteGET /admin/docs/{docID}/reminders/history- Obtenir l'historique des rappels en JSONGET /admin/docs/{docID}/metadata- Obtenir les métadonnées du document en JSONPOST /admin/docs/{docID}/metadata- Créer ou mettre à jour les métadonnées du documentDELETE /admin/docs/{docID}/metadata- Supprimer les métadonnées du documentGET /admin/docs/{docID}/status.json- Statut du document en JSON (AJAX)GET /admin/api/chain-integrity/{docID}- Vérification d'intégrité de chaîne (JSON)
Contrôle d'accès: définir ACKIFY_ADMIN_EMAILS avec des emails admins, séparés par des virgules (correspondance exacte, insensible à la casse). Exemple:
ACKIFY_ADMIN_EMAILS="alice@entreprise.com,bob@entreprise.com"
Gestion des Métadonnées de Documents
Les administrateurs peuvent gérer des métadonnées complètes pour chaque document :
- Stocker les informations : Titre, URL/emplacement, checksum, description
- Vérification d'intégrité : Support pour les checksums SHA-256, SHA-512 et MD5
- Accès facile : Copie en un clic pour les checksums, URLs de documents cliquables
- Horodatage automatique : Suivi de la création et des mises à jour avec triggers PostgreSQL
- Intégration email : URL du document automatiquement incluse dans les emails de rappel
Fonctionnalité Signataires Attendus
Les administrateurs peuvent définir et suivre les signataires attendus pour chaque document :
- Ajouter des signataires : Coller des emails séparés par des sauts de ligne, virgules ou point-virgules
- Support des noms : Utiliser le format "Nom email@example.com" pour les emails personnalisés
- Suivre la complétion : Barre de progression visuelle avec pourcentage
- Monitorer le statut : Voir qui a signé (✓) vs. qui est en attente (⏳)
- Rappels par email : Envoyer des rappels en masse ou sélectifs dans la langue de l'utilisateur
- Détecter les signatures inattendues : Identifier les utilisateurs qui ont signé sans être attendus
- Partage facile : Copie en un clic du lien de signature du document
- Gestion en masse : Ajouter/retirer des signataires individuellement ou en lot
🔍 Développement & Tests
Build local
# Dépendances
go mod tidy
# Build
go build ./cmd/community
# Linting
go fmt ./...
go vet ./...
# Tests (TODO: ajouter des tests)
go test -v ./...
Docker development
# Build image
docker build -t ackify-ce:dev .
# Run avec base locale
docker run -p 8080:8080 --env-file .env ackify:dev
🤝 Support
Aide & Documentation
- 🐛 Issues : GitHub Issues
- 💬 Discussions : GitHub Discussions
Licence AGPLv3
Distribué sous la licence GNU Affero General Public License v3.0. Voir LICENSE pour plus de détails.
Développé avec ❤️ par Benjamin TOUCHARD





