Documentation
Limites du plan
Application server-side des limites du plan avec le catalogue de billing et checkLimit().
Motoko Base définit des limites numériques du plan dans src/lib/billing/config/plans.ts (PLAN_CATALOG). La page des paramètres Usage affiche la progression par rapport à ces limites. L'application s'effectue côté serveur dans les mutations de features — jamais dans l'UI seule.
Architecture
PLAN_CATALOG.limits
↓
getBillingSummary(userId) → summaryGetLimit()
↓
checkLimit(userId, limitId, currentUsage, delta)
↓
Server Action / route handler rejects or allows mutationLes limites sont résolues à partir du résumé de billing de l'utilisateur. Les utilisateurs sans accès payant (y compris past_due) reçoivent les limites du plan Free. Lorsque Polar n'est pas configuré, checkLimit() autorise les mutations pour que le développement local avec configuration minimale continue de fonctionner.
checkLimit API
import { checkLimit } from "@/lib/billing";
const result = await checkLimit(userId, "links", currentCount, 1);
if (result.status === "limit_reached") {
// reject mutation with user-facing message
}
if (result.status === "unavailable") {
// billing lookup failed — fail closed with safe error
}Résultats :
| Status | Meaning |
|---|---|
allowed | La mutation peut continuer (limit: null = illimité) |
limit_reached | Dépasserait la limite du plan |
unavailable | Impossible de résoudre le résumé de billing |
Shipped enforcement
| Feature | Boundary | Notes |
|---|---|---|
| Links | createLinkAction | Update/delete ne sont pas bloqués par la limite |
| Storage | createUploadAction + confirmUploadAction | Pré-vérification à l'init ; vérification autoritaire à la confirmation (cycle de vie d'upload presigné) |
L'utilisation du stockage compte les lignes files avec status = "ready", en additionnant sizeBytes. Les uploads en attente ne sont inclus que dans la pré-vérification à l'init.
Usage metrics registry
La visualisation de l'utilisation (src/lib/billing/usage.ts) lit les métriques depuis un registre. Chaque feature enregistre sa mesure :
// src/features/links/usage-metric.ts
registerUsageMetric({
id: "links",
limitId: "links",
label: "Links",
measure: countLinksForUser,
});Importez @/features/dashboard/lib/bootstrap-usage-metrics (ou les modules individuels usage-metric.ts) avant d'appeler getUsageSnapshot() pour que les métriques soient enregistrées.
Supprimer une démo : supprimez le dossier du feature et son usage-metric.ts. Aucune modification de src/lib/billing/usage.ts n'est requise.
Adding limits to a new feature
- Ajoutez un
LimitIdet une valeur de limite àPLAN_CATALOGdansconfig/plans.ts. - Exportez une fonction
measure(userId)depuis les queries de votre feature. - Enregistrez la métrique dans
<feature>/usage-metric.ts. - Appelez
checkLimit()dans la mutation serveur avant de persister le nouvel état consommant du quota. - Passez l'utilisation
currenten paramètre — ne hardcodez pas les limites du plan dans le feature.
Concurrency
Links et le stockage utilisent une application best-effort : deux créations concurrentes près de la limite peuvent toutes deux réussir brièvement. C'est acceptable pour le starter et documenté honnêtement. Une application stricte nécessiterait des transactions ou des verrous par utilisateur — ajoutez cela dans votre produit si vous avez besoin de garanties fermes.
Les uploads de stockage concurrents suivent le même modèle : la vérification autoritaire s'exécute à la confirmation/finalisation, mais deux confirmations près de la limite peuvent toutes deux passer en conditions de course.
Related docs
- Payments (Polar) — résumé de billing et entitlements
- Storage — cycle de vie des uploads
src/lib/security/README.md— valeurs par défaut de sécurité