Présentation
once est un utilitaire écrit en Go (compatible Go 1.27+) qui exécute une commande dans le répertoire courant, affiche son stdout et conserve ce résultat en mémoire via un petit démon utilisateur. Le cache persiste tant que la clé de cache (tenant, répertoire et commande) reste valide ; il disparaît automatiquement dès que la dernière entrée expire.
Fonctionnement et architecture
Lorsqu’une invocation once --ttl 8h --no-dir -- op read op://Private/GitHub/token est lancée, le client crée une clé de cache composée du tenant (défini par la variable d’environnement ONCE_TENANT ou --tenant), du répertoire de travail (sauf si --no-dir est indiqué) et de la chaîne de commande complète. Cette clé est hachée avec HMAC‑SHA256, garantissant une identification unique sans révéler le contenu de la commande.
Le démon, lancé en arrière‑plan, maintient un tableau d’entrées contenant le hachage, le résultat stdout, le code de sortie et un horodatage d’expiration. L’expiration est calculée à partir de deux paramètres : --ttl, durée relative (ex. 30m, 1h), et --until, date/heure absolue. L’entrée est supprimée dès que l’un des deux critères est atteint. Si --until est déjà passé, la commande s’exécute normalement mais le résultat n’est pas mis en cache.
once --ttl 1h -- sh -c 'op item get "AWS" --format json | jq -r .fields[0].value'Le démon ne stocke que stdout. stdin et stderr sont transmis en temps réel, ce qui préserve le comportement interactif (par ex. la saisie d’un empreinte digitale). Les commandes qui renvoient un code de sortie non nul ne sont jamais mises en cache, afin d’éviter la persistance d’erreurs.
Analyse des impacts et limites
Le principal avantage réside dans la réduction du nombre d’appels répétés à des services externes, comme 1Password, où chaque appel nécessite une authentification biométrique. En limitant les appels, on diminue la charge réseau et le temps d’attente utilisateur. Cependant, le cache n’est pas conçu comme une barrière de sécurité : le tenant key n’est pas secret et ne doit pas être considéré comme un mécanisme d’isolation. Un attaquant disposant d’un accès au même compte utilisateur pourrait récupérer les valeurs mises en cache en interrogeant le démon.
Le modèle de stockage en mémoire implique que les données sont perdues lors d’un redémarrage du processus ou du système d’exploitation. Aucun mécanisme de persistance sur disque n’est fourni, ce qui limite l’utilisation à des sessions temporaires. De plus, la dépendance à un démon unique signifie qu’une défaillance du démon entraîne la perte de toutes les entrées, même si le client continue de fonctionner.
Enfin, la granularité du cache repose sur la combinaison répertoire + commande. Dans des environnements où la même commande produit des sorties différentes selon le contexte (par ex. git rev-parse HEAD), l’option --no-dir doit être évitée, sous peine d’obtenir des résultats incohérents.