Documentation technique

cult-track en détail

Cette page décrit précisément comment fonctionne cult-track : ce qu'il demande à l'API GraphQL de Cults3D, où vont les données, comment la clé API est protégée, et ce qui se passe en cas de refus. Elle est publique pour que le fonctionnement soit vérifiable.

Projet indépendant. cult-track n'est ni développé ni hébergé par Cults3D. Il utilise uniquement l'API GraphQL officielle et les métadonnées déjà publiques de vos créations, avec votre accord. Aucun fichier 3D n'est téléchargé, aucun compte n'est modifié.

Résumé

  • But : transformer les statistiques d'un compte créateur Cults3D en courbes lisibles (revenus, ventes, versements, TVA, audience, conversion).
  • Données lues : uniquement les métadonnées de vos propres créations et de vos propres ventes.
  • Données non lues : aucun fichier 3D (les archives ne sont pas exposées par l'API), aucune donnée personnelle d'un autre utilisateur que son pseudo sur une vente.
  • Stockage : la base de données Supabase du créateur. Rien n'est partagé, revendu ni analysé à des fins publicitaires.
  • Coût : gratuit, sans publicité ni traceur tiers.

Architecture

Trois composants, que vous pouvez auditer : le code du front, du Worker et du relais vous est remis sur demande, et le Worker comme le relais peuvent être déployés dans votre propre infrastructure. Le principe directeur est « la clé API reste sous le contrôle du créateur » :

Navigateur  ──(1)──▶  Cloudflare Worker  ──▶  Supabase (votre base)
     │                          │
     │                          └──(2)──▶  Relais Node (Render)  ──(3)──▶  POST /graphql Cults3D
     └──────(4) clé en mémoire, jamais écrite sur l'appareil ─────────────────┘

(1) À la connexion, le navigateur envoie pseudo + clé au Worker, qui la chiffre
    (AES-256-GCM) avant de la stocker dans la base du créateur. La clé n'est
    jamais écrite dans localStorage ni sessionStorage : elle vit en mémoire,
    le temps de l'onglet ouvert, et n'est plus affichée ensuite.
(2) Le Worker est bloqué par le pare-feu de Cults3D (IP data center) : le relais
    central, en accès sortant, est le chemin principal vers l'API.
(3) HTTP Basic (pseudo : clé API), comme documenté par Cults3D. La clé transite
    en TLS vers le relais, qui la présente à Cults3D et ne la conserve pas.
(4) À chaque synchronisation, le navigateur transmet la clé au relais (jamais à
    un tiers) : c'est ce qui permet d'appeler l'API sans exposer l'IP du
    navigateur ni l'IP du Worker.
Les trois appels réseau de l'API
RequêteCibleContenu
POST /api/configureWorkerPseudo + clé API, chiffrés en AES-256-GCM avant stockage (Supabase), sessions hachées SHA-256. La clé n'est jamais renvoyée au navigateur ensuite.
POST /graphqlRelais → Cults3DRequête GraphQL, en-tête Authorization: Basic. Aucune donnée d'un tiers.
POST /api/ingestWorkerRésultat brut de la requête, stocké et agrégé. Aucune clé API dans le corps.

Requêtes envoyées à l'API GraphQL

Quatre requêtes au maximum par synchronisation, toutes en lecture, toutes sur le compte du créateur connecté :

1. moi / user          → pseudo, avatar, bio, nombre d'abonnés
2. moi / creationsBatch → métadonnées de VOS créations, paginées (50 par page)
3. moi / salesBatch     → VOS ventes, paginées, avec revenu, TVA et date de versement
4. moi / user (contrôle) → vérification que la clé correspond bien au pseudo saisi

Champs demandés sur une création : identifier, name, url, illustrationImageUrl, downloadsCount, likesCount, viewsCount, totalSalesAmount, price, publishedAt, visibility, tags, madeWithAi.

Champs demandés sur une vente : id, createdAt, payedOutAt, income, vat, discount, creation, user { nick }.

Une variante « sûre » de chaque requête existe, sans les champs les plus récents, et n'est essayée qu'en cas d'erreur de schéma GraphQL (et jamais après un HTTP 403).

Données collectées et leur durée de vie

DonnéeOrigineConservation
Clé APISaisie par le créateurChiffrée (AES-256-GCM) dans la base du créateur. Jamais renvoyée au navigateur, jamais en clair.
Métadonnées de créationscreationsBatchConservées (c'est l'intérêt de l'outil) ; historique quotidien allégé après 30 jours.
VentessalesBatchConservées, dédupliquées par identifiant.
SessionToken signéHashée en base, expiration 90 jours, révoquée à la déconnexion.
Journal de syncUsage interneStatut, volumes, erreurs. Jamais de contenu de clé.

Aucune donnée n'est transmise à un service tiers d'analyse, de publicité ou de recoupement d'audience. Le seul trafic sortant est celui vers Cults3D (lecture) et vers la base du créateur (stockage).

Sécurité

  • Chiffrement au repos : la clé API est chiffrée en AES-256-GCM côté Worker ; seule la clé de chiffrement vit dans un secret Cloudflare.
  • Jamais en clair côté client : la clé n'est pas conservée dans le navigateur (elle vit en mémoire, le temps de l'onglet) et n'apparaît dans aucune URL.
  • Authentification : sessions hachées SHA-256, expiration, révocation immédiate à la déconnexion, invalidation au changement de clé.
  • CORS restreint : un seul frontal autorisé côté Worker, plus les aperçus *.pages.dev.
  • Limitation de débit : 10 requêtes / 10 min sur la configuration du compte, 180 / min sur le reste de l'API.
  • En-têtes : CSP stricte sans script en ligne, nosniff, X-Frame-Options: DENY, Referrer-Policy: no-referrer, Permissions-Policy restreinte.
  • Protection du relais : origine vérifiée, taille de requête plafonnée, limitation par IP, et arrêt immédiat sur refus de l'API (voir ci-dessous).

Gestion des HTTP 403 (arrêt immédiat)

Un 403 renvoyé par l'API GraphQL est traité comme un refus, jamais comme une panne transitoire. cult-track ne réessaie pas et n'essaie aucune autre variante de requête sur ce code.

  1. Au premier 403, la boucle de pagination s'arrête dans la milliseconde. Les pages déjà récupérées sont conservées, la reprise reprendra à l'offset exacte.
  2. Un seul essai est alors effectué via le relais (IP différente de celle du Worker). Si le relais reçoit lui aussi un 403, l'utilisateur est considéré comme bloqué.
  3. Refus au niveau de la clé : les appels pour ce compte sont gelés 5 minutes côté relais, 15 minutes côté Worker (côté Worker, la date de reprise est conservée en base : c'est cette contrainte qui fait autorité, y compris après un redémarrage du relais).
  4. Refus au niveau du relais : après 3 refus 403 consécutifs, le relais coupe tous ses appels pendant 15 minutes et interrompt les requêtes déjà en vol, afin de ne pas exposer son adresse IP à un bannissement.
  5. Côté navigateur, un message explicite s'affiche et le bouton de synchronisation est désactivé jusqu'à l'heure de reprise. Aucune relance automatique n'est programmée.
  6. Côté serveur, la date de reprise est mémorisée en base : même après un redéploiement, aucun appel vers Cults3D n'est effectué avant cette date. La tâche planifiée saute simplement ce compte et continue les autres.
POST /api/sync  →  429 Too Many Requests
Retry-After: 900
{
  "status": "blocked",
  "code": "CULTS_FORBIDDEN",
  "error": "Cults3D a refusé la dernière requête (HTTP 403) : nouvel essai dans 15 min…",
  "retry_after": 900
}

Le relayage est également exposé sur GET /status du relais (breaker.globalBlockedSeconds, breaker.consecutive403, breaker.keysBlocked) pour faciliter le diagnostic.

Limites de débit et volumes

  • 50 éléments par page GraphQL, 4 pages maximum par appel serveur, 200 ms entre deux pages.
  • Le quota indiqué par l'API (en-têtes x-ratelimit-*) est respecté : une pause est insérée quand il approche de zéro, et il est affiché dans le tableau de bord.
  • Une synchronisation complète d'un compte de 500 créations représente environ 12 requêtes, plus 1 requête par tranche de 50 ventes.
  • Aucune tâche automatique n'est active par défaut : la synchronisation est déclenchée par le créateur depuis le tableau de bord. Une tâche planifiée externe (cron-job.org, GitHub Action, ou le déclencheur scheduled du Worker) peut être activée à la demande ; un compte en refroidissement est alors simplement ignoré, sans interrompre les autres.

Cache et disponibilité

  • L'application est une PWA installable ; le dernier affichage reste lisible hors ligne.
  • Les réponses de l'API mises en cache sont marquées __cached: true et l'interface affiche un bandeau « hors ligne — données du dernier affichage ». Elles sont purgées à la déconnexion.
  • Le relais central fonctionne sur l'offre gratuite de Render : il se met en veille après quelques minutes d'inactivité. Le premier appel peut donc prendre jusqu'à une minute ; c'est signalé explicitement dans l'interface.

Conformité et respect de l'API

  • Seul l'endpoint documenté https://cults3d.com/graphql est utilisé, en lecture, avec une clé API créée par le créateur pour ce seul usage.
  • Aucune tentative de contournement du rate limit, aucun appel massif, aucun balayage d'utilisateurs : on ne lit que « moi ».
  • Aucun contenu de création n'est redistribué, téléchargé ou mis en cache publiquement : les miniatures ne sont affichées que dans l'espace privé du créateur.
  • Le refus est respecté : en cas de 403, l'outil se tait (voir la section précédente).
  • Aucune revente, republication ou mise à disposition des métadonnées à des tiers.

Tester le service

L'outil est utilisable immédiatement. Nous mettons à disposition un compte de démonstration (pseudo et clé API dédiés, chiffres factices) et les éléments de test ci-dessous — la mise en avant sur la page des initiatives API revient entièrement à Cults3D.

  • Compte de démo : pseudo et clé API d'un compte de test dédié, transmissibles sur simple demande.
  • Captures d'écran : dashboard complet (revenus, versements, conversion, prix, heatmap, top acheteurs, objectif), export CSV et vue mobile.
  • Enregistrement vidéo : ~2 min, parcours de connexion → première synchronisation → lecture des courbes. Disponible sur demande.
  • Code : le front, le Worker et le relais peuvent être fournis pour audit, et le Worker comme le relais déployés dans votre propre infrastructure pour une démonstration interne.
  • Endpoints utiles pour un test : GET /status (état du relais et du coupe-circuit, sans authentification) et POST /api/cron/sync-all (synchronisation serveur de tous les comptes, protégée par un secret — à activer si vous le souhaitez).

Contact : cybermaitraise@gmail.com — réponse sous 48 h.