fix: readUnion regroupe par sujet réel — la fusion était une divergence
`readUnion` indexait par DOCUMENT une table nommée `bySubject`, créait ses entrées avec `subject: doc`, et jetait le sujet réellement lu après s'en être servi pour écarter la machinerie. Tout triplet non-machinerie d'un document tombait donc dans un sac unique étiqueté par la référence du document : deux entités écrites sous deux sujets revenaient **conflées**, une entité écrite sous un autre sujet revenait **ré-étiquetée**. Sans erreur, sans trace. **C'était une divergence, et c'est à ce titre qu'elle tombe.** NextGraph dit l'inverse aux deux niveaux : une requête ancrée résout le graphe du repo comme graphe par défaut et rend les sujets tels qu'ils sont ; et l'ORM porte sur chaque objet **deux** propriétés distinctes, `@id` et `@graph`, dont il FABRIQUE la première quand on la laisse vide (`graphIri + ":q:" + aléa`). Plusieurs objets par graphe est le cas prévu, et `@id` existe pour les distinguer à l'intérieur d'un `@graph`. La règle du projet reste **« un document séparé par entité métier »**, mais c'est une recommandation de placement dictée par le modèle de sécurité — une clé est par repo, donc l'isolation par entité exige un repo par entité. Ce n'est pas une contrainte que la lecture a le droit d'imposer en rendant l'autre disposition invisible. Le contrat porte désormais la recommandation, le code porte la capacité ; il faisait exactement l'inverse. **La justification de l'épinglage était une erreur de catégorie**, et elle a été retirée plutôt que contournée : `repo_graph_name` formate un nom de GRAPHE, il est estampillé sur les quads et aucun sujet n'est réécrit. Deux confirmations indépendantes, dont la suite e2e qui écrit un sujet puis le relit par correspondance exacte contre le vrai broker. `UnionSubject.subject` passe de `Nuri` à `string` — un sujet RDF réel est un IRI quelconque. `graph` reste `Nuri` et devient le champ à repasser au SDK ; l'app d'exemple l'utilise à ses deux sites, où le sens était « le document ». **Et la suite e2e ne comptait que les entrées.** C'est pour cela qu'elle est restée verte pendant tout le défaut : compter ne distingue pas un regroupement par document d'un regroupement par sujet. Elle écrit maintenant deux sujets dans le dernier document et vérifie les trois choses qui comptent — quatre entrées pour trois documents, chaque entrée portant le sujet sous lequel elle a été écrite, et son `graph` étant la référence du document. 202 tests unitaires (5 ajoutés, dont 3 échouent si l'on restaure l'ancien repliage), e2e 42/42 et applicatif 12/12.
This commit is contained in:
@@ -54,7 +54,7 @@ export const storeRegistry: { // no identity parameter — the session
|
||||
|
||||
// ── reading ──────────────────────────────────────────────────────────────
|
||||
export async function readUnion(docs: NuriLike[]): Promise<UnionSubject[]>;
|
||||
export interface UnionSubject { subject: Nuri; graph: Nuri; props: Record<string, string[]> }
|
||||
export interface UnionSubject { subject: string; graph: Nuri; props: Record<string, string[]> }
|
||||
export function useShape(shapeType: unknown, scope: unknown): unknown; // read-filtered view
|
||||
export function watchShape(query: ShapeQuery): ShapeObservable;
|
||||
export function subscribeDoc(nuri: NuriLike, onChange: (r: DocChange, t: DocChangeType) => void): Unsubscribe;
|
||||
@@ -97,6 +97,10 @@ export function initNg(...args: any[]): any;
|
||||
|
||||
**A reference is not recursive.** A widely circulated document may point at a restricted one; following the reference yields a name, not a key. This is what lets confidentiality be composed inside a document you share, and it holds through every read path here.
|
||||
|
||||
**A document may hold several objects, and reading returns them separately.** `readUnion` yields one entry per distinct subject present in a document: `subject` is that subject's IRI exactly as it was written, `graph` is the document reference you passed in. Properties of different subjects are never merged, and the same subject IRI found in two documents stays two entries, told apart by `graph`. Only `graph` is a `Nuri`, and it is the field to hand back to this surface; `subject` is a `string`, because a subject may be any IRI. **One document per business entity stays the recommended placement** — a key is per document, so isolating an entity requires a document of its own — but it is a recommendation, and reading reports the objects a document actually holds.
|
||||
|
||||
**`urn:ng-eventually:` is a reserved name space.** Subjects under that prefix belong to the library and are not returned by `readUnion`. An application that writes its own data under it will not read it back; every other IRI is yours.
|
||||
|
||||
**Writing is ownership.** Only a document's owner writes to it. Holding its read key — however it arrived — never grants a write.
|
||||
|
||||
**Giving to read is ONE act, and the recipient calls nothing.** `inbox.share(doc, toUser)` names the document and the person; the key is looked up and sealed into a deposit, and the recipient applies it by connecting. There is no "receive" operation, and an application never handles a key or an inbox address.
|
||||
|
||||
Reference in New Issue
Block a user