From 38be2c584df01b29f24fe4cd12776b80ea12552d Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Sun, 22 Feb 2026 18:38:09 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20karapace-dbus=20=E2=80=94=20socket-acti?= =?UTF-8?q?vated=20D-Bus=20service=20with=2011=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - org.karapace.Manager1 D-Bus interface - 11 methods: ListEnvironments, GetEnvironmentStatus, GetEnvironmentHash, BuildEnvironment, BuildNamedEnvironment, DestroyEnvironment, RunEnvironment, RenameEnvironment, ListPresets, GarbageCollect, VerifyStore - Name-aware resolution (env_id, short_id, name, prefix) - Desktop notifications via notify-rust (non-fatal if daemon unavailable) - Typed serde response structs (no hand-rolled JSON) - 30-second idle timeout for socket activation - Hardened systemd unit: ProtectSystem=strict, ProtectHome=read-only, PrivateTmp, NoNewPrivileges --- crates/karapace-dbus/Cargo.toml | 30 + crates/karapace-dbus/karapace-dbus.cdx.json | 4190 +++++++++++++++++++ crates/karapace-dbus/src/interface.rs | 672 +++ crates/karapace-dbus/src/lib.rs | 12 + crates/karapace-dbus/src/main.rs | 30 + crates/karapace-dbus/src/service.rs | 50 + 6 files changed, 4984 insertions(+) create mode 100644 crates/karapace-dbus/Cargo.toml create mode 100644 crates/karapace-dbus/karapace-dbus.cdx.json create mode 100644 crates/karapace-dbus/src/interface.rs create mode 100644 crates/karapace-dbus/src/lib.rs create mode 100644 crates/karapace-dbus/src/main.rs create mode 100644 crates/karapace-dbus/src/service.rs diff --git a/crates/karapace-dbus/Cargo.toml b/crates/karapace-dbus/Cargo.toml new file mode 100644 index 0000000..944413d --- /dev/null +++ b/crates/karapace-dbus/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "karapace-dbus" +description = "Socket-activated D-Bus desktop integration service for Karapace" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[lints] +workspace = true + +[[bin]] +name = "karapace-dbus" +path = "src/main.rs" + +[dependencies] +zbus.workspace = true +tokio.workspace = true +serde.workspace = true +serde_json.workspace = true +thiserror.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +notify-rust.workspace = true +karapace-core = { path = "../karapace-core" } +karapace-schema = { path = "../karapace-schema" } +karapace-store = { path = "../karapace-store" } + +[dev-dependencies] +tempfile.workspace = true diff --git a/crates/karapace-dbus/karapace-dbus.cdx.json b/crates/karapace-dbus/karapace-dbus.cdx.json new file mode 100644 index 0000000..43f5b16 --- /dev/null +++ b/crates/karapace-dbus/karapace-dbus.cdx.json @@ -0,0 +1,4190 @@ +{ + "bomFormat": "CycloneDX", + "specVersion": "1.3", + "version": 1, + "serialNumber": "urn:uuid:d11d7832-967c-4d8f-9ab7-288a855c0172", + "metadata": { + "timestamp": "2026-02-22T14:03:10.618097730Z", + "tools": [ + { + "vendor": "CycloneDX", + "name": "cargo-cyclonedx", + "version": "0.5.5" + } + ], + "component": { + "type": "application", + "bom-ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-dbus#0.1.0", + "name": "karapace-dbus", + "version": "0.1.0", + "description": "Socket-activated D-Bus desktop integration service for Karapace", + "scope": "required", + "licenses": [ + { + "expression": "EUPL-1.2" + } + ], + "purl": "pkg:cargo/karapace-dbus@0.1.0?download_url=file://.", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/marcoallegretti/karapace" + } + ], + "components": [ + { + "type": "library", + "bom-ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-dbus#0.1.0 bin-target-0", + "name": "karapace_dbus", + "version": "0.1.0", + "purl": "pkg:cargo/karapace-dbus@0.1.0?download_url=file://.#src/lib.rs" + }, + { + "type": "application", + "bom-ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-dbus#0.1.0 bin-target-1", + "name": "karapace-dbus", + "version": "0.1.0", + "purl": "pkg:cargo/karapace-dbus@0.1.0?download_url=file://.#src/main.rs" + } + ] + } + }, + "components": [ + { + "type": "library", + "bom-ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-core#0.1.0", + "name": "karapace-core", + "version": "0.1.0", + "description": "Build engine, lifecycle state machine, drift control, and concurrency for Karapace", + "scope": "required", + "licenses": [ + { + "expression": "EUPL-1.2" + } + ], + "purl": "pkg:cargo/karapace-core@0.1.0?download_url=file://../karapace-core", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/marcoallegretti/karapace" + } + ] + }, + { + "type": "library", + "bom-ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-remote#0.1.0", + "name": "karapace-remote", + "version": "0.1.0", + "description": "Remote content-addressable store for Karapace environment sharing", + "scope": "required", + "licenses": [ + { + "expression": "EUPL-1.2" + } + ], + "purl": "pkg:cargo/karapace-remote@0.1.0?download_url=file://../karapace-remote", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/marcoallegretti/karapace" + } + ] + }, + { + "type": "library", + "bom-ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-runtime#0.1.0", + "name": "karapace-runtime", + "version": "0.1.0", + "description": "Container runtime backends, image management, sandbox, and host integration for Karapace", + "scope": "required", + "licenses": [ + { + "expression": "EUPL-1.2" + } + ], + "purl": "pkg:cargo/karapace-runtime@0.1.0?download_url=file://../karapace-runtime", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/marcoallegretti/karapace" + } + ] + }, + { + "type": "library", + "bom-ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-schema#0.1.0", + "name": "karapace-schema", + "version": "0.1.0", + "description": "Manifest parsing, normalization, identity hashing, and lock file for Karapace", + "scope": "required", + "licenses": [ + { + "expression": "EUPL-1.2" + } + ], + "purl": "pkg:cargo/karapace-schema@0.1.0?download_url=file://../karapace-schema", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/marcoallegretti/karapace" + } + ] + }, + { + "type": "library", + "bom-ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-store#0.1.0", + "name": "karapace-store", + "version": "0.1.0", + "description": "Content-addressable store, metadata, layers, GC, and integrity for Karapace", + "scope": "required", + "licenses": [ + { + "expression": "EUPL-1.2" + } + ], + "purl": "pkg:cargo/karapace-store@0.1.0?download_url=file://../karapace-store", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/marcoallegretti/karapace" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#adler2@2.0.1", + "name": "adler2", + "version": "2.0.1", + "description": "A simple clean-room implementation of the Adler-32 checksum", + "scope": "required", + "licenses": [ + { + "expression": "0BSD OR MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/adler2@2.0.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/adler2/" + }, + { + "type": "vcs", + "url": "https://github.com/oyvindln/adler2" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#aho-corasick@1.1.4", + "name": "aho-corasick", + "version": "1.1.4", + "description": "Fast multiple substring searching.", + "scope": "required", + "licenses": [ + { + "expression": "Unlicense OR MIT" + } + ], + "purl": "pkg:cargo/aho-corasick@1.1.4", + "externalReferences": [ + { + "type": "website", + "url": "https://github.com/BurntSushi/aho-corasick" + }, + { + "type": "vcs", + "url": "https://github.com/BurntSushi/aho-corasick" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#arrayref@0.3.9", + "name": "arrayref", + "version": "0.3.9", + "description": "Macros to take array references of slices", + "scope": "required", + "licenses": [ + { + "expression": "BSD-2-Clause" + } + ], + "purl": "pkg:cargo/arrayref@0.3.9", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/arrayref" + }, + { + "type": "vcs", + "url": "https://github.com/droundy/arrayref" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#arrayvec@0.7.6", + "name": "arrayvec", + "version": "0.7.6", + "description": "A vector with fixed capacity, backed by an array (it can be stored on the stack too). Implements fixed capacity ArrayVec and ArrayString.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/arrayvec@0.7.6", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/arrayvec/" + }, + { + "type": "vcs", + "url": "https://github.com/bluss/arrayvec" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#async-broadcast@0.7.2", + "name": "async-broadcast", + "version": "0.7.2", + "description": "Async broadcast channels", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/async-broadcast@0.7.2", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/async-broadcast" + }, + { + "type": "vcs", + "url": "https://github.com/smol-rs/async-broadcast" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#async-channel@2.5.0", + "name": "async-channel", + "version": "2.5.0", + "description": "Async multi-producer multi-consumer channel", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/async-channel@2.5.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/async-channel" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#async-executor@1.14.0", + "name": "async-executor", + "version": "1.14.0", + "description": "Async executor", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/async-executor@1.14.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/async-executor" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#async-io@2.6.0", + "name": "async-io", + "version": "2.6.0", + "description": "Async I/O and timers", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/async-io@2.6.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/async-io" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#async-lock@3.4.2", + "name": "async-lock", + "version": "3.4.2", + "description": "Async synchronization primitives", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/async-lock@3.4.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/async-lock" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#async-process@2.5.0", + "name": "async-process", + "version": "2.5.0", + "description": "Async interface for working with processes", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/async-process@2.5.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/async-process" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#async-signal@0.2.13", + "name": "async-signal", + "version": "0.2.13", + "description": "Async signal handling", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/async-signal@0.2.13", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/async-signal" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#async-task@4.7.1", + "name": "async-task", + "version": "4.7.1", + "description": "Task abstraction for building executors", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/async-task@4.7.1", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/async-task" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#async-trait@0.1.89", + "name": "async-trait", + "version": "0.1.89", + "description": "Type erasure for async trait methods", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/async-trait@0.1.89", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/async-trait" + }, + { + "type": "vcs", + "url": "https://github.com/dtolnay/async-trait" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#atomic-waker@1.1.2", + "name": "atomic-waker", + "version": "1.1.2", + "description": "A synchronization primitive for task wakeup", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/atomic-waker@1.1.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/atomic-waker" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#autocfg@1.5.0", + "name": "autocfg", + "version": "1.5.0", + "description": "Automatic cfg for Rust compiler features", + "scope": "excluded", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/autocfg@1.5.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/autocfg/" + }, + { + "type": "vcs", + "url": "https://github.com/cuviper/autocfg" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1", + "name": "base64", + "version": "0.22.1", + "description": "encodes and decodes base64 as bytes or utf8", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/base64@0.22.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/base64" + }, + { + "type": "vcs", + "url": "https://github.com/marshallpierce/rust-base64" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.0", + "name": "bitflags", + "version": "2.11.0", + "description": "A macro to generate structures which behave like bitflags. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/bitflags@2.11.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/bitflags" + }, + { + "type": "website", + "url": "https://github.com/bitflags/bitflags" + }, + { + "type": "vcs", + "url": "https://github.com/bitflags/bitflags" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#blake3@1.8.3", + "name": "blake3", + "version": "1.8.3", + "description": "the BLAKE3 hash function", + "scope": "required", + "licenses": [ + { + "expression": "CC0-1.0 OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception" + } + ], + "purl": "pkg:cargo/blake3@1.8.3", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/blake3" + }, + { + "type": "vcs", + "url": "https://github.com/BLAKE3-team/BLAKE3" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#blocking@1.6.2", + "name": "blocking", + "version": "1.6.2", + "description": "A thread pool for isolating blocking I/O in async programs", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/blocking@1.6.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/blocking" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#bytes@1.11.1", + "name": "bytes", + "version": "1.11.1", + "description": "Types and traits for working with bytes", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/bytes@1.11.1", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/tokio-rs/bytes" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#cc@1.2.56", + "name": "cc", + "version": "1.2.56", + "description": "A build-time dependency for Cargo build scripts to assist in invoking the native C compiler to compile native C code into a static archive to be linked into Rust code. ", + "scope": "excluded", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/cc@1.2.56", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/cc" + }, + { + "type": "website", + "url": "https://github.com/rust-lang/cc-rs" + }, + { + "type": "vcs", + "url": "https://github.com/rust-lang/cc-rs" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "name": "cfg-if", + "version": "1.0.4", + "description": "A macro to ergonomically define an item depending on a large number of #[cfg] parameters. Structured like an if-else chain, the first matching branch is the item that gets emitted. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/cfg-if@1.0.4", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/rust-lang/cfg-if" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#cfg_aliases@0.2.1", + "name": "cfg_aliases", + "version": "0.2.1", + "description": "A tiny utility to help save you a lot of effort with long winded `#[cfg()]` checks.", + "scope": "excluded", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/cfg_aliases@0.2.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/cfg_aliases" + }, + { + "type": "website", + "url": "https://github.com/katharostech/cfg_aliases" + }, + { + "type": "vcs", + "url": "https://github.com/katharostech/cfg_aliases" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#chrono@0.4.43", + "name": "chrono", + "version": "0.4.43", + "description": "Date and time library for Rust", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/chrono@0.4.43", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/chrono/" + }, + { + "type": "website", + "url": "https://github.com/chronotope/chrono" + }, + { + "type": "vcs", + "url": "https://github.com/chronotope/chrono" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#concurrent-queue@2.5.0", + "name": "concurrent-queue", + "version": "2.5.0", + "description": "Concurrent multi-producer multi-consumer queue", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/concurrent-queue@2.5.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/concurrent-queue" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#constant_time_eq@0.4.2", + "name": "constant_time_eq", + "version": "0.4.2", + "description": "Compares two equal-sized byte strings in constant time.", + "scope": "required", + "licenses": [ + { + "expression": "CC0-1.0 OR MIT-0 OR Apache-2.0" + } + ], + "purl": "pkg:cargo/constant_time_eq@0.4.2", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/constant_time_eq" + }, + { + "type": "vcs", + "url": "https://github.com/cesarb/constant_time_eq" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#cpufeatures@0.2.17", + "name": "cpufeatures", + "version": "0.2.17", + "description": "Lightweight runtime CPU feature detection for aarch64, loongarch64, and x86/x86_64 targets, with no_std support and support for mobile targets including Android and iOS ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/cpufeatures@0.2.17", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/cpufeatures" + }, + { + "type": "vcs", + "url": "https://github.com/RustCrypto/utils" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#crc32fast@1.5.0", + "name": "crc32fast", + "version": "1.5.0", + "description": "Fast, SIMD-accelerated CRC32 (IEEE) checksum computation", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/crc32fast@1.5.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/srijs/rust-crc32fast" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#crossbeam-utils@0.8.21", + "name": "crossbeam-utils", + "version": "0.8.21", + "description": "Utilities for concurrent programming", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/crossbeam-utils@0.8.21", + "externalReferences": [ + { + "type": "website", + "url": "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils" + }, + { + "type": "vcs", + "url": "https://github.com/crossbeam-rs/crossbeam" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#ctrlc@3.5.2", + "name": "ctrlc", + "version": "3.5.2", + "description": "Easy Ctrl-C handler for Rust projects", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/ctrlc@3.5.2", + "externalReferences": [ + { + "type": "documentation", + "url": "https://detegr.github.io/doc/ctrlc" + }, + { + "type": "website", + "url": "https://github.com/Detegr/rust-ctrlc" + }, + { + "type": "vcs", + "url": "https://github.com/Detegr/rust-ctrlc.git" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#endi@1.1.1", + "name": "endi", + "version": "1.1.1", + "description": "A simple endian-handling library", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/endi@1.1.1", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/zeenix/endi" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#enumflags2@0.7.12", + "name": "enumflags2", + "version": "0.7.12", + "description": "Enum-based bit flags", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/enumflags2@0.7.12", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/enumflags2" + }, + { + "type": "vcs", + "url": "https://github.com/meithecatte/enumflags2" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#enumflags2_derive@0.7.12", + "name": "enumflags2_derive", + "version": "0.7.12", + "description": "Do not use directly, use the reexport in the `enumflags2` crate. This allows for better compatibility across versions.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/enumflags2_derive@0.7.12", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/meithecatte/enumflags2" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#equivalent@1.0.2", + "name": "equivalent", + "version": "1.0.2", + "description": "Traits for key comparison in maps.", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/equivalent@1.0.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/indexmap-rs/equivalent" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#errno@0.3.14", + "name": "errno", + "version": "0.3.14", + "description": "Cross-platform interface to the `errno` variable.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/errno@0.3.14", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/errno" + }, + { + "type": "vcs", + "url": "https://github.com/lambda-fairy/rust-errno" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#event-listener-strategy@0.5.4", + "name": "event-listener-strategy", + "version": "0.5.4", + "description": "Block or poll on event_listener easily", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/event-listener-strategy@0.5.4", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/event-listener-strategy" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#event-listener@5.4.1", + "name": "event-listener", + "version": "5.4.1", + "description": "Notify async tasks or threads", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/event-listener@5.4.1", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/event-listener" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#fastrand@2.3.0", + "name": "fastrand", + "version": "2.3.0", + "description": "A simple and fast random number generator", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/fastrand@2.3.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/fastrand" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#filetime@0.2.27", + "name": "filetime", + "version": "0.2.27", + "description": "Platform-agnostic accessors of timestamps in File metadata ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/filetime@0.2.27", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/filetime" + }, + { + "type": "website", + "url": "https://github.com/alexcrichton/filetime" + }, + { + "type": "vcs", + "url": "https://github.com/alexcrichton/filetime" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#find-msvc-tools@0.1.9", + "name": "find-msvc-tools", + "version": "0.1.9", + "description": "Find windows-specific tools, read MSVC versions from the registry and from COM interfaces", + "scope": "excluded", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/find-msvc-tools@0.1.9", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/find-msvc-tools" + }, + { + "type": "vcs", + "url": "https://github.com/rust-lang/cc-rs" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#flate2@1.1.9", + "name": "flate2", + "version": "1.1.9", + "description": "DEFLATE compression and decompression exposed as Read/BufRead/Write streams. Supports miniz_oxide and multiple zlib implementations. Supports zlib, gzip, and raw deflate streams. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/flate2@1.1.9", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/flate2" + }, + { + "type": "website", + "url": "https://github.com/rust-lang/flate2-rs" + }, + { + "type": "vcs", + "url": "https://github.com/rust-lang/flate2-rs" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#fs2@0.4.3", + "name": "fs2", + "version": "0.4.3", + "description": "Cross-platform file locks and file duplication.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/fs2@0.4.3", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/fs2" + }, + { + "type": "vcs", + "url": "https://github.com/danburkert/fs2-rs" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32", + "name": "futures-core", + "version": "0.3.32", + "description": "The core traits and types in for the `futures` library. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/futures-core@0.3.32", + "externalReferences": [ + { + "type": "website", + "url": "https://rust-lang.github.io/futures-rs" + }, + { + "type": "vcs", + "url": "https://github.com/rust-lang/futures-rs" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32", + "name": "futures-io", + "version": "0.3.32", + "description": "The `AsyncRead`, `AsyncWrite`, `AsyncSeek`, and `AsyncBufRead` traits for the futures-rs library. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/futures-io@0.3.32", + "externalReferences": [ + { + "type": "website", + "url": "https://rust-lang.github.io/futures-rs" + }, + { + "type": "vcs", + "url": "https://github.com/rust-lang/futures-rs" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#futures-lite@2.6.1", + "name": "futures-lite", + "version": "2.6.1", + "description": "Futures, streams, and async I/O combinators", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/futures-lite@2.6.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/futures-lite" + }, + { + "type": "website", + "url": "https://github.com/smol-rs/futures-lite" + }, + { + "type": "vcs", + "url": "https://github.com/smol-rs/futures-lite" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#getrandom@0.2.17", + "name": "getrandom", + "version": "0.2.17", + "description": "A small cross-platform library for retrieving random data from system source", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/getrandom@0.2.17", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/getrandom" + }, + { + "type": "vcs", + "url": "https://github.com/rust-random/getrandom" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#getrandom@0.4.1", + "name": "getrandom", + "version": "0.4.1", + "description": "A small cross-platform library for retrieving random data from system source", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/getrandom@0.4.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/getrandom" + }, + { + "type": "vcs", + "url": "https://github.com/rust-random/getrandom" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#hashbrown@0.16.1", + "name": "hashbrown", + "version": "0.16.1", + "description": "A Rust port of Google's SwissTable hash map", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/hashbrown@0.16.1", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/rust-lang/hashbrown" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#hex@0.4.3", + "name": "hex", + "version": "0.4.3", + "description": "Encoding and decoding data into/from hexadecimal representation.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/hex@0.4.3", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/hex/" + }, + { + "type": "vcs", + "url": "https://github.com/KokaKiwi/rust-hex" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#http@1.4.0", + "name": "http", + "version": "1.4.0", + "description": "A set of types for representing HTTP requests and responses. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/http@1.4.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/http" + }, + { + "type": "vcs", + "url": "https://github.com/hyperium/http" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#httparse@1.10.1", + "name": "httparse", + "version": "1.10.1", + "description": "A tiny, safe, speedy, zero-copy HTTP/1.x parser.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/httparse@1.10.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/httparse" + }, + { + "type": "vcs", + "url": "https://github.com/seanmonstar/httparse" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#iana-time-zone@0.1.65", + "name": "iana-time-zone", + "version": "0.1.65", + "description": "get the IANA time zone for the current system", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/iana-time-zone@0.1.65", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/strawlab/iana-time-zone" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#indexmap@2.13.0", + "name": "indexmap", + "version": "2.13.0", + "description": "A hash table with consistent order and fast iteration.", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/indexmap@2.13.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/indexmap/" + }, + { + "type": "vcs", + "url": "https://github.com/indexmap-rs/indexmap" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.17", + "name": "itoa", + "version": "1.0.17", + "description": "Fast integer primitive to string conversion", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/itoa@1.0.17", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/itoa" + }, + { + "type": "vcs", + "url": "https://github.com/dtolnay/itoa" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#lazy_static@1.5.0", + "name": "lazy_static", + "version": "1.5.0", + "description": "A macro for declaring lazily evaluated statics in Rust.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/lazy_static@1.5.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/lazy_static" + }, + { + "type": "vcs", + "url": "https://github.com/rust-lang-nursery/lazy-static.rs" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180", + "name": "libc", + "version": "0.2.180", + "description": "Raw FFI bindings to platform libraries like libc.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/libc@0.2.180", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/rust-lang/libc" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#linux-raw-sys@0.11.0", + "name": "linux-raw-sys", + "version": "0.11.0", + "description": "Generated bindings for Linux's userspace API", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/linux-raw-sys@0.11.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/linux-raw-sys" + }, + { + "type": "vcs", + "url": "https://github.com/sunfishcode/linux-raw-sys" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#log@0.4.29", + "name": "log", + "version": "0.4.29", + "description": "A lightweight logging facade for Rust ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/log@0.4.29", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/log" + }, + { + "type": "vcs", + "url": "https://github.com/rust-lang/log" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#matchers@0.2.0", + "name": "matchers", + "version": "0.2.0", + "description": "Regex matching on character and byte streams. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/matchers@0.2.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/matchers/" + }, + { + "type": "website", + "url": "https://github.com/hawkw/matchers" + }, + { + "type": "vcs", + "url": "https://github.com/hawkw/matchers" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0", + "name": "memchr", + "version": "2.8.0", + "description": "Provides extremely fast (uses SIMD on x86_64, aarch64 and wasm32) routines for 1, 2 or 3 byte search and single substring search. ", + "scope": "required", + "licenses": [ + { + "expression": "Unlicense OR MIT" + } + ], + "purl": "pkg:cargo/memchr@2.8.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/memchr/" + }, + { + "type": "website", + "url": "https://github.com/BurntSushi/memchr" + }, + { + "type": "vcs", + "url": "https://github.com/BurntSushi/memchr" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#miniz_oxide@0.8.9", + "name": "miniz_oxide", + "version": "0.8.9", + "description": "DEFLATE compression and decompression library rewritten in Rust based on miniz", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Zlib OR Apache-2.0" + } + ], + "purl": "pkg:cargo/miniz_oxide@0.8.9", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/miniz_oxide" + }, + { + "type": "website", + "url": "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" + }, + { + "type": "vcs", + "url": "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#nix@0.31.1", + "name": "nix", + "version": "0.31.1", + "description": "Rust friendly bindings to *nix APIs", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/nix@0.31.1", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/nix-rust/nix" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#notify-rust@4.12.0", + "name": "notify-rust", + "version": "4.12.0", + "description": "Show desktop notifications (linux, bsd, mac). Pure Rust dbus client and server.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/notify-rust@4.12.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/notify-rust/" + }, + { + "type": "vcs", + "url": "https://github.com/hoodie/notify-rust" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#nu-ansi-term@0.50.3", + "name": "nu-ansi-term", + "version": "0.50.3", + "description": "Library for ANSI terminal colors and styles (bold, underline)", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/nu-ansi-term@0.50.3", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/nushell/nu-ansi-term" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#num-traits@0.2.19", + "name": "num-traits", + "version": "0.2.19", + "description": "Numeric traits for generic mathematics", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/num-traits@0.2.19", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/num-traits" + }, + { + "type": "website", + "url": "https://github.com/rust-num/num-traits" + }, + { + "type": "vcs", + "url": "https://github.com/rust-num/num-traits" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.3", + "name": "once_cell", + "version": "1.21.3", + "description": "Single assignment cells and lazy values.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/once_cell@1.21.3", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/once_cell" + }, + { + "type": "vcs", + "url": "https://github.com/matklad/once_cell" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#ordered-stream@0.2.0", + "name": "ordered-stream", + "version": "0.2.0", + "description": "Streams that are ordered relative to external events", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/ordered-stream@0.2.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/danieldg/ordered-stream" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#parking@2.2.1", + "name": "parking", + "version": "2.2.1", + "description": "Thread parking and unparking", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/parking@2.2.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/parking" + }, + { + "type": "website", + "url": "https://github.com/smol-rs/parking" + }, + { + "type": "vcs", + "url": "https://github.com/smol-rs/parking" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#percent-encoding@2.3.2", + "name": "percent-encoding", + "version": "2.3.2", + "description": "Percent encoding and decoding", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/percent-encoding@2.3.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/servo/rust-url/" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16", + "name": "pin-project-lite", + "version": "0.2.16", + "description": "A lightweight version of pin-project written with declarative macros. ", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/pin-project-lite@0.2.16", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/taiki-e/pin-project-lite" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#piper@0.2.4", + "name": "piper", + "version": "0.2.4", + "description": "Async pipes, channels, mutexes, and more.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/piper@0.2.4", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/piper" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#polling@3.11.0", + "name": "polling", + "version": "3.11.0", + "description": "Portable interface to epoll, kqueue, event ports, and IOCP", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/polling@3.11.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/smol-rs/polling" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro-crate@3.4.0", + "name": "proc-macro-crate", + "version": "3.4.0", + "description": "Replacement for crate (macro_rules keyword) in proc-macros ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/proc-macro-crate@3.4.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/proc-macro-crate" + }, + { + "type": "vcs", + "url": "https://github.com/bkchr/proc-macro-crate" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "name": "proc-macro2", + "version": "1.0.106", + "description": "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/proc-macro2@1.0.106", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/proc-macro2" + }, + { + "type": "vcs", + "url": "https://github.com/dtolnay/proc-macro2" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "name": "quote", + "version": "1.0.44", + "description": "Quasi-quoting macro quote!(...)", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/quote@1.0.44", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/quote/" + }, + { + "type": "vcs", + "url": "https://github.com/dtolnay/quote" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#regex-automata@0.4.14", + "name": "regex-automata", + "version": "0.4.14", + "description": "Automata construction and matching using regular expressions.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/regex-automata@0.4.14", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/regex-automata" + }, + { + "type": "website", + "url": "https://github.com/rust-lang/regex/tree/master/regex-automata" + }, + { + "type": "vcs", + "url": "https://github.com/rust-lang/regex" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#regex-syntax@0.8.9", + "name": "regex-syntax", + "version": "0.8.9", + "description": "A regular expression parser.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/regex-syntax@0.8.9", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/regex-syntax" + }, + { + "type": "website", + "url": "https://github.com/rust-lang/regex/tree/master/regex-syntax" + }, + { + "type": "vcs", + "url": "https://github.com/rust-lang/regex" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#ring@0.17.14", + "name": "ring", + "version": "0.17.14", + "description": "An experiment.", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 AND ISC" + } + ], + "purl": "pkg:cargo/ring@0.17.14", + "externalReferences": [ + { + "type": "other", + "url": "ring_core_0_17_14_" + }, + { + "type": "vcs", + "url": "https://github.com/briansmith/ring" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#rustix@1.1.3", + "name": "rustix", + "version": "1.1.3", + "description": "Safe Rust bindings to POSIX/Unix/Linux/Winsock-like syscalls", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/rustix@1.1.3", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/rustix" + }, + { + "type": "vcs", + "url": "https://github.com/bytecodealliance/rustix" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#rustls-pki-types@1.14.0", + "name": "rustls-pki-types", + "version": "1.14.0", + "description": "Shared types for the rustls PKI ecosystem", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/rustls-pki-types@1.14.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/rustls-pki-types" + }, + { + "type": "website", + "url": "https://github.com/rustls/pki-types" + }, + { + "type": "vcs", + "url": "https://github.com/rustls/pki-types" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#rustls-webpki@0.103.9", + "name": "rustls-webpki", + "version": "0.103.9", + "description": "Web PKI X.509 Certificate Verification.", + "scope": "required", + "licenses": [ + { + "expression": "ISC" + } + ], + "purl": "pkg:cargo/rustls-webpki@0.103.9", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/rustls/webpki" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#rustls@0.23.36", + "name": "rustls", + "version": "0.23.36", + "description": "Rustls is a modern TLS library written in Rust.", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR ISC OR MIT" + } + ], + "purl": "pkg:cargo/rustls@0.23.36", + "externalReferences": [ + { + "type": "website", + "url": "https://github.com/rustls/rustls" + }, + { + "type": "vcs", + "url": "https://github.com/rustls/rustls" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "name": "serde", + "version": "1.0.228", + "description": "A generic serialization/deserialization framework", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/serde@1.0.228", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/serde" + }, + { + "type": "website", + "url": "https://serde.rs" + }, + { + "type": "vcs", + "url": "https://github.com/serde-rs/serde" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228", + "name": "serde_core", + "version": "1.0.228", + "description": "Serde traits only, with no support for derive -- use the `serde` crate instead", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/serde_core@1.0.228", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/serde_core" + }, + { + "type": "website", + "url": "https://serde.rs" + }, + { + "type": "vcs", + "url": "https://github.com/serde-rs/serde" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228", + "name": "serde_derive", + "version": "1.0.228", + "description": "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/serde_derive@1.0.228", + "externalReferences": [ + { + "type": "documentation", + "url": "https://serde.rs/derive.html" + }, + { + "type": "website", + "url": "https://serde.rs" + }, + { + "type": "vcs", + "url": "https://github.com/serde-rs/serde" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149", + "name": "serde_json", + "version": "1.0.149", + "description": "A JSON serialization file format", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/serde_json@1.0.149", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/serde_json" + }, + { + "type": "vcs", + "url": "https://github.com/serde-rs/json" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde_repr@0.1.20", + "name": "serde_repr", + "version": "0.1.20", + "description": "Derive Serialize and Deserialize that delegates to the underlying repr of a C-like enum.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/serde_repr@0.1.20", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/serde_repr" + }, + { + "type": "vcs", + "url": "https://github.com/dtolnay/serde-repr" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde_spanned@0.6.9", + "name": "serde_spanned", + "version": "0.6.9", + "description": "Serde-compatible spanned Value", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/serde_spanned@0.6.9", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/toml-rs/toml" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#sharded-slab@0.1.7", + "name": "sharded-slab", + "version": "0.1.7", + "description": "A lock-free concurrent slab. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/sharded-slab@0.1.7", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/sharded-slab/" + }, + { + "type": "website", + "url": "https://github.com/hawkw/sharded-slab" + }, + { + "type": "vcs", + "url": "https://github.com/hawkw/sharded-slab" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0", + "name": "shlex", + "version": "1.3.0", + "description": "Split a string into shell words, like Python's shlex.", + "scope": "excluded", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/shlex@1.3.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/comex/rust-shlex" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#signal-hook-registry@1.4.8", + "name": "signal-hook-registry", + "version": "1.4.8", + "description": "Backend crate for signal-hook", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/signal-hook-registry@1.4.8", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/signal-hook-registry" + }, + { + "type": "vcs", + "url": "https://github.com/vorner/signal-hook" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#simd-adler32@0.3.8", + "name": "simd-adler32", + "version": "0.3.8", + "description": "A SIMD-accelerated Adler-32 hash algorithm implementation.", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/simd-adler32@0.3.8", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/mcountryman/simd-adler32" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#slab@0.4.12", + "name": "slab", + "version": "0.4.12", + "description": "Pre-allocated storage for a uniform data type", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/slab@0.4.12", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/tokio-rs/slab" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#smallvec@1.15.1", + "name": "smallvec", + "version": "1.15.1", + "description": "'Small vector' optimization: store up to a small number of items on the stack", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/smallvec@1.15.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/smallvec/" + }, + { + "type": "vcs", + "url": "https://github.com/servo/rust-smallvec" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#subtle@2.6.1", + "name": "subtle", + "version": "2.6.1", + "description": "Pure-Rust traits and utilities for constant-time cryptographic implementations.", + "scope": "required", + "licenses": [ + { + "expression": "BSD-3-Clause" + } + ], + "purl": "pkg:cargo/subtle@2.6.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/subtle" + }, + { + "type": "website", + "url": "https://dalek.rs/" + }, + { + "type": "vcs", + "url": "https://github.com/dalek-cryptography/subtle" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117", + "name": "syn", + "version": "2.0.117", + "description": "Parser for Rust source code", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/syn@2.0.117", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/syn" + }, + { + "type": "vcs", + "url": "https://github.com/dtolnay/syn" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#tar@0.4.44", + "name": "tar", + "version": "0.4.44", + "description": "A Rust implementation of a TAR file reader and writer. This library does not currently handle compression, but it is abstract over all I/O readers and writers. Additionally, great lengths are taken to ensure that the entire contents are never required to be entirely resident in memory all at once. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/tar@0.4.44", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/tar" + }, + { + "type": "website", + "url": "https://github.com/alexcrichton/tar-rs" + }, + { + "type": "vcs", + "url": "https://github.com/alexcrichton/tar-rs" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#tempfile@3.25.0", + "name": "tempfile", + "version": "3.25.0", + "description": "A library for managing temporary files and directories.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/tempfile@3.25.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/tempfile" + }, + { + "type": "website", + "url": "https://stebalien.com/projects/tempfile-rs/" + }, + { + "type": "vcs", + "url": "https://github.com/Stebalien/tempfile" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#thiserror-impl@2.0.18", + "name": "thiserror-impl", + "version": "2.0.18", + "description": "Implementation detail of the `thiserror` crate", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/thiserror-impl@2.0.18", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/dtolnay/thiserror" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18", + "name": "thiserror", + "version": "2.0.18", + "description": "derive(Error)", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/thiserror@2.0.18", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/thiserror" + }, + { + "type": "vcs", + "url": "https://github.com/dtolnay/thiserror" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#thread_local@1.1.9", + "name": "thread_local", + "version": "1.1.9", + "description": "Per-object thread-local storage", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/thread_local@1.1.9", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/thread_local/" + }, + { + "type": "vcs", + "url": "https://github.com/Amanieu/thread_local-rs" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#tokio-macros@2.6.0", + "name": "tokio-macros", + "version": "2.6.0", + "description": "Tokio's proc macros. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/tokio-macros@2.6.0", + "externalReferences": [ + { + "type": "website", + "url": "https://tokio.rs" + }, + { + "type": "vcs", + "url": "https://github.com/tokio-rs/tokio" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#tokio@1.49.0", + "name": "tokio", + "version": "1.49.0", + "description": "An event-driven, non-blocking I/O platform for writing asynchronous I/O backed applications. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/tokio@1.49.0", + "externalReferences": [ + { + "type": "website", + "url": "https://tokio.rs" + }, + { + "type": "vcs", + "url": "https://github.com/tokio-rs/tokio" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#toml@0.8.23", + "name": "toml", + "version": "0.8.23", + "description": "A native Rust encoder and decoder of TOML-formatted files and streams. Provides implementations of the standard Serialize/Deserialize traits for TOML data to facilitate deserializing and serializing Rust structures. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/toml@0.8.23", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/toml-rs/toml" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#toml_datetime@0.6.11", + "name": "toml_datetime", + "version": "0.6.11", + "description": "A TOML-compatible datetime type", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/toml_datetime@0.6.11", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/toml-rs/toml" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#toml_datetime@0.7.5+spec-1.1.0", + "name": "toml_datetime", + "version": "0.7.5+spec-1.1.0", + "description": "A TOML-compatible datetime type", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/toml_datetime@0.7.5+spec-1.1.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/toml-rs/toml" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#toml_edit@0.22.27", + "name": "toml_edit", + "version": "0.22.27", + "description": "Yet another format-preserving TOML parser.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/toml_edit@0.22.27", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/toml-rs/toml" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#toml_edit@0.23.10+spec-1.0.0", + "name": "toml_edit", + "version": "0.23.10+spec-1.0.0", + "description": "Yet another format-preserving TOML parser.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/toml_edit@0.23.10+spec-1.0.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/toml-rs/toml" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#toml_parser@1.0.9+spec-1.1.0", + "name": "toml_parser", + "version": "1.0.9+spec-1.1.0", + "description": "Yet another format-preserving TOML parser.", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/toml_parser@1.0.9+spec-1.1.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/toml-rs/toml" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#toml_write@0.1.2", + "name": "toml_write", + "version": "0.1.2", + "description": "A low-level interface for writing out TOML ", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/toml_write@0.1.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/toml-rs/toml" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#tracing-attributes@0.1.31", + "name": "tracing-attributes", + "version": "0.1.31", + "description": "Procedural macro attributes for automatically instrumenting functions. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/tracing-attributes@0.1.31", + "externalReferences": [ + { + "type": "website", + "url": "https://tokio.rs" + }, + { + "type": "vcs", + "url": "https://github.com/tokio-rs/tracing" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36", + "name": "tracing-core", + "version": "0.1.36", + "description": "Core primitives for application-level tracing. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/tracing-core@0.1.36", + "externalReferences": [ + { + "type": "website", + "url": "https://tokio.rs" + }, + { + "type": "vcs", + "url": "https://github.com/tokio-rs/tracing" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#tracing-log@0.2.0", + "name": "tracing-log", + "version": "0.2.0", + "description": "Provides compatibility between `tracing` and the `log` crate. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/tracing-log@0.2.0", + "externalReferences": [ + { + "type": "website", + "url": "https://tokio.rs" + }, + { + "type": "vcs", + "url": "https://github.com/tokio-rs/tracing" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#tracing-subscriber@0.3.22", + "name": "tracing-subscriber", + "version": "0.3.22", + "description": "Utilities for implementing and composing `tracing` subscribers. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/tracing-subscriber@0.3.22", + "externalReferences": [ + { + "type": "website", + "url": "https://tokio.rs" + }, + { + "type": "vcs", + "url": "https://github.com/tokio-rs/tracing" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44", + "name": "tracing", + "version": "0.1.44", + "description": "Application-level tracing for Rust. ", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/tracing@0.1.44", + "externalReferences": [ + { + "type": "website", + "url": "https://tokio.rs" + }, + { + "type": "vcs", + "url": "https://github.com/tokio-rs/tracing" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24", + "name": "unicode-ident", + "version": "1.0.24", + "description": "Determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31", + "scope": "required", + "licenses": [ + { + "expression": "(MIT OR Apache-2.0) AND Unicode-3.0" + } + ], + "purl": "pkg:cargo/unicode-ident@1.0.24", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/unicode-ident" + }, + { + "type": "vcs", + "url": "https://github.com/dtolnay/unicode-ident" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#untrusted@0.9.0", + "name": "untrusted", + "version": "0.9.0", + "description": "Safe, fast, zero-panic, zero-crashing, zero-allocation parsing of untrusted inputs in Rust.", + "scope": "required", + "licenses": [ + { + "expression": "ISC" + } + ], + "purl": "pkg:cargo/untrusted@0.9.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://briansmith.org/rustdoc/untrusted/" + }, + { + "type": "vcs", + "url": "https://github.com/briansmith/untrusted" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#ureq-proto@0.5.3", + "name": "ureq-proto", + "version": "0.5.3", + "description": "ureq support crate", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/ureq-proto@0.5.3", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/algesten/ureq-proto" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#ureq@3.2.0", + "name": "ureq", + "version": "3.2.0", + "description": "Simple, safe HTTP client", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/ureq@3.2.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/algesten/ureq" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#utf-8@0.7.6", + "name": "utf-8", + "version": "0.7.6", + "description": "Incremental, zero-copy UTF-8 decoding with error handling", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/utf-8@0.7.6", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/SimonSapin/rust-utf8" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#uuid@1.21.0", + "name": "uuid", + "version": "1.21.0", + "description": "A library to generate and parse UUIDs.", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/uuid@1.21.0", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/uuid" + }, + { + "type": "website", + "url": "https://github.com/uuid-rs/uuid" + }, + { + "type": "vcs", + "url": "https://github.com/uuid-rs/uuid" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#webpki-roots@1.0.6", + "name": "webpki-roots", + "version": "1.0.6", + "description": "Mozilla's CA root certificates for use with webpki", + "scope": "required", + "licenses": [ + { + "expression": "CDLA-Permissive-2.0" + } + ], + "purl": "pkg:cargo/webpki-roots@1.0.6", + "externalReferences": [ + { + "type": "website", + "url": "https://github.com/rustls/webpki-roots" + }, + { + "type": "vcs", + "url": "https://github.com/rustls/webpki-roots" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#winnow@0.7.14", + "name": "winnow", + "version": "0.7.14", + "description": "A byte-oriented, zero-copy, parser combinators library", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/winnow@0.7.14", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/winnow-rs/winnow" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#xattr@1.6.1", + "name": "xattr", + "version": "1.6.1", + "description": "unix extended filesystem attributes", + "scope": "required", + "licenses": [ + { + "expression": "MIT OR Apache-2.0" + } + ], + "purl": "pkg:cargo/xattr@1.6.1", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/xattr" + }, + { + "type": "vcs", + "url": "https://github.com/Stebalien/xattr" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#zbus@5.13.2", + "name": "zbus", + "version": "5.13.2", + "description": "API for D-Bus communication", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/zbus@5.13.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/z-galaxy/zbus/" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#zbus_macros@5.13.2", + "name": "zbus_macros", + "version": "5.13.2", + "description": "proc-macros for zbus", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/zbus_macros@5.13.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/z-galaxy/zbus/" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#zbus_names@4.3.1", + "name": "zbus_names", + "version": "4.3.1", + "description": "A collection of D-Bus bus names types", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/zbus_names@4.3.1", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/z-galaxy/zbus/" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#zeroize@1.8.2", + "name": "zeroize", + "version": "1.8.2", + "description": "Securely clear secrets from memory with a simple trait built on stable Rust primitives which guarantee memory is zeroed using an operation will not be 'optimized away' by the compiler. Uses a portable pure Rust implementation that works everywhere, even WASM! ", + "scope": "required", + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "purl": "pkg:cargo/zeroize@1.8.2", + "externalReferences": [ + { + "type": "website", + "url": "https://github.com/RustCrypto/utils/tree/master/zeroize" + }, + { + "type": "vcs", + "url": "https://github.com/RustCrypto/utils" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21", + "name": "zmij", + "version": "1.0.21", + "description": "A double-to-string conversion algorithm based on Schubfach and yy", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/zmij@1.0.21", + "externalReferences": [ + { + "type": "documentation", + "url": "https://docs.rs/zmij" + }, + { + "type": "vcs", + "url": "https://github.com/dtolnay/zmij" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#zvariant@5.9.2", + "name": "zvariant", + "version": "5.9.2", + "description": "D-Bus & GVariant encoding & decoding", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/zvariant@5.9.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/z-galaxy/zbus/" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#zvariant_derive@5.9.2", + "name": "zvariant_derive", + "version": "5.9.2", + "description": "D-Bus & GVariant encoding & decoding", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/zvariant_derive@5.9.2", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/z-galaxy/zbus/" + } + ] + }, + { + "type": "library", + "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#zvariant_utils@3.3.0", + "name": "zvariant_utils", + "version": "3.3.0", + "description": "Various utilities used internally by the zvariant crate.", + "scope": "required", + "licenses": [ + { + "expression": "MIT" + } + ], + "purl": "pkg:cargo/zvariant_utils@3.3.0", + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/z-galaxy/zbus/" + } + ] + } + ], + "dependencies": [ + { + "ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-core#0.1.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#blake3@1.8.3", + "registry+https://github.com/rust-lang/crates.io-index#chrono@0.4.43", + "registry+https://github.com/rust-lang/crates.io-index#ctrlc@3.5.2", + "registry+https://github.com/rust-lang/crates.io-index#fs2@0.4.3", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-remote#0.1.0", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-runtime#0.1.0", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-schema#0.1.0", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-store#0.1.0", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149", + "registry+https://github.com/rust-lang/crates.io-index#tempfile@3.25.0", + "registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18", + "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44" + ] + }, + { + "ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-dbus#0.1.0", + "dependsOn": [ + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-core#0.1.0", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-schema#0.1.0", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-store#0.1.0", + "registry+https://github.com/rust-lang/crates.io-index#notify-rust@4.12.0", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149", + "registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18", + "registry+https://github.com/rust-lang/crates.io-index#tokio@1.49.0", + "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44", + "registry+https://github.com/rust-lang/crates.io-index#tracing-subscriber@0.3.22", + "registry+https://github.com/rust-lang/crates.io-index#zbus@5.13.2" + ] + }, + { + "ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-remote#0.1.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#blake3@1.8.3", + "registry+https://github.com/rust-lang/crates.io-index#chrono@0.4.43", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-store#0.1.0", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149", + "registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18", + "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44", + "registry+https://github.com/rust-lang/crates.io-index#ureq@3.2.0" + ] + }, + { + "ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-runtime#0.1.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#blake3@1.8.3", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-schema#0.1.0", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-store#0.1.0", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149", + "registry+https://github.com/rust-lang/crates.io-index#tempfile@3.25.0", + "registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18", + "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44" + ] + }, + { + "ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-schema#0.1.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#blake3@1.8.3", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149", + "registry+https://github.com/rust-lang/crates.io-index#tempfile@3.25.0", + "registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18", + "registry+https://github.com/rust-lang/crates.io-index#toml@0.8.23" + ] + }, + { + "ref": "path+file:///home/lateuf/Projects/Karapace/crates/karapace-store#0.1.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#blake3@1.8.3", + "registry+https://github.com/rust-lang/crates.io-index#chrono@0.4.43", + "registry+https://github.com/rust-lang/crates.io-index#fs2@0.4.3", + "path+file:///home/lateuf/Projects/Karapace/crates/karapace-schema#0.1.0", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149", + "registry+https://github.com/rust-lang/crates.io-index#tar@0.4.44", + "registry+https://github.com/rust-lang/crates.io-index#tempfile@3.25.0", + "registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18", + "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#adler2@2.0.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#aho-corasick@1.1.4", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#arrayref@0.3.9", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#arrayvec@0.7.6", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#async-broadcast@0.7.2", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#event-listener@5.4.1", + "registry+https://github.com/rust-lang/crates.io-index#event-listener-strategy@0.5.4", + "registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#async-channel@2.5.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#concurrent-queue@2.5.0", + "registry+https://github.com/rust-lang/crates.io-index#event-listener-strategy@0.5.4", + "registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#async-executor@1.14.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#async-task@4.7.1", + "registry+https://github.com/rust-lang/crates.io-index#concurrent-queue@2.5.0", + "registry+https://github.com/rust-lang/crates.io-index#fastrand@2.3.0", + "registry+https://github.com/rust-lang/crates.io-index#futures-lite@2.6.1", + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16", + "registry+https://github.com/rust-lang/crates.io-index#slab@0.4.12" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#async-io@2.6.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#autocfg@1.5.0", + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#concurrent-queue@2.5.0", + "registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#futures-lite@2.6.1", + "registry+https://github.com/rust-lang/crates.io-index#parking@2.2.1", + "registry+https://github.com/rust-lang/crates.io-index#polling@3.11.0", + "registry+https://github.com/rust-lang/crates.io-index#rustix@1.1.3", + "registry+https://github.com/rust-lang/crates.io-index#slab@0.4.12" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#async-lock@3.4.2", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#event-listener@5.4.1", + "registry+https://github.com/rust-lang/crates.io-index#event-listener-strategy@0.5.4", + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#async-process@2.5.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#async-channel@2.5.0", + "registry+https://github.com/rust-lang/crates.io-index#async-io@2.6.0", + "registry+https://github.com/rust-lang/crates.io-index#async-lock@3.4.2", + "registry+https://github.com/rust-lang/crates.io-index#async-signal@0.2.13", + "registry+https://github.com/rust-lang/crates.io-index#async-task@4.7.1", + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#event-listener@5.4.1", + "registry+https://github.com/rust-lang/crates.io-index#futures-lite@2.6.1", + "registry+https://github.com/rust-lang/crates.io-index#rustix@1.1.3" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#async-signal@0.2.13", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#async-io@2.6.0", + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#rustix@1.1.3", + "registry+https://github.com/rust-lang/crates.io-index#signal-hook-registry@1.4.8" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#async-task@4.7.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#async-trait@0.1.89", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#atomic-waker@1.1.2", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#autocfg@1.5.0", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.0", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#blake3@1.8.3", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#arrayref@0.3.9", + "registry+https://github.com/rust-lang/crates.io-index#arrayvec@0.7.6", + "registry+https://github.com/rust-lang/crates.io-index#cc@1.2.56", + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#constant_time_eq@0.4.2", + "registry+https://github.com/rust-lang/crates.io-index#cpufeatures@0.2.17" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#blocking@1.6.2", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#async-channel@2.5.0", + "registry+https://github.com/rust-lang/crates.io-index#async-task@4.7.1", + "registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#futures-lite@2.6.1", + "registry+https://github.com/rust-lang/crates.io-index#piper@0.2.4" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#bytes@1.11.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#cc@1.2.56", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#find-msvc-tools@0.1.9", + "registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#cfg_aliases@0.2.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#chrono@0.4.43", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#iana-time-zone@0.1.65", + "registry+https://github.com/rust-lang/crates.io-index#num-traits@0.2.19", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#concurrent-queue@2.5.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#crossbeam-utils@0.8.21" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#constant_time_eq@0.4.2", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#cpufeatures@0.2.17", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#crc32fast@1.5.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#crossbeam-utils@0.8.21", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#ctrlc@3.5.2", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#nix@0.31.1" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#endi@1.1.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#enumflags2@0.7.12", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#enumflags2_derive@0.7.12", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#enumflags2_derive@0.7.12", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#equivalent@1.0.2", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#errno@0.3.14", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#event-listener-strategy@0.5.4", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#event-listener@5.4.1", + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#event-listener@5.4.1", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#concurrent-queue@2.5.0", + "registry+https://github.com/rust-lang/crates.io-index#parking@2.2.1", + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#fastrand@2.3.0", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#filetime@0.2.27", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#find-msvc-tools@0.1.9", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#flate2@1.1.9", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#crc32fast@1.5.0", + "registry+https://github.com/rust-lang/crates.io-index#miniz_oxide@0.8.9" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#fs2@0.4.3", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#futures-lite@2.6.1", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#fastrand@2.3.0", + "registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#parking@2.2.1", + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#getrandom@0.2.17", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#getrandom@0.4.1", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#hashbrown@0.16.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#hex@0.4.3", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#http@1.4.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#bytes@1.11.1", + "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.17" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#httparse@1.10.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#iana-time-zone@0.1.65", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#indexmap@2.13.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#equivalent@1.0.2", + "registry+https://github.com/rust-lang/crates.io-index#hashbrown@0.16.1", + "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.17", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#lazy_static@1.5.0", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#linux-raw-sys@0.11.0", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#log@0.4.29", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#matchers@0.2.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#regex-automata@0.4.14" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#miniz_oxide@0.8.9", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#adler2@2.0.1", + "registry+https://github.com/rust-lang/crates.io-index#simd-adler32@0.3.8" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#nix@0.31.1", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.0", + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#cfg_aliases@0.2.1", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#notify-rust@4.12.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#futures-lite@2.6.1", + "registry+https://github.com/rust-lang/crates.io-index#log@0.4.29", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#zbus@5.13.2" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#nu-ansi-term@0.50.3", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#num-traits@0.2.19", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#autocfg@1.5.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.3", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#ordered-stream@0.2.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#parking@2.2.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#percent-encoding@2.3.2", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#piper@0.2.4", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#atomic-waker@1.1.2", + "registry+https://github.com/rust-lang/crates.io-index#fastrand@2.3.0", + "registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#polling@3.11.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#rustix@1.1.3" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro-crate@3.4.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#toml_edit@0.23.10+spec-1.0.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#regex-automata@0.4.14", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#aho-corasick@1.1.4", + "registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0", + "registry+https://github.com/rust-lang/crates.io-index#regex-syntax@0.8.9" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#regex-syntax@0.8.9", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#ring@0.17.14", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#cc@1.2.56", + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "registry+https://github.com/rust-lang/crates.io-index#getrandom@0.2.17", + "registry+https://github.com/rust-lang/crates.io-index#untrusted@0.9.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#rustix@1.1.3", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.0", + "registry+https://github.com/rust-lang/crates.io-index#errno@0.3.14", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180", + "registry+https://github.com/rust-lang/crates.io-index#linux-raw-sys@0.11.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#rustls-pki-types@1.14.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#zeroize@1.8.2" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#rustls-webpki@0.103.9", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#ring@0.17.14", + "registry+https://github.com/rust-lang/crates.io-index#rustls-pki-types@1.14.0", + "registry+https://github.com/rust-lang/crates.io-index#untrusted@0.9.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#rustls@0.23.36", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#log@0.4.29", + "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.3", + "registry+https://github.com/rust-lang/crates.io-index#ring@0.17.14", + "registry+https://github.com/rust-lang/crates.io-index#rustls-pki-types@1.14.0", + "registry+https://github.com/rust-lang/crates.io-index#rustls-webpki@0.103.9", + "registry+https://github.com/rust-lang/crates.io-index#subtle@2.6.1", + "registry+https://github.com/rust-lang/crates.io-index#zeroize@1.8.2" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.17", + "registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0", + "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#serde_repr@0.1.20", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#serde_spanned@0.6.9", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#sharded-slab@0.1.7", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#lazy_static@1.5.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#signal-hook-registry@1.4.8", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#errno@0.3.14", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#simd-adler32@0.3.8", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#slab@0.4.12", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#smallvec@1.15.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#subtle@2.6.1", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#tar@0.4.44", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#filetime@0.2.27", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180", + "registry+https://github.com/rust-lang/crates.io-index#xattr@1.6.1" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#tempfile@3.25.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#fastrand@2.3.0", + "registry+https://github.com/rust-lang/crates.io-index#getrandom@0.4.1", + "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.3", + "registry+https://github.com/rust-lang/crates.io-index#rustix@1.1.3" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#thiserror-impl@2.0.18", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#thiserror-impl@2.0.18" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#thread_local@1.1.9", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#tokio-macros@2.6.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#tokio@1.49.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16", + "registry+https://github.com/rust-lang/crates.io-index#tokio-macros@2.6.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#toml@0.8.23", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_spanned@0.6.9", + "registry+https://github.com/rust-lang/crates.io-index#toml_datetime@0.6.11", + "registry+https://github.com/rust-lang/crates.io-index#toml_edit@0.22.27" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#toml_datetime@0.6.11", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#toml_datetime@0.7.5+spec-1.1.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#toml_edit@0.22.27", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#indexmap@2.13.0", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_spanned@0.6.9", + "registry+https://github.com/rust-lang/crates.io-index#toml_datetime@0.6.11", + "registry+https://github.com/rust-lang/crates.io-index#toml_write@0.1.2", + "registry+https://github.com/rust-lang/crates.io-index#winnow@0.7.14" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#toml_edit@0.23.10+spec-1.0.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#indexmap@2.13.0", + "registry+https://github.com/rust-lang/crates.io-index#toml_datetime@0.7.5+spec-1.1.0", + "registry+https://github.com/rust-lang/crates.io-index#toml_parser@1.0.9+spec-1.1.0", + "registry+https://github.com/rust-lang/crates.io-index#winnow@0.7.14" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#toml_parser@1.0.9+spec-1.1.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#winnow@0.7.14" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#toml_write@0.1.2", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#tracing-attributes@0.1.31", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.3" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#tracing-log@0.2.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#log@0.4.29", + "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.3", + "registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#tracing-subscriber@0.3.22", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#matchers@0.2.0", + "registry+https://github.com/rust-lang/crates.io-index#nu-ansi-term@0.50.3", + "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.3", + "registry+https://github.com/rust-lang/crates.io-index#regex-automata@0.4.14", + "registry+https://github.com/rust-lang/crates.io-index#sharded-slab@0.1.7", + "registry+https://github.com/rust-lang/crates.io-index#smallvec@1.15.1", + "registry+https://github.com/rust-lang/crates.io-index#thread_local@1.1.9", + "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44", + "registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36", + "registry+https://github.com/rust-lang/crates.io-index#tracing-log@0.2.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.16", + "registry+https://github.com/rust-lang/crates.io-index#tracing-attributes@0.1.31", + "registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#untrusted@0.9.0", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#ureq-proto@0.5.3", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1", + "registry+https://github.com/rust-lang/crates.io-index#http@1.4.0", + "registry+https://github.com/rust-lang/crates.io-index#httparse@1.10.1", + "registry+https://github.com/rust-lang/crates.io-index#log@0.4.29" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#ureq@3.2.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1", + "registry+https://github.com/rust-lang/crates.io-index#flate2@1.1.9", + "registry+https://github.com/rust-lang/crates.io-index#log@0.4.29", + "registry+https://github.com/rust-lang/crates.io-index#percent-encoding@2.3.2", + "registry+https://github.com/rust-lang/crates.io-index#rustls@0.23.36", + "registry+https://github.com/rust-lang/crates.io-index#rustls-pki-types@1.14.0", + "registry+https://github.com/rust-lang/crates.io-index#ureq-proto@0.5.3", + "registry+https://github.com/rust-lang/crates.io-index#utf-8@0.7.6", + "registry+https://github.com/rust-lang/crates.io-index#webpki-roots@1.0.6" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#utf-8@0.7.6", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#uuid@1.21.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#webpki-roots@1.0.6", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#rustls-pki-types@1.14.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#winnow@0.7.14", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#xattr@1.6.1", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#rustix@1.1.3" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#zbus@5.13.2", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#async-broadcast@0.7.2", + "registry+https://github.com/rust-lang/crates.io-index#async-executor@1.14.0", + "registry+https://github.com/rust-lang/crates.io-index#async-io@2.6.0", + "registry+https://github.com/rust-lang/crates.io-index#async-lock@3.4.2", + "registry+https://github.com/rust-lang/crates.io-index#async-process@2.5.0", + "registry+https://github.com/rust-lang/crates.io-index#async-task@4.7.1", + "registry+https://github.com/rust-lang/crates.io-index#async-trait@0.1.89", + "registry+https://github.com/rust-lang/crates.io-index#blocking@1.6.2", + "registry+https://github.com/rust-lang/crates.io-index#enumflags2@0.7.12", + "registry+https://github.com/rust-lang/crates.io-index#event-listener@5.4.1", + "registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32", + "registry+https://github.com/rust-lang/crates.io-index#futures-lite@2.6.1", + "registry+https://github.com/rust-lang/crates.io-index#hex@0.4.3", + "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.180", + "registry+https://github.com/rust-lang/crates.io-index#ordered-stream@0.2.0", + "registry+https://github.com/rust-lang/crates.io-index#rustix@1.1.3", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#serde_repr@0.1.20", + "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44", + "registry+https://github.com/rust-lang/crates.io-index#uuid@1.21.0", + "registry+https://github.com/rust-lang/crates.io-index#winnow@0.7.14", + "registry+https://github.com/rust-lang/crates.io-index#zbus_macros@5.13.2", + "registry+https://github.com/rust-lang/crates.io-index#zbus_names@4.3.1", + "registry+https://github.com/rust-lang/crates.io-index#zvariant@5.9.2" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#zbus_macros@5.13.2", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro-crate@3.4.0", + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117", + "registry+https://github.com/rust-lang/crates.io-index#zbus_names@4.3.1", + "registry+https://github.com/rust-lang/crates.io-index#zvariant@5.9.2", + "registry+https://github.com/rust-lang/crates.io-index#zvariant_utils@3.3.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#zbus_names@4.3.1", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#winnow@0.7.14", + "registry+https://github.com/rust-lang/crates.io-index#zvariant@5.9.2" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#zeroize@1.8.2", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21", + "dependsOn": [] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#zvariant@5.9.2", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#endi@1.1.1", + "registry+https://github.com/rust-lang/crates.io-index#enumflags2@0.7.12", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#winnow@0.7.14", + "registry+https://github.com/rust-lang/crates.io-index#zvariant_derive@5.9.2", + "registry+https://github.com/rust-lang/crates.io-index#zvariant_utils@3.3.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#zvariant_derive@5.9.2", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro-crate@3.4.0", + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117", + "registry+https://github.com/rust-lang/crates.io-index#zvariant_utils@3.3.0" + ] + }, + { + "ref": "registry+https://github.com/rust-lang/crates.io-index#zvariant_utils@3.3.0", + "dependsOn": [ + "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.44", + "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117", + "registry+https://github.com/rust-lang/crates.io-index#winnow@0.7.14" + ] + } + ] +} \ No newline at end of file diff --git a/crates/karapace-dbus/src/interface.rs b/crates/karapace-dbus/src/interface.rs new file mode 100644 index 0000000..1455e87 --- /dev/null +++ b/crates/karapace-dbus/src/interface.rs @@ -0,0 +1,672 @@ +use karapace_core::StoreLock; +use karapace_store::StoreLayout; +use serde::{Deserialize, Serialize}; +use tracing::{error, info}; +use zbus::interface; + +pub const DBUS_INTERFACE: &str = "org.karapace.Manager1"; +pub const DBUS_PATH: &str = "/org/karapace/Manager1"; +pub const API_VERSION: u32 = 1; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct EnvInfo { + pub env_id: String, + pub short_id: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + pub state: String, +} + +#[derive(Debug, Serialize)] +struct DestroyResponse { + destroyed: String, +} + +#[derive(Debug, Serialize)] +struct EnterResponse { + entered: String, +} + +#[derive(Debug, Serialize)] +struct RenameResponse { + env_id: String, + name: String, +} + +fn to_fdo(msg: impl std::fmt::Display) -> zbus::fdo::Error { + zbus::fdo::Error::Failed(msg.to_string()) +} + +fn send_notification(summary: &str, body: &str) { + if let Err(e) = notify_rust::Notification::new() + .appname("Karapace") + .summary(summary) + .body(body) + .timeout(notify_rust::Timeout::Milliseconds(5000)) + .show() + { + tracing::debug!("desktop notification failed (non-fatal): {e}"); + } +} + +pub struct KarapaceManager { + store_root: String, +} + +impl KarapaceManager { + pub fn new(store_root: String) -> Self { + Self { store_root } + } + + fn engine(&self) -> karapace_core::Engine { + karapace_core::Engine::new(&self.store_root) + } + + fn acquire_lock(&self) -> Result { + let layout = StoreLayout::new(&self.store_root); + StoreLock::acquire(&layout.lock_file()).map_err(|e| { + error!("store lock acquisition failed: {e}"); + to_fdo(format!("store lock: {e}")) + }) + } + + fn resolve_env(&self, id_or_name: &str) -> Result { + let engine = self.engine(); + if id_or_name.len() == 64 { + return Ok(id_or_name.to_owned()); + } + let envs = engine.list().map_err(to_fdo)?; + for e in &envs { + if *e.env_id == *id_or_name + || *e.short_id == *id_or_name + || e.name.as_deref() == Some(id_or_name) + { + return Ok(e.env_id.to_string()); + } + } + for e in &envs { + if e.env_id.starts_with(id_or_name) || e.short_id.starts_with(id_or_name) { + return Ok(e.env_id.to_string()); + } + } + Err(to_fdo(format!("no environment matching '{id_or_name}'"))) + } +} + +#[allow(clippy::unused_async)] +#[interface(name = "org.karapace.Manager1")] +impl KarapaceManager { + #[zbus(property)] + async fn api_version(&self) -> u32 { + API_VERSION + } + + #[zbus(property)] + async fn store_root(&self) -> &str { + &self.store_root + } + + async fn list_environments(&self) -> Result { + info!("D-Bus: ListEnvironments"); + let envs = self.engine().list().map_err(|e| { + error!("ListEnvironments failed: {e}"); + to_fdo(e) + })?; + let infos: Vec = envs + .iter() + .map(|e| EnvInfo { + env_id: e.env_id.to_string(), + short_id: e.short_id.to_string(), + name: e.name.clone(), + state: e.state.to_string(), + }) + .collect(); + serde_json::to_string(&infos).map_err(to_fdo) + } + + async fn get_environment_status(&self, id_or_name: String) -> Result { + info!("D-Bus: GetEnvironmentStatus {id_or_name}"); + let resolved = self.resolve_env(&id_or_name)?; + let meta = self.engine().inspect(&resolved).map_err(|e| { + error!("GetEnvironmentStatus failed for {id_or_name}: {e}"); + to_fdo(e) + })?; + serde_json::to_string(&EnvInfo { + env_id: meta.env_id.to_string(), + short_id: meta.short_id.to_string(), + name: meta.name, + state: meta.state.to_string(), + }) + .map_err(to_fdo) + } + + async fn get_environment_hash(&self, id_or_name: String) -> Result { + info!("D-Bus: GetEnvironmentHash {id_or_name}"); + let resolved = self.resolve_env(&id_or_name)?; + let meta = self.engine().inspect(&resolved).map_err(|e| { + error!("GetEnvironmentHash failed for {id_or_name}: {e}"); + to_fdo(e) + })?; + Ok(meta.env_id.to_string()) + } + + async fn build_environment(&self, manifest_path: String) -> Result { + info!("D-Bus: BuildEnvironment {manifest_path}"); + let _lock = self.acquire_lock()?; + let result = match self.engine().build(std::path::Path::new(&manifest_path)) { + Ok(r) => { + send_notification( + "Build Complete", + &format!("Environment {} built", &r.identity.short_id), + ); + r + } + Err(e) => { + send_notification("Build Failed", &e.to_string()); + error!("BuildEnvironment failed: {e}"); + return Err(to_fdo(e)); + } + }; + serde_json::to_string(&EnvInfo { + env_id: result.identity.env_id.to_string(), + short_id: result.identity.short_id.to_string(), + name: None, + state: "built".to_owned(), + }) + .map_err(to_fdo) + } + + async fn build_named_environment( + &self, + manifest_path: String, + name: String, + ) -> Result { + info!("D-Bus: BuildNamedEnvironment {manifest_path} name={name}"); + let _lock = self.acquire_lock()?; + let engine = self.engine(); + let result = match engine.build(std::path::Path::new(&manifest_path)) { + Ok(r) => { + send_notification( + "Build Complete", + &format!("Environment '{}' ({}) built", name, &r.identity.short_id), + ); + r + } + Err(e) => { + send_notification("Build Failed", &e.to_string()); + error!("BuildNamedEnvironment failed: {e}"); + return Err(to_fdo(e)); + } + }; + engine + .set_name(&result.identity.env_id, Some(name.clone())) + .map_err(|e| { + error!("BuildNamedEnvironment set_name failed: {e}"); + to_fdo(e) + })?; + serde_json::to_string(&EnvInfo { + env_id: result.identity.env_id.to_string(), + short_id: result.identity.short_id.to_string(), + name: Some(name), + state: "built".to_owned(), + }) + .map_err(to_fdo) + } + + async fn destroy_environment(&self, id_or_name: String) -> Result { + info!("D-Bus: DestroyEnvironment {id_or_name}"); + let resolved = self.resolve_env(&id_or_name)?; + let _lock = self.acquire_lock()?; + self.engine().destroy(&resolved).map_err(|e| { + error!("DestroyEnvironment failed for {id_or_name}: {e}"); + to_fdo(e) + })?; + serde_json::to_string(&DestroyResponse { + destroyed: resolved, + }) + .map_err(to_fdo) + } + + async fn run_environment(&self, id_or_name: String) -> Result { + info!("D-Bus: RunEnvironment {id_or_name}"); + let resolved = self.resolve_env(&id_or_name)?; + let _lock = self.acquire_lock()?; + self.engine().enter(&resolved).map_err(|e| { + error!("RunEnvironment failed for {id_or_name}: {e}"); + to_fdo(e) + })?; + serde_json::to_string(&EnterResponse { entered: resolved }).map_err(to_fdo) + } + + async fn rename_environment( + &self, + id_or_name: String, + new_name: String, + ) -> Result { + info!("D-Bus: RenameEnvironment {id_or_name} -> {new_name}"); + let resolved = self.resolve_env(&id_or_name)?; + let _lock = self.acquire_lock()?; + self.engine().rename(&resolved, &new_name).map_err(|e| { + error!("RenameEnvironment failed: {e}"); + to_fdo(e) + })?; + serde_json::to_string(&RenameResponse { + env_id: resolved, + name: new_name, + }) + .map_err(to_fdo) + } + + async fn list_presets(&self) -> Result { + info!("D-Bus: ListPresets"); + let presets: Vec = karapace_schema::list_presets() + .iter() + .map(|p| { + serde_json::json!({ + "name": p.name, + "description": p.description, + }) + }) + .collect(); + serde_json::to_string(&presets).map_err(to_fdo) + } + + async fn garbage_collect(&self, dry_run: bool) -> Result { + info!("D-Bus: GarbageCollect (dry_run={dry_run})"); + let lock = self.acquire_lock()?; + let report = self.engine().gc(&lock, dry_run).map_err(|e| { + error!("GarbageCollect failed: {e}"); + to_fdo(e) + })?; + serde_json::to_string(&serde_json::json!({ + "dry_run": dry_run, + "removed_envs": report.removed_envs, + "removed_layers": report.removed_layers, + "removed_objects": report.removed_objects, + })) + .map_err(to_fdo) + } + + async fn verify_store(&self) -> Result { + info!("D-Bus: VerifyStore"); + let layout = StoreLayout::new(&self.store_root); + let report = karapace_store::verify_store_integrity(&layout).map_err(|e| { + error!("VerifyStore failed: {e}"); + to_fdo(e) + })?; + serde_json::to_string(&serde_json::json!({ + "checked": report.checked, + "passed": report.passed, + "failed": report.failed.len(), + })) + .map_err(to_fdo) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn setup() -> (tempfile::TempDir, tempfile::TempDir, KarapaceManager) { + let store = tempfile::tempdir().unwrap(); + let project = tempfile::tempdir().unwrap(); + let manager = KarapaceManager::new(store.path().to_string_lossy().to_string()); + (store, project, manager) + } + + fn write_mock_manifest(dir: &std::path::Path) -> std::path::PathBuf { + let path = dir.join("karapace.toml"); + std::fs::write( + &path, + r#"manifest_version = 1 +[base] +image = "rolling" +[runtime] +backend = "mock" +"#, + ) + .unwrap(); + path + } + + #[tokio::test] + async fn list_environments_empty() { + let (_store, _project, mgr) = setup(); + let result = mgr.list_environments().await; + // Empty store may return empty list or error — both are valid + if let Ok(json) = result { + let parsed: Vec = serde_json::from_str(&json).unwrap(); + assert!(parsed.is_empty()); + } + } + + #[tokio::test] + async fn build_and_list_roundtrip() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + assert_eq!(info.state, "built"); + assert!(!info.env_id.is_empty()); + + let list_result = mgr.list_environments().await.unwrap(); + let envs: Vec = serde_json::from_str(&list_result).unwrap(); + assert_eq!(envs.len(), 1); + assert_eq!(envs[0].env_id, info.env_id); + } + + #[tokio::test] + async fn get_status_of_built_env() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + + let status = mgr + .get_environment_status(info.env_id.clone()) + .await + .unwrap(); + let status_info: EnvInfo = serde_json::from_str(&status).unwrap(); + assert_eq!(status_info.state, "built"); + } + + #[tokio::test] + async fn get_hash_returns_env_id() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + + let hash = mgr.get_environment_hash(info.env_id.clone()).await.unwrap(); + assert_eq!(hash, info.env_id); + } + + #[tokio::test] + async fn destroy_removes_environment() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + + mgr.destroy_environment(info.env_id.clone()).await.unwrap(); + + // Should no longer be in the list + let list_result = mgr.list_environments().await.unwrap(); + let envs: Vec = serde_json::from_str(&list_result).unwrap(); + assert!(envs.is_empty()); + } + + #[tokio::test] + async fn gc_on_empty_store() { + let (_store, _project, mgr) = setup(); + // GC on empty/uninitialized store should not panic + let result = mgr.garbage_collect(true).await; + // May succeed or fail depending on store init — should not panic + assert!(result.is_ok() || result.is_err()); + } + + #[tokio::test] + async fn get_status_nonexistent_returns_error() { + let (_store, _project, mgr) = setup(); + let result = mgr.get_environment_status("nonexistent".to_owned()).await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn build_named_environment_sets_name() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let result = mgr + .build_named_environment(manifest.to_string_lossy().to_string(), "my-env".to_owned()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&result).unwrap(); + assert_eq!(info.name, Some("my-env".to_owned())); + assert_eq!(info.state, "built"); + + // List should include name + let list_result = mgr.list_environments().await.unwrap(); + let envs: Vec = serde_json::from_str(&list_result).unwrap(); + assert_eq!(envs[0].name, Some("my-env".to_owned())); + } + + #[tokio::test] + async fn rename_environment_works() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + + mgr.rename_environment(info.env_id.clone(), "renamed-env".to_owned()) + .await + .unwrap(); + + // Verify name via status + let status = mgr + .get_environment_status(info.env_id.clone()) + .await + .unwrap(); + let status_info: EnvInfo = serde_json::from_str(&status).unwrap(); + assert_eq!(status_info.name, Some("renamed-env".to_owned())); + } + + #[tokio::test] + async fn resolve_by_name_works() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_named_environment( + manifest.to_string_lossy().to_string(), + "named-env".to_owned(), + ) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + + // Get status by name + let status = mgr + .get_environment_status("named-env".to_owned()) + .await + .unwrap(); + let status_info: EnvInfo = serde_json::from_str(&status).unwrap(); + assert_eq!(status_info.env_id, info.env_id); + } + + #[tokio::test] + async fn list_presets_returns_presets() { + let (_store, _project, mgr) = setup(); + let result = mgr.list_presets().await.unwrap(); + let presets: Vec = serde_json::from_str(&result).unwrap(); + assert!(!presets.is_empty()); + assert!(presets.iter().any(|p| p["name"] == "dev")); + assert!(presets.iter().any(|p| p["name"] == "minimal")); + } + + #[tokio::test] + async fn destroy_by_name_works() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + mgr.build_named_environment( + manifest.to_string_lossy().to_string(), + "to-destroy".to_owned(), + ) + .await + .unwrap(); + + mgr.destroy_environment("to-destroy".to_owned()) + .await + .unwrap(); + + let list_result = mgr.list_environments().await.unwrap(); + let envs: Vec = serde_json::from_str(&list_result).unwrap(); + assert!(envs.is_empty()); + } + + #[tokio::test] + async fn build_invalid_manifest_returns_error() { + let (_store, project, mgr) = setup(); + let bad_path = project.path().join("nonexistent.toml"); + let result = mgr + .build_environment(bad_path.to_string_lossy().to_string()) + .await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn rename_to_taken_name_returns_error() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + mgr.build_named_environment( + manifest.to_string_lossy().to_string(), + "first-env".to_owned(), + ) + .await + .unwrap(); + + // Build a second manifest with different content to get a different env_id + let path2 = project.path().join("karapace2.toml"); + std::fs::write( + &path2, + r#"manifest_version = 1 +[base] +image = "rolling" +[system] +packages = ["curl"] +[runtime] +backend = "mock" +"#, + ) + .unwrap(); + let build2 = mgr + .build_environment(path2.to_string_lossy().to_string()) + .await + .unwrap(); + let info2: EnvInfo = serde_json::from_str(&build2).unwrap(); + + let result = mgr + .rename_environment(info2.env_id, "first-env".to_owned()) + .await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn destroy_nonexistent_returns_error() { + let (_store, _project, mgr) = setup(); + let result = mgr.destroy_environment("does-not-exist".to_owned()).await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn gc_after_build_and_destroy() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + + mgr.destroy_environment(info.env_id).await.unwrap(); + + let gc_result = mgr.garbage_collect(false).await.unwrap(); + let gc: serde_json::Value = serde_json::from_str(&gc_result).unwrap(); + assert_eq!(gc["dry_run"], false); + } + + #[tokio::test] + async fn verify_store_on_fresh_store() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + mgr.build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + + let result = mgr.verify_store().await.unwrap(); + let report: serde_json::Value = serde_json::from_str(&result).unwrap(); + assert!(report["checked"].as_u64().unwrap() > 0); + assert_eq!(report["failed"], 0); + } + + #[tokio::test] + async fn list_after_rename_shows_new_name() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + + mgr.rename_environment(info.env_id.clone(), "new-name".to_owned()) + .await + .unwrap(); + + let list_result = mgr.list_environments().await.unwrap(); + let envs: Vec = serde_json::from_str(&list_result).unwrap(); + assert_eq!(envs.len(), 1); + assert_eq!(envs[0].name, Some("new-name".to_owned())); + } + + #[tokio::test] + async fn destroy_response_is_valid_json() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + + let destroy_result = mgr.destroy_environment(info.env_id.clone()).await.unwrap(); + let parsed: serde_json::Value = serde_json::from_str(&destroy_result).unwrap(); + assert_eq!(parsed["destroyed"].as_str().unwrap(), info.env_id); + } + + #[tokio::test] + async fn rename_response_is_valid_json() { + let (_store, project, mgr) = setup(); + let manifest = write_mock_manifest(project.path()); + + let build_result = mgr + .build_environment(manifest.to_string_lossy().to_string()) + .await + .unwrap(); + let info: EnvInfo = serde_json::from_str(&build_result).unwrap(); + + let rename_result = mgr + .rename_environment(info.env_id.clone(), "test-rename".to_owned()) + .await + .unwrap(); + let parsed: serde_json::Value = serde_json::from_str(&rename_result).unwrap(); + assert_eq!(parsed["env_id"].as_str().unwrap(), info.env_id); + assert_eq!(parsed["name"].as_str().unwrap(), "test-rename"); + } +} diff --git a/crates/karapace-dbus/src/lib.rs b/crates/karapace-dbus/src/lib.rs new file mode 100644 index 0000000..eb7d9bf --- /dev/null +++ b/crates/karapace-dbus/src/lib.rs @@ -0,0 +1,12 @@ +//! D-Bus desktop integration service for Karapace. +//! +//! This crate exposes the Karapace engine over the `org.karapace.Manager1` D-Bus +//! interface, enabling desktop applications and system services to build, destroy, +//! enter, and query environments without invoking the CLI directly. Designed for +//! socket activation with an idle timeout. + +pub mod interface; +pub mod service; + +pub use interface::{KarapaceManager, API_VERSION, DBUS_INTERFACE, DBUS_PATH}; +pub use service::{run_service, run_service_with_timeout, ServiceError}; diff --git a/crates/karapace-dbus/src/main.rs b/crates/karapace-dbus/src/main.rs new file mode 100644 index 0000000..e433f16 --- /dev/null +++ b/crates/karapace-dbus/src/main.rs @@ -0,0 +1,30 @@ +use std::path::PathBuf; +use tracing::info; + +fn default_store_path() -> PathBuf { + if let Ok(home) = std::env::var("HOME") { + PathBuf::from(home).join(".local/share/karapace") + } else { + PathBuf::from("/tmp/karapace") + } +} + +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<(), Box> { + tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::try_from_env("KARAPACE_LOG") + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")), + ) + .with_target(false) + .without_time() + .init(); + + let store_root = + std::env::var("KARAPACE_STORE").map_or_else(|_| default_store_path(), PathBuf::from); + + info!("karapace-dbus starting, store: {}", store_root.display()); + karapace_dbus::run_service(store_root.to_string_lossy().to_string()).await?; + + Ok(()) +} diff --git a/crates/karapace-dbus/src/service.rs b/crates/karapace-dbus/src/service.rs new file mode 100644 index 0000000..80dca55 --- /dev/null +++ b/crates/karapace-dbus/src/service.rs @@ -0,0 +1,50 @@ +use crate::interface::{KarapaceManager, DBUS_PATH}; +use thiserror::Error; +use tracing::info; +use zbus::connection::Builder; + +/// Default idle timeout before the service exits (for socket activation). +const IDLE_TIMEOUT_SECS: u64 = 30; + +#[derive(Debug, Error)] +pub enum ServiceError { + #[error("DBus error: {0}")] + Dbus(#[from] zbus::Error), +} + +/// Run the D-Bus service. If `idle_timeout` is Some, the service will exit +/// after that many seconds of inactivity. Use None for infinite runtime. +pub async fn run_service(store_root: String) -> Result<(), ServiceError> { + run_service_with_timeout(store_root, Some(IDLE_TIMEOUT_SECS)).await +} + +pub async fn run_service_with_timeout( + store_root: String, + idle_timeout: Option, +) -> Result<(), ServiceError> { + let manager = KarapaceManager::new(store_root); + + let _conn = Builder::session()? + .name("org.karapace.Manager1")? + .serve_at(DBUS_PATH, manager)? + .build() + .await?; + + info!("karapace-dbus service started on session bus"); + + match idle_timeout { + Some(secs) => { + info!("idle timeout: {secs}s"); + // In a socket-activated setup, the service exits after idle timeout. + // The D-Bus broker will restart it on next method call. + tokio::time::sleep(std::time::Duration::from_secs(secs)).await; + info!("idle timeout reached, shutting down"); + } + None => { + // Run forever (e.g., when started manually for debugging) + std::future::pending::<()>().await; + } + } + + Ok(()) +}