Cargo.toml
Rama main · réplica de lectura del repositorio original.
[package]
name = "kei"
version = "0.26.1-dev"
edition = "2024"
# src/download/paths.rs calls str::floor_char_boundary, stabilized in 1.91.
# Cargo refuses to build on older toolchains with a clean error naming this
# version; the clippy::incompatible_msrv lint below catches regressions on PR.
rust-version = "1.91"
[[bin]]
name = "kei"
path = "src/main.rs"
[features]
# XMP metadata embedding + sidecar writing. Default-on; build with
# `--no-default-features` on platforms where Adobe's vendored C++ XMP
# Toolkit does not compile (notably FreeBSD - see #256). Disabling drops XMP
# embedding and sidecars; native JPEG/TIFF EXIF writes
# remain available through little_exif.
default = ["xmp"]
xmp = ["dep:xmp_toolkit"]
# Re-exports parser entry points for cargo-fuzz harnesses (`fuzz/`).
# Off by default; production builds never see the `kei::__fuzz` module.
__fuzz_internals = []
[package.metadata.cargo-udeps.ignore]
# Used only by no-default-features builds (`#[cfg(not(feature = "xmp"))]`).
# The unused-deps CI job runs the default feature set, so cargo-udeps cannot
# see the native EXIF path even though `cargo test --no-default-features`
# exercises it.
normal = ["little_exif"]
[dependencies]
# CLI
clap = { version = "4", features = ["derive", "env"] }
# Async runtime
tokio = { version = "1", features = ["fs", "io-util", "macros", "process", "rt-multi-thread", "signal", "sync", "time"] }
# HTTP
reqwest = { version = "0.13", default-features = false, features = ["rustls", "cookies", "json", "stream", "http2"] }
bytes = "1"
futures-util = "0.3"
tokio-stream = "0.1"
tokio-util = "0.7"
cookie = "0.18"
# Bandwidth throttling (token-bucket for global download rate cap)
async-speed-limit = "0.4"
# Serialization
serde = { version = "1", features = ["derive", "rc"] }
# Durable JSON evidence must retain float bits for exact identity checks.
serde_json = { version = "1", features = ["float_roundtrip"] }
toml = "1"
# Crypto (SRP auth)
sha2 = "0.10"
pbkdf2 = "0.12"
num-bigint = "0.4"
base64 = "0.22"
uuid = { version = "1", features = ["v4"] }
# Credential security
secrecy = "0.10"
aes-gcm = "0.10"
# Dates
chrono = { version = "0.4", default-features = false, features = ["clock", "serde", "std"] }
# Logging
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
# `non_blocking` writer wraps stderr so that a slow consumer (Docker stdout
# pipe, screen PTY, journald) cannot back-pressure into every tracing call
# and stall the runtime. Configured `lossy(true)` in `lib.rs` so events drop
# under saturation instead of parking spawn-blocking workers and the
# heartbeat task on the writer mutex (issue #347).
tracing-appender = "0.2"
# Metrics / observability
prometheus-client = "0.22"
axum = { version = "0.8", default-features = false, features = ["http1", "tokio"] }
# Progress / UI
indicatif = "0.18"
rpassword = "7"
dialoguer = "0.12"
# Already pulled in transitively by indicatif; declared explicitly so the
# personality layer can use `console::Style` for friendly-mode glyph color
# without depending on indicatif's internals.
console = "0.16"
# XMP metadata via Adobe's XMP Toolkit (vendored C++ source).
# Handles JPEG, PNG, TIFF, MP4, MOV, PSD, PDF, and more via XMPFiles.
# Does NOT handle HEIC - the bundled XMPFiles has no HEIF handler. HEIC
# containers use kei's byte-preserving XMP item writer instead.
# Optional (behind the `xmp` feature, default-on) so platforms without a
# working C++ toolchain for the vendored sources can opt out. See #256.
xmp_toolkit = { version = "1", optional = true }
# Native EXIF writing used by `set_exif_*` settings, including builds that
# disable the default `xmp` feature.
little_exif = "0.6"
# ISO-BMFF (MP4 / HEIF / HEIC) atom parsing. HEIC's XMP packet lives in a
# `mime`-type item inside the `meta` box; mp4-atom reads existing packets and
# remains test-only for fixture construction because production HEIC writes
# preserve raw item-graph bytes.
#
# Pinned because kei depends on specific HEIF fixes included in 0.11.0:
# - #123 `uri ` infe-item support for iOS 17+ HEICs (kei #274)
# - #153 colr cursor advance for `prof` / `rICC` ICC profiles, covering
# HDR HEIC parser fixtures (kei #269, #276)
# - #157 bound `Vec::with_capacity` in `parse_vorbis_comment` / `Avcc`,
# fixes the fuzz-found OOM (upstream #154)
# - #161 drops mp4-atom's unmaintained `paste` dep in favor of `pastey`
# - #163 returns Err instead of panicking on reserved iloc *_size nibbles
# found by fuzzing (upstream #158)
mp4-atom = "=0.11.0"
# Error handling
anyhow = "1"
thiserror = "2"
# Random
rand = "0.10.1"
# File locking
fs4 = "0.13"
# Glob pattern matching
glob = "0.3"
# Bit flags
bitflags = "2"
# Misc
url = "2"
dirs = "6"
async-trait = "0.1"
# SQLite state tracking
rusqlite = { version = "0.39", features = ["bundled", "backup"] }
# Binary plist decoding for iCloud *Enc fields (location, keywords, etc.)
plist = "1"
# System
libc = "0.2"
rustc-hash = "2.1"
data-encoding = "2.10.0"
[target.'cfg(target_os = "macos")'.dependencies]
keyring = { version = "3", features = ["apple-native"] }
[target.'cfg(target_os = "linux")'.dependencies]
keyring = { version = "3", features = ["sync-secret-service"] }
sd-notify = "0.5"
# FreeBSD: Secret Service D-Bus API is available via ports (dbus + a
# keyring daemon like gnome-keyring or KWallet). If no daemon is running,
# `CredentialStore` falls back to the encrypted file backend. See #256.
[target.'cfg(target_os = "freebsd")'.dependencies]
keyring = { version = "3", features = ["sync-secret-service"] }
[target.'cfg(target_os = "windows")'.dependencies]
keyring = { version = "3", features = ["windows-native"] }
windows-service = "0.7"
# Used only for the named ERROR_* constants returned by windows-service
# error variants (1060, 1063). 0.52 matches the version windows-service
# 0.7 already brings in transitively, so no extra version in the build.
windows-sys = { version = "0.52", features = ["Win32_Foundation", "Win32_Storage_FileSystem"] }
[dev-dependencies]
assert_cmd = "2"
predicates = "3"
tempfile = "3"
dotenvy = "0.15"
rusqlite = { version = "0.39", features = ["bundled", "backup"] }
http = "1"
wiremock = "0.6"
tracing-test = "0.2"
sha1 = "0.10"
# test-util enables `tokio::test(start_paused = true)` so retry/backoff
# tests in the auth layer don't sleep through real wall-clock delays.
tokio = { version = "1", features = ["test-util"] }
[[test]]
name = "cli"
path = "tests/cli.rs"
[[test]]
name = "sync"
path = "tests/sync.rs"
[[test]]
name = "state_auth"
path = "tests/state_auth.rs"
[lints.clippy]
# Baseline lint group. Lower priority so individual lints below can override.
all = { level = "warn", priority = -1 }
# ── Don't Panic ───────────────────────────────────────────────────────
unwrap_used = "warn"
expect_used = "warn"
panic = "warn"
todo = "warn"
unimplemented = "warn"
unreachable = "warn"
get_unwrap = "warn"
indexing_slicing = "warn"
string_slice = "warn"
unwrap_in_result = "warn"
panic_in_result_fn = "warn"
# ── Don't Fail Silently ───────────────────────────────────────────────
let_underscore_future = "warn"
unused_result_ok = "warn"
map_err_ignore = "warn"
# ── Don't Do Bad Async Stuff ─────────────────────────────────────────
await_holding_lock = "warn"
await_holding_refcell_ref = "warn"
large_futures = "warn"
# ── Don't Do Unsafe Things with Memory ────────────────────────────────
mem_forget = "warn"
undocumented_unsafe_blocks = "warn"
multiple_unsafe_ops_per_block = "warn"
# ── Don't Do Bad Things with Numbers ─────────────────────────────────
cast_possible_truncation = "warn"
cast_precision_loss = "warn"
cast_sign_loss = "warn"
float_cmp = "warn"
float_cmp_const = "warn"
lossy_float_literal = "warn"
invalid_upcast_comparisons = "warn"
# ── Don't Do Bad Things That Are Easy to Avoid ────────────────────────
rc_mutex = "warn"
debug_assert_with_mut_call = "warn"
iter_not_returning_iterator = "warn"
expl_impl_clone_on_copy = "warn"
dbg_macro = "warn"
# ── Logging hygiene ──────────────────────────────────────────────────
print_stdout = "warn"
print_stderr = "warn"
# ── MSRV ─────────────────────────────────────────────────────────────
incompatible_msrv = "warn"