Files
neckfireandClaude Opus 4.8 af32669931
Build & Deploy / build (push) Successful in 18s
StreakFit — API Laravel 13 OSDD + Octane/FrankenPHP
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 03:00:17 +02:00

4.1 KiB

StreakFit — Contrat d'API (v1)

Base API : https://api.streakfit.nfteam.ovh. Front : https://streakfit.nfteam.ovh. Auth = Sanctum SPA par COOKIE de session (pas de token exposé au front). Cookie de session sur .streakfit.nfteam.ovh. SANCTUM_STATEFUL_DOMAINS=streakfit.nfteam.ovh, SESSION_DOMAIN=.streakfit.nfteam.ovh, CORS supports_credentials=true, origine autorisée = le front. Toute la logique est back. Le front ne fait que : GET /sanctum/csrf-cookie, envoyer le cookie XSRF, afficher.

Auth (couche functional/users)

  • GET /sanctum/csrf-cookie — pose le cookie XSRF (Sanctum).
  • POST /register {name,email,password} → 201, ouvre la session. Crée User (locale/units par défaut) + Streak vide.
  • POST /login {email,password} → 200 {user}, ouvre la session.
  • POST /logout → 204.
  • GET /auth/oidc/redirect → 302 vers pocket-id (authorization code + PKCE). État en session.
  • GET /auth/oidc/callback?code&state → échange le code (OIDC_ISSUER=https://pocket.nfteam.ovh, client via env OIDC_CLIENT_ID/SECRET, redirect OIDC_REDIRECT_URI), lie/crée le user par oidc_sub puis email, ouvre la session, 302 vers APP_FRONT_URL.
  • GET /api/me (auth) → { user:{id,name,email,locale,units,timezone,avatar_url}, streak:{current,longest,freezes} }.

Exercices (public, lecture seule — couche exercises)

  • GET /api/exercises?search=&body_part=&equipment=&target=&category=&per_page= → pagination { data:[{id,name,slug,body_part,equipment,target,image_url,gif_url}], meta:{current_page,last_page,total} }.
  • GET /api/exercises/{id}?locale=fr|pt-BR|en{id,name,slug,body_part,category,equipment,target,muscle_group, secondary_muscles[], instructions:[...étapes dans la locale (pt-BR→fallback en/fr)], image_url, gif_url, attribution}.
  • GET /api/exercises/facets → valeurs distinctes pour filtres {body_parts[],equipments[],targets[],categories[]}.

Routines (auth, scopées user — couche routines)

CRUD REST : GET/POST /api/routines, GET/PUT/DELETE /api/routines/{id}. Routine = {id,name,description,is_public,estimated_minutes, exercises:[{exercise_id,position,sets,target_reps,rest_seconds,tempo,target_weight,notes, exercise:{id,name,image_url,target}}]}. POST/PUT accepte exercises[] (sync du pivot routine_exercises).

Programmes (auth — couche programs)

CRUD REST : /api/programs. Program = {id,name,description,duration_weeks,days_per_week, slots:[{week,weekday,routine_id,label}]}.

Séances / tracking (auth — couche tracking)

  • POST /api/sessions {routine_id?,title?} → démarre une séance (status=active) → {session}.
  • GET /api/sessions/{id} → séance + setLogs.
  • POST /api/sessions/{id}/sets {exercise_id,set_number,reps?,weight?,rpe?,duration_seconds?,distance_meters?,is_warmup?} → log un set → {set_log}.
  • POST /api/sessions/{id}/complete {ended_at?} → passe status=completed (déclenche WorkoutCompleted → streak). → {session, streak, unlocked_achievements[]}.
  • GET /api/history?per_page= → séances completed paginées.
  • GET /api/metrics / POST /api/metrics {measured_on,weight?,body_fat?,notes?} — mensurations.

Dashboard (LE cœur — couche streaks, controller view-model)

  • GET /api/dashboard (auth) → objet prêt-à-afficher :
{
  streak: { current, longest, freezes_available, last_active_date, flame_level (0..5 selon current), active_today (bool) },
  week:   { goal_sessions, done_sessions, days:[{date,done,source}] },   // 7 derniers jours
  recent_sessions: [ {id,title,started_at,total_volume,set_count} ],
  achievements: [ {key,earned_at,label} ],
  suggestion: { type:'routine'|'rest', routine_id?, label }              // proposition prochaine séance
}
  • GET /api/achievements → liste complète des badges de l'user.

Conventions

  • Tout scopé par auth()->id() (access-control lomkit ou policies) sauf exercices (public).
  • Réponses JSON camelCase OU snake_case — rester COHÉRENT (snake_case, comme ci-dessus).
  • Erreurs : 401 non authentifié, 403 non autorisé, 422 validation (format Laravel {message,errors}).
  • Pagination Laravel standard (meta, links).