Moteur client local du protocole Aithos.
Statut :
0.1.0-alpha.1en préparation — verticale A–D–W validée. Le moteur offline, le binding WASM minimal, les handles opaques et les sessions navigateur en mémoire sont verts. Le contrat W rejoue 19 scénarios concrets et 117 étapes sans@wip. La mutation E est explicitement hors de cette première prérelease, plutôt que publiée sous une forme partielle.
aithos-client reçoit des artefacts Aithos non fiables et des capacités locales,
puis décide et exécute les opérations protocolaires autorisées :
- vérifier DID, éditions, racines, certificats et gamma ;
- vérifier une chaîne de mandats, sa portée, ses contraintes et ses révocations ;
- utiliser des clés locales sans les exposer à l'appelant ;
- déchiffrer uniquement ce que l'autorité courante permet de lire ;
- produire des artefacts chiffrés et signés pour une publication ultérieure ;
- produire des enveloppes de requête signées sans effectuer la requête.
Le client est offline par construction. Il ne connaît ni HTTP, ni provider, ni control plane, ni gateway, ni tenant de facturation.
La première API disponible est volontairement étroite :
let snapshot = ArtifactSnapshot::try_from_iter(artifacts)?;
let verified = snapshot.cold_verify()?;VerifiedSnapshot n'est constructible qu'après vérification du DID, de toutes
les éditions, des pins, du gamma et des racines engagées. À ce stade, il expose
uniquement la provenance vérifiée, jamais les octets internes ni du plaintext.
Une session locale ajoute ensuite une preuve de possession fraîche :
- l'Owner prouve
content_signet la clé KEX publiées dans son DID ; - le grantee prouve la clé feuille d'une chaîne de mandats valide ;
- le challenge lie rôle, DID, édition, temps et nonce injecté ;
- la clé root owner n'entre jamais dans le keyholder de session courant ;
- verrouiller ou abandonner une session détruit son autorité locale.
Le keyholder ne signe pas des octets arbitraires : il reçoit uniquement un
SessionChallenge construit par le client et non constructible par l'appelant.
La session expose une provenance publique, jamais les secrets importés.
Chaque lecture circle passe ensuite par une décision distincte :
let authorized = session.authorize_read(
ReadIntent::circle("projets/note"),
AuthorizationContext::new("2026-07-05T12:30:00Z"),
)?;Le chemin d'affichage est résolu par aithos-bundle vers sa cible canonique.
Pour un grantee, le client rejoue à l'instant de l'opération la chaîne complète,
les révocations, les fenêtres actives et la couverture du périmètre. La décision
emprunte la session qui l'a produite et enregistre édition, cible et provenance,
avant toute ouverture de header ou de ciphertext.
La même session peut ensuite produire un read-model stable et ouvrir le contenu couvert :
let read = session.read_content(
Zone::Circle,
"projets/note",
AuthorizationContext::new("2026-07-05T12:30:00Z"),
ReadLimits::default(),
)?;Les opérations de contenu sont construites par le client et exécutées à travers
le keyholder opaque. L'Owner conserve seulement content_sign et owner_kex,
jamais la clé root. Un grantee est réautorisé à l'instant de chaque lecture,
même si une ancienne capacité cryptographique pourrait encore ouvrir les
octets. Les sorties et diagnostics n'exposent ni clé, ni wire row, ni plaintext
en cas de refus.
La première intégration produit visera le dashboard dans le navigateur :
- le dashboard ou une fine couche de transport récupère les artefacts chiffrés ;
- un binding WASM minimal transmet ces octets au moteur Rust ;
- la capacité owner, ou la paire clé + mandat du grantee, est importée localement dans une session mémoire ;
- une même clé importée peut louer plusieurs sessions isolées, chacune liée à son propre Ethos et à sa propre chaîne de mandats ;
- le moteur vérifie, autorise et déchiffre localement ;
- aucun secret ni plaintext n'est envoyé au provider ou à Aithos.
Le client reste volontairement mono-Ethos par session. Une application d'entreprise peut conserver un catalogue d'Ethos et orchestrer plusieurs sessions simultanées au-dessus du client ; croiser un mandat ou un handle avec un autre Ethos est refusé avant toute utilisation de clé.
Ce premier palier ne comprend pas encore la persistance sécurisée des clés, le support matériel, l'isolation avancée ni le durcissement complet du déploiement. Il ne reporte toutefois ni la vérification cryptographique, ni le contrôle des mandats, ni le refus fail-closed.
Dashboard / application
|
v
Aithos SDK réseau, sync, cache, CAS, retries
|
v
Aithos Client décision, vérification, crypto, artefacts
|
+----+----+
v v
aithos-core aithos-bundle
Le SDK déplacera les octets. Le client déterminera ce qu'ils signifient et s'ils sont acceptables. Le SDK ne construira jamais lui-même un mandat, un manifest, une entrée gamma ou une enveloppe signée.
- Zéro réseau. Aucune dépendance HTTP, DNS ou socket dans le graphe client.
- Deux portes pour un grantee. Une clé qui ouvre ne suffit pas : la chaîne de mandats doit aussi autoriser l'opération à l'instant injecté.
- Entrées non fiables. Tout pack venant du provider est hostile jusqu'à vérification complète.
- Clés opaques. L'API expose des opérations, jamais les octets secrets.
- Fail-closed. Une ambiguïté de chaîne, de tête, de preuve ou de portée est un refus nommé, sans plaintext partiel.
- Une seule logique protocolaire. Le client orchestre
aithos-coreetaithos-bundle; il ne réimplémente aucun wire ni primitive. - Temps et entropie injectés. Aucun comportement de sécurité ne lit implicitement l'horloge ou le RNG.
Pour chaque phase :
- écrire le parcours Gherkin en anglais, avec scénarios
@wip; - faire valider le contrat avant le code ;
- committer le contrat seul ;
- écrire le vecteur indépendant ou le test unitaire rouge ;
- implémenter en TDD ;
- détaguer les scénarios un à un ;
- exécuter la suite E2E réelle, puis fmt, clippy et tests ;
- faire valider le gate avant la phase suivante.
Voir docs/EXECUTION-PLAN.md.
cargo fmt --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo check -p aithos-client-wasm --target wasm32-unknown-unknown
./scripts/build-browser.sh
./scripts/check-native.sh
./scripts/smoke-npm.shLe harnais Cucumber natif ignore uniquement les scénarios explicitement @wip
et les features @browser, exécutées par le harnais du crate WASM.
Le script de gate vérifie aussi que le graphe normal du client ne contient
aucune bibliothèque HTTP, DNS ou socket connue.
Les dépendances Core et Bundle utilisent la version exacte
=0.1.0-alpha.1, tout en conservant les chemins frères pour le développement
local. Le crate WASM reste non publiable sur crates.io : il alimente uniquement
le paquet navigateur.
Le nom public @aithos/client est confirmé. Le paquet déclare explicitement
une publication publique sous le dist-tag de prérelease next. Le scope
@aithos contient déjà une ligne legacy distincte ; aucun package existant
ne sera remplacé silencieusement.
npm install @aithos/client@nextVoir docs/RELEASE-BOUNDARY.md pour la frontière de la prérelease et la séparation avec la mutation E et le futur SDK. Les notes de prérelease sont dans CHANGELOG.md.
Le logiciel utilise BUSL-1.1 avec l'Additional Use Grant Aithos et bascule vers Apache-2.0 le 19 juillet 2030. Les documents et vecteurs utilisent CC BY 4.0. Voir LICENSE et LICENSE-DOCUMENTATION.md.
crates/aithos-client/ moteur offline
features/ contrats d'acceptation Gherkin
vectors/ fixtures et attentes indépendantes
docs/EXECUTION-PLAN.md ordre, gates et définition de fini
npm/ manifeste, README et types du paquet navigateur