fix(inbox): une inbox appartient à un document, jamais à plusieurs
Retour sur l'adresse par défaut livrée en 8a382f2, qui faisait pointer tout
document vers l'inbox de son propriétaire. C'était acheter le coût au prix de
la forme — le mauvais arbitrage pour cette bibliothèque.
Vérifié en amont : le verifier route un message entrant par
`inboxes: PubKey → RepoId` (`engine/verifier/src/verifier.rs:1677,1928`) et le
déchiffre avec la moitié privée de CE repo. Et `InboxMsgBody`
(`engine/net/src/types.rs:4265`) ne porte aucun document cible — il n'en a pas
besoin : l'adresse EST l'identification. Une inbox appartient donc à exactement
un repo, et faire tenir plusieurs documents derrière une inbox émule une
relation que le modèle ne peut pas exprimer.
Conséquences :
- `createEntityDoc` ne publie plus rien. Un document neuf n'a pas d'inbox et
`documentInboxAddress` rend `undefined`.
- Une inbox s'ouvre par `openDocumentInbox(doc)`, sur décision du propriétaire.
C'est aussi ce qui règle le coût sans toucher à la forme : seuls les
documents destinés à RECEVOIR en paient une — l'app le sait, la bibliothèque
non.
- `inbox.postToDocument(doc, { payload })` : l'app nomme le DOCUMENT, jamais une
inbox. Lève quand le document n'en a pas, au lieu de rendre la main
silencieusement — un dépôt qui disparaît sans erreur est exactement le bug que
ce chemin traînait.
- Pas de champ « document cible » sur un dépôt. Ce serait une invention que les
apps devraient désapprendre à la migration.
README, principe de conception : les deux moitiés sont contraignantes, et c'est
la seconde qu'on brade. La surface doit être au plus près du futur SDK, mais
l'IMPLÉMENTATION aussi doit être au plus près de ce que NextGraph prévoit, sans
exception. Ce qui est connu vaut spécification. La pression à dévier ne se
présente jamais comme une déviation : elle arrive comme un coût, une latence,
une gêne d'ergonomie — bien réels. Deux cas déjà rencontrés sont consignés, avec
le signal commun : un choix qui ferait apprendre au consommateur quelque chose
qu'il devra DÉSAPPRENDRE.
157 tests unitaires, e2e 40/40 contre le broker en ligne.
This commit is contained in:
@@ -77,6 +77,35 @@ The application code is written as if the target NextGraph existed. All
|
||||
compensation lives here, beside the app. As NextGraph matures, this layer falls
|
||||
away; the app code (SDK-shaped) is unchanged.
|
||||
|
||||
**Both halves are binding, and the second is the one that gets traded away.** The
|
||||
SURFACE must be as close as possible to the future SDK — that much is obvious, it is
|
||||
what the consumer codes against. But the IMPLEMENTATION must be as close as possible to
|
||||
what NextGraph actually plans, and there is no exception to that. Where upstream's
|
||||
behaviour is known, it is a specification, not a reference: **when it is known, hold to
|
||||
it**. What "known" means here is narrow — read in `nextgraph-rs` or stated by the
|
||||
NextGraph developer, never inferred from what an npm package happens to expose, and
|
||||
never inferred from an absent implementation ("the engine has no X" says nothing about
|
||||
whether the target will).
|
||||
|
||||
The pressure to deviate never announces itself as a deviation. It shows up as a cost, a
|
||||
latency, an ergonomic wrinkle — a real one. Two instances, both caught only by asking
|
||||
the question:
|
||||
|
||||
- *Every document has a native inbox* was written into the docs from general
|
||||
reasoning. It is false, and it had already become an implementation.
|
||||
- A per-document inbox was made to point at **the owner's** inbox, to avoid a measured
|
||||
cost (9m37 → 21m30 on the consumer's suite). It emulates a many-to-one relation
|
||||
upstream cannot express: the verifier routes by `inboxes: PubKey → RepoId` and unseals
|
||||
with that one repo's key (`engine/verifier/src/verifier.rs:1677,1928`), and a message
|
||||
carries no target document because it needs none. Reverted. The cost was then solved
|
||||
without touching the shape — only documents meant to receive open an inbox.
|
||||
|
||||
The tell in both: an implementation choice that would make the consumer learn something
|
||||
it must **unlearn** at migration. That is the thing this library exists to prevent, so
|
||||
it outranks cost, latency and convenience. When the shape and the cost conflict, keep
|
||||
the shape and attack the cost elsewhere — and if it truly cannot be solved, say so
|
||||
rather than bend the model quietly.
|
||||
|
||||
- SDK-identical surface: the client wraps the real `ng` (a Proxy that forwards
|
||||
everything and overrides only what must be emulated) and `useShape`. The real
|
||||
SDK is injected via `configure()` (no hard import → build-alias safe and
|
||||
|
||||
Reference in New Issue
Block a user