Use case: time-travel audit & compliance snapshots
Every fact in little big brain is append-only and carries its own provenance, so the graph already is an audit log and you do not build a separate one. To answer a compliance question like “who had access to customer PII on 2026-06-15?” you read the graph as it was at that point in time, and every read echoes back the exact snapshot it ran against, so the result stays citable.
This guide builds a small audit and compliance viewer on two primitives.
-
The bitemporal cursor pins any read to a past commit (
as_of_commit_seq) or a past instant (as_of_valid_time). -
Run a compliance query at a past commit. Pin a SPARQL query with
as_of_commit_seq. The response echoes the pin, so the result set and its watermark can be stored together as one audit record.Terminal window curl -sS -X POST "https://0abc1def--production.db.eu.littlebigbrain.com/v1/query/sparql-text?graph=main" \-H "Authorization: Bearer $LBB_API_KEY" \-H "Content-Type: application/json" \-d '{"query":"SELECT ?service WHERE { ?service <https://littlebigbrain.com/r/had_access_to> ?pii }","as_of_commit_seq":96}'A pin past head is an
invalid_inputerror, so a stale pin is never silently served as a head read. -
Reproduce one entity’s state as-of that commit. The same pin works on the point-read surfaces, so you can read exactly what the graph held about a single subject.
POST /v1/query/statereturns the entity’s current relations at the pinned commit, andPOST /v1/query/transitionstraces one status relation’s history.Terminal window curl -sS -X POST "https://0abc1def--production.db.eu.littlebigbrain.com/v1/query/state?graph=main" \-H "Authorization: Bearer $LBB_API_KEY" \-H "Content-Type: application/json" \-d '{"entity": {"type": "SERVICE", "name": "billing-service"},"relations": ["HAS_ACCESS_TO"],"as_of_commit_seq": 96}'const state = await lbb.currentState({entity: { type: "SERVICE", name: "billing-service" },relations: ["HAS_ACCESS_TO"],as_of_commit_seq: 96,});// state.snapshot.as_of_commit_seq === 96state = lbb.current_state({"entity": {"type": "SERVICE", "name": "billing-service"},"relations": ["HAS_ACCESS_TO"],"as_of_commit_seq": 96,})# state["snapshot"]["as_of_commit_seq"] == 96Request-time SHACL shape selection is not a query surface. Treat published conformance as its own versioned artifact, as described next.
-
Record published conformance separately. Read
GET /v1/ontology/conformanceand store itsvalidated_at_seq, ontology version, and shapes version with the audit. Validation is a durable maintenance artifact, and the HTTP request never revalidates an arbitrary past snapshot. A strong request returnsstrong_read_pendinguntil the report matches head.Terminal window curl -sS "https://0abc1def--production.db.eu.littlebigbrain.com/v1/ontology/conformance?graph=main&consistency=strong" \-H "Authorization: Bearer $LBB_API_KEY" -
Stream the change-log between two points.
GET /v1/graph/changesreturns everything committed since a commit seq: entities, observations, andedge_eventswith anopofassert,retract,supersede,confidence_update, orannotation. This is the diff and audit trail: the record of what access was granted and what was revoked between two dates. There is no dedicated SDK method, so call the endpoint directly and honortruncatedandnext_since.Terminal window curl -sS "https://0abc1def--production.db.eu.littlebigbrain.com/v1/graph/changes?graph=main&branch=main&since=64&limit=500" \-H "Authorization: Bearer $LBB_API_KEY"A single response looks like:
{"from_commit_seq": 64,"to_commit_seq": 96,"entities": [ { "id": "...", "type": "SERVICE", "name": "billing-service", "commit_seq": 71 } ],"observations": [ { "id": "...", "commit_seq": 88, "text": "access review note" } ],"edge_events": [ {"edge_event_id": "...", "source": "SERVICE", "source_id": "...","relation": "HAS_ACCESS_TO", "target": "DATASET", "target_id": "...","op": "retract", "commit_seq": 90} ],"next_since": 96,"snapshot_token": "...","truncated": false,"reset": false}Because a large window can be paged, keep calling with
since=next_sincewhiletruncatedistrue:async function auditTrail(since: number) {const base = "https://0abc1def--production.db.eu.littlebigbrain.com/v1/graph/changes";const headers = { Authorization: `Bearer ${process.env.LBB_API_KEY}` };const events: unknown[] = [];let truncated = true;while (truncated) {const url = `${base}?graph=main&branch=main&since=${since}&limit=500`;const page = await fetch(url, { headers }).then((r) => r.json());events.push(...page.edge_events);since = page.next_since; // advance the cursortruncated = page.truncated; // stop when the window is drained}return events;}import os, requestsdef audit_trail(since: int):base = "https://0abc1def--production.db.eu.littlebigbrain.com/v1/graph/changes"headers = {"Authorization": f"Bearer {os.environ['LBB_API_KEY']}"}events, truncated = [], Truewhile truncated:params = {"graph": "main", "branch": "main", "since": since, "limit": 500}page = requests.get(base, headers=headers, params=params).json()events.extend(page["edge_events"])since = page["next_since"] # advance the cursortruncated = page["truncated"] # stop when the window is drainedreturn eventsFilter the collected
edge_eventsbyopto separate grants (assert) from revocations (retract/supersede), and you have a per-relation change history for the review period. A response withreset: truemeansnext_sinceis no longer valid, so re-read from the start.
Why this shape
Section titled “Why this shape”- The graph is the audit log. Facts are append-only with provenance, so a
point-in-time question is answered by a read. Nothing is overwritten: a
revoked grant becomes a
retractedge event and the earlier grant stays on the record. - Pins are exact while retained.
as_of_commit_seqselects one immutable generation and every response echoes the pin insnapshot.as_of_commit_seq. The server never substitutes a nearby generation. SPARQL retains the current generation plus 15 predecessors by default; outside that window it returnshistorical_generation_unavailable. - Two clocks, one cursor.
as_of_commit_seqanswers “what was recorded at commit N?” andas_of_valid_timeanswers “what was true in the world at time T?” Compliance questions usually need valid-time, the state on the date of record. Reproducing a specific past query uses the commit pin.
Related
Section titled “Related”- Load RDF data: the writes whose history you replay here.
- Reasoning & inference: reasoning pins to the same bitemporal cursor, so you can reason over the graph as it was.
- Branch-per-session workspaces: merges preserve event ids, so a merged branch keeps its place in this history.
- HTTP API & SPARQL protocol: the raw endpoints and the bitemporal cursor reference.