Skip to Content

Stockage de fichiers

Chaque backend de données d’application est fourni avec un stockage d’objets privé à côté de ses tables. Là où le backend de données contient vos lignes de séries temporelles, le stockage de fichiers contient tout ce qui n’a pas sa place dans une ligne : images de caméra, rapports PDF, blobs de firmware, clips audio, exports.

Les deux sont conçus pour être utilisés ensemble. Stocker un fichier vous renvoie une URL permanente, et le schéma prévu consiste à écrire cette URL dans une colonne de table dans la foulée — un widget de tableau de bord affiche alors l’image sans travail supplémentaire :

info = await ironflock.files.put("part-1.jpg", jpeg_bytes, content_type="image/jpeg") await ironflock.publish_to_table("inspections", part_id="1", photo_url=info.url)

L’API cliente complète — lecture, listage, utilisation, liens de partage, objets volumineux, codes d’erreur — est documentée dans la référence du SDK. Cette page couvre le côté plateforme : comment le stockage est déclaré, gouverné, partagé et exploité.

Fonctionnement

  1. Déclarez éventuellement une section files: dans .ironflock/data-template.yml.
  2. Lorsqu’un utilisateur installe votre application dans un projet, IronFlock lui provisionne une zone de stockage privée — exactement comme il provisionne la base de données du projet.
  3. Votre code edge stocke et lit des objets via l’API files du SDK.
  4. Désinstaller l’application supprime intégralement son stockage : chaque objet et chaque identifiant, tout comme le schéma de base de données est supprimé.

Comme la base de données, le stockage est par projet. La même application installée dans deux projets obtient deux zones de stockage entièrement distinctes, et en tant que développeur de l’application vous n’avez accès à aucune des deux — les données appartiennent à l’utilisateur qui exécute votre application.

L’absence de configuration est une configuration valide : une application sans section files: obtient malgré tout un espace de noms nommé default, de sorte que files.put(...) fonctionne d’emblée pour chaque application.

Déclarer le stockage dans le data template

La section files: se place à côté de data: dans data-template.yml :

files: description: Camera frames and generated inspection reports. # Storage budget the app SUGGESTS for itself, in bytes (here 5 GiB). # The project user can override it; their setting is what gets enforced. quotaBytes: 5368709120 namespaces: - name: frames description: Raw camera frames, one JPEG per inspected part. contentTypes: ["image/jpeg"] maxObjectBytes: 20971520 retention: { deleteAfter: 30 days } - name: reports description: Generated PDF inspection reports. contentTypes: ["application/pdf"] private: true

Espaces de noms

Un espace de noms est un préfixe de clé porteur de règles. Ce n’est pas un bucket de stockage distinct — chaque espace de noms d’une application vit à l’intérieur de l’unique zone de stockage de l’application, et le nom de l’espace de noms devient simplement le premier segment du chemin de stockage de chaque objet.

Cette distinction vous indique quand en déclarer un :

  • Vous organisez des fichiers ? Utilisez des chemins de clés — 2026/03/part-1.jpg — à l’intérieur de l’espace de noms default. Les clés façon dossiers sont le cas normal.
  • Des règles différentes pour un ensemble d’objets ? Déclarez un espace de noms. Les règles sont la seule chose qu’un espace de noms ajoute.

Les règles qu’un espace de noms peut porter :

ChampSignification
nameLettres minuscules, chiffres et traits d’union, commençant par une lettre. sys, system, ironflock et ironflock-* sont réservés
descriptionAffiché aux utilisateurs et lisible par les agents IA
privateExclut l’espace de noms de l’accès inter-applications. Vaut false par défaut (partagé), exactement comme les tables
contentTypesTypes MIME autorisés, globs acceptés (image/*). Par défaut : tous
maxObjectBytesPlus grand objet unique, jusqu’à 5 Gio. Par défaut 100 Mio
retention.deleteAfterLes objets plus anciens que cette durée sont supprimés automatiquement (30 days, 2 weeks, 1 year, …)

Le budget de stockage

quotaBytes est déclaré une seule fois pour toute l’application, et non par espace de noms. Un espace de noms n’est qu’un préfixe de clé : il n’y a donc rien contre quoi un budget par préfixe pourrait être appliqué — le quota s’applique à l’unique zone de stockage de l’application, et le magasin d’objets lui-même l’applique sur chaque chemin d’écriture, y compris les envois directs.

Deux valeurs existent, et la différence est délibérée :

  • Le quota suggéré — ce que votre template demande. Appliqué lors de la première installation de l’application.
  • Le quota appliqué — ce que l’utilisateur du projet a défini. Une fois qu’un utilisateur modifie le budget dans les paramètres de stockage de l’application, c’est sa valeur qui l’emporte, et redéployer votre application ne la réinitialise pas.

Si votre template ne dit rien, la valeur par défaut de la plateforme s’applique (1 Gio pour les backends de développement, 10 Gio pour ceux de production).

Rétention

Les objets ayant dépassé l’âge deleteAfter de leur espace de noms sont supprimés automatiquement — l’équivalent côté fichiers de la politique dropAfter des tables. La rétention s’exécute à l’intérieur du magasin d’objets lorsque celui-ci le prend en charge, et sous forme de tâche de plateforme quotidienne lorsqu’il ne le prend pas en charge (appliances sur site), de sorte que la rétention déclarée se comporte de la même façon partout.

URL permanentes et tableaux de bord

Chaque objet stocké possède une URL stable de la forme https://files.ironflock.com/f/<backend>/<namespace>/<key>. Trois propriétés en font la bonne chose à écrire dans une colonne de table :

  • Elle n’expire jamais. L’URL est une adresse pure ; elle reste valide pendant toute la durée de vie de l’objet.
  • Ce n’est pas un lien public. Chaque requête passe par un proxy d’authentification qui vérifie que le demandeur est connecté et dispose de l’accès READ sur ce backend de données — revérifié à chaque requête. Révoquer l’accès d’un utilisateur révoque immédiatement sa capacité à récupérer chaque fichier.
  • Elle s’affiche dans une balise <img>. Le navigateur envoie automatiquement son cookie de session, de sorte qu’un widget de tableau de bord peut utiliser l’URL dans <img src>, <video src> ou un lien de téléchargement, sans aucun JavaScript.

Pour remettre un fichier à quelqu’un en dehors du projet, le share_url du SDK génère à la place un lien au porteur expirant — voir partager des objets pour savoir lequel utiliser et quand.

Fichiers volumineux

Les transferts jusqu’à 6 Mio circulent en un seul appel via le système de messagerie. Tout ce qui dépasse est transporté directement entre l’appareil et le stockage d’objets en HTTPS — le SDK bascule automatiquement, transfère en flux depuis et vers le disque, et un fichier de plusieurs gigaoctets n’a jamais à tenir en mémoire. Le plafond d’envoi en une seule fois est de 5 Gio.

Le chemin direct exige que l’appareil puisse joindre l’hôte du stockage d’objets (s3.ironflock.com), et pas seulement le routeur de messages. Si un proxy d’usine n’autorise que le routeur, les transferts volumineux échouent avec le code explicite PRESIGN_UNREACHABLE plutôt qu’avec une erreur générique — et une horloge d’appareil décalée de plus de 15 minutes échoue avec CLOCK_SKEW, ce qui invite à vérifier NTP, non les identifiants.

Partager des fichiers entre applications

L’accès inter-applications aux fichiers repose sur le même consentement que l’accès inter-applications aux tables. Il n’y a qu’un seul interrupteur : lorsqu’un utilisateur de projet accorde à l’application B l’accès aux données de l’application A (le consentement data_access dans les paramètres de l’application), cette autorisation couvre les tables de A et les espaces de noms de fichiers non privés de A. La révoquer révoque les deux.

Ce que votre application contrôle en tant que fournisseuse, c’est l’indicateur private par espace de noms :

  • private: false (la valeur par défaut) — les applications disposant d’une autorisation d’accès aux données peuvent le lire (jamais y écrire).
  • private: true — l’espace de noms est invisible pour les autres applications, un point c’est tout, même sous une autorisation.

Cela reflète exactement Consommer les données d’autres applications : les espaces de noms et les tables ont la même valeur par défaut. Rien n’est partagé sans l’autorisation de l’utilisateur du projet — private: ne fait que restreindre ce que voit un lecteur déjà autorisé, ce n’est pas le consentement lui-même.

Ce que voit l’utilisateur

Les utilisateurs de projet voient et gouvernent le stockage de votre application à deux endroits :

  • La vue Données affiche une entrée Fichiers à côté des tables et des vues de chaque application — un listing consultable de chaque objet stocké avec sa taille, son type et sa date de modification, ainsi qu’un téléchargement fichier par fichier.
  • Les paramètres de stockage de l’application affichent l’utilisation (octets et nombre d’objets), le budget appliqué à côté de la suggestion de votre application, une commande pour modifier le budget, et une action Supprimer tous les fichiers — l’équivalent, côté fichiers, du vidage de toutes les tables. La suppression se confirme en saisissant le nom de l’application et est irréversible.
  • L’assistant IA peut lister, rechercher et lire ces fichiers pour le compte d’un utilisateur. Le même contrôle DATABACKEND/READ s’applique : il ne fait jamais apparaître un fichier que l’utilisateur ne pourrait pas ouvrir lui-même. La recherche porte sur les chemins, pas sur le contenu, et il lit les fichiers texte, les images et les PDF — les archives et les autres formats binaires, non.

Comme pour les tables, ce sont les données de l’utilisateur : il peut les inspecter, les plafonner et les supprimer sans vous impliquer.

Accès S3 direct

Pour tout ce qui dépasse le SDK — un analyste avec DuckDB, une sauvegarde rclone nocturne, un pipeline BI — un utilisateur de projet peut émettre des identifiants S3 en lecture seule par application depuis les paramètres de stockage de l’application.

Chaque identifiant est limité à la zone de stockage de cette seule application : un identifiant émis pour l’application A ne fonctionne pas pour les fichiers de l’application B, structurellement — la politique de stockage de B ne le nomme tout simplement jamais. Un projet peut détenir plusieurs identifiants par application (un par consommateur : une tâche CI, un script de sauvegarde, un ordinateur portable), et en révoquer un laisse les autres fonctionner. C’est aussi la logique de rotation : si une clé fuit, émettez un second identifiant, faites-y basculer le consommateur, puis révoquez le premier — aucun autre consommateur n’est perturbé.

Le secret est affiché une seule fois, à la création. L’émission requiert un accès en lecture au backend de données de cette application — la même permission que celle qui permet de lire les fichiers en premier lieu, de sorte que l’identifiant ne peut jamais élargir la portée de qui que ce soit.

# rclone rclone config create myapp s3 provider=Other \ endpoint=https://s3.ironflock.com \ access_key_id=ifs-key-3317-x7k2m secret_access_key=<shown once> rclone ls myapp:if-1042-3317
# DuckDB CREATE SECRET (TYPE S3, KEY_ID 'ifs-key-3317-x7k2m', SECRET '<shown once>', ENDPOINT 's3.ironflock.com'); SELECT * FROM read_parquet('s3://if-1042-3317/exports/*.parquet');

Les paramètres de stockage indiquent le point de terminaison et le nom exact du bucket vers lequel pointer un client. Notez qu’un listage des buckets de premier niveau (aws s3 ls sans argument) ne renvoie rien, et c’est voulu — l’identifiant ne possède aucun bucket ; il se voit accorder l’accès à un seul. Adressez le bucket directement, comme ci-dessus.

Appliances sur site

Le stockage de fichiers fonctionne de façon identique sur une appliance sur site, avec trois différences qui découlent de la conception de l’appliance :

  • Les fichiers sont servis en même origine sous l’adresse propre de l’appliance (/files/...) — aucun nom DNS supplémentaire, aucun certificat supplémentaire, et cela fonctionne dans les installations en HTTP simple. Les URL permanentes et <img src> se comportent exactement comme dans le cloud.
  • Le backend de stockage de l’appliance transmet les téléchargements de fichiers en flux à travers la plateforme au lieu de rediriger vers un hôte de stockage distinct, de sorte que le service de stockage n’est jamais exposé comme une seconde origine.
  • Les identifiants S3 directs ne sont pas disponibles sur les appliances — le magasin d’objets embarqué ne sait pas exprimer d’autorisations d’accès par identifiant. La section n’apparaît tout simplement pas dans les paramètres de stockage. Tout le reste, y compris le comportement des fichiers volumineux via le SDK et la rétention déclarée, fonctionne de la même façon.

Une appliance isolée du réseau sert tout le trafic de fichiers localement : les logos d’application, les images de tableau de bord et les téléchargements de fichiers n’ont besoin d’aucune connectivité internet.

Récapitulatif des limites

LimiteValeurOrigine
Transfert inline (appel unique)6 MioIndiqué à l’exécution ; peut être relevé côté serveur
Objet unique100 Mio par défaut, 5 Gio maxmaxObjectBytes par espace de noms
Envoi unique5 GioPlafond de PUT unique du magasin d’objets ; le multipart n’est pas encore disponible
Budget de stockage1 Gio en dev / 10 Gio en prod par défautSuggéré par le template, décidé par l’utilisateur
Longueur et caractères de cléUTF-8, chemins séparés par /../, les caractères de contrôle et les préfixes réservés sont rejetés
Last updated on