Box est une messagerie orientée files d’attente (« queues ») pensée pour fonctionner en environnement hostile : dépendance minimale vis‑à‑vis du DNS, priorité à l’IPv6 natif et contrôle strict des identités (UUID utilisateur + UUID nœud). Le dépôt est désormais 100 % Swift 6.2 / SwiftPM ; l’ancienne implémentation C (sources, CMake, scripts) a été retirée.
- Toolchain Swift 6.2 (recommandé : Swiftly,
swiftly install 6.2.0puisswiftly use 6.2.0). - macOS 14+ ou Linux (amd64/arm64) avec IPv6 global si possible.
libsodiumreste requis à terme pour Noise/XChaCha, mais la phase courante fonctionne en clair.- Pour l’administration distante : accès SSH non-root et UFW/nftables configuré en
default deny.
# Construire le binaire SwiftPM (client + serveur dans le même exécutable)
swift build --product box
# Lancer la batterie de tests (unitaires + intégrations CLI, timeout 30 s par scénario)
swift test --parallel- Serveur :
swift run box --server [--port 12567] [--address ::] - Client :
swift run box [--address <ip|[ipv6]>] [--port <udp>] - Canal admin (même exécutable) :
swift run box admin statusouswift run box admin locate <uuid>
L’admin s’appuie sur ~/.box/run/boxd.socket (Unix) ou \\.\pipe\boxd-admin (Windows, à venir). L’exécutable refuse de tourner en root/admin et crée automatiquement ~/.box/{logs,queues,run} avec permissions restreintes.
box put [from [<bind_ipv6>] [port <local_port>]] at <target> [queue <name>] "<payload>" [as <mime>]publie un message.<target>accepte un UUID nœud / utilisateur ou une URLbox://<user_uuid>@<node_uuid|*>[:port]/<queue>.- Quand
<target>est un user UUID oubox://…@*, le client contacte tous les nœuds connus via le Location Service. - En l’absence d’enregistrement
whoswho, le client retombe surclient.address/client.portdéfinis dansBox.plist. queueest optionnelle (INBOXpar défaut) ettext/plainest choisi lorsqu’aucune valeuras <mime>n’est fournie.
box get from <target> [queue <name>]récupère un message (queueINBOXpar défaut, sans destruction lorsqu’elle est marquée permanente).box locate <uuid>résout un UUID nœud ou utilisateur en se basant sur les entrées du Location Service (client → serveur distant).
- Section
common:node_uuid,user_uuid(générés au premier lancement et persistés). - Section
server:port,address,log_level,log_target(par défautfile:~/.box/logs/boxd.log),port_mapping,external_address,external_port,permanent_queues. - Section
client:address,port,log_target, préférences d’auto‑locate. - Les paramètres CLI prennent le pas, puis les variables d’environnement, puis le fichier PLIST.
- Lors de la première exécution, une queue
INBOXet la file permanentewhoswho/sont créées sous~/.box/queues/. swift run box init-config [--rotate-identities] [--json]crée ou répareBox.plist(UUID garantis, sections par défaut) et prépare~/.box/{queues,logs,run}.- Les identités Noise sont gérées par
BoxNoiseKeyStore(~/.box/keys/node.identity.jsonetclient.identity.jsonen hex JSON, prêtes pour l’intégration libsodium).
- Une installation de développement peut se contenter d’un VPS OVH VPS‑2/3 (Ubuntu 24.04/25.04) avec IPv6 statique : cloner le dépôt, installer Swift 6.2, lancer
swift run box --server. - En production : au moins trois serveurs racines géographiquement distincts et fournis aux clients sous forme d’adresses IPv6 statiques. Recommandation actuelle (~265 €/mois HT) :
- OVHcloud Advance‑2 (Roubaix) — ≈ 120 €.
- Hetzner AX52 (Falkenstein) — ≈ 65 €.
- Scaleway EM-A5800 (Paris) ou Exoscale équivalent — ≈ 80 €.
- Aucun load balancer ni DNS dynamique : chaque client conserve une liste triée de racines (
Box.plist→common.root_servers). À chaque minute, tout serveur Box publie sa présence vers chaque racine (whoswho/<node_uuid>.jsonetwhoswho/<user_uuid>.json). Deux rafraîchissements manqués (> 120 s) marquent l’entrée comme expirée. - Les échanges racine⇔nœud seront signés via Noise/libsodium (en cours) afin d’éviter les faux relais.
LocationServiceCoordinatorpublie unLocationServiceNodeRecordcommun aux réponses admin et aux fichierswhoswho/. Chaque enregistrement contient : adresses IPv6/IPv4 (origineprobe|config|manual), état NAT/port mapping (portMapping*), métadonnées de reachability, timestamplastPresenceUpdate.box admin locate <uuid>résout aussi bien un User UUID qu’un Node UUID : en mode utilisateur, la réponse agrège tous les nœuds encore « actifs » (last_seen <= 120 s).- Les queues déclarées dans
server.permanent_queuesne consomment pas leurs messages lors desGET;BoxServerStoreexpose désormaispeekpour les restituer plusieurs fois.
- Sonde IPv6 automatique au démarrage (
hasGlobalIPv6,globalIPv6Addresses,ipv6ProbeError). - Option
--enable-port-mapping/port_mapping = true: séquence UPnP → PCP (MAP+PEER) → NAT-PMP, puis sondeHELLOsur l’endpoint externe. Télemetrie renvoyée via admin :portMappingStatus,portMappingBackend,portMappingPeer*,portMappingReachability*, etc. swift run box admin nat-probe [--gateway <ip>]exécute la séquence côté CLI (tests en CI attendentdisabled|skippedlorsque le mapping est désactivé).swift run box admin location-summary [--json|--prometheus] [--fail-on-stale] [--fail-if-empty]inspectewhoswho/(affiche les nœuds actifs/stale, export Prometheus si demandé, et retourne un code ≠ 0 selon les options — idéal pour la supervision des racines).- Pas de dépendance STUN/ICE ; si la passerelle ne supporte pas ces protocoles, configurer un forwarding manuel et renseigner
external_address/external_port. La validation « succès » denat-probesera traitée sur un jalon ultérieur (post‑0.4.0) lorsque du matériel compatible sera accessible.
BoxCLIIntegrationTestscouvrebox admin status|ping|locate|nat-probe|location-summaryet les flux clientbox locate,box put,box get(queues éphémères et permanentes). Chaque test se termine en < 30 s par design (XCTExpectFailuresi timeout).BoxClientServerIntegrationTestsvérifie PUT/GET/LOCATE via UDP, y compris le comportement « permanent queue ».- Pour lancer manuellement une session de test :
swift test --filter BoxCLIIntegrationTests.testNatProbeDisabled.
Package.swift,Package.resolvedswift/Sources/—BoxCommandParser,BoxCore,BoxServer,BoxClient,BoxAdminswift/Tests/— suites unitaires et intégration Swift (BoxAppTests,BoxCLIIntegrationTests, etc.)systemd/boxd.service— exemple à adapter (ExecStart=/usr/local/bin/box --server)pki/— autorités de test utilisées par les suites crypto (préparation Noise)NEXT_STEPS.md,DEVELOPMENT_STRATEGY.md,SPECS.md— feuille de route et spécification de protocole
- SPECS.md — protocole, format des queues, enregistrements Location Service (
whoswho). - DEVELOPMENT_STRATEGY.md — jalons Swift (S0–S4), opérations/hosting, intégration libsodium à venir.
- NEXT_STEPS.md — backlog court terme (alerting racines, init-config, préparation Noise/libsodium).
- AGENTS.md — aide-mémoire pour les contributeurs.
Le dépôt suit les conventions Swift décrites dans CODE_CONVENTIONS.md. Avant toute contribution :
- formater via
swift format(ouswift-formatsi disponible), - exécuter
swift test --parallel, - mettre à jour la documentation lorsque le comportement change.
Les contributions portant sur l’ancienne base C ne sont plus acceptées.
- La version exposée par
box -vprovient du marqueur// BOX_VERSION: …dansPackage.swift. - Avant de créer une release/tag, mettre à jour cette valeur avec :
scripts/bump_version.swift 0.3.0
- Réexécuter
swift buildouswift testpour régénérer la métadonnée d’exécutable, puis committer avant de publier sur GitHub.