Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
49fd6f3
feat: implement Evodron Referral Program (backend, frontend, tests)
Copilot Aug 11, 2026
e4fb1fe
Merge pull request #1 from julesdemangeot-ship-it/copilot/ajout-progr…
julesdemangeot-ship-it Aug 11, 2026
e697b42
feat: EVODRON architecture — rate limiting, health check, Docker, CI,…
Copilot Aug 11, 2026
1184d60
feat: add EVODRON platform — API, CLI, DB, referral/rewards/stats system
Copilot Aug 11, 2026
8d8ad29
fix: add workflow permissions and rate limit health endpoint (CodeQL)
Copilot Aug 11, 2026
4ca3219
Merge pull request #2 from julesdemangeot-ship-it/copilot/evolution-e…
julesdemangeot-ship-it Aug 11, 2026
5f213c5
fix: code review — rejection sampling for random codes, referral stat…
Copilot Aug 11, 2026
9b0f0dc
Merge pull request #3 from julesdemangeot-ship-it/copilot/evodron-ref…
julesdemangeot-ship-it Aug 11, 2026
d247100
chore: prioritize workspace consolidation
Copilot Aug 11, 2026
7c9c38b
feat: align workspace tooling and tests
Copilot Aug 11, 2026
5e4e578
feat: harden workspace api and cli
Copilot Aug 11, 2026
098c97c
chore: finalize EVODRON workspace verification
Copilot Aug 11, 2026
b4b5f8d
Initial plan
Copilot Aug 11, 2026
0101e3e
Fix CI: build shared packages before linting to resolve TS2307/TS7006…
Copilot Aug 11, 2026
aea4696
Merge pull request #7 from julesdemangeot-ship-it/copilot/fix-with-co…
julesdemangeot-ship-it Aug 11, 2026
8fef6cd
Merge pull request #4 from julesdemangeot-ship-it/copilot/inspect-cur…
Copilot Aug 11, 2026
0e73c98
Fix CI: build @evodron/shared and @evodron/db before running lint
Copilot Aug 11, 2026
6919ccb
Merge pull request #5 from julesdemangeot-ship-it/copilot/fix-with-co…
Copilot Aug 11, 2026
e5d8f87
Update Dockerfile
julesdemangeot-ship-it Aug 12, 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
32 changes: 32 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# EVODRON repository entrypoint
#
# The runnable product now lives in /evodron.
# Copy this file to .env at the repository root or to evodron/.env.

# Secret used to sign JWTs. Use a long random value (32+ chars).
EVODRON_JWT_SECRET=change-me-to-a-long-random-secret

# API bind address.
EVODRON_API_HOST=0.0.0.0
EVODRON_API_PORT=3000

# API URL used by the CLI.
EVODRON_API_URL=http://localhost:3000

# SQLite path for local development.
EVODRON_DB_URL=file:./evodron.db

# Public base URL used to build referral links.
EVODRON_REFERRAL_BASE_URL=http://localhost:3000

# Minimum completed sessions before a referral is rewarded.
EVODRON_REWARD_MIN_SESSIONS=3

# Optional comma-separated CORS allowlist. Leave unset for development.
# EVODRON_CORS_ORIGIN=https://app.evodron.io,https://admin.evodron.io

# Max JSON request size in bytes.
EVODRON_BODY_LIMIT_BYTES=1048576

NODE_ENV=development
LOG_LEVEL=info
45 changes: 45 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: CI

on:
push:
branches: ["**"]
pull_request:

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Install dependencies
working-directory: evodron
run: npm ci

- name: Build dependencies
working-directory: evodron
run: npm run build -w @evodron/shared -w @evodron/db

- name: Lint workspace
working-directory: evodron
run: npm run lint

- name: Run tests
env:
EVODRON_JWT_SECRET: test-secret-ci-secret-ci-secret-ci
EVODRON_DB_URL: file:/tmp/evodron-ci.db
NODE_ENV: test
working-directory: evodron
run: npm test

- name: Build workspace
working-directory: evodron
run: npm run build
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules/
evodron.db
*.db
.env
48 changes: 48 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Guide de contribution — Evodron

Merci de contribuer à Evodron ! Voici les règles à suivre.

## Pré-requis

- Node.js >= 18
- npm >= 9

## Installation locale

```bash
git clone https://github.com/julesdemangeot-ship-it/EVODRON.git
cd EVODRON
npm install
cp .env.example .env
# Éditer .env et définir JWT_SECRET
```

## Lancer les tests

```bash
npm test
```

Les tests utilisent une base SQLite en mémoire. Aucune configuration externe requise.

## Conventions

- **Code** : `'use strict'` en tête de chaque fichier JS.
- **Commits** : messages en anglais, préfixés (`feat:`, `fix:`, `chore:`, `docs:`, `test:`).
- **Branches** : `feature/<nom>`, `fix/<nom>`, `chore/<nom>`.
- **Tests** : toute nouvelle fonctionnalité doit être accompagnée de tests dans `tests/`.

## Structure du code EVODRON

Voir `EVODRON.md` pour la description complète de l'architecture.

## Pull Requests

1. Créer une branche depuis `main`.
2. Écrire ou adapter les tests.
3. S'assurer que `npm test` passe à 100%.
4. Ouvrir une PR avec une description claire.

## Sécurité

Voir `SECURITY.md` pour signaler une vulnérabilité.
42 changes: 42 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
FROM node:20-alpine AS builder

WORKDIR /app/evodron

COPY evodron/package*.json ./
COPY evodron/packages/api/package.json ./packages/api/package.json
COPY evodron/packages/cli/package.json ./packages/cli/package.json
COPY evodron/packages/db/package.json ./packages/db/package.json
COPY evodron/packages/shared/package.json ./packages/shared/package.json

RUN npm ci

COPY evodron/ ./

RUN npm run build

FROM node:20-alpine AS runtime

WORKDIR /app/evodron

COPY evodron/package*.json ./
COPY evodron/packages/api/package.json ./packages/api/package.json
COPY evodron/packages/cli/package.json ./packages/cli/package.json
COPY evodron/packages/db/package.json ./packages/db/package.json
COPY evodron/packages/shared/package.json ./packages/shared/package.json

RUN npm ci --omit=dev

COPY --from=builder /app/evodron/packages/api/dist ./packages/api/dist
COPY --from=builder /app/evodron/packages/db/dist ./packages/db/dist
COPY --from=builder /app/evodron/packages/shared/dist ./packages/shared/dist

# VOLUME ["/data"]
ENV EVODRON_DB_URL=file:/data/evodron.db
ENV EVODRON_API_HOST=0.0.0.0
ENV EVODRON_API_PORT=3000

EXPOSE 3000

USER node

CMD ["sh", "-c", "npm run db:migrate && npm run start --workspace=@evodron/api"]
145 changes: 145 additions & 0 deletions EVODRON.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Evodron

**Plateforme EVODRON** — API TypeScript/Fastify, CLI EVODRON, base SQLite et architecture modulaire.

> ℹ️ Le fichier `README.md` à la racine documente le **GitHub Copilot CLI** hérité du dépôt. Le produit EVODRON réellement exécutable vit désormais dans le dossier `/evodron` et est piloté depuis la racine via les scripts npm de ce dépôt.

---

## Architecture

```
/
├── package.json # Scripts racine (setup / build / test / start)
├── Dockerfile # Image API EVODRON
├── docker-compose.yml # Déploiement local/simple
└── evodron/
├── package.json # Workspace npm
├── docs/ # Documentation produit / architecture
├── scripts/setup.sh # Setup développeur
└── packages/
├── api/ # API Fastify + auth + referrals + rewards
├── cli/ # CLI EVODRON
├── db/ # Schéma, migrations, seed
└── shared/ # Types et schémas partagés
```

## Prérequis

- **Node.js** >= 18
- **npm** >= 9

## Installation

```bash
cd /home/runner/work/EVODRON/EVODRON
cp .env.example .env
# Éditer .env et définir EVODRON_JWT_SECRET
npm run setup
```

## Démarrage

```bash
npm start
```

Le serveur écoute sur `http://localhost:3000` (configurable via `EVODRON_API_PORT`).

## Tests

```bash
npm test
```

La suite lance les tests workspace EVODRON (`evodron/packages/*`).

## API

### Authentification

| Méthode | Endpoint | Description |
|---------|----------|-------------|
| `POST` | `/auth/register` | Créer un compte (avec code de parrainage optionnel) |
| `POST` | `/auth/login` | Se connecter, obtenir access token + refresh token |
| `POST` | `/auth/refresh` | Renouveler la session |
| `POST` | `/auth/logout` | Révoquer un refresh token |

### Parrainage

| Méthode | Endpoint | Auth | Description |
|---------|----------|------|-------------|
| `GET` | `/users/me` | ✅ | Profil courant |
| `GET` | `/referrals/code` | ✅ | Obtenir son code et lien |
| `GET` | `/referrals/stats` | ✅ | Statistiques de parrainage |
| `POST` | `/sessions/start` | ✅ | Démarrer une session CLI |
| `POST` | `/sessions/end` | ✅ | Terminer une session CLI |
| `GET` | `/rewards` | ✅ | Historique des crédits |
| `GET` | `/rewards/rules` | ✅ | Règles actives |
| `GET` | `/stats` | ✅ | Statistiques d’utilisation |

### Santé

| Méthode | Endpoint | Description |
|---------|----------|-------------|
| `GET` | `/health` | État de l'application et de la base de données |

### Authentification JWT

Passer l’access token JWT via le header HTTP `Authorization: ******

## Variables d'environnement

Voir `.env.example` pour la liste complète.

| Variable | Obligatoire | Défaut | Description |
|----------|-------------|--------|-------------|
| `EVODRON_JWT_SECRET` | ✅ | — | Clé secrète JWT |
| `EVODRON_API_PORT` | ❌ | `3000` | Port d'écoute |
| `EVODRON_API_HOST` | ❌ | `0.0.0.0` | Host d'écoute |
| `EVODRON_API_URL` | ❌ | `http://localhost:3000` | URL de l’API pour le CLI |
| `EVODRON_REFERRAL_BASE_URL` | ❌ | `https://evodron.io` | URL de base des liens de parrainage |
| `EVODRON_DB_URL` | ❌ | `file:./evodron.db` | Chemin/URL de base SQLite |
| `EVODRON_REWARD_MIN_SESSIONS` | ❌ | `3` | Seuil avant validation d’un parrainage |
| `EVODRON_BODY_LIMIT_BYTES` | ❌ | `1048576` | Taille max des payloads JSON |
| `NODE_ENV` | ❌ | `development` | Environnement d'exécution |
| `LOG_LEVEL` | ❌ | `info` | Niveau de logs |

## Déploiement Docker

```bash
# Copier et éditer les variables
cp .env.example .env
# Démarrer
docker compose up -d
```

## Flux de parrainage

```
Alice crée son compte → obtient un code de parrainage unique
↓
Alice partage son lien : /ref/ABCD1234
↓
Bob s'inscrit avec ce code → reçoit un bonus de bienvenue (50 crédits)
↓
Bob complète le nombre minimum de sessions configuré
↓
Alice reçoit sa récompense de parrain (100 crédits par défaut)
```

## Sécurité

- Mots de passe hachés avec **bcrypt** (coût 12)
- Access tokens courts + refresh tokens révoquables
- Rate limiting global et spécifique auth
- Auto-parrainage interdit
- Un utilisateur ne peut avoir qu'un seul parrain
- IP hachées pour l’anti-abus
- Pas de récompense sans usage vérifié

## Licence

Le code source EVODRON exécutable se trouve dans `evodron/` et est propriétaire.

Le fichier `README.md`, `install.sh`, `changelog.md` et `LICENSE.md` sont des fichiers hérités du **GitHub Copilot CLI** distribués sous leur propre licence (voir `LICENSE.md`).
26 changes: 26 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Politique de sécurité — Evodron

## Signaler une vulnérabilité

Si vous découvrez une vulnérabilité de sécurité dans Evodron, **ne l'ouvrez pas publiquement** en tant qu'issue GitHub.

Contactez directement le mainteneur via la fonctionnalité **"Report a vulnerability"** de GitHub (onglet "Security" du dépôt) ou par email privé.

Nous nous engageons à :
- Accuser réception sous 48 heures.
- Fournir un correctif ou un plan d'action sous 7 jours pour les vulnérabilités critiques.
- Créditer le rapporteur dans le changelog si souhaité.

## Versions supportées

| Version | Support sécurité |
|---------|-----------------|
| 1.x | ✅ Oui |

## Bonnes pratiques intégrées

- Mots de passe hachés avec **bcrypt** (coût 12)
- Tokens JWT signés HS256 avec expiration
- Rate limiting sur toutes les routes d'authentification
- Protection anti-auto-parrainage (modèle + contrainte DB)
- Variables sensibles jamais commitées (`.env` dans `.gitignore`)
46 changes: 46 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';

const express = require('express');
const cookieParser = require('cookie-parser');
const path = require('path');

const authRoutes = require('./src/routes/auth');
const referralRoutes = require('./src/routes/referral');
const healthRoutes = require('./src/routes/health');
const { authLimiter, apiLimiter } = require('./src/middleware/rateLimiter');

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

// Serve static frontend files
app.use(express.static(path.join(__dirname, 'public')));

// Health check (no rate limit)
app.use('/api/health', healthRoutes);

// API routes
app.use('/api/auth', authLimiter, authRoutes);
app.use('/api/referral', apiLimiter, referralRoutes);

// Catch-all: serve index.html for client-side navigation
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

// Only start listening when run directly (not during tests)
if (require.main === module) {
if (!process.env.JWT_SECRET) {
console.error('ERROR: JWT_SECRET environment variable is not set. Refusing to start.');
process.exit(1);
}
app.listen(PORT, () => {
console.log(`Evodron Referral server running on http://localhost:${PORT}`);
});
}

module.exports = app;
Loading