Files
ng-eventually/docs/decisions/sparql-delete-for-orm-objects.md
T
Sylvain Duchesne bea9f51d91 docs: own the current-NextGraph-state knowledge + boundary (lib side)
This library presents a mature-NextGraph SDK face to consumers while
compensating for the current SDK's gaps via a shared-wallet simulation. It
therefore OWNS all current-state + simulation knowledge — moved here out of the
Festipod app repo, which must treat this library as a finished SDK.

New docs/:
- nextgraph-current-state.md — what the current SDK/broker do and don't expose
  (5 store types, document=repo, per-document ReadCap, inbox not exposed, iframe
  RPC proxy, mono-user/no-global-data, wallet import constraint). Keeps the
  nextgraph-rs source pointers.
- simulation.md — how the lib emulates the mature behaviour on one shared wallet
  (shim, store!=document two axes, docCreate→private store, RepoNotFound scope
  rule, @ng-org double-proxy DataCloneError, emulated ReadCap/inbox/curator).
- decisions/ — the current-SDK ADRs (private-store-nuri-scope, sparql-delete,
  shared-wallet-login, discovery mechanism).
- fork-inbox-fallback.md — the Rust-patch/self-host route not taken.
- migration-guide.md — the checklist for when real NextGraph matures.

README: boundary framing from the lib's side + docs/ index; replaced the stale
"scaffold/stubbed" status with the actually-implemented mechanisms per source.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 23:23:23 +02:00

2.5 KiB

ADR — Use SPARQL DELETE (not ORM ngSet.delete()) to remove objects

Date: 2026-03-17 · Status: Accepted → Superseded (2026-06-15). Historical decision, ported for the current-SDK behaviour it records. Original context: the consuming app.

Superseded (2026-06-15). The ngSet.delete() non-persistence bug that motivated this decision was largely fixed upstream in @ng-org/orm; deletion code went back to ngSet.delete(). Kept as arbitration memory — the CRDT conflict rule ("don't combine the two") still holds.

Context

Removing an object from the NextGraph store: DeepSignalSet.delete() updates the local reactive state (immediate UI) but does not persist to the broker — after refresh the object reappears.

Options considered

A — ORM ngSet.delete(item)

Official API, instant local reactive update. Against: did not persist in practice (delete() returned true, local set updated, object back after refresh); graph_orm_update seemed to mishandle "remove" patches for top-level set objects (likely engine bug); failed silently.

B — ng.sparql_update() with SPARQL DELETE

DELETE WHERE { GRAPH <graph> { <subject> ?p ?o } } removes all the RDF triples. For: persists (survives refresh); the broker confirms via a GraphOrmUpdate op: "remove" that reactively removes the item from the ORM set; direct control. Against: not instant (~50ms SPARQL round-trip + broker callback); must NOT be combined with ngSet.delete().

C — both together

Does not work: the ORM .delete() patch and the SPARQL DELETE conflict at the CRDT level → neither UI nor persistence.

Decision

Option B — SPARQL DELETE alone. The broker returns a GraphOrmUpdate op: "remove" that reactively removes the item from the ORM set (UI updates, just not synchronously). Do NOT call ngSet.delete() alongside.

await ng.sparql_update(
  session_id,
  `DELETE WHERE { GRAPH <${partGraph}> { <${partId}> ?p ?o } }`,
  partGraph,
);

This is the authoritative-delete pattern this lib's emulation relies on for inbox deposits and shim graphs (an interpolated NURI/subject must pass through assertNuri/escapeLiteral first — see SPARQL hardening in ../simulation.md).

Consequences

  • Positive: deletion persists; single source of truth (broker → ORM → UI).
  • Negative: slight UI delay (~50ms); diverges from the ORM README examples.
  • Risk: if ng.sparql_update changes, this breaks; revisit as ngSet.delete() matures upstream.