# Changelog

Toutes les évolutions notables d'Hydrogen sont consignées ici.

Le format suit [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/) et la
politique de version suit [SemVer 2.0.0](https://semver.org/lang/fr/) :

- **MAJOR** : changement incompatible de l'API publique.
- **MINOR** : ajout fonctionnel rétro-compatible.
- **PATCH** : correctif rétro-compatible.

Tant qu'Hydrogen est en `0.x`, les bumps `MINOR` peuvent contenir des
changements cassants — la garantie « pas de breaking sans bump majeur » ne
prend effet qu'à partir de `1.0.0`.

Codenames : séquence des isotopes de l'hydrogène (`Protium` → `Deuterium`
→ `Tritium` → …). Sans portée sémantique, juste un marqueur lisible pour
les release notes et les rapports d'incident.

## [Unreleased]

## [0.1.0] - 2026-06-10 — Protium

Première version étiquetée. Tout ce qui suit est livré.

### Added

- **Socle HTTP** : Slim 4 + PSR-7, format JSON:API 1.1 (responder partagé,
  envelope `data`/`errors`/`meta`/`links`), middleware `LocaleResolver` /
  `Authentication` / `OptionalAuthentication` / `JsonResponse`, factories
  de pagination keyset (`?cursor` + `?before`) et offset.
- **Identité framework** : `Hydrogen\Hydrogen` (constantes `VERSION` +
  `CODENAME`), fichier `VERSION` à la racine comme source unique, exposé
  via `GET /api/ping` (pas de header HTTP — choix sécurité).
- **Authentification** : inscription + confirmation email + reset de mot
  de passe, login par mot de passe, OAuth Google / Apple / Facebook
  (ID Token flow), sessions glissantes 30 jours avec rotation côté
  `SessionService`, listing et révocation de sessions.
- **Sessions web (cookie)** : transport cookie réutilisant les mêmes
  lignes `user_session` que l'API ; double-submit CSRF, `SameSite=Lax`,
  `ReturnUrlSanitizer` anti open-redirect, globals Twig (`viewer`,
  `csrf_token`, `locale`).
- **Profil utilisateur** : username (set + change avec contraintes
  d'unicité et délai), password, OAuth identities, settings, avatar
  (upload WebP redimensionné + suppression), cover, adresse postale
  privée.
- **Followers / découverte** : follow / unfollow, listings keyset
  (`me/following`, `me/followers`, `{userId}/following`,
  `{userId}/followers`), `users/search` (Meilisearch offset).
- **Photos / médias** : upload multipart avec EXIF + perceptual hash +
  blurhash + résolution géographique, suppression, listings keyset
  (`me/media`, `{userId}/media`), recherche géographique (`media/nearby`
  rayon, `media/in-bounds` bbox), endpoint Glide signé pour le resizing
  à la volée, ACL serveur sur médias non publiés.
- **Réactions** : like / dislike via PUT idempotent, listings publics
  des likers / dislikers, listings personnels et publics par
  utilisateur, pas de XP, pas de self-react.
- **Commentaires** : threads adjacency-list avec `root_id` dénormalisé,
  profondeur configurable (≤ 5), soft-delete par auteur ou owner, edit
  window configurable, compteurs applicatifs.
- **Favoris (bookmarks)** : style Pinterest, collections nommées (avec
  cap envs), bucket non-classé, strictement privé (auth required
  partout), upsert qui fait office de move.
- **Notifications** : table `notification` polymorphe, dispatch avec
  préférence `inApp` filtrée à l'écriture et `push` filtrée au flush,
  dedup 5 min, digest cron OneSignal (`bin/notifications-flush.php`),
  i18n côté serveur, préférences par type × canal.
- **Parrainage** : code Crockford Base32 (6 caractères), validation 422
  avant insert user, compteurs `numUserTotal` / `numUserValid`,
  notification mail au parrain à l'inscription (try/catch silencieux).
- **Coupons** : redemption tx atomique avec `ExperienceService`,
  contrainte "une fois par user" via PK composite `coupon_user`,
  non-bloquant à l'inscription (échec → `meta.coupon`).
- **Thèmes (topics)** : catalogue éditorial localisé (`topic` +
  `topic_translation` + `user_topic`), slug comme identité publique
  JSON:API, sélection 5..10 env-driven, `setMine` atomique, `getMine`
  garde les inactifs.
- **Établissements / Offres / Marques** : trois endpoints de discovery
  Meilisearch read-only (`establishments/search`, `offers/search`,
  `brands`), recherche full-text et geo combinables.
- **Gamification (XP)** : `ExperienceService.award()` avec audit
  `user_transaction`, montants par événement sur env, calcul de `level`
  via courbe quadratique inverse (`USER_LEVEL_FACTOR`).
- **i18n** : `SupportedLocales` (catalogue + locale par défaut),
  `Translator`, fallback double-LEFT-JOIN côté repos, extension Twig.
- **Documentation API** : `docs/api.md` maintenue à la main, mise à
  jour dans le même commit que toute modification de route.

### Notes ops

- Migration topics (`database/migrations/2026_06_10_220000_create_topic_tables.sql`)
  jouée sur `hxa@109.221.218.146` — peuplement à la charge de l'équipe
  produit.
- Migrations notifications + autres tables back-office : voir
  `database/migrations/`. Sequencer toute nouvelle release par jeu de
  migrations en attente.
- Cron `notifications-flush` à planifier (Task Scheduler / cron) avec
  l'intervalle de `NOTIFICATION_DIGEST_INTERVAL_MINUTES` (2 min dev,
  5 min prod).

[Unreleased]: #unreleased
[0.1.0]: #010---2026-06-10--protium
