Gunnar

nordisk/skade

Cargo.toml

[package]
name = "skade-katalog"
# 0.1.20: DRIFTED from the published 0.1.19 — crates.io bytes are immutable, so the
# edit only reaches a consumer as a new version. Found by `dwarves release_drift`
# during the 2026-08-23 cascade; it is the only drifted crate in this workspace.
version = "0.2.0"
edition = "2024"
rust-version = "1.85"
description = "The katalog under skade: an embedded, single-file ACID Apache Iceberg catalog (redb) with time-travel snapshots and atomic multi-table release commits — the Norns recording the world's icebergs."
license = "Apache-2.0"
repository = "https://git.gunnar.rs/nordisk/skade"
readme = "README.md"
keywords = ["iceberg", "catalog", "redb", "warehouse", "embedded"]
categories = ["database", "data-structures"]
# Keep the published package lean: the bench crate (own workspace) and the
# .nornir design-docs/runtime dir are not part of the library.
# The tri-modal serving crates (rest/, grpc/, serve/) are their own detached
# workspaces — shipped separately, never part of the core library's tarball.
exclude = [
    "bench/",
    "skade/",
    "rest/",
    "grpc/",
    "serve/",
    "skade.webp",
    ".nornir/",
    "HANDOFF.md",
    "TODO.md",
    "REDB_WISHLIST.md",
    "design.md",
    "plan.md",
    ".githooks/",
    ".github/",
    "docs/",
    "brokkr.toml",
    "bench_history.jsonl",
    ".gitattributes",
]

[dependencies]
# arrow-58 Iceberg. The vendored fork (skade/vendor/iceberg-arrow59) is
# published under the unique crates.io name `iceberg-arrow59` but keeps its
# library named `iceberg`, so source `use iceberg::…` is unchanged. `path`
# is used for local dev; `version` for the published manifest. This replaces
# the old `[patch.crates-io] iceberg = {path=../iceberg-arrow59}` that
# crates.io would strip on publish.
iceberg = { package = "iceberg-arrow59", version = "0.11.0", path = "vendor/iceberg-arrow59" }
redb = "2"
async-trait = "0.1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["sync", "rt"] }
# The `s3` feature's backend: our own tiny pure-Rust SigV4 S3 client. Dep-key
# stays `aegir` (code says `use aegir::…`); the PUBLISH name is `skade-aegir`
# because bare `aegir` is squatted on crates.io by an unrelated autodiff lib.
aegir = { package = "skade-aegir", version = "0.2.1", path = "bench/aegir", optional = true }
bytes = { version = "1", optional = true }
typetag = { version = "0.2", optional = true }
futures = { version = "0.3", optional = true }
thiserror = "2"
moka = { version = "0.12", features = ["future"] }
arc-swap = "1"
imbl = "7"
# Fast, well-distributed hasher for the L1 pointer mirror (internal,
# content-addressed keys — no HashDoS surface, so SipHash is needless cost).
foldhash = "0.2"
# Ragnar static search tree (STree64) for the historical snapshot-id index.
znippy-zoomies = "0.1.26"
# The reusable multi-aspect test-matrix engine — pulled in ONLY under the
# `testmatrix` feature (optional dep). With the feature ON, the library's own
# hot paths (`atomic_release` multi-table commit, `load_table` read) emit one
# `functional_status` row per real operation via the `crate::testmatrix` shim,
# so live catalog activity turns into test-matrix rows. A normal build (and
# `cargo publish`) has the feature OFF: `functional_status` compiles to a no-op
# and nornir-testmatrix is not linked. Kept a crates.io registry dep (no path)
# so the published manifest stays clean.
nornir-testmatrix = { version = "0.2.8", optional = true, default-features = false }

[dev-dependencies]
iceberg = { package = "iceberg-arrow59", path = "vendor/iceberg-arrow59" }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "fs"] }
anyhow = "1"
tempfile = "3"
uuid = { version = "1", features = ["v4"] }
# The silenced-test guard (`tests/no_silenced_tests.rs`): a `tests/*.rs` whose
# crate-level `#![cfg(feature = "X")]` is unsatisfied compiles to an EMPTY binary
# and prints `running 0 tests ... ok` — green-by-vacuum. `audit_repo` RED-flags
# those. skade's one gated target, `tests/testmatrix_wiring.rs`, can never be
# default-reachable (see the `testmatrix` feature below), so the arm declared in
# `.nornir/testmatrix-arms.json` is the only thing keeping it honest — and this
# guard is what keeps the ARM honest.
#
# SAME registry spec as the optional runtime dep above (no `path`), deliberately:
# it keeps the ONE source, since two copies of nornir-testmatrix would be two
# distinct `TestResultRow` types. It used to need a `[patch.crates-io]` bridge to
# reach `gatedtests` at all; 0.2.8 carries the module, so this is now a plain
# registry dep resolved from crates.io like any other (see the retired-bridge
# note at the bottom of this file).
#
# Non-optional and NOT behind `testmatrix`: a guard that can be switched off is
# not a guard — it must run on a plain `cargo test`.
nornir-testmatrix = { version = "0.2.8", default-features = false }

[features]
# `testmatrix` pulls in nornir-testmatrix (optional dep) AND flips its own
# `testmatrix` feature, turning `nornir_testmatrix::functional_status` from a
# compiled-out no-op into a real row-appender. Both the library hot-path emits
# (via `crate::testmatrix::functional_status`) and every emit call in this
# repo's tests are wrapped in `#[cfg(feature = "testmatrix")]`, so a normal
# build (and `cargo publish`) strips all of them and the engine edge stays
# dormant. Build/test with `--features testmatrix` to emit the functional rows.
testmatrix = ["dep:nornir-testmatrix", "nornir-testmatrix/testmatrix"]

# `bench` (opt-in, default OFF) — a pub hook exposing the `pub(crate)` redb key
# builders (`keys::{table_key,namespace_key,table_prefix,…}`) as
# `skade_katalog::bench_keys::*` so the out-of-crate `skade-katalog-bench`
# harness can time them (`skade.catalog_key`) without leaking the internals
# into a normal build. Pulls NO extra deps and adds no code to a default build
# (and `cargo publish`) — it only re-gates visibility of already-compiled fns.
bench = []

# `s3` (opt-in, default OFF) — `src/s3_storage.rs`: the aegir-backed iceberg
# `Storage`/`StorageFactory` (SigV4 over ureq, spawn_blocking bridge), moved up
# from the bench harness (2026-08-17) so it publishes with the catalog instead
# of living in a publish=false crate. The bench re-exports this one copy.
s3 = ["dep:aegir", "dep:bytes", "dep:typetag", "dep:futures"]

[lib]
path = "src/lib.rs"

# skade-katalog roots its own workspace and pulls in the vendored, separately
# published arrow-59 Iceberg forks as members so `cargo build` here compiles
# them and the path deps resolve. They publish under their own unique crates.io
# names — `iceberg-arrow59` 0.9.10, `iceberg-datafusion-arrow59` 0.9.9 and
# `iceberg-catalog-rest-arrow59` 0.9.6, all three confirmed live on 2026-08-24 —
# and skade is the single canonical publisher of those global names.
# `iceberg-datafusion-arrow59` is a member here (so its
# `iceberg = {path=../iceberg-arrow59}` resolves) even though skade-katalog
# itself doesn't use it — the detached `skade/` workspace (the `sql` feature) does.
#
# ⚠ This paragraph said "arrow-58" and named a crate `iceberg-datafusion-arrow58`
# that does not exist, three lines above a `members` list that has always read
# `iceberg-datafusion-arrow59`. Corrected 2026-08-24.
#
# RENAMING is the mechanism that makes these survive publication: a
# `[patch.crates-io]` is stripped by `cargo publish`, a uniquely-named crate is
# not. knut's remaining fork (`vendor/spark-connect-arrow59`; orc-rust's retired 2026-10-02)
# keeps upstream's package name and is consequently path-only.
[workspace]
members = [
    "vendor/iceberg-arrow59",
    "vendor/iceberg-datafusion-arrow59",
    "vendor/iceberg-catalog-rest-arrow59",
    # Rebased onto apache/iceberg-rust main 2026-10-02: upstream `iceberg` now
    # depends on its property macro (crates.io holds only a 0.0.0 placeholder
    # under that name), and the REST catalog's tests on its test-utils crate.
    "vendor/iceberg-property-macro-arrow59",
    "vendor/iceberg-test-utils",
    # skade's `impl BuildThing` (lane AG, 2026-08-30) — a member, not a
    # dependency: nothing skade ships or publishes links it. It exists so
    # `.nornir/build-variants.toml` can be EMITTED from code instead of
    # hand-written, and dwarves' forge finds it by package name. It is the ONE
    # place in this repo with a PATH dep on edda's nornir-build-thing: the
    # emitter and the schema rule are 0.1.12 vocabulary and the published 0.1.11
    # has neither. `publish = false`, so skade's own release cascade is untouched.
    "crates/skade-build-thing",
]

# ── the nornir-testmatrix `[patch.crates-io]` bridge is RETIRED ──
# It existed because the dev-only silenced-test guard calls
# `nornir_testmatrix::audit_repo`, which lives in the `gatedtests` module — a
# module no PUBLISHED nornir-testmatrix contained; it existed only in edda's
# working tree. The patch redirected that one source edge at the sibling
# checkout, so the guard compiled without either dep growing a `path =` (two
# copies of the crate would be two non-unifying `TestResultRow` types).
#
# RETIRED 2026-08-04. `gatedtests` (incl. `audit_repo`) shipped in
# nornir-testmatrix **0.2.8**, verified in the published tarball
# (`nornir-testmatrix-0.2.8/src/gatedtests.rs:1156`), so the redirect has nothing
# left to bridge and skade is patch-free. The two reqs above were widened from
# `"0.2"` to `"0.2.8"` at the same time: `"0.2"` also admits 0.2.0–0.2.7, none of
# which contain the module the guard calls — a floor that cannot be met is the
# same defect the patch was hiding, just declared instead of resolved.