fix: quatre écarts entre la surface publiée et ce que NextGraph déclare

Un audit de la surface contre la source amont en a trouvé cinq ; voici les
quatre mécaniques. La cinquième — l'adresse d'inbox, qui traverse sept symboles
— relève du dessin et reste ouverte.

L'identifiant de session bloquait. Amont le déclare string | number
(sdk/js/web/src/index.ts:16) et le binding désérialise un u64 ; nous exigions
une chaîne. Une application ne pouvait donc pas passer la valeur que le SDK
venait de lui remettre. Élargi à ce qu'amont déclare, sur toute la chaîne, et
jamais converti : une chaîne échoue pour de vrai (Deserialization error of
session_id JsValue("1"), observé).

sparqlUpdate annonçait Promise<void> alors qu'il relayait DÉJÀ les commits.
C'était donc un mensonge de typage, pas un comportement — et la doublure de test
qui rendait undefined, un état que le vrai broker ne produit jamais, est ce qui
l'a laissé sans contradicteur.

ng était publié en Record<string, any>, ce qui perdait les 88 membres typés
d'amont — 88, pas 77 : le chiffre de notre propre documentation était faux.

Et materialize, second nom publié de read, sans appelant ni contrepartie amont,
est retiré.

docs/api-contract.md qualifiait docs.* de passthrough « 1:1 ». C'était faux sur
les deux premiers points. Corrigé, pas complété : un document qui se déclare
vérifié et qui ment est pire qu'un document absent, parce qu'on cesse d'aller
voir.

Une déviation assumée : amont type le retour en any, interdit ici ; on rend
unknown, comme sparqlQuery le fait déjà pour le même any amont.
This commit is contained in:
Sylvain Duchesne
2026-08-14 10:00:40 +02:00
parent e32b6d04fc
commit 12eba6eea6
17 changed files with 227 additions and 99 deletions
+19 -4
View File
@@ -44,8 +44,15 @@ function rowCount(result: unknown): number {
* document in the (shared) private store: `docCreate(sid, "Graph", "data:graph",
* "store")` (store_repo left undefined → private store).
*/
// The session id is `string | number` because that is what upstream DECLARES for it
// (`Session.session_id`, `sdk/js/web/src/index.ts:16` and the installed `index.d.ts:266`),
// and the wasm side deserializes it as a `u64` (`sdk/js/lib-wasm/src/lib.rs:352-358`
// `sparql_query`, `:452-457` `sparql_update`, `:1575` `doc_create`). It only ever TRAVELS
// through this chain — never normalise it, and above all never stringify it: a JS string
// fails that deserialization, observed live as
// `Deserialization error of session_id JsValue("1")`.
export async function docCreate(
sessionId: string,
sessionId: string | number,
crdt: string,
cls: string,
dest: string,
@@ -82,13 +89,21 @@ export async function docCreate(
*
* Mirrors `ng.sparql_update(session_id, query, anchor?)`, where `anchor` is the
* document NURI the update is scoped/base'd to (optional).
*
* Returns what the real method returns: upstream answers the COMMITS the update
* produced (`sdk/js/lib-wasm/src/lib.rs:481-483` serialises `AppResponseV0::Commits`;
* the installed `index.d.ts:297` types it `Promise<any>`). This function already
* relayed that value at runtime — only the declared type said `void`, which threw the
* answer away for every caller. Typed `unknown` rather than `any`, exactly as
* {@link sparqlQuery} already renders the same upstream `Promise<any>`: the value is
* the broker's to shape, and a caller that ignores it is unaffected.
*/
export async function sparqlUpdate(
sessionId: string,
sessionId: string | number,
query: string,
anchorLike?: NuriLike,
label = "sparqlUpdate",
): Promise<void> {
): Promise<unknown> {
const { ng } = getConfig();
const anchor = anchorLike === undefined ? undefined : toNuri(anchorLike, "docs.sparqlUpdate");
// The boundary, in two questions that are NOT the same one.
@@ -117,7 +132,7 @@ export async function sparqlUpdate(
* query base IRI (usually `undefined`); `anchor` is the document NURI to query.
*/
export async function sparqlQuery(
sessionId: string,
sessionId: string | number,
query: string,
base?: string,
anchorLike?: NuriLike,