Tupi-Guarani for “small”

mirim

An embedded SQL database, encrypted at rest, with post-quantum sealed exports.

A Rust core with #![forbid(unsafe_code)], XChaCha20-Poly1305 storage, and ML-KEM-768 exports. The 1.1.1 maintenance release is in preparation, with security fixes and complete guides in English and Brazilian Portuguese.

ML-KEM-768 · FIPS 203 XChaCha20-Poly1305 at rest EN / PT-BR documentation AGPL-3.0 / commercial
sealed export illustration
plaintext db
services
secrets
access_log
sealed export
a3f1 9c4e
7bd0 228a
1655 e27f
↑ ML-KEM-768 encapsulation ↑

key wrapped per recipient · recipient secret key required

1.1.1 · Release preparation

Maintenance with clear security and documentation.

The fixes preserve existing binary layouts. This page introduces the source update; 1.1.0 remains the previous stable release until publication is complete.

Changes in 1.1.1
AreaChange
Private filesExclusive creation of randomly named temporary files with private Unix permissions; key generation avoids overwriting existing files.
WALStatements too large for the WAL format are rejected before acknowledgement, keeping accepted writes recoverable.
Writer lockingExclusive Unix and Windows locks through safe Rust; unsupported platforms or filesystems fail the open.
DesktopUpdated graphics dependencies and accurate documentation of the secret retained by a session for checkpoints.
DocumentationComplete English and Brazilian Portuguese guides, consistent backup instructions, and explicit security and platform limits.
PublishingRelease assets and packaging for more systems are being prepared. Actual availability is defined by release attachments, not by a submitted PR.

Changelog · Complete guide

Downloads

Choose a published release.

Version 1.1.1 is in preparation. For the previous stable version, find 1.1.0 on the mirrors below. Check each release’s attachments and notes; binaries are not guaranteed for every platform.

Release mirrors
MirrorDownloads
git.securityops.coBrowse releases and attachments
git.securityops.com.brBrowse releases and attachments
GitHubBrowse releases and attachments
CodebergBrowse releases and attachments

Verify before installing

  • sha256sum -c SHA256SUMS --ignore-missing
  • Require OK for each file you will install. A checksum does not authenticate its publisher.
  • When a .mf signature is attached, use a trusted verifier and a previously authenticated public key.
  • mirim-sign verify <artifact> <artifact>.mf mirim-release.pub

Choose your platform

  • Select the OS, architecture, and version from actual attachments; native packages and GUI availability may differ.
  • The prepared v1.1.1 GNU/Linux x86_64 CLI, signer, and CLI AppImage require glibc 2.34 or newer; the GUI requires glibc 2.39 or newer. Build from source for musl or older glibc systems.
  • The local GNU Guix recipe repackages x86_64-linux binaries. Its presence does not establish inclusion in official Guix.
  • GNU/Linux, BSD, macOS, and Windows installation

What it does

Small data, kept private and durable.

mirim holds data that should stay in memory, encrypted on disk, and recoverable after a crash: keys, credentials, capability records, audit trails, configuration.

Encrypted at rest

Snapshots use XChaCha20-Poly1305 with authenticated headers. Keys come from Argon2id or a caller-provided 32-byte raw key.

Post-quantum sealed exports

ML-KEM-768 seals a snapshot for one or several recipients. Each opens it with a matching secret key. Authenticating the sender requires a signature.

Crash-safe durability

DurableDb syncs mutations to the WAL before reporting success. The SIGKILL harness checks process crashes; physical power-loss behavior also depends on the filesystem and device.

SQL with an index

CREATE, INSERT, SELECT, UPDATE, and DELETE with parameters, ORDER BY, LIMIT, and COUNT(*). PRIMARY KEY and UNIQUE have equality indexes; data remains in RAM.

Rotation, and one writer

rotate_secret replaces current ciphertext and rebinds the WAL. Sessions use exclusive locks on Unix and Windows; opening fails if the system does not support locking.

Embed from C

The C API has documented pointer and error contracts. Its harness uses Rust ASan and C ASan/UBSan; invalid pointers remain the caller’s responsibility.

Dialect

The whole SQL surface, on one screen.

Two types, no coercion, no surprises. What follows is not a summary of the language. It is the language.

cheat sheet
-- Line comments, and /* block comments */.

CREATE TABLE users (
  id    INTEGER PRIMARY KEY,  -- unique, indexed
  email TEXT UNIQUE,          -- allows many NULLs
  age   INTEGER
);

-- One row per INSERT. Unlisted columns become NULL.
INSERT INTO users VALUES (1, 'ana@x.io', 30);
INSERT INTO users (id, email) VALUES (2, 'bia@x.io');

SELECT email, age FROM users
  WHERE age >= 18 AND email IS NOT NULL;
SELECT * FROM users ORDER BY age DESC;
SELECT id FROM users ORDER BY id LIMIT 10 OFFSET 20;
SELECT COUNT(*) FROM users WHERE age IS NULL;

-- Atomic per statement: a violation changes nothing.
UPDATE users SET age = 31 WHERE id = 1;
DELETE FROM users WHERE id = 2;

+ In the language

  • INTEGER (i64) and TEXT (UTF-8). Nothing else.
  • Single-column PRIMARY KEY and UNIQUE, each carrying an O(1) equality index.
  • WHERE with AND-chained comparisons and IS [NOT] NULL.
  • ORDER BY, multi-key and stable. NULL sorts first under ASC, last under DESC.
  • LIMIT, OFFSET and COUNT(*).
  • ? parameter binding. Bound values are data, never SQL.
  • Line and block comments.

- Deliberately absent

  • Joins and sub-queries.
  • GROUP BY, OR, and every aggregate except COUNT(*).
  • Transactions spanning statements. Each statement is atomic on its own.
  • Secondary indexes beyond PRIMARY KEY / UNIQUE, and a query planner.
  • Type coercion. REAL, BLOB, DATE, BOOLEAN.
  • FOREIGN KEY, NOT NULL, DEFAULT, CHECK, composite keys.
  • Data larger than RAM. Durability is real, out-of-core storage is not.

Untrusted input goes in as a bound ? parameter, never as SQL text. Full walkthrough in the guide. Five worked schemas in samples/.

Use cases

Match the limits to your application.

Configuration, local secrets, and small application datasets can benefit from encrypted storage. Evaluate size, queries, concurrency, and recovery before choosing.

Limits and evaluation
AspectBehavior
Small dataThe whole database and its indexes must fit in RAM.
SQLTables, filters, ordering, and parameters; no joins or multi-statement transactions.
IndexesPRIMARY KEY and UNIQUE equality predicates use expected constant-time hash lookups; other predicates scan rows.
PersistenceDurableDb uses a snapshot and WAL. Db persists only when the application explicitly saves it.
EvaluationRun cargo bench --locked --bench core on your hardware and test behavior on the target OS.

Cryptography

Named primitives, with their standards.

Mirim combines primitives from RustCrypto dependencies in its own file formats. The suite includes pinned cryptographic vectors; this is not an independent certification.

Cryptography inventory
RolePrimitiveParametersStandard
Key encapsulationML-KEM-7681088-byte ciphertext, implicit rejectionFIPS 203
SignaturesML-DSA-874627-byte signature, sign featureFIPS 204
AEADXChaCha20-Poly130524-byte nonce, header bound as associated dataRFC 8439 and extension
Passphrase KDFArgon2id64 MiB, 3 passes, 4 lanesRFC 9106
Key derivationHKDF-SHA256domain-separated info string per formatRFC 5869
HashingSHA-256snapshot identity, manifest target digestFIPS 180-4
RandomnessOS CSPRNGvia getrandomplatform

Authentication failures return Error::Crypto. Public structure, version, and secret-kind errors can differ. See SECURITY.md for the full model.

On disk

Versioned, documented file formats.

Binary layouts remain compatible in this maintenance update. The guide consolidates field sizes, layouts, and key derivation.

File formats
ArtifactMagicVersionLayout
VaultMIRIM1\0\0v1 50-byte header (magic, version, KDF id, salt, nonce), then the AEAD ciphertext of the snapshot. File extension .mrm.
Sealed export, one recipientMIRIMSL1v1 1088-byte ML-KEM-768 ciphertext, 24-byte nonce, then the AEAD payload.
Sealed export, many recipientsMIRIMSL1v2 Payload encrypted once under a random key, which is then wrapped per recipient: a 1088-byte KEM ciphertext and a 48-byte wrapped key each. Any one of them opens it.
Write-ahead logMIRIMWL1v1 41-byte header carrying the SHA-256 of the vault it extends, then AEAD records with authenticated consecutive sequence numbers. Recovery can truncate an incomplete or invalid final record.
Signed manifestMIRIMMF1v1 4677 bytes: header, target kind, counter, the SHA-256 of the target, and an ML-DSA-87 signature over the first 50. File extension .mf.
Trust fileMIRIMTS1v1 49 bytes: the highest accepted counter and the hash of the last accepted target. This is the local trust root for rollback rejection.

Encryption headers are authenticated, but local trust state is not ciphertext. Recovery can discard a damaged WAL tail or a WAL naming another snapshot; this does not prevent malicious rollback. Binary reference.

Assurance

Checked more than once.

Complementary methods check different properties. A test in the repository is not evidence that it ran for a particular release or platform.

  • +Differential model. Compares the SQL evaluator with an independent model over generated sequences.
  • +Properties. Checks round trips, replay, checkpoints, and uniqueness invariants.
  • +Fuzzing. Five targets cover wire, SQL, exports, manifests, and WAL; a finite run is not exhaustive.
  • +FFI. C conformance harness with sanitizers and separately checked dependencies.
  • +Recovery. SIGKILL harness for process crashes; it does not simulate every physical power failure.
  • +Dependencies. cargo audit, cargo deny, and an SBOM; GUI and FFI have separate lockfiles.
  • +Results. Consult release notes for the checks and platforms actually exercised.
secrets.mrm
$ mirim secrets.mrm
creating new vault: secrets.mrm
new passphrase:
repeat passphrase:
mirim 1.1.1 — .help for commands
mirim> .read samples/secrets_vault.sql
ok: ran 30 statement(s) from samples/secrets_vault.sql
mirim> SELECT COUNT(*) FROM access_log WHERE allowed = 0;
count(*)
--------
4
mirim> SELECT actor, ts FROM access_log
   ...> WHERE allowed = 0 ORDER BY ts DESC LIMIT 3;
actor        | ts
-------------------------
unknown-host | 1717301000
ex-employee  | 1717300800
svc-web      | 1717300500
mirim> 

Security model

Understand the protections and their limits.

Choose a deployment with memory, storage, recovery, and key trust in mind.

Protections

  • Encrypted storage. Snapshots and WAL records protect content with authenticated encryption; metadata remains visible.
  • Passphrases. Argon2id increases guessing cost. A weak passphrase remains vulnerable to guessing.
  • Exports. ML-KEM-768 is designed to resist known quantum attacks, without a guarantee against every future cryptanalytic advance.
  • Malformed inputs. Decoders check structure and lengths; this does not impose a total memory budget.

Limits

  • Compromised host. Open process memory, swap, and core dumps can expose data and secrets.
  • Rollback. An attacker can restore older database copies or truncate the WAL. Signatures require explicit checks and protected trust state.
  • Metadata. Size, existence, times, and access patterns are visible, as are WAL record sizes.
  • Concurrency. Sessions acquire exclusive locks on Unix and Windows. Direct vault::save and path aliases need coordination; unsupported locking fails the open.
  • Rotation. Old backups and residual blocks are not erased. Lost secrets cannot be recovered.

Constant-time behavior principally depends on the cryptographic implementations. The complete binary has no independent constant-time certification. SECURITY.md · Operational guide

New · desktop

A front end that refuses by default.

mirim-gui is a small point-and-click way to open a vault, built on eframe and egui. It lives in its own crate so the core stays tiny and unsafe-free.

  • +Local. The application works with local vaults and uses the same database core.
  • +Explicit writes. Allow writes enables mutating SQL. Opening can create or repair the WAL; this is not forensic read-only access.
  • +Session secret. Login fields are cleared, but DurableDb retains a copy for checkpoints until the session closes.
  • +Durability. Acknowledged mutations are synced; sessions acquire exclusive writer locks on Unix and Windows.
  • +Controls. Ctrl+Enter executes SQL; controls provide checkpointing, passphrase rotation, and an offline Licenses window with bundled font notices.
mirim-gui
# Build from the checkout
$ cargo build --release --locked \
  --manifest-path gui/Cargo.toml
$ ./gui/target/release/mirim-gui

Check release attachments for prebuilt binaries.

License

Dual-licensed. Pick the one that fits.

Open by default under AGPL-3.0-only. A commercial license exists for the cases the AGPL's terms do not suit.

AGPL-3.0-only open source

Files carrying the public option can be used under AGPL-3.0-only according to its terms. MIT-marked files and dependencies retain their own licenses.

Commercial on request

The commercial option requires a separate agreement signed by the applicable rights holder. LICENSE-COMMERCIAL is an inquiry notice, not a public grant. Contact: sac@securityops.co.

Full terms in LICENSE and LICENSING.md. Copyright (c) 2026 Cristian Cezar Moisés.

1.1.1 · In preparation

Read the source and the guides.

The 1.1.1 update is in preparation. Consult published notes and attachments to choose a release; the guides cover installation, backups, APIs, and verification.