Stability & the 1.0 Promise

Exactly what pinning a 1.x mnesis crate buys you — crate tiers, semver surface, on-disk format, MSRV, and deprecation policy.

Stability

What pinning a 1.x mnesis crate buys you. This document takes effect at the 1.0 release of the core crates; until that release every crate is 0.x and this is the policy being frozen, not yet a promise in force.

Crate tiers

TierCratesPromise
1.0 (frozen)mnesis, mnesis-macros, mnesis-store, mnesis-wake, mnesis-wake-nostdFull semver: breaking changes only at a major release
0.x (evolving)mnesis-inmemory, mnesis-fjall, mnesis-postgres, mnesis-store-testingBreaking changes allowed in any 0.(x+1) release, called out in release notes
Unpublishedworkspace-hack, mnesis-nostd-smoketest, examplesNo promise

Coupling rules across the tiers:

  • mnesis-macros is version-locked to mnesis (the serde/serde_derive pattern): they release together, always at the same version.
  • A mnesis major forces a mnesis-store major — kernel types (Version, Events, the aggregate traits) appear in store APIs.
  • A mnesis-store major forces a major of both wake crates — they implement its public WakeSource contract in their public API.
  • Adapters are consumers: a core major forces nothing on a 0.x crate beyond a routine dependency bump.
  • No 0.x type appears in the public API of a 1.0-tier crate, with one acknowledged exception listed under Public dependencies.

Semver surface

The public API of the 1.0-tier crates is:

  • Every documented pub item — types, traits, functions, macros, and feature-gated items when their feature is enabled.
  • Documented trait semantics — behavior, not just signatures. The store contract's promises (inclusive read_stream bound, exclusive read_all bound — an intentional asymmetry — strict-after subscription resume, CaughtUp emitted exactly once, conflicting appends rejected with nothing landing, spurious wakes permitted) are API; the mnesis-store-testing conformance kit is their executable form. Changing one is a breaking change even if every signature still compiles.
  • Documented Send/Sync bounds on public types and on returned streams and futures.

Explicitly not public API:

  • Anything #[doc(hidden)].
  • Sealed traits' internals (RawItem, ConflictPredicate, KeyspaceConfig, …): implementing them outside this workspace is unsupported.
  • The exact text of Display/Debug output, including ErrorId truncation rendering. Match on error variants, never on strings.
  • Adapter internals: on-disk key layouts, partition names, and connection/session behavior of the 0.x adapters.
  • The conformance kit's check list: new checks may be added in any release. A new check failing an adapter is the kit doing its job, not a breaking change.

Public dependencies

Three external crates appear in 1.0-tier public APIs; their major version is part of our contract, so a semver-incompatible bump of any of them is a mnesis major:

  • bytes (1.x) — Bytes in envelope and codec APIs.
  • futures-core (0.3) — Stream in stream and subscription bounds. It is 0.x upstream but de-facto frozen; we treat 0.3 as its major and acknowledge it as the one 0.x type in a 1.0 surface.
  • minicbor (2.x, behind the cbor feature) — the backup box's sink trait (minicbor::encode::Write bounds on ChunkWriter/SectionWriter) and encode errors (WriteError::Encode).

Everything else (arrayvec, tokio, parking_lot, foldhash, event-listener, fjall, sqlx, …) is an implementation detail and may change in any release.

On-disk format

The event frame (mnesis-store's wire module) carries a leading format-version byte; the CBOR backup box carries a format_version header field. The promise, for both:

  • Within 1.x: the default write format never changes (frame v2 today), and every 1.x release reads everything any 1.x release wrote.
  • Across one major: 2.x may introduce and default to a new format, but must still read every format 1.x wrote — an in-place upgrade never needs a migration step.
  • Beyond one major: export → CBOR box → import is the supported migration path.
  • Unknown format versions always fail with a typed error (DecodeError::UnsupportedFrameVersion for the frame, ChunkError for the box) — never a misparse.

Adapters are 0.x: their key layouts and partitions may change in a 0.x release, but any such change ships with a documented migration path (export/import at minimum). The CBOR box is the durable interchange format; raw store bytes are not.

MSRV

rust-version in every published Cargo.toml equals the pinned stable toolchain we build and test with. Raising the MSRV is a minor change, never a patch. We claim no trailing floor: the declared MSRV is the only supported toolchain lower bound, and cargo enforces it.

Feature flags

All cargo features of the 1.0-tier crates are additive: enabling a feature never changes or removes an existing item's signature. Adding a feature is a minor change; changing a crate's default feature set is a major change. There are no unstable features at 1.0; if one is ever introduced it will be named unstable-* and excluded from this promise.

Enums

  • Public error enums carry #[non_exhaustive]: adding a variant is a minor change. Always match errors with a wildcard arm.
  • Public non-error enums (Step, Hydrated, Atomicity, …) are deliberately exhaustive: adding a variant is a major change. Exhaustive matching that catches new domain states at compile time is a promised feature, not an oversight.

Deprecation

Nothing is removed silently:

  • An item is removed only at a major release, and must have shipped with #[deprecated(note = "…")] — naming its replacement — in at least one published minor release before that major.
  • 0.x crates: deprecated in at least one 0.x release before removal.