Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
3f8612f
Add pluggable storage layer to TinkerStorageGraph
spmallette Jul 14, 2026
9258a7d
Move TinkerStorageGraph storage changelog entries to 4.0.0 section
spmallette Jul 30, 2026
9119429
Make TinkerStorageGraph commits fsync-durable with a configurable syn…
spmallette Aug 3, 2026
432820e
Serialize concurrent commit writes to TinkerStorageGraph storage
spmallette Aug 3, 2026
2d2fb96
Lock TinkerStorageGraph storage directory to a single writer
spmallette Aug 4, 2026
c306c61
Auto-compact TinkerStorageGraph log to bound its growth
spmallette Aug 4, 2026
e12352e
Stream TinkerStorageGraph snapshots one element at a time
spmallette Aug 4, 2026
1047d18
Add integrity checks to TinkerStorageGraph storage format
spmallette Aug 4, 2026
57217ff
Add crash-consistency and streaming-scale tests for TinkerStorageGrap…
spmallette Aug 4, 2026
d5b30cc
Record TinkerStorageGraph format version once per store
spmallette Aug 4, 2026
64b73a7
Document TinkerStorageGraph durability, compaction, and locking
spmallette Aug 4, 2026
bfef424
Extract AbstractLogStorage base from GraphBinaryStorage
spmallette Aug 19, 2026
1b18262
Encode TinkerStorageGraph elements as dictionary-referenced components
spmallette Aug 19, 2026
94b8b3f
Add opt-in vertex-property id persistence to TinkerStorageGraph storage
spmallette Aug 19, 2026
bc851ef
Document TinkerStorageGraph compact encoding and vertex-property id o…
spmallette Aug 19, 2026
a8cd43d
Broaden TinkerStorage TCK: value types, ids, varints, unicode round-t…
spmallette Aug 19, 2026
bc27081
Test TinkerStorage durability, lifecycle, and dictionary crash window
spmallette Aug 19, 2026
c22b22d
Reject corrupt TinkerStorage frames with a clear error
spmallette Aug 19, 2026
9668342
Document TinkerStorageGraph single-writer stance; enforce meta-proper…
spmallette Aug 20, 2026
8adf403
Document TinkerStorageGraph persistence and fix stale class doc
spmallette Aug 20, 2026
918638d
Rename graphLocation to storage.directory for TinkerStorageGraph
spmallette Sep 4, 2026
c944a6b
Revised Upgrade docs around TinkerGraph storage capabilities.
spmallette Sep 4, 2026
0f1538b
Document that TinkerStorageGraph is in-memory without a storage engine
spmallette Sep 8, 2026
1c210ec
Bound decoder allocations and dictionary refs in TinkerStorageGraph s…
spmallette Sep 8, 2026
b12c5fc
Publish TinkerStorageGraph commits under the storage lock
spmallette Sep 9, 2026
9a08e00
Rename ByteBufferBuffer to TinkerByteBuffer and add its unit tests
spmallette Sep 9, 2026
db8f1d9
Restore TinkerStorageGraph index definitions on reopen
spmallette Sep 9, 2026
200e855
Document that persisted multi-properties require setting default card…
spmallette Sep 10, 2026
8c487fe
Snapshot compaction from committed state so close() cannot persist un…
spmallette Sep 11, 2026
2b4c370
Rebuild the write-side dictionary on replay to stop unbounded reopen …
spmallette Sep 11, 2026
92e43a0
Cut the storage log back to its last complete frame on replay
spmallette Oct 2, 2026
5694ab0
Fix NullPointerException on rollback with a vertex index but no edge …
spmallette Oct 2, 2026
8bae1d5
Roll back and stop accepting commits when the storage log fails
spmallette Oct 2, 2026
a777535
Reject commits on a TinkerStorageGraph after its storage is closed
spmallette Oct 2, 2026
98aa2ad
Trim the header comment in tinkerstoragegraph-persistent.properties
spmallette Oct 7, 2026
4852291
Add a read-only recovery open for a damaged TinkerStorageGraph store
spmallette Oct 7, 2026
a7b5982
Undo dictionary entries from a commit that fails to encode in TinkerS…
spmallette Oct 8, 2026
491f582
Checksum the length of each TinkerStorageGraph log frame so corruptio…
spmallette Oct 8, 2026
89e9918
Close TinkerStorageGraph storage and release its directory lock even …
spmallette Oct 8, 2026
72d42e6
Back off a failed TinkerStorageGraph auto-compaction and remove its p…
spmallette Oct 8, 2026
9934211
Detect a missing TinkerStorageGraph snapshot, log or VERSION marker i…
spmallette Oct 8, 2026
54fe044
Document the value types TinkerStorageGraph can persist and name the …
spmallette Oct 8, 2026
414ae47
Document how a persisted TinkerStorageGraph behaves under concurrent …
spmallette Oct 8, 2026
7461f62
Reject a blank storage directory and a negative compaction threshold …
spmallette Oct 8, 2026
da49a0a
Update the threat model for TinkerStorageGraph persistence
spmallette Oct 8, 2026
eda0698
Share TinkerStorageGraph file helpers and drop the deprecated Class.n…
spmallette Oct 8, 2026
711bc5b
Record the settings a TinkerStorageGraph store was created with and k…
spmallette Oct 8, 2026
9cdc46c
Stop TinkerStorageGraph commits when its storage directory or log is …
spmallette Oct 8, 2026
b50bb82
Keep TinkerStorageGraph indexes unchanged when a commit fails in storage
spmallette Oct 12, 2026
303a055
Detect TinkerStorageGraph snapshot and log files copied in from anoth…
spmallette Oct 12, 2026
bdd8d8a
Tighten TinkerStorageGraph configuration checks and leave directories…
spmallette Oct 12, 2026
600e9ec
Stop TinkerStorageGraph writing index definitions after close and ser…
spmallette Oct 12, 2026
5d1159a
Fix stale and misplaced Javadoc in the TinkerStorageGraph storage pac…
spmallette Oct 12, 2026
ebb938f
Document what TinkerStorageGraph persistence does not preserve or detect
spmallette Oct 12, 2026
1240ab9
Refuse explicit compaction of a closed or recovered TinkerStorageGraph
spmallette Oct 12, 2026
64ffac0
Tell agents the CHANGELOG breaking marker is applied only at release
spmallette Oct 12, 2026
e9a2dc5
Skip TinkerStorageGraph storage writes for transactions that changed …
spmallette Oct 14, 2026
6257805
Make TinkerStorageGraph clear() durable and refuse what a closed or f…
spmallette Oct 14, 2026
87100da
Harden TinkerStorageGraph storage against torn writes, corrupt record…
spmallette Oct 14, 2026
b573a40
Refuse TinkerStorageGraph opens that would hide lost data or damaged …
spmallette Oct 14, 2026
127fde2
Tighten TinkerStorageGraph storage test assertions
spmallette Oct 14, 2026
fff15ea
Update TinkerStorageGraph persistence and upgrade docs
spmallette Oct 14, 2026
8f7cf01
Move TinkerStorageGraph storage internals into a tinkergraph-gremlin …
spmallette Oct 14, 2026
88eeb49
Warn that a single-cardinality TinkerStorageGraph keeps only the last…
spmallette Oct 14, 2026
4665809
Remove the breaking tag from a hand-written CHANGELOG entry
spmallette Oct 14, 2026
8eac240
Fix preserveVertexPropertyIds when a TinkerStorageGraph store is created
spmallette Oct 14, 2026
f87ca2c
Stop TinkerStorageGraph commits when its LOCK file is removed or repl…
spmallette Oct 14, 2026
0700a8f
Number TinkerStorageGraph log records so repeated or reordered ones f…
spmallette Oct 14, 2026
a3f21ca
Skip an interrupted compaction's old log in a TinkerStorageGraph reco…
spmallette Oct 14, 2026
2817142
Report a TinkerStorageGraph commit that fails after its storage write…
spmallette Oct 14, 2026
a53cc02
Skip TinkerStorageGraph compaction when nothing was committed since t…
spmallette Oct 14, 2026
d28dde8
Fail a TinkerStorageGraph commit that was waiting on the commit lock …
spmallette Oct 14, 2026
6f6904c
Checksum TinkerStorageGraph file headers so a damaged one is reported…
spmallette Oct 14, 2026
f6ec2c3
Bound every size a stored TinkerStorageGraph value declares, includin…
spmallette Oct 14, 2026
d5fbfa5
Correct TinkerStorageGraph notes on why dictionary numbering survives…
spmallette Oct 14, 2026
b3366ee
Read TinkerStorageGraph settings independent of the default locale an…
spmallette Oct 14, 2026
881164a
Fix stale and orphaned comments in the TinkerStorageGraph storage code
spmallette Oct 14, 2026
46831bb
Document the remaining TinkerStorageGraph persistence caveats and poi…
spmallette Oct 14, 2026
a433562
Document how GraphBinary writes a ByteBuffer value
spmallette Oct 14, 2026
ac53092
Keep the TinkerStorageGraph directory lock held against other processes
spmallette Oct 15, 2026
93db5a8
Empty a TinkerStorageGraph store on clear() even when nothing was log…
spmallette Oct 15, 2026
a647d29
Keep a TinkerStorageGraph vertex re-added after clear() when an older…
spmallette Oct 15, 2026
0576841
Cut a damaged final TinkerStorageGraph log record only when it ends i…
spmallette Oct 15, 2026
1c7f40e
Keep a TinkerStorageGraph commit and its storage healthy when automat…
spmallette Oct 15, 2026
afc3b5f
Warn when TinkerMemoryGraph is configured with storage settings it ig…
spmallette Oct 15, 2026
b6a53a7
Test that TinkerStorageGraph stops commits when a compaction cannot i…
spmallette Oct 15, 2026
5f7691c
Name the TinkerStorageGraph crash-window tests for what they verify
spmallette Oct 15, 2026
160d70c
Pin the single-cardinality multi-property collapse of a reopened Tink…
spmallette Oct 15, 2026
e81d1f5
Bound the commit-lock wait in a TinkerStorageGraph clear() test
spmallette Oct 15, 2026
de2964d
Checksum the TinkerStorageGraph VERSION marker and let a recover open…
spmallette Oct 15, 2026
77b4987
Report an unusable value in a TinkerStorageGraph settings record as a…
spmallette Oct 15, 2026
05c223f
Link the TinkerGraph disk storage upgrade note to the reference docs …
spmallette Oct 15, 2026
99ab7a7
Close small gaps in the TinkerStorageGraph persistence docs
spmallette Oct 15, 2026
6dfece3
Keep the TinkerStorageGraph directory lock held when a second open in…
spmallette Oct 16, 2026
8704b51
Keep an element added while TinkerStorageGraph clear() runs consisten…
spmallette Oct 19, 2026
2c29b15
Fail-stop TinkerStorageGraph storage when clear() cannot empty it and…
spmallette Oct 19, 2026
34f4468
Say that a TinkerStorageGraph commit that fails after its storage wri…
spmallette Oct 19, 2026
c7e2614
Fail a TinkerStorageGraph open that sets a storage directory without …
spmallette Oct 19, 2026
e0931d0
Close configured services and the storage engine when a TinkerStorage…
spmallette Oct 19, 2026
fd48ac3
Use the inherited directory delete in TinkerStorageGraphProvider
spmallette Oct 19, 2026
9a67396
Merge TinkerTransaction's vertex and edge storage mutation conversion…
spmallette Oct 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .skills/tinker-dev/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,12 @@ ones that are easy to miss:
use the **tinker-doc** skill. The mechanical minimum: add new content to the right book and update
its `index.asciidoc`.
- **Changelog**: for user-visible or API changes, add a concise `CHANGELOG.asciidoc` entry in the
correct version section. Do not invent version numbers or release names. See the **tinker-doc**
skill for changelog discipline (one entry per user-facing change, not per commit) and voice.
correct version section. Do not invent version numbers or release names. Never add the
`*(breaking)*` marker to an entry you write: it is applied only at release, to the lines generated
from JIRA issues labelled `breaking` (see `docs/src/dev/developer/release.asciidoc`), so a
hand-written entry without it is correct. Explain a breaking change in the upgrade docs instead.
See the **tinker-doc** skill for changelog discipline (one entry per user-facing change, not per
commit) and voice.

Otherwise, match the existing code in neighboring files — explicit imports (no wildcards),
`final` where practical, SLF4J logging over `println`, Hamcrest matchers, and closing any
Expand Down
7 changes: 5 additions & 2 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima

* Added a `Char` type to `gremlin-go` to represent the Gremlin `Character` type in `GremlinLang`.
* Fixed `gremlin-go` to report a malformed or truncated GraphBinary response as a deserialization error rather than a bare decoder message.
* Made `TinkerGraph` an interface and renamed the in-memory implementation to `TinkerMemoryGraph`; `TinkerGraph.open()` and `gremlin.graph=...TinkerGraph` behave as before. *(breaking)*
* Renamed `TinkerTransactionGraph` to `TinkerStorageGraph`. *(breaking)*
* Made `TinkerGraph` an interface and renamed the in-memory implementation to `TinkerMemoryGraph`; `TinkerGraph.open()` and `gremlin.graph=...TinkerGraph` behave as before.
* Renamed `TinkerTransactionGraph` to `TinkerStorageGraph`.
* Fixed a `NullPointerException` when rolling back a transaction on a `TinkerStorageGraph` that has a vertex index but no edge index.
* Added a pluggable storage layer to `TinkerStorageGraph` that durably persists each committed transaction to disk.
* Removed automatic persistence from `TinkerMemoryGraph`, which is now purely in-memory and ignores `gremlin.tinkergraph.graphLocation`/`graphFormat`. Use `TinkerStorageGraph` for durability or `g.io()` for interchange.

[[release-4-0-0-beta-3]]
=== TinkerPop 4.0.0-beta.3 (July 20, 2026)
Expand Down
11 changes: 8 additions & 3 deletions THREAT_MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ under the License.
| **Core traversal machine + structure API** (`gremlin-core`) | `GraphTraversal`, strategies, `Vertex`/`Edge` | filesystem (IO formats) | **In** |
| **Serialization** (`gremlin-core`/`gremlin-util`/`gremlin-shaded`) | GraphSON + GraphBinary wire readers. Gryo (Kryo) is IO-format-only, not on the wire | deserializes untrusted wire bytes. Gryo only reads IO/file bytes | **In** (see §9) |
| **Gremlin Language Variants** (Java `gremlin-driver`, `gremlin-python`, `-dotnet`, `-go`, `-js`) | deserialize server responses | network (connect) | **In**, response-deserialization robustness + TLS cert validation. Java shares the JVM serializers. The others have own per-language deserializers not covered by hardening the JVM server |
| **Reference graph** (`tinkergraph-gremlin`) | in-memory graph, the **shipped default graph**, with optional file persistence via the `io()` readers | filesystem (persistence) | **In**, TinkerPop reference code on the default reachable path, so a defect in unmodified TinkerGraph is `VALID` (§3). Loading a persisted graph uses the same GraphSON/Gryo/GraphML readers (§6 IO surface). A custom `graphFormat` reader is provider code (§3) |
| **Reference graph** (`tinkergraph-gremlin`) | in-memory graph, the **shipped default graph**. `TinkerStorageGraph` optionally persists committed transactions to a storage directory through a pluggable storage engine (the `graphbinary` reference engine) | filesystem (storage directory) | **In**, TinkerPop reference code on the default reachable path, so a defect in unmodified TinkerGraph is `VALID` (§3). The storage directory is operator-trusted like any data directory, so its files are not an attack surface (§6). A custom storage engine is provider code (§3) |
| **OLAP** (`gremlin-core`/`tinkergraph` computer, `hadoop-gremlin`, `spark-gremlin`) | `GraphComputer`, remote-reachable when the operator configures an OLAP-capable graph | network, filesystem, cluster | **In**, reference code (incl. Hadoop/Spark modules). The third-party Hadoop/Spark runtime + cluster config are out (§3) |
| **`gremlin-console`** | local Groovy REPL. `:remote console` submits **arbitrary Groovy scripts** to a server and deserializes responses. `:install` loads plugins (credentials/hadoop/spark) via Grape | network (connects) | Local REPL **Out** (operator-trusted). As a remote client, submitting arbitrary Groovy = server-side RCE **by-design** (§9), subject to server auth. Response-deserialization robustness + TLS cert validation **In** (like a GLV). Plugins are operator-installed code in the operator's own JVM, so the install decision, the third-party download channel (Grape), and plugin behavior are **Out** (trusted-input, §3) |
| **`gremlint`** | client-side Gremlin formatter (parse-and-reprint, no query execution); published as a library for integration into client applications. | none (runs in the caller's browser/process) | **In**, valid surface for security reports since it's a published, user-integrated library |
Expand Down Expand Up @@ -267,11 +267,12 @@ Per-surface trust table:
| Gremlin Server — script request | Gremlin (or, if `gremlin-groovy` is enabled, Groovy) script text | **yes** (pre-auth if auth off) | auth; script restriction / sandbox; who may script; traversal-step allow-list; resource limits |
| Gremlin Server — transaction id | server-generated UUID, echoed back by the client on follow-up requests | **yes** (a client can present any id) | looked up with no owning-user check, so any client presenting a valid id shares that transaction (see §11b) |
| Request deserialization (GraphSON / GraphBinary) | serialized bytes | **yes** (pre-auth only when auth is off, see the ordering note below) | robustness of the wire serializers |
| Graph IO — Gryo/GraphSON/GraphML files (`io()` step, persistence, OLAP) | on-disk / cluster bytes | only if the caller loads untrusted files | GraphSON, the hardened Gryo mappers the IO paths build (`registrationRequired=true` plus `javaSerializationAllowed=false`), and GraphML with the default XML factory owe deserializer integrity. Unlocked Gryo, a Gryo mapper that keeps Java serialization, and a caller-supplied unhardened `XMLInputFactory` (XXE) are the caller's responsibility |
| Graph IO — Gryo/GraphSON/GraphML files (`io()` step, OLAP) | on-disk / cluster bytes | only if the caller loads untrusted files | GraphSON, the hardened Gryo mappers the IO paths build (`registrationRequired=true` plus `javaSerializationAllowed=false`), and GraphML with the default XML factory owe deserializer integrity. Unlocked Gryo, a Gryo mapper that keeps Java serialization, and a caller-supplied unhardened `XMLInputFactory` (XXE) are the caller's responsibility |
| Gremlin string parser (`gremlin-language` ANTLR) | Gremlin string | **yes** | parser robustness, no crash/hang/OOM on malformed input and no grammar breakout / step injection (distinct from execution cost, §8/Q7) |
| Any string the grammar accepts as an argument (e.g. a `regex` pattern) | Gremlin string | **yes** | a grammatically valid string must not enable DoS (e.g. ReDoS via a pathological pattern), the Q7 super-linear-amplification carve-out (§8) |
| GLV (client) — server response | serialized bytes from the server | yes if the server is malicious/compromised, or a MITM (TLS off / cert not validated) | response-deserialization robustness; TLS with cert validation |
| `gremlin-server.yaml`, host, data dir | local | no — operator-trusted | filesystem permissions |
| `TinkerStorageGraph` storage directory (`snapshot.gbin`, `log.gbin`, `INDEXES`, `VERSION`, `settings.properties`) | on-disk bytes decoded when the graph opens | no — operator-trusted, a data directory | filesystem permissions. The engine's checks against damaged files (checksums, bounded decoding, the `recover` open, described in `tinkergraph-gremlin/DESIGN.md`) are a reliability property against disk damage, not a security property |

- **Pre-auth vs post-auth (ordering note):** "pre-auth" marks what an attacker can reach **without valid
credentials**, which is what makes a defect there security-critical (§8). Gremlin Server authenticates
Expand Down Expand Up @@ -442,7 +443,7 @@ Per-surface trust table:
(`GryoMapper.Builder.javaSerializationAllowed(boolean)` selects the behavior), so a break there is `VALID`. A
directly built `GryoMapper` and `GryoPool` keep them, as do the `spark-gremlin` and Hadoop object pools that
additionally run unlocked; those remain the user's responsibility.
Gryo is not on the wire, so this is an IO/file-surface concern (`io()` step, persistence, OLAP).
Gryo is not on the wire, so this is an IO/file-surface concern (`io()` step, OLAP).

- **A `TraversalStrategy` is not an access-control boundary on its own.** The Gremlin language lets any
request remove or replace strategies on its traversal source (`withoutStrategies()`,
Expand Down Expand Up @@ -517,6 +518,10 @@ Per-surface trust table:
- "Calling application concatenates untrusted input into a Groovy string (Gremlin-injection)" — the calling
application's responsibility (§9). A `gremlin-language` parser breakout is the opposite: an in-model
TinkerPop bug (§8). Disposition: `BY-DESIGN: property-disclaimed`.
- "A crafted or corrupted `TinkerStorageGraph` store file crashes, hangs, or exhausts memory when the graph opens" —
the storage directory is operator-trusted (§5, §6), so writing a malicious file there already requires the
operator's access. A store that fails to open, or opens wrongly, after ordinary disk damage is an ordinary
reliability bug, not a security report. Disposition: `OUT-OF-MODEL: trusted-input`.
- Findings in any test-only module, any module containing examples, or build tooling (e.g. `gremlin-test`,
`gremlin-examples`, `gremlin-tools`) — out of scope (§3). Disposition:
`OUT-OF-MODEL: unsupported-component`.
Expand Down
Loading
Loading