tramai-persistence-file
Version: 0.6.0
Status: Preview
Role: Single-node, AES-256-GCM encrypted file-backed implementations of the sovereign store contracts.
Purpose
tramai-persistence-file implements the store contracts owned by tramai-core and tramai-security — ApprovalStore, ApprovalContinuationStore, AuditStore and SuspendedInvocationStore — on top of the local filesystem. It is the durable option for single-node sovereign deployments that must not depend on a database or a cloud service.
Every record is authenticated-encrypted with AES-256-GCM. Filenames are SHA-256 digests of the record identity — never raw record IDs — and directory (0700) / file (0600) permissions are enforced, symlinks are rejected at every managed path, and an exclusive .tramai.lock prevents two JVM processes from opening the same store root.
What it provides
| Type | Role |
|---|---|
FileBackedSovereignStores.open(configuration) | Composition root; returns all four stores behind one shared lock, AutoCloseable |
FileBackedStoreConfiguration(rootDirectory, encryption, verifyOnOpen) | Store root, encryption settings, optional integrity verification on open |
FileStoreEncryptionConfiguration(activeKeyId, keyProvider) | Active key id plus caller-owned key resolution |
FileStoreEncryptionKeyProvider | fun interface — resolve(keyId: String): SecretKey |
FileApprovalStore, FileApprovalContinuationStore, FileAuditStore, FileSuspendedInvocationStore | The four store implementations |
FileStoreException hierarchy | Configuration, LockUnavailable, Permission, Corruption, UnsupportedFormat |
Behavioral contracts worth knowing:
- Atomic writes — mutable records are written to a temp sibling and
ATOMIC_MOVEd into place; immutable audit events useCREATE_NEWso silent replacement is impossible. - Exactly-once continuation claim —
claimForExecutionreleases the raw tool arguments once and re-encrypts the record witharguments = null.CLAIMEDrecords never lazy-expire; onlyPENDINGrecords transition toEXPIRED. - Hash-chained audit stream — each append validates sequence continuity,
previousEventHashlinkage and uniqueeventId;verifyAll()re-verifies the whole store on open. - Safe failure messages — exception text carries reason codes only, never record IDs, tool arguments, keys, ciphertext or nonces.
Dependencies
dependencies {
implementation(platform("dev.tramai:tramai-bom:0.6.0"))
implementation("dev.tramai:tramai-persistence-file")
}
val stores = FileBackedSovereignStores.open(
FileBackedStoreConfiguration(
rootDirectory = Path.of("/var/tramai/sovereign"),
encryption = FileStoreEncryptionConfiguration(
activeKeyId = "production-key-1",
keyProvider = FileStoreEncryptionKeyProvider { keyId -> loadKey(keyId) },
),
verifyOnOpen = true,
),
)
stores.approvalStore.create(request)
stores.auditStore.appendNext(streamId) { latest -> buildEvent(latest) }
stores.close() // releases the exclusive lock
Spring Boot applications normally wire these stores through tramai-spring-boot-starter-sovereign-persistence-file with tramai.sovereign.persistence.type: file instead of calling open directly.
When to use this module
- A single-node sovereign deployment that needs durable approvals, continuations and audit without running PostgreSQL.
- You want at-rest encryption and tamper evidence for sovereign state with a key you own.
- You are building a reference or air-gapped deployment where the filesystem is the only available store.
When NOT to use this module
- Multiple application nodes must share the same store — there is no distributed locking or network filesystem support.
- You need key rotation, JDBC, or cloud KMS integration; use tramai-persistence-jdbc or a custom
AuditStore/ApprovalStoreimplementation. - You are not on a POSIX filesystem — the store requires
PosixFilePermissions.
