Skip to content

Model entity tags and Memento in the graph store model - #500

Merged
namedgraph merged 2 commits into
developfrom
formal/etags-memento
Oct 27, 2026
Merged

namedgraph merged 2 commits into
developfrom
formal/etags-memento

Conversation

@namedgraph

Copy link
Copy Markdown
Member

Stacked on #499: it's based on formal/http-status, and GitHub retargets it as the stack merges. It is the follow-up to step 4 of the formal roadmap (formal/README.md).

Entity tags (formal/http/LdhHttp/ETag.lean)

  • The tag: a function of the document and its graph (ETags). It is the same for the same set of triples, since toSortedNTriples sorts them. The model's one assumption is that different graphs get different tags, i.e. that the 128 bits of SHA-256 EntityTags.entityTag keeps are collision-free on the graphs that occur.
  • Cond.resolve: reads If-Match against the stored graph, as evaluatePreconditions does.
  • no_lost_update: a write guarded by If-Match with the tag of the graph a client read changes the store only if the document still holds that graph.
  • concurrent_write_changes_nothing: once another write has changed that graph, the client's write changes nothing.

Memento (formal/http/LdhHttp/Memento.lean)

  • TimeGate: selectMemento transcribed. The server picks the commit closest in time, the more recent of two equally close, and the most recent when no datetime is given. RFC 7089 leaves the choice to the server. Proven: the Memento is one of the document's commits (select_mem, select_none_iff), the newest with no datetime (select_latest), and none is closer while every more recent commit is further away (select_closest).
  • TimeMap: toTimeMap transcribed. Each Memento is a prov:wasRevisionOf of exactly the one before it in the history (mem_revisions).
  • Commit queue: VersioningFilter, commitAsync and reconcile. Whenever no reconcile is queued, the newest version is the document's graph (drained_is_current). Versions are snapshots taken when a reconcile runs, not one per write.
  • Version file: path transcribed. It has a collision: versionFile_root_collides. The root document and a top-level document named root/ both map to graphs/root.nt, which I confirmed by calling the real GraphVersioningService.path. On a versioned dataspace they share one file, TimeMap and TimeGate. versionFile_inj proves this is the only collision. The Java is unchanged: a fix would rename the root document's file, and existing repositories' root.nt histories would need migrating.

Checked in CI

  • Golden file: ldh-http --select-cases prints 500 generated histories and datetimes, 64 of them with a tie, together with the model's choice for each. They are committed as src/test/resources/.../memento-cases.tsv.
    • GraphVersioningServiceTest.testSelectMementoAgreesWithTheModel checks the Java against every case.
    • The Formal workflow regenerates the file and fails if it differs from the model.
  • HTTP replay: tests/http/versioning/memento-conformance.sh writes a document four times on a versioned dataspace and reads its history from GitHub. It then checks the TimeMap's members and revision links, and the TimeGate at no datetime, at each commit, midway between two, and outside the history, against ldh-http --select. http-tests now also builds ldh-http.
  • Drift check: formal/http/tracks-code.sh now also watches EntityTags, GraphVersioningService, VersioningFilter and GitHubClient.

Testing

  • lake build of both packages: no sorry; the axioms are propext, Quot.sound and Classical.choice
  • tracks-code.sh for both packages
  • GraphVersioningServiceTest: 15 tests pass, including the 500 golden cases. Corrupting one expected index makes the new test fail on that case.
  • The golden file is byte-identical to a fresh ldh-http --select-cases
  • memento-conformance.sh, not yet run. It needs the versioning test repo, so it skips locally and runs in CI where VERSIONING_TEST_TOKEN is set.

🤖 Generated with Claude Code

namedgraph and others added 2 commits October 26, 2026 23:52
ETag.lean takes the entity tag as a function of the document and its graph, collision-free by
assumption, resolves If-Match against the stored graph as evaluatePreconditions does, and proves
that a write guarded by the tag of the graph a client read changes the store only if the document
still holds that graph.

Memento.lean transcribes the TimeGate (the closest commit, the more recent of two as close, the
most recent with no datetime), the TimeMap (the history, each Memento a revision of the next one
down it), the commit queue (once drained, the newest version is the document's graph) and the
version file, where the root document and a top-level document named root collide.

The TimeGate is replayed against the Java on 500 cases ldh-http --select-cases generates, which
GraphVersioningServiceTest checks and the Formal workflow regenerates, and against the server by
tests/http/versioning/memento-conformance.sh on a versioned dataspace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A section after the test suite's: what the graph store and access control models prove, how the Formal workflow and
the HTTP replay keep them tied to the code, and a link to the roadmap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@namedgraph
namedgraph changed the base branch from formal/http-status to develop October 27, 2026 08:02
@namedgraph
namedgraph merged commit 353d37e into develop Oct 27, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant