alkblobs 0.1.0

Content-addressed blob storage: multi-hash put/get/verify store with pluggable backends, transport- and protocol-agnostic
Documentation
//! `alkblobs` — content-addressed blob storage in the alk* family: a
//! put/get/verify store keyed under one canonical content hash, the
//! git-family oid derivation (`"blob <len>\0" + content`, SHA-256,
//! legacy SHA-1 tolerated — ADR-002), with tier engines underneath and
//! no wire/protocol layer welded on.
//!
//! ## Layer map
//!
//! - **[`store::Store`]** — the facade consumers program against:
//!   `put`/`get`/`stat`/`read_range`/`has`/`list`, the [`Batch`]
//!   write seam, and the GC protocol (`sweep`, direct `delete`,
//!   liveness registration). Engine-blind: consumers name engines only
//!   through named constructors. The size-threshold routing between a
//!   store's kv tier and its large tier is the pure function in
//!   [`dispatch`], threshold [`DEFAULT_DISPATCH_THRESHOLD`].
//! - **Engines** — one module per deployment shape: [`local`] (the
//!   filesystem large tier, always present) and the feature-gated
//!   [`mem`] (feature `mem`, default) and [`sqlite`] (feature
//!   `sqlite`, default); the postgres shapes (`postgres`, fleet CAS;
//!   `pg-lo`, large-object tier) are gated but not hyper-linked here —
//!   they resolve only under their feature's doc run. Engines implement the crate-internal
//!   [`backend`] trait; they are never named in the public surface.
//! - **`ops`** (feature `ops`) — the network ops surface (verified
//!   fetch, put, JSON control ops) riding the alkcall substrate;
//!   authorization rides alkcall's `AccessControl` seam, not an
//!   in-band scheme.
//! - **Types** — [`Key`] and [`Digest`]/[`Algorithm`] (the addressing
//!   vocabulary), [`EntryMeta`] and the facade carriers in [`facade`],
//!   [`Error`] (the error enum), the GC-side carriers in [`gc`].
//!
//! ## Substrate-agnostic posture
//!
//! The store never knows where bytes came from. `Store::put` takes a
//! stream and a length; the ops layer, a local writer, and a network
//! offer are all just callers. Transport, framing, and serialization
//! live above this crate (in `ops`, gated off by default) or nowhere.
//!
//! ## Construction
//!
//! No `new`: the `Store` is built through named constructors, each
//! declaring its tier shape (see [`StoreMode`], three ADR-pinned
//! variants). The mem shapes — [`Store::mem_only`],
//! [`Store::kv_only_mem`], [`Store::dual_tier_mem_local`] — are the
//! feature-`mem` baseline; the sqlite pair ([`Store::kv_only_sqlite`],
//! [`Store::dual_tier_sqlite_local`]) is the default build's durable
//! shape; the postgres constructors (feature `postgres`) add the
//! fleet-shared variants (`*_fleet`, over a `FleetSharedMedia::asserted`
//! declaration); the pg-lo pairings
//! (feature `pg-lo`) pair a kv tier with the large-object tier.
//! [`Store::mode`] reports what was built.
//!
//! ## Spec and ADR record
//!
//! This crate's contract lives in `docs/architecture/` within the
//! repository: `store-api.md` is the facade contract this rustdoc
//! paraphrases, `overview.md` the system orientation, and
//! `decisions/` the ADRs the prose cites by number. Where this doc
//! and the specs disagree, the specs win.
//!
//! The features above compose: `postgres` and `pg-lo` are independent
//! (both pull the tokio-postgres pool), `ops` composes with anything.

pub mod backend;
pub mod dispatch;
pub mod error;
pub mod facade;
pub mod gc;
pub mod hashing;
pub mod keys;
pub mod local;
pub mod store;

pub use dispatch::DEFAULT_DISPATCH_THRESHOLD;
pub use error::Error;
pub use facade::{
    Batch, EntryMeta, GcAbortCause, LivenessRegistration, LivenessSource, Pin, PinState,
    ProtectCallback, Registration, SweepReport,
};
pub use hashing::{Algorithm, Digest};
pub use keys::{Key, KeyBytes};
pub use store::{Store, StoreMode, DEFAULT_DELETE_WINDOW_DELAY};

#[cfg(feature = "postgres")]
pub use store::{FleetSharedMedia, DEFAULT_PIN_TTL};

#[cfg(feature = "mem")]
pub mod mem;

#[cfg(feature = "pg-lo")]
pub mod pg_lo;

#[cfg(feature = "ops")]
pub mod ops;

#[cfg(feature = "ops")]
pub use ops::{
    delete_pair, fetch_openables, have_pair, put_openables, stat_pair, FanoutChunk,
    FanoutPublisher, FanoutReceiver, FanoutRegistry, OpsConfig, OpsContext, PinConverter, PinToken,
    RenewalOutcome, SlowSubscriberPolicy, TokenRegistry, BLOBS_CHANNEL_ALPN, BLOB_MISSING,
    DIGEST_MISMATCH, FETCH_OP_ID, GC_REFUSED, INVALID_DIGEST, INVALID_RENEWAL_FORM, PUT_OP_ID,
    PUT_REFUSED, VERIFICATION_REFUSED,
};

/// Fuzz/test-only surface: the ranged-fetch bounds ingress
/// (`fetch_ranges_ingress`) and its data carriers (`FetchRange`,
/// `RangedBounds`), exposed for the ops-ingress fuzz target's drive of
/// the exact production function — not contract surface, not consumer
/// API, no stability guarantee.
#[cfg(feature = "ops")]
#[doc(hidden)]
pub use ops::{fetch_ranges_ingress, FetchRange, RangedBounds};

#[cfg(all(test, feature = "ops"))]
mod fuzz_surface_tests;

#[cfg(any(feature = "postgres", feature = "pg-lo"))]
mod pg_common;

#[cfg(feature = "postgres")]
pub mod postgres;

#[cfg(any(feature = "postgres", feature = "pg-lo"))]
pub use pg_common::PgOpts;

#[cfg(feature = "sqlite")]
pub mod sqlite;