mod-rand 1.0.0

Tiered randomness for Rust: fast PRNG, process-unique seeds, and OS-backed cryptographic random — plus bounded ranges, strings, tokens, shuffle, sample, and weighted choice. Zero dependencies, MSRV 1.75.
Documentation
# mod-rand — Stability and SemVer Policy

> This document is the formal stability contract for the `1.x` line.
> It is binding: any release that violates it is a bug.

## Headline guarantee

**Every public symbol in `1.0.0` is locked for the entire `1.x` line.**
Signatures, observable behaviour, and (for Tier 1) byte-for-byte output
for a given seed and call sequence cannot change without a major
version bump to `2.0.0`.

This applies to:

- Every symbol re-exported under `mod_rand::tier1`, `mod_rand::tier2`,
  `mod_rand::tier3`, and `mod_rand::charsets`.
- The trait implementations on `Xoshiro256` (`Debug`, `Clone`, `Eq`,
  `PartialEq`).
- The numeric values of every `charsets::*` constant.

## Version policy

The `1.x` line follows [Semantic Versioning 2.0.0](https://semver.org/).
The specific rules for this crate:

### Patch releases (`1.x.Y`)

May contain:

- Bug fixes that do not change observable output for a given seed (Tier
  1) or change the documented contract (Tier 2 / Tier 3).
- Documentation improvements.
- Internal performance work that does not move any public surface.
- Test additions.

May NOT contain:

- New public items.
- Changes to Tier 1 output for any given `(seed, call sequence)` pair.
- MSRV bumps.

### Minor releases (`1.Y.0`)

May contain everything a patch release may contain, plus:

- New public items (functions, methods, constants, modules) so long as
  they are pure additions — no signature change to any existing symbol.
- New optional Cargo features that default to off, or that activate
  purely additive code paths.
- MSRV bumps. Each MSRV bump is a minor-version bump minimum and is
  called out in the CHANGELOG.

### Major releases (`2.0.0`)

Required for any change that violates the above. Specifically, any
of the following requires `2.0.0`:

- Removal or rename of any public symbol.
- A signature change to any existing public symbol (including making
  panicking conditions stricter or looser in a user-observable way).
- A change to Tier 1's output for any `(seed, call sequence)` pair —
  i.e., breaking algorithmic determinism on Tier 1.
- Changing the byte values of any `charsets::*` constant (these are
  effectively format-level — re-ordering or substituting any byte is
  a breaking change).
- A change to the documented invariants of Tier 2 or Tier 3 (e.g., if
  Tier 2's "every call in the same process returns a distinct value"
  were ever weakened, that's `2.0.0`).

## Determinism on Tier 1

Tier 1 (`mod_rand::tier1::Xoshiro256`) is **deterministic** under the
following identity:

```text
Xoshiro256::seed_from_u64(s)
    .call(api_1)
    .call(api_2)
    ...
    .call(api_N)
```

For any fixed `s` and fixed sequence of API calls, the result is
identical across every `1.x` release on every platform.

This includes, specifically:

- `next_u64`, `next_u32`, `next_f64`, `fill_bytes`.
- Every `gen_range_*` and `gen_range_inclusive_*` method, on every
  integer width and on `f64`.
- `gen_f64`, `gen_f32`, `gen_bool`.
- `gen_string`, `gen_alphanumeric`, `gen_alpha`, `gen_numeric`,
  `gen_hex`.
- `shuffle`, `sample`, `weighted_index`, `weighted_choice`.
- `jump`, `long_jump`.

Determinism is enforced by hardcoded known-answer test vectors in
[tests/kat.rs](../tests/kat.rs). Any code change that flips a KAT
vector is, by definition, a determinism break.

Tier 2 and Tier 3 are **explicitly non-deterministic** — Tier 2
mixes in PID and wall-clock time; Tier 3 reads from the OS CSPRNG.
Neither makes any reproducibility claim.

## Deprecation policy

A symbol marked `#[deprecated]` in a `1.x.Y` release:

- Remains callable for the entire `1.x` line.
- Continues to behave per its documented contract.
- May only be removed in a `2.0.0` release.

Deprecation is for guidance, not removal. Code that compiles against
`1.0.0` must continue to compile against `1.x.LATEST` (modulo the
deprecation warning), without source changes.

## What is NOT covered

The stability contract does NOT cover:

- **Internal performance characteristics.** A `1.x.Y` may make any
  operation faster or slower than `1.0.0`, so long as it remains
  within an order of magnitude of the documented per-tier target
  (Tier 1: ~1 ns/u64; Tier 2: <100 ns/call; Tier 3: one syscall).
  Documented benchmark numbers in the README are illustrative, not
  contractual.
- **Internal types and modules.** Any item not re-exported through
  `lib.rs` is internal and may move or change between minor releases.
- **Exact wording of error messages and panic messages.** The error
  *kind* (`io::Error::kind()`) and the fact that a given input panics
  are part of the contract; the human-readable text is not.
- **Compile-time errors that depend on call patterns.** If a future
  Rust version's type inference rejects an `mod_rand::tier1::*` call
  that compiled under the MSRV, that may need to be addressed in a
  patch release; it does not constitute a stability break.

## Dependencies

Zero runtime dependencies outside of `std` (when `std` feature is
enabled). This is a hard architectural property, not just a current
state — adding any external dependency to the `[dependencies]` table
of `Cargo.toml` requires a `2.0.0` bump.

The point: `mod-rand` exists partly to break the
`getrandom`-induced MSRV ratchet. Adding a dep would defeat the
purpose.

## MSRV

`1.0.0` ships with MSRV `1.75.0`. Any change to the MSRV is a
minor-version bump minimum.

Recent or upcoming Rust features the crate does **not** use, to keep
the MSRV low:

- `let_chains` (1.88)
- The `OptionExt::is_some_and` family (1.70 — predates MSRV anyway)
- Inline `const {...}` expressions (1.79)

If a future internal optimisation requires a newer language feature,
the change goes into the next minor release with an MSRV bump.

## Feature flags

The default feature set is `["std", "tier2", "tier3"]`. Removing any
feature from this set, or adding a new default feature, requires a
major version bump (it's a breaking change for users who pin features
explicitly).

Adding a non-default feature is a minor bump. Renaming a feature is
a major bump.

## Reporting a stability break

If you encounter what looks like a `1.x` stability break:

1. Run the failing case against the latest patch release of `1.x` to
   confirm reproducibility.
2. Capture the exact `seed`, API call sequence, and output values that
   differ between releases.
3. Open an issue at
   <https://github.com/jamesgober/mod-rand/issues>
   with the repro and a link to your KAT-style vectors.

Stability breaks are bugs and are fixed in the next patch release.