Individual Subscription For Front¶
Ce document décrit ce que les fronts doivent ajouter ou adapter après l'introduction du modèle individual sur les capabilities et quotas.
Périmètre:
- configuration admin des plans perso
- lecture du plan courant côté utilisateur
- impacts front sur les actions
eventetevent_proposal
Les exemples ci-dessous utilisent le préfixe /v1/web/api.
Les mêmes routes existent aussi sous /v1/mobile/api et /v1/dev/api.
État Des Endpoints¶
Aucun nouvel endpoint n'est requis pour la V1 individual.
Les routes à utiliser existent déjà:
GET /subscription-plansGET /subscription-plans/{idPlan}POST /subscription-plansPATCH /subscription-plans/{idPlan}GET /me/subscription
Les actions produit déjà branchées sur ce modèle sont:
POST /eventsPATCH /events/{idEvent}POST /events/{idEvent}/registerPOST /event-proposalsPATCH /event-proposals/{idEventProposal}
Ce Que Le Front Admin Doit Gérer¶
Le front admin doit continuer à gérer 4 blocs distincts sur un plan:
rights: droits solidarité personneorganizerCapabilities: capabilities de configuration solidarité sur eventcapabilities: capabilitiesindividualuniquementquotasetindividualQuotas: limites numériques
Important:
- sur les endpoints admin,
capabilitiesne sert qu'au sous-ensembleindividual - le front ne doit pas essayer d'y poster les capabilities canoniques solidarité
- les droits solidarité restent portés par
rights - les capabilities de configuration event solidarité restent portées par
organizerCapabilities
Catalogue Admin En Écriture¶
rights¶
Valeurs supportées:
hosting.offerhosting.requestcarpool.offercarpool.requestequipment.offerequipment.request
organizerCapabilities¶
Valeurs supportées:
enable_hostingenable_carpoolenable_equipmentallow_external_helpers
capabilities¶
Valeurs supportées:
events.individual.createevents.registerevent_proposals.create
quotas¶
Le champ legacy quotas reste réservé au domaine solidarité.
Format:
{
"module": "hosting|carpool|equipment",
"metric": "open_requests|consumed_completed",
"period": "none|subscription_month",
"limitValue": 0
}
individualQuotas¶
Format:
{
"key": "string",
"limitValue": 0
}
Clés supportées:
events.individual.create_per_subscription_monthevents.register_per_subscription_monthevent_proposals.create_per_subscription_monthevents.individual.max_seats_per_eventevent_proposals.max_seats_per_proposalevent_proposals.max_invitees_per_proposal
Sémantique Des Payloads Admin¶
Create¶
POST /subscription-plans accepte:
codenameactiveisDefaultrightsorganizerCapabilitiescapabilitiesquotasindividualQuotas
Exemple minimal avec le nouveau bloc individual:
{
"code": "ESSENTIAL",
"name": "Essentiel",
"active": true,
"isDefault": true,
"rights": [
"hosting.request",
"carpool.request",
"equipment.request"
],
"organizerCapabilities": [
"enable_hosting",
"enable_carpool",
"enable_equipment"
],
"capabilities": [
"events.individual.create",
"events.register",
"event_proposals.create"
],
"individualQuotas": [
{
"key": "events.individual.create_per_subscription_month",
"limitValue": 2
},
{
"key": "events.register_per_subscription_month",
"limitValue": 10
},
{
"key": "event_proposals.create_per_subscription_month",
"limitValue": 3
},
{
"key": "events.individual.max_seats_per_event",
"limitValue": 12
},
{
"key": "event_proposals.max_seats_per_proposal",
"limitValue": 8
},
{
"key": "event_proposals.max_invitees_per_proposal",
"limitValue": 10
}
]
}
Patch¶
PATCH /subscription-plans/{idPlan} est partiel.
Règles importantes:
- champ absent => ne change rien
rightsprésent => remplace tout le maskrightsorganizerCapabilitiesprésent => remplace tout le maskorganizerCapabilitiescapabilitiesprésent => remplace toutes les capabilitiesindividualquotasprésent => remplace tous les quotas legacy solidaritéindividualQuotasprésent => remplace tous les quotasindividual[]est validé et signifie "vider complètement ce bloc"isDefaultn'est pas patchable
Exemple:
{
"capabilities": [
"events.register",
"event_proposals.create"
],
"individualQuotas": [
{
"key": "events.register_per_subscription_month",
"limitValue": 12
},
{
"key": "event_proposals.create_per_subscription_month",
"limitValue": 4
}
]
}
Contrat De Lecture Admin¶
GET /subscription-plans et GET /subscription-plans/{idPlan} renvoient:
rightsorganizerCapabilitiescapabilitiesquotasindividualQuotas
Important:
- côté admin,
capabilitiesrenvoie uniquement le sous-ensembleindividual - le front peut donc relire puis re-poster ce champ tel quel sans convertir les droits solidarité
Exemple de forme:
{
"id": 2,
"code": "ESSENTIAL",
"name": "Essentiel",
"active": true,
"isDefault": true,
"rights": [
"hosting.request",
"carpool.request",
"equipment.request"
],
"organizerCapabilities": [
"enable_hosting",
"enable_carpool",
"enable_equipment"
],
"capabilities": [
"events.individual.create",
"events.register",
"event_proposals.create"
],
"quotas": [],
"individualQuotas": []
}
Contrat De Lecture Self¶
GET /me/subscription reste le point d'entrée front pour connaître le plan effectif de l'utilisateur connecté.
La réponse contient:
planhasExplicitSubscriptionsubscriptionrightsorganizerCapabilitiescapabilitiesquotasquotaUsage
Important:
- côté self,
capabilitiesest un catalogue canonique de lecture - il agrège les capabilities
individualet les mappings canoniques issus derightsetorganizerCapabilities quotascontient uniquement les limites configuréesquotaUsagecontient les usages des quotas mensuels consommablesquotaUsagene couvre pas les quotas de gabarit
Exemple de capabilities canoniques possibles dans GET /me/subscription:
events.individual.createevents.registerevent_proposals.createsolidarity.hosting.requestsolidarity.hosting.offersolidarity.carpool.requestsolidarity.carpool.offersolidarity.equipment.requestsolidarity.equipment.offerevent_solidarity.hosting.enableevent_solidarity.carpool.enableevent_solidarity.equipment.enableevent_solidarity.external_helpers.allow
Exemple de quotas canoniques possibles dans GET /me/subscription:
events.individual.create_per_subscription_monthevents.register_per_subscription_monthevent_proposals.create_per_subscription_monthevents.individual.max_seats_per_eventevent_proposals.max_seats_per_proposalevent_proposals.max_invitees_per_proposalsolidarity.hosting.requests.opensolidarity.hosting.requests.completed_per_subscription_monthsolidarity.carpool.requests.opensolidarity.carpool.requests.completed_per_subscription_monthsolidarity.equipment.requests.opensolidarity.equipment.requests.completed_per_subscription_month
quotaUsage renvoie aujourd'hui uniquement les quotas mensuels consommables:
events.individual.create_per_subscription_monthevents.register_per_subscription_monthevent_proposals.create_per_subscription_monthsolidarity.hosting.requests.completed_per_subscription_monthsolidarity.carpool.requests.completed_per_subscription_monthsolidarity.equipment.requests.completed_per_subscription_month
Forme:
{
"key": "events.register_per_subscription_month",
"limitValue": 12,
"used": 4,
"remaining": 8,
"periodStart": "2026-04-08T10:29:05Z",
"periodEnd": "2026-05-08T10:29:05Z"
}
Impacts Front Sur Les Actions Produit¶
Les fronts qui créent ou modifient des objets doivent maintenant prendre en compte des refus backend liés au plan individual.
Actions concernées:
- création d'event
- augmentation de
maxSeatssur un event - inscription à un event
- création d'event proposal
- patch d'event proposal quand
maxSeatsou les invitées changent - auto-conversion proposal -> event
Règle front:
- le backend reste la source de vérité
- si le front veut pré-checker une feature, il peut s'appuyer sur
GET /me/subscription - mais le front doit quand même gérer les erreurs HTTP renvoyées par l'action
Sémantique utile:
400= payload invalide ou limite de gabarit violée403= capability ou quota mensuel bloqué409= conflit d'état métier, surtout côtéevent_proposal
Le front doit afficher le message d'erreur backend tel quel.
Exemples de messages possibles:
Event creation is not allowed for the current subscriptionMonthly event creation quota exceededmaxSeats too high for current subscription (max X)Event registration is not allowed for the current subscriptionMonthly event registration quota exceededEvent proposal creation is not allowed for the current subscriptionMonthly event proposal quota exceeded
Ce Qui N'Existe Pas Encore¶
Il n'existe pas encore:
- d'endpoint de catalogue dynamique pour lister les clés autorisées
- de payload admin unifie qui remplace
rightsetorganizerCapabilities
Pour la V1 front, il faut donc:
- continuer à utiliser
rightsetorganizerCapabilitiespour la solidarité - ajouter
capabilitiesetindividualQuotassur l'admin des plans - consommer
GET /me/subscriptionpour la lecture du plan effectif, des limites et des usages mensuels